You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
247 lines
8.7 KiB
C++
247 lines
8.7 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: QVTKOpenGLNativeWidget.h
|
|
|
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
PURPOSE. See the above copyright notice for more information.
|
|
|
|
=========================================================================*/
|
|
/**
|
|
* @class QVTKOpenGLNativeWidget
|
|
* @brief QOpenGLWidget subclass to house a vtkGenericOpenGLRenderWindow in a Qt
|
|
* application.
|
|
*
|
|
* QVTKOpenGLNativeWidget extends QOpenGLWidget to make it work with a
|
|
* vtkGenericOpenGLRenderWindow.
|
|
*
|
|
* Please note that QVTKOpenGLNativeWidget only works with vtkGenericOpenGLRenderWindow.
|
|
* This is necessary since QOpenGLWidget wants to take over the window management as
|
|
* well as the OpenGL context creation. Getting that to work reliably with
|
|
* vtkXRenderWindow or vtkWin32RenderWindow (and other platform specific
|
|
* vtkRenderWindow subclasses) was tricky and fraught with issues.
|
|
*
|
|
* Since QVTKOpenGLNativeWidget uses QOpenGLWidget to create the OpenGL context,
|
|
* it uses QSurfaceFormat (set using `QOpenGLWidget::setFormat` or
|
|
* `QSurfaceFormat::setDefaultFormat`) to create appropriate window and context.
|
|
* You can use `QVTKOpenGLNativeWidget::copyToFormat` to obtain a QSurfaceFormat
|
|
* appropriate for a vtkRenderWindow.
|
|
*
|
|
* A typical usage for QVTKOpenGLNativeWidget is as follows:
|
|
* @code{.cpp}
|
|
*
|
|
* // before initializing QApplication, set the default surface format.
|
|
* QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());
|
|
*
|
|
* vtkNew<vtkGenericOpenGLRenderWindow> window;
|
|
* QPointer<QVTKOpenGLNativeWidget> widget = new QVTKOpenGLNativeWidget(...);
|
|
* widget->SetRenderWindow(window.Get());
|
|
*
|
|
* // If using any of the standard view e.g. vtkContextView, then
|
|
* // you can do the following.
|
|
* vtkNew<vtkContextView> view;
|
|
* view->SetRenderWindow(window.Get());
|
|
*
|
|
* // You can continue to use `window` as a regular vtkRenderWindow
|
|
* // including adding renderers, actors etc.
|
|
*
|
|
* @endcode
|
|
*
|
|
* @section OpenGLContext OpenGL Context
|
|
*
|
|
* In QOpenGLWidget (superclass for QVTKOpenGLNativeWidget), all rendering happens in a
|
|
* framebuffer object. Thus, care must be taken in the rendering code to never
|
|
* directly re-bind the default framebuffer i.e. ID 0.
|
|
*
|
|
* QVTKOpenGLNativeWidget creates an internal QOpenGLFramebufferObject, independent of the
|
|
* one created by superclass, for vtkRenderWindow to do the rendering in. This
|
|
* explicit double-buffering is useful in avoiding temporary back-buffer only
|
|
* renders done in VTK (e.g. when making selections) from destroying the results
|
|
* composed on screen.
|
|
*
|
|
* @section RenderAndPaint Handling Render and Paint.
|
|
*
|
|
* QWidget subclasses (including `QOpenGLWidget` and `QVTKOpenGLNativeWidget`) display
|
|
* their contents on the screen in `QWidget::paint` in response to a paint event.
|
|
* `QOpenGLWidget` subclasses are expected to do OpenGL rendering in
|
|
* `QOpenGLWidget::paintGL`. QWidget can receive paint events for various
|
|
* reasons including widget getting focus/losing focus, some other widget on
|
|
* the UI e.g. QProgressBar in status bar updating, etc.
|
|
*
|
|
* In VTK applications, any time the vtkRenderWindow needs to be updated to
|
|
* render a new result, one call `vtkRenderWindow::Render` on it.
|
|
* vtkRenderWindowInteractor set on the render window ensures that as
|
|
* interactions happen that affect the rendered result, it calls `Render` on the
|
|
* render window.
|
|
*
|
|
* Since paint in Qt can be called more often then needed, we avoid potentially
|
|
* expensive `vtkRenderWindow::Render` calls each time that happens. Instead,
|
|
* QVTKOpenGLNativeWidget relies on the VTK application calling
|
|
* `vtkRenderWindow::Render` on the render window when it needs to update the
|
|
* rendering. `paintGL` simply passes on the result rendered by the most render
|
|
* vtkRenderWindow::Render to Qt windowing system for composing on-screen.
|
|
*
|
|
* There may still be occasions when we may have to render in `paint` for
|
|
* example if the window was resized or Qt had to recreate the OpenGL context.
|
|
* In those cases, `QVTKOpenGLNativeWidget::paintGL` can request a render by calling
|
|
* `QVTKOpenGLNativeWidget::renderVTK`.
|
|
*
|
|
* @section Caveats
|
|
* QVTKOpenGLNativeWidget does not support stereo,
|
|
* please use QVTKOpenGLStereoWidget if you need support for stereo rendering
|
|
*
|
|
* QVTKOpenGLNativeWidget is targeted for Qt version 5.5 and above.
|
|
*
|
|
* @sa QVTKOpenGLStereoWidget QVTKRenderWidget
|
|
*
|
|
*/
|
|
#ifndef QVTKOpenGLNativeWidget_h
|
|
#define QVTKOpenGLNativeWidget_h
|
|
|
|
#include <QOpenGLWidget>
|
|
#include <QScopedPointer> // for QScopedPointer.
|
|
|
|
#include "QVTKInteractor.h" // needed for QVTKInteractor
|
|
#include "vtkGUISupportQtModule.h" // for export macro
|
|
#include "vtkNew.h" // needed for vtkNew
|
|
#include "vtkSmartPointer.h" // needed for vtkSmartPointer
|
|
|
|
class QVTKInteractor;
|
|
class QVTKInteractorAdapter;
|
|
class QVTKRenderWindowAdapter;
|
|
class vtkGenericOpenGLRenderWindow;
|
|
|
|
class VTKGUISUPPORTQT_EXPORT QVTKOpenGLNativeWidget : public QOpenGLWidget
|
|
{
|
|
Q_OBJECT
|
|
typedef QOpenGLWidget Superclass;
|
|
|
|
public:
|
|
QVTKOpenGLNativeWidget(QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
|
|
QVTKOpenGLNativeWidget(vtkGenericOpenGLRenderWindow* window, QWidget* parent = nullptr,
|
|
Qt::WindowFlags f = Qt::WindowFlags());
|
|
~QVTKOpenGLNativeWidget() override;
|
|
|
|
//@{
|
|
/**
|
|
* Set a render window to use. It a render window was already set, it will be
|
|
* finalized and all of its OpenGL resource released. If the \c win is
|
|
* non-null and it has no interactor set, then a QVTKInteractor instance will
|
|
* be created as set on the render window as the interactor.
|
|
*/
|
|
void setRenderWindow(vtkGenericOpenGLRenderWindow* win);
|
|
void setRenderWindow(vtkRenderWindow* win);
|
|
//@}
|
|
|
|
/**
|
|
* Returns the render window that is being shown in this widget.
|
|
*/
|
|
vtkRenderWindow* renderWindow() const;
|
|
|
|
/**
|
|
* Get the QVTKInteractor that was either created by default or set by the user.
|
|
*/
|
|
QVTKInteractor* interactor() const;
|
|
|
|
/**
|
|
* @copydoc QVTKRenderWindowAdapter::defaultFormat(bool)
|
|
*/
|
|
static QSurfaceFormat defaultFormat(bool stereo_capable = false);
|
|
|
|
//@{
|
|
/**
|
|
* Enable or disable support for HiDPI displays. When enabled, this enabled
|
|
* DPI scaling i.e. `vtkWindow::SetDPI` will be called with a DPI value scaled
|
|
* by the device pixel ratio every time the widget is resized. The unscaled
|
|
* DPI value can be specified by using `setUnscaledDPI`.
|
|
*/
|
|
void setEnableHiDPI(bool enable);
|
|
bool enableHiDPI() const { return this->EnableHiDPI; }
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* Set/Get unscaled DPI value. Defaults to 72, which is also the default value
|
|
* in vtkWindow.
|
|
*/
|
|
void setUnscaledDPI(int);
|
|
int unscaledDPI() const { return this->UnscaledDPI; }
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* Set/get the default cursor to use for this widget.
|
|
*/
|
|
void setDefaultCursor(const QCursor& cursor);
|
|
const QCursor& defaultCursor() const { return this->DefaultCursor; }
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* @deprecated in VTK 9.0
|
|
*/
|
|
VTK_LEGACY(void SetRenderWindow(vtkGenericOpenGLRenderWindow* win));
|
|
VTK_LEGACY(void SetRenderWindow(vtkRenderWindow* win));
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* These methods have be deprecated to fix naming style. Since
|
|
* QVTKOpenGLNativeWidget is QObject subclass, we follow Qt naming conventions
|
|
* rather than VTK's.
|
|
*/
|
|
VTK_LEGACY(vtkRenderWindow* GetRenderWindow());
|
|
VTK_LEGACY(QVTKInteractor* GetInteractor());
|
|
//@}
|
|
|
|
/**
|
|
* @deprecated in VTK 9.0
|
|
* QVTKInteractorAdapter is an internal helper. Hence the API was removed.
|
|
*/
|
|
VTK_LEGACY(QVTKInteractorAdapter* GetInteractorAdapter());
|
|
|
|
/**
|
|
* @deprecated in VTK 9.0. Simply use `QWidget::setCursor` API to change
|
|
* cursor.
|
|
*/
|
|
VTK_LEGACY(void setQVTKCursor(const QCursor& cursor));
|
|
|
|
/**
|
|
* @deprecated in VTK 9.0. Use `setDefaultCursor` instead.
|
|
*/
|
|
VTK_LEGACY(void setDefaultQVTKCursor(const QCursor& cursor));
|
|
|
|
protected slots:
|
|
/**
|
|
* Called as a response to `QOpenGLContext::aboutToBeDestroyed`. This may be
|
|
* called anytime during the widget lifecycle. We need to release any OpenGL
|
|
* resources allocated in VTK work in this method.
|
|
*/
|
|
virtual void cleanupContext();
|
|
|
|
void updateSize();
|
|
|
|
protected:
|
|
bool event(QEvent* evt) override;
|
|
void initializeGL() override;
|
|
void paintGL() override;
|
|
|
|
protected:
|
|
vtkSmartPointer<vtkGenericOpenGLRenderWindow> RenderWindow;
|
|
QScopedPointer<QVTKRenderWindowAdapter> RenderWindowAdapter;
|
|
|
|
private:
|
|
Q_DISABLE_COPY(QVTKOpenGLNativeWidget);
|
|
|
|
bool EnableHiDPI;
|
|
int UnscaledDPI;
|
|
QCursor DefaultCursor;
|
|
};
|
|
|
|
#endif
|