From fba185e6c2fa5158aa60ba4468c1f1a70177f77a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kera=CC=88nen=20Pasi?= Date: Mon, 16 Dec 2013 16:17:07 +0200 Subject: Antialiasing and direct rendering with QML. Task-id: QTRD-2565 Change-Id: I4099c869f157361ee6a900dfc1c29301b373ac30 Reviewed-by: Miikka Heikkinen --- examples/qmlbars/main.cpp | 13 ++ examples/qmlcustominput/main.cpp | 13 ++ examples/qmlscatter/main.cpp | 13 ++ examples/qmlsurface/main.cpp | 12 ++ .../engine/abstract3dcontroller.cpp | 109 +------------- .../engine/abstract3dcontroller_p.h | 23 +-- .../engine/abstract3drenderer.cpp | 41 +++--- .../engine/abstract3drenderer_p.h | 72 +++++---- src/datavisualization/engine/bars3drenderer.cpp | 108 ++++---------- src/datavisualization/engine/bars3drenderer_p.h | 4 - src/datavisualization/engine/q3dbars.cpp | 26 ---- src/datavisualization/engine/q3dbars.h | 4 - src/datavisualization/engine/q3dscatter.cpp | 27 ---- src/datavisualization/engine/q3dscatter.h | 4 - src/datavisualization/engine/q3dscene.cpp | 161 ++++++++++++++++++--- src/datavisualization/engine/q3dscene.h | 25 +++- src/datavisualization/engine/q3dscene_p.h | 8 +- src/datavisualization/engine/q3dsurface.cpp | 10 -- src/datavisualization/engine/q3dsurface.h | 1 - src/datavisualization/engine/q3dwindow.cpp | 12 ++ src/datavisualization/engine/q3dwindow.h | 1 + src/datavisualization/engine/scatter3drenderer.cpp | 53 +++---- src/datavisualization/engine/scatter3drenderer_p.h | 2 - src/datavisualization/engine/surface3drenderer.cpp | 95 ++++-------- src/datavisualization/engine/surface3drenderer_p.h | 4 - src/datavisualizationqml2/abstractdeclarative.cpp | 110 ++++++++++---- src/datavisualizationqml2/abstractdeclarative_p.h | 13 +- .../datavisualizationqml2.pro | 2 - src/datavisualizationqml2/declarativebars.cpp | 2 - src/datavisualizationqml2/declarativerenderer.cpp | 97 ------------- src/datavisualizationqml2/declarativerenderer_p.h | 67 --------- src/datavisualizationqml2/declarativescatter.cpp | 2 - src/datavisualizationqml2/declarativesurface.cpp | 2 - tests/qmlcamera/main.cpp | 13 ++ tests/qmlcamera/qml/qmlcamera/main.qml | 2 +- 35 files changed, 487 insertions(+), 664 deletions(-) delete mode 100644 src/datavisualizationqml2/declarativerenderer.cpp delete mode 100644 src/datavisualizationqml2/declarativerenderer_p.h diff --git a/examples/qmlbars/main.cpp b/examples/qmlbars/main.cpp index 58cd5e32..49bacdc8 100644 --- a/examples/qmlbars/main.cpp +++ b/examples/qmlbars/main.cpp @@ -29,6 +29,19 @@ int main(int argc, char *argv[]) QGuiApplication app(argc, argv); QtQuick2ApplicationViewer viewer; + + // Enable antialiasing + QSurfaceFormat surfaceFormat; + surfaceFormat.setDepthBufferSize(24); +#if !defined(QT_OPENGL_ES_2) + surfaceFormat.setSamples(8); + surfaceFormat.setRenderableType(QSurfaceFormat::OpenGL); +#else + surfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES); +#endif + surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer); + viewer.setFormat(surfaceFormat); + #ifdef Q_OS_ANDROID viewer.addImportPath(QString::fromLatin1("assets:/qml")); viewer.engine()->addPluginPath(QString::fromLatin1("%1/../%2").arg(QDir::homePath(), diff --git a/examples/qmlcustominput/main.cpp b/examples/qmlcustominput/main.cpp index 232d7587..91ba6588 100644 --- a/examples/qmlcustominput/main.cpp +++ b/examples/qmlcustominput/main.cpp @@ -29,6 +29,19 @@ int main(int argc, char *argv[]) QGuiApplication app(argc, argv); QtQuick2ApplicationViewer viewer; + + // Enable antialiasing + QSurfaceFormat surfaceFormat; + surfaceFormat.setDepthBufferSize(24); +#if !defined(QT_OPENGL_ES_2) + surfaceFormat.setSamples(8); + surfaceFormat.setRenderableType(QSurfaceFormat::OpenGL); +#else + surfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES); +#endif + surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer); + viewer.setFormat(surfaceFormat); + #ifdef Q_OS_ANDROID viewer.addImportPath(QString::fromLatin1("assets:/qml")); viewer.engine()->addPluginPath(QString::fromLatin1("%1/../%2").arg(QDir::homePath(), diff --git a/examples/qmlscatter/main.cpp b/examples/qmlscatter/main.cpp index cc3fa4c3..43c0a9fb 100644 --- a/examples/qmlscatter/main.cpp +++ b/examples/qmlscatter/main.cpp @@ -29,6 +29,19 @@ int main(int argc, char *argv[]) QGuiApplication app(argc, argv); QtQuick2ApplicationViewer viewer; + + // Enable antialiasing + QSurfaceFormat surfaceFormat; + surfaceFormat.setDepthBufferSize(24); +#if !defined(QT_OPENGL_ES_2) + surfaceFormat.setSamples(8); + surfaceFormat.setRenderableType(QSurfaceFormat::OpenGL); +#else + surfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES); +#endif + surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer); + viewer.setFormat(surfaceFormat); + #ifdef Q_OS_ANDROID viewer.addImportPath(QString::fromLatin1("assets:/qml")); viewer.engine()->addPluginPath(QString::fromLatin1("%1/../%2").arg(QDir::homePath(), diff --git a/examples/qmlsurface/main.cpp b/examples/qmlsurface/main.cpp index ac9dda35..428e4026 100644 --- a/examples/qmlsurface/main.cpp +++ b/examples/qmlsurface/main.cpp @@ -30,6 +30,18 @@ int main(int argc, char *argv[]) QtQuick2ApplicationViewer viewer; + // Enable antialiasing + QSurfaceFormat surfaceFormat; + surfaceFormat.setDepthBufferSize(24); +#if !defined(QT_OPENGL_ES_2) + surfaceFormat.setSamples(8); + surfaceFormat.setRenderableType(QSurfaceFormat::OpenGL); +#else + surfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES); +#endif + surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer); + viewer.setFormat(surfaceFormat); + #ifdef Q_OS_ANDROID viewer.addImportPath(QString::fromLatin1("assets:/qml")); viewer.engine()->addPluginPath(QString::fromLatin1("%1/../%2").arg(QDir::homePath(), diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp index f2483216..7392b714 100644 --- a/src/datavisualization/engine/abstract3dcontroller.cpp +++ b/src/datavisualization/engine/abstract3dcontroller.cpp @@ -34,9 +34,8 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE -Abstract3DController::Abstract3DController(QRect boundRect, QObject *parent) : +Abstract3DController::Abstract3DController(QRect initialViewport, QObject *parent) : QObject(parent), - m_boundingRect(boundRect.x(), boundRect.y(), boundRect.width(), boundRect.height()), m_themeManager(new ThemeManager(this)), m_selectionMode(QDataVis::SelectionItem), m_shadowQuality(QDataVis::ShadowQualityMedium), @@ -54,6 +53,8 @@ Abstract3DController::Abstract3DController(QRect boundRect, QObject *parent) : // Set initial theme setTheme(new Q3DTheme(Q3DTheme::ThemeQt)); + m_scene->setViewport(initialViewport); + // Populate the scene m_scene->activeLight()->setPosition(defaultLightPos); @@ -133,17 +134,6 @@ void Abstract3DController::synchDataToRenderer() if (!m_renderer) return; - if (m_changeTracker.boundingRectChanged || m_changeTracker.sizeChanged) { - m_renderer->updateBoundingRect(m_boundingRect); - m_changeTracker.boundingRectChanged = false; - m_changeTracker.sizeChanged = false; - } - - if (m_changeTracker.positionChanged) { - m_renderer->updatePosition(m_boundingRect); - m_changeTracker.positionChanged = false; - } - m_renderer->updateScene(m_scene); m_renderer->updateTheme(m_themeManager->theme()); @@ -367,99 +357,10 @@ void Abstract3DController::wheelEvent(QWheelEvent *event) m_activeInputHandler->wheelEvent(event); } -void Abstract3DController::setSize(const int width, const int height) -{ - float devicePixelRatio = m_scene->devicePixelRatio(); - m_scene->setViewportSize(width, height); - m_boundingRect.setWidth(width * devicePixelRatio); - m_boundingRect.setHeight(height * devicePixelRatio); - - m_changeTracker.boundingRectChanged = true; - emitNeedRender(); -} - -void Abstract3DController::setBoundingRect(const QRect boundingRect) -{ - float devicePixelRatio = m_scene->devicePixelRatio(); - m_boundingRect = QRect(boundingRect.x() * devicePixelRatio, - boundingRect.y() * devicePixelRatio, - boundingRect.width() * devicePixelRatio, - boundingRect.height() * devicePixelRatio); - m_scene->setViewport(boundingRect); - - m_changeTracker.boundingRectChanged = true; - emitNeedRender(); -} - -void Abstract3DController::setWidth(const int width) -{ - m_boundingRect.setWidth(width * m_scene->devicePixelRatio()); - m_scene->setViewportSize(width, m_scene->viewport().height()); - - m_changeTracker.sizeChanged = true; - emitNeedRender(); -} - -void Abstract3DController::setHeight(const int height) -{ - m_boundingRect.setHeight(height * m_scene->devicePixelRatio()); - m_scene->setViewportSize(m_scene->viewport().width(), height); - - m_changeTracker.sizeChanged = true; - emitNeedRender(); -} - -void Abstract3DController::setX(const int x) -{ - m_boundingRect.setX(x * m_scene->devicePixelRatio()); - m_scene->setViewport( QRect(x, - m_scene->viewport().y(), - m_scene->viewport().width(), - m_scene->viewport().height())); - - m_changeTracker.positionChanged = true; - emitNeedRender(); -} - -void Abstract3DController::setY(const int y) -{ - m_boundingRect.setY(y * m_scene->devicePixelRatio()); - m_scene->setViewport( QRect(m_scene->viewport().x(), - y, - m_scene->viewport().width(), - m_scene->viewport().height())); - - m_changeTracker.positionChanged = true; - emitNeedRender(); -} - -QRect Abstract3DController::primarySubViewport() const -{ - return m_scene->primarySubViewport(); -} - -void Abstract3DController::setPrimarySubViewport(const QRect &primarySubViewport) -{ - m_scene->setPrimarySubViewport(primarySubViewport); -} - -QRect Abstract3DController::secondarySubViewport() const -{ - return m_scene->secondarySubViewport(); -} - -void Abstract3DController::setSecondarySubViewport(const QRect &secondarySubViewport) -{ - m_scene->setSecondarySubViewport(secondarySubViewport); -} - void Abstract3DController::handlePixelRatioChanged(float ratio) { - m_boundingRect.setX(ratio * m_scene->viewport().x()); - m_boundingRect.setY(ratio * m_scene->viewport().y()); - m_boundingRect.setWidth(ratio * m_scene->viewport().width()); - m_boundingRect.setHeight(ratio * m_scene->viewport().height()); - m_changeTracker.boundingRectChanged = true; + Q_UNUSED(ratio); + emitNeedRender(); } diff --git a/src/datavisualization/engine/abstract3dcontroller_p.h b/src/datavisualization/engine/abstract3dcontroller_p.h index b8ad5daa..90a59b38 100644 --- a/src/datavisualization/engine/abstract3dcontroller_p.h +++ b/src/datavisualization/engine/abstract3dcontroller_p.h @@ -50,11 +50,8 @@ class QAbstract3DSeries; class ThemeManager; struct Abstract3DChangeBitField { - bool positionChanged : 1; bool zoomLevelChanged : 1; bool themeChanged : 1; - bool boundingRectChanged : 1; - bool sizeChanged : 1; bool shadowQualityChanged : 1; bool selectionModeChanged : 1; bool objFileChanged : 1; @@ -83,11 +80,8 @@ struct Abstract3DChangeBitField { bool inputPositionChanged : 1; Abstract3DChangeBitField() : - positionChanged(true), zoomLevelChanged(true), themeChanged(true), - boundingRectChanged(true), - sizeChanged(true), shadowQualityChanged(true), selectionModeChanged(true), objFileChanged(true), @@ -139,7 +133,6 @@ public: private: Abstract3DChangeBitField m_changeTracker; - QRect m_boundingRect; GLfloat m_horizontalRotation; GLfloat m_verticalRotation; ThemeManager *m_themeManager; @@ -165,7 +158,7 @@ protected: QList m_seriesList; - explicit Abstract3DController(QRect boundRect, QObject *parent = 0); + explicit Abstract3DController(QRect initialViewport, QObject *parent = 0); virtual ~Abstract3DController(); public: @@ -180,20 +173,6 @@ public: virtual void removeSeries(QAbstract3DSeries *series); QList seriesList(); - // Size - virtual void setSize(const int width, const int height); - virtual void setBoundingRect(const QRect boundingRect); - virtual void setWidth(const int width); - virtual void setHeight(const int height); - virtual void setX(const int x); - virtual void setY(const int y); - - virtual QRect primarySubViewport() const; - virtual void setPrimarySubViewport(const QRect &primarySubViewport); - - virtual QRect secondarySubViewport() const; - virtual void setSecondarySubViewport(const QRect &secondarySubViewport); - virtual void setAxisX(Q3DAbstractAxis *axis); virtual Q3DAbstractAxis *axisX(); virtual void setAxisY(Q3DAbstractAxis *axis); diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp index f250fe40..89a7944d 100644 --- a/src/datavisualization/engine/abstract3drenderer.cpp +++ b/src/datavisualization/engine/abstract3drenderer.cpp @@ -36,7 +36,6 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller) m_hasNegativeValues(false), m_cachedTheme(new Q3DTheme()), m_drawer(new Drawer(m_cachedTheme)), - m_cachedBoundingRect(QRect(0, 0, 0, 0)), m_cachedShadowQuality(QDataVis::ShadowQualityMedium), m_autoScaleAdjustment(1.0f), m_cachedSelectionMode(QDataVis::SelectionNone), @@ -117,11 +116,11 @@ void Abstract3DRenderer::render(const GLuint defaultFboHandle) glDisable(GL_BLEND); // For QtQuick2 blending is enabled by default, but we don't want it to be } - glViewport(m_cachedScene->viewport().x(), - m_cachedScene->viewport().y(), - m_cachedScene->viewport().width(), - m_cachedScene->viewport().height()); - + // Clear the graph background to the theme color + glViewport(m_viewport.x(), + m_viewport.y(), + m_viewport.width(), + m_viewport.height()); QVector3D clearColor = Utils::vectorFromColor(m_cachedTheme->windowColor()); glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -152,17 +151,6 @@ void Abstract3DRenderer::initGradientShaders(const QString &vertexShader, const Q_UNUSED(fragmentShader) } -void Abstract3DRenderer::updateBoundingRect(const QRect &boundingRect) -{ - m_cachedBoundingRect = boundingRect; - handleResize(); -} - -void Abstract3DRenderer::updatePosition(const QRect &boundingRect) -{ - m_cachedBoundingRect = boundingRect; -} - void Abstract3DRenderer::updateTheme(Q3DTheme *theme) { // Synchronize the controller theme with renderer @@ -183,6 +171,16 @@ void Abstract3DRenderer::updateScene(Q3DScene *scene) updateInputPosition(QPoint(logicalPixelPosition.x() * devicePixelRatio, logicalPixelPosition.y() * devicePixelRatio)); + m_viewport = m_cachedScene->glViewport(); + m_secondarySubViewport = m_cachedScene->glSecondarySubViewport(); + + if (m_primarySubViewport != m_cachedScene->glPrimarySubViewport()) { + // Resize of primary subviewport means resizing shadow and selection buffers + m_primarySubViewport = m_cachedScene->glPrimarySubViewport(); + handleResize(); + } + + if (Q3DScene::invalidSelectionPoint() == logicalPixelPosition) { updateSelectionState(SelectNone); } else { @@ -254,14 +252,15 @@ void Abstract3DRenderer::updateSelectionMode(QDataVis::SelectionFlags mode) void Abstract3DRenderer::handleResize() { - if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0) + if (m_primarySubViewport.width() == 0 || m_primarySubViewport.height() == 0) return; + // Calculate zoom level based on aspect ratio GLfloat div; GLfloat zoomAdjustment; - div = qMin(m_cachedBoundingRect.width(), m_cachedBoundingRect.height()); - zoomAdjustment = defaultRatio * ((m_cachedBoundingRect.width() / div) - / (m_cachedBoundingRect.height() / div)); + div = qMin(m_primarySubViewport.width(), m_primarySubViewport.height()); + zoomAdjustment = defaultRatio * ((m_primarySubViewport.width() / div) + / (m_primarySubViewport.height() / div)); m_autoScaleAdjustment = qMin(zoomAdjustment, 1.0f); // clamp to 1.0f // Re-init selection buffer diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h index 97951260..f9e97299 100644 --- a/src/datavisualization/engine/abstract3drenderer_p.h +++ b/src/datavisualization/engine/abstract3drenderer_p.h @@ -59,33 +59,6 @@ protected: SelectOnSlice }; - bool m_hasNegativeValues; - Q3DTheme *m_cachedTheme; - Drawer *m_drawer; - QRect m_cachedBoundingRect; - QDataVis::ShadowQuality m_cachedShadowQuality; - GLfloat m_autoScaleAdjustment; - - QDataVis::SelectionFlags m_cachedSelectionMode; - - AxisRenderCache m_axisCacheX; - AxisRenderCache m_axisCacheY; - AxisRenderCache m_axisCacheZ; - TextureHelper *m_textureHelper; - Q3DBox m_boundingBox; - - Q3DScene *m_cachedScene; - bool m_selectionDirty; - SelectionState m_selectionState; - QPoint m_inputPosition; - QVector m_visibleSeriesList; - -#ifdef DISPLAY_RENDER_SPEED - bool m_isFirstFrame; - QTime m_lastFrameTime; - GLint m_numFrames; -#endif - QString generateValueLabel(const QString &format, float value); public: @@ -96,9 +69,6 @@ public: virtual void render(GLuint defaultFboHandle); - virtual void updateBoundingRect(const QRect &boundingRect); - virtual void updatePosition(const QRect &boundingRect); - virtual void updateTheme(Q3DTheme *theme); virtual void updateSelectionMode(QDataVis::SelectionFlags newMode); virtual void updateScene(Q3DScene *scene); @@ -141,6 +111,48 @@ protected: AxisRenderCache &axisCacheForOrientation(Q3DAbstractAxis::AxisOrientation orientation); virtual void lowerShadowQuality(); + + void fixGradient(QLinearGradient *gradient, GLuint *gradientTexture); + + bool m_hasNegativeValues; + Q3DTheme *m_cachedTheme; + Drawer *m_drawer; + QRect m_viewport; + QDataVis::ShadowQuality m_cachedShadowQuality; + GLfloat m_autoScaleAdjustment; + + QDataVis::SelectionFlags m_cachedSelectionMode; + + Q3DTheme::ColorStyle m_cachedColorStyle; + QColor m_cachedObjectColor; + QLinearGradient m_cachedObjectGradient; + GLuint m_objectGradientTexture; + QColor m_cachedSingleHighlightColor; + QLinearGradient m_cachedSingleHighlightGradient; + GLuint m_singleHighlightGradientTexture; + QColor m_cachedMultiHighlightColor; + QLinearGradient m_cachedMultiHighlightGradient; + GLuint m_multiHighlightGradientTexture; + + AxisRenderCache m_axisCacheX; + AxisRenderCache m_axisCacheY; + AxisRenderCache m_axisCacheZ; + TextureHelper *m_textureHelper; + Q3DBox m_boundingBox; + + Q3DScene *m_cachedScene; + bool m_selectionDirty; + SelectionState m_selectionState; + QPoint m_inputPosition; + QVector m_visibleSeriesList; + QRect m_primarySubViewport; + QRect m_secondarySubViewport; + +#ifdef DISPLAY_RENDER_SPEED + bool m_isFirstFrame; + QTime m_lastFrameTime; + GLint m_numFrames; +#endif }; QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp index fec4a7d6..f8afd0dc 100644 --- a/src/datavisualization/engine/bars3drenderer.cpp +++ b/src/datavisualization/engine/bars3drenderer.cpp @@ -42,7 +42,6 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE const GLfloat labelMargin = 0.05f; const GLfloat gridLineWidth = 0.005f; -const int smallerVPSize = 5; const bool sliceGridLabels = true; // TODO: Make this user controllable (QTRD-2546) @@ -139,10 +138,6 @@ void Bars3DRenderer::initializeOpenGL() // Load label mesh loadLabelMesh(); - // Set view port - glViewport(m_sliceViewPort.x(), m_sliceViewPort.y(), - m_sliceViewPort.width(), m_sliceViewPort.height()); - // Load background mesh (we need to be initialized first) loadBackgroundMesh(); } @@ -244,19 +239,6 @@ void Bars3DRenderer::updateData() void Bars3DRenderer::updateScene(Q3DScene *scene) { - // TODO: Move these to more suitable place e.g. controller should be controlling the viewports. - float devicePixelRatio = scene->devicePixelRatio(); - QRect logicalPrimarySubViewport = QRect(m_mainViewPort.x() / devicePixelRatio, - m_mainViewPort.y() / devicePixelRatio, - m_mainViewPort.width() / devicePixelRatio, - m_mainViewPort.height() / devicePixelRatio); - QRect logicalSecondarySubViewport = QRect(m_sliceViewPort.x() / devicePixelRatio, - m_sliceViewPort.y() / devicePixelRatio, - m_sliceViewPort.width() / devicePixelRatio, - m_sliceViewPort.height() / devicePixelRatio); - scene->setPrimarySubViewport(logicalPrimarySubViewport); - scene->setSecondarySubViewport(logicalSecondarySubViewport); - // TODO: See QTRD-2374 if (m_hasNegativeValues) scene->activeCamera()->setMinYRotation(-90.0); @@ -296,13 +278,15 @@ void Bars3DRenderer::drawSlicedScene() QVector3D lightPos; // Specify viewport - glViewport(m_sliceViewPort.x(), m_sliceViewPort.y(), - m_sliceViewPort.width(), m_sliceViewPort.height()); + glViewport(m_secondarySubViewport.x(), + m_secondarySubViewport.y(), + m_secondarySubViewport.width(), + m_secondarySubViewport.height()); // Set up projection matrix QMatrix4x4 projectionMatrix; - projectionMatrix.perspective(40.0f, (GLfloat)m_sliceViewPort.width() - / (GLfloat)m_sliceViewPort.height(), 0.1f, 100.0f); + projectionMatrix.perspective(40.0f, (GLfloat)m_secondarySubViewport.width() + / (GLfloat)m_secondarySubViewport.height(), 0.1f, 100.0f); // Set view matrix QMatrix4x4 viewMatrix; @@ -712,13 +696,14 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) const Q3DCamera *activeCamera = m_cachedScene->activeCamera(); - // Specify viewport - glViewport(m_mainViewPort.x(), m_mainViewPort.y(), - m_mainViewPort.width(), m_mainViewPort.height()); + glViewport(m_primarySubViewport.x(), + m_primarySubViewport.y(), + m_primarySubViewport.width(), + m_primarySubViewport.height()); // Set up projection matrix QMatrix4x4 projectionMatrix; - GLfloat viewPortRatio = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height(); + GLfloat viewPortRatio = (GLfloat)m_primarySubViewport.width() / (GLfloat)m_primarySubViewport.height(); projectionMatrix.perspective(45.0f, viewPortRatio, 0.1f, 100.0f); // Get the view matrix @@ -792,8 +777,8 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) // Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows. // Depth viewport must always start from 0, 0, as it is rendered into a texture, not screen glViewport(0, 0, - m_mainViewPort.width() * m_shadowQualityMultiplier, - m_mainViewPort.height() * m_shadowQualityMultiplier); + m_primarySubViewport.width() * m_shadowQualityMultiplier, + m_primarySubViewport.height() * m_shadowQualityMultiplier); // Get the depth view matrix // It may be possible to hack lightPos here if we want to make some tweaks to shadow @@ -894,8 +879,10 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) glCullFace(GL_BACK); // Revert to original viewport - glViewport(m_mainViewPort.x(), m_mainViewPort.y(), - m_mainViewPort.width(), m_mainViewPort.height()); + glViewport(m_primarySubViewport.x(), + m_primarySubViewport.y(), + m_primarySubViewport.width(), + m_primarySubViewport.height()); } #endif @@ -908,6 +895,10 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) // Draw bars to selection buffer glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer); + glViewport(0, 0, + m_primarySubViewport.width(), + m_primarySubViewport.height()); + glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Set clear color to white (= selectionSkipColor) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer @@ -980,24 +971,15 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) // Read color under cursor QVector3D clickedColor = Utils::getSelection(m_inputPosition, - m_cachedBoundingRect.height()); + m_viewport.height()); emit barClicked(selectionColorToArrayPosition(clickedColor), selectionColorToSeries(clickedColor)); + // Revert to original render target and viewport glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); - -#if 0 // Use this if you want to see what is being drawn to the framebuffer - glCullFace(GL_BACK); - m_labelShader->bind(); - glDisable(GL_DEPTH_TEST); - glEnable(GL_TEXTURE_2D); - QMatrix4x4 modelMatrix; - QMatrix4x4 viewmatrix; - viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.0f), zeroVector, upVector); - QMatrix4x4 MVPMatrix = projectionViewMatrix * modelMatrix; - m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix); - m_drawer->drawObject(m_labelShader, m_labelObj, m_selectionTexture); - glDisable(GL_TEXTURE_2D); -#endif + glViewport(m_primarySubViewport.x(), + m_primarySubViewport.y(), + m_primarySubViewport.width(), + m_primarySubViewport.height()); } // Enable texturing @@ -1845,16 +1827,6 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) m_selectionDirty = false; } -void Bars3DRenderer::handleResize() -{ - if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0) - return; - - setViewPorts(); - - Abstract3DRenderer::handleResize(); -} - void Bars3DRenderer::updateBarSpecs(GLfloat thicknessRatio, const QSizeF &spacing, bool relative) { // Convert ratio to QSizeF, as we need it in that format for autoscaling calculations @@ -2110,8 +2082,6 @@ void Bars3DRenderer::updateSlicingActive(bool isSlicing) m_cachedIsSlicingActivated = isSlicing; - setViewPorts(); - if (!m_cachedIsSlicingActivated) initSelectionBuffer(); // We need to re-init selection buffer in case there has been a resize @@ -2122,22 +2092,6 @@ void Bars3DRenderer::updateSlicingActive(bool isSlicing) m_selectionDirty = true; } -void Bars3DRenderer::setViewPorts() -{ - // Update view ports - if (m_cachedIsSlicingActivated) { - m_mainViewPort = QRect(0, - m_cachedBoundingRect.height() - - (m_cachedBoundingRect.height() / smallerVPSize), - m_cachedBoundingRect.width() / smallerVPSize, - m_cachedBoundingRect.height() / smallerVPSize); - m_sliceViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height()); - } else { - m_mainViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height()); - m_sliceViewPort = QRect(0, 0, 0, 0); - } -} - void Bars3DRenderer::initShaders(const QString &vertexShader, const QString &fragmentShader) { if (m_barShader) @@ -2170,10 +2124,10 @@ void Bars3DRenderer::initSelectionBuffer() m_selectionTexture = 0; } - if (m_cachedIsSlicingActivated || m_mainViewPort.size().isEmpty()) + if (m_cachedIsSlicingActivated || m_primarySubViewport.size().isEmpty()) return; - m_selectionTexture = m_textureHelper->createSelectionTexture(m_mainViewPort.size(), + m_selectionTexture = m_textureHelper->createSelectionTexture(m_primarySubViewport.size(), m_selectionFrameBuffer, m_selectionDepthBuffer); } @@ -2195,11 +2149,11 @@ void Bars3DRenderer::updateDepthBuffer() m_depthTexture = 0; } - if (m_mainViewPort.size().isEmpty()) + if (m_primarySubViewport.size().isEmpty()) return; if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { - m_depthTexture = m_textureHelper->createDepthTextureFrameBuffer(m_mainViewPort.size(), + m_depthTexture = m_textureHelper->createDepthTextureFrameBuffer(m_primarySubViewport.size(), m_depthFrameBuffer, m_shadowQualityMultiplier); if (!m_depthTexture) diff --git a/src/datavisualization/engine/bars3drenderer_p.h b/src/datavisualization/engine/bars3drenderer_p.h index f60c5014..16e7a476 100644 --- a/src/datavisualization/engine/bars3drenderer_p.h +++ b/src/datavisualization/engine/bars3drenderer_p.h @@ -66,8 +66,6 @@ private: bool m_xFlipped; bool m_zFlipped; bool m_yFlipped; - QRect m_mainViewPort; - QRect m_sliceViewPort; bool m_updateLabels; ShaderHelper *m_barShader; ShaderHelper *m_barGradientShader; @@ -141,9 +139,7 @@ private: void drawSlicedScene(); void drawScene(GLuint defaultFboHandle); - void handleResize(); - void setViewPorts(); void loadBackgroundMesh(); void loadGridLineMesh(); void loadLabelMesh(); diff --git a/src/datavisualization/engine/q3dbars.cpp b/src/datavisualization/engine/q3dbars.cpp index ef77c34f..d4e97519 100644 --- a/src/datavisualization/engine/q3dbars.cpp +++ b/src/datavisualization/engine/q3dbars.cpp @@ -200,14 +200,6 @@ void Q3DBars::wheelEvent(QWheelEvent *event) dptr()->m_shared->wheelEvent(event); } -/*! - * \internal - */ -void Q3DBars::resizeEvent(QResizeEvent *event) -{ - Q_UNUSED(event); - dptr()->m_shared->setSize(width(), height()); -} Q3DBarsPrivate *Q3DBars::dptr() { @@ -219,24 +211,6 @@ const Q3DBarsPrivate *Q3DBars::dptrc() const return static_cast(d_ptr.data()); } -/*! - * Sets window \a width. - */ -void Q3DBars::setWidth(const int width) -{ - dptr()->m_shared->setWidth(width); - QWindow::setWidth(width); -} - -/*! - * Sets window \a height. - */ -void Q3DBars::setHeight(const int height) -{ - dptr()->m_shared->setHeight(height); - QWindow::setHeight(height); -} - /*! * \property Q3DBars::barThickness * diff --git a/src/datavisualization/engine/q3dbars.h b/src/datavisualization/engine/q3dbars.h index 1ad321eb..add3b11b 100644 --- a/src/datavisualization/engine/q3dbars.h +++ b/src/datavisualization/engine/q3dbars.h @@ -70,9 +70,6 @@ public: Q3DScene *scene() const; - void setWidth(const int width); - void setHeight(const int height); - void setShadowQuality(QDataVis::ShadowQuality quality); QDataVis::ShadowQuality shadowQuality() const; @@ -102,7 +99,6 @@ protected: void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void wheelEvent(QWheelEvent *event); - void resizeEvent(QResizeEvent *event); private: Q3DBarsPrivate *dptr(); diff --git a/src/datavisualization/engine/q3dscatter.cpp b/src/datavisualization/engine/q3dscatter.cpp index b19a82a3..3c28b4a5 100644 --- a/src/datavisualization/engine/q3dscatter.cpp +++ b/src/datavisualization/engine/q3dscatter.cpp @@ -181,15 +181,6 @@ void Q3DScatter::wheelEvent(QWheelEvent *event) dptr()->m_shared->wheelEvent(event); } -/*! - * \internal - */ -void Q3DScatter::resizeEvent(QResizeEvent *event) -{ - Q_UNUSED(event); - dptr()->m_shared->setSize(width(), height()); -} - Q3DScatterPrivate *Q3DScatter::dptr() { return static_cast(d_ptr.data()); @@ -200,24 +191,6 @@ const Q3DScatterPrivate *Q3DScatter::dptrc() const return static_cast(d_ptr.data()); } -/*! - * Sets window \a width. - */ -void Q3DScatter::setWidth(const int width) -{ - dptr()->m_shared->setWidth(width); - QWindow::setWidth(width); -} - -/*! - * Sets window \a height. - */ -void Q3DScatter::setHeight(const int height) -{ - dptr()->m_shared->setHeight(height); - QWindow::setHeight(height); -} - /*! * \property Q3DScatter::theme * diff --git a/src/datavisualization/engine/q3dscatter.h b/src/datavisualization/engine/q3dscatter.h index 205fd31b..e58146a1 100644 --- a/src/datavisualization/engine/q3dscatter.h +++ b/src/datavisualization/engine/q3dscatter.h @@ -59,9 +59,6 @@ public: Q3DScene *scene() const; - void setWidth(const int width); - void setHeight(const int height); - void setShadowQuality(QDataVis::ShadowQuality quality); QDataVis::ShadowQuality shadowQuality() const; @@ -87,7 +84,6 @@ protected: void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void wheelEvent(QWheelEvent *event); - void resizeEvent(QResizeEvent *event); private: Q3DScatterPrivate *dptr(); diff --git a/src/datavisualization/engine/q3dscene.cpp b/src/datavisualization/engine/q3dscene.cpp index c7c54bd3..b3a4cc55 100644 --- a/src/datavisualization/engine/q3dscene.cpp +++ b/src/datavisualization/engine/q3dscene.cpp @@ -26,6 +26,7 @@ #include "q3dlight_p.h" QT_DATAVISUALIZATION_BEGIN_NAMESPACE + /*! * \class Q3DScene * \inmodule QtDataVisualization @@ -37,7 +38,9 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE * * The 3D scene also keeps track of the viewport in which visualization rendering is done, * the primary subviewport inside the viewport where the main 3D data visualization view resides - * and the secondary subviewport where the 2D sliced view of the data resides. + * and the secondary subviewport where the 2D sliced view of the data resides. The subviewports are + * by default resized by the \a Q3DScene. To override the resize behavior you need to listen to both + * \l viewportChanged() and \l slicingActiveChanged() signals and recalculate the subviewports accordingly. * * Also the scene has flag for tracking if the secondary 2D slicing view is currently active or not. * \note Not all visualizations support the secondary 2D slicing view. @@ -149,7 +152,7 @@ Q3DScene::~Q3DScene() /*! * \property Q3DScene::viewport * - * This property contains the current viewport rectangle where all 3D rendering + * This read only property contains the current viewport rectangle where all 3D rendering * is targeted. */ QRect Q3DScene::viewport() const @@ -159,13 +162,10 @@ QRect Q3DScene::viewport() const void Q3DScene::setViewport(const QRect &viewport) { - if (d_ptr->m_viewport.width() != viewport.width() - || d_ptr->m_viewport.height() != viewport.height()) { + if (d_ptr->m_viewport != viewport) { d_ptr->m_viewport = viewport; - d_ptr->m_viewport.setX(0); - d_ptr->m_viewport.setY(0); - d_ptr->m_changeTracker.viewportChanged = true; - emit viewportChanged(viewport); + calculateSubViewports(); + emit needRender(); } } @@ -178,11 +178,66 @@ void Q3DScene::setViewportSize(int width, int height) || d_ptr->m_viewport.height() != height) { d_ptr->m_viewport.setWidth(width); d_ptr->m_viewport.setHeight(height); - d_ptr->m_changeTracker.viewportChanged = true; - emit viewportChanged(d_ptr->m_viewport); + calculateSubViewports(); + emit needRender(); } } +/*! + * \internal + */ +void Q3DScene::calculateSubViewports() +{ + // Calculates the default subviewport layout + const float smallerViewPortRatio = 0.2; + if (d_ptr->m_isSlicingActive) { + setPrimarySubViewport(QRect(0, + 0, + d_ptr->m_viewport.width() * smallerViewPortRatio, + d_ptr->m_viewport.height() * smallerViewPortRatio)); + setSecondarySubViewport(QRect(0, 0, d_ptr->m_viewport.width(), d_ptr->m_viewport.height())); + } else { + setPrimarySubViewport(QRect(0, 0, d_ptr->m_viewport.width(), d_ptr->m_viewport.height())); + setSecondarySubViewport(QRect(0, 0, 0, 0)); + } + + updateGLViewport(); +} + +/*! + * \internal + */ +void Q3DScene::updateGLViewport() +{ + // Update GL viewport + d_ptr->m_glViewport.setX(d_ptr->m_viewport.x() * d_ptr->m_devicePixelRatio); + d_ptr->m_glViewport.setY((d_ptr->m_windowSize.height() - (d_ptr->m_viewport.y() + d_ptr->m_viewport.height())) * d_ptr->m_devicePixelRatio); + d_ptr->m_glViewport.setWidth(d_ptr->m_viewport.width() * d_ptr->m_devicePixelRatio); + d_ptr->m_glViewport.setHeight(d_ptr->m_viewport.height() * d_ptr->m_devicePixelRatio); + + d_ptr->m_changeTracker.viewportChanged = true; + + // Do default subviewport changes first, then allow signal listeners to override. + updateGLSubViewports(); + emit viewportChanged(d_ptr->m_viewport); +} + +/*! + * \internal + */ +void Q3DScene::updateGLSubViewports() +{ + d_ptr->m_glPrimarySubViewport.setX((d_ptr->m_primarySubViewport.x() + d_ptr->m_viewport.x()) * d_ptr->m_devicePixelRatio); + d_ptr->m_glPrimarySubViewport.setY((d_ptr->m_windowSize.height() - (d_ptr->m_primarySubViewport.y() + d_ptr->m_viewport.y() + d_ptr->m_primarySubViewport.height())) * d_ptr->m_devicePixelRatio); + d_ptr->m_glPrimarySubViewport.setWidth(d_ptr->m_primarySubViewport.width() * d_ptr->m_devicePixelRatio); + d_ptr->m_glPrimarySubViewport.setHeight(d_ptr->m_primarySubViewport.height() * d_ptr->m_devicePixelRatio); + + d_ptr->m_glSecondarySubViewport.setX(d_ptr->m_secondarySubViewport.x() * d_ptr->m_devicePixelRatio); + d_ptr->m_glSecondarySubViewport.setY((d_ptr->m_windowSize.height() - (d_ptr->m_secondarySubViewport.y() + d_ptr->m_viewport.y() + d_ptr->m_secondarySubViewport.height())) * d_ptr->m_devicePixelRatio); + d_ptr->m_glSecondarySubViewport.setWidth(d_ptr->m_secondarySubViewport.width() * d_ptr->m_devicePixelRatio); + d_ptr->m_glSecondarySubViewport.setHeight(d_ptr->m_secondarySubViewport.height() * d_ptr->m_devicePixelRatio); +} + /*! * \property Q3DScene::primarySubViewport * @@ -197,9 +252,12 @@ QRect Q3DScene::primarySubViewport() const void Q3DScene::setPrimarySubViewport(const QRect &primarySubViewport) { if (d_ptr->m_primarySubViewport != primarySubViewport) { - d_ptr->m_primarySubViewport = primarySubViewport; + QRect clipRect = QRect(0, 0, d_ptr->m_viewport.width(), d_ptr->m_viewport.height()); + d_ptr->m_primarySubViewport = primarySubViewport.intersected(clipRect); + updateGLSubViewports(); d_ptr->m_changeTracker.primarySubViewportChanged = true; emit primarySubViewportChanged(primarySubViewport); + emit needRender(); } } @@ -215,9 +273,9 @@ bool Q3DScene::isPointInPrimarySubView(const QPoint &point) int x = point.x(); int y = point.y(); int areaMinX = d_ptr->m_primarySubViewport.x(); - int areaMaxX = d_ptr->m_primarySubViewport.x() + d_ptr->m_primarySubViewport.width(); - int areaMaxY = d_ptr->m_viewport.height() - d_ptr->m_primarySubViewport.y(); - int areaMinY = d_ptr->m_viewport.height() - (d_ptr->m_primarySubViewport.y() + d_ptr->m_primarySubViewport.height()); + int areaMaxX = d_ptr->m_viewport.x() + d_ptr->m_primarySubViewport.x() + d_ptr->m_primarySubViewport.width(); + int areaMaxY = d_ptr->m_viewport.y() + d_ptr->m_primarySubViewport.y() + d_ptr->m_primarySubViewport.height(); + int areaMinY = d_ptr->m_viewport.y() + d_ptr->m_primarySubViewport.y(); return ( x > areaMinX && x < areaMaxX && y > areaMinY && y < areaMaxY ); } @@ -234,9 +292,9 @@ bool Q3DScene::isPointInSecondarySubView(const QPoint &point) int x = point.x(); int y = point.y(); int areaMinX = d_ptr->m_secondarySubViewport.x(); - int areaMaxX = d_ptr->m_secondarySubViewport.x() + d_ptr->m_secondarySubViewport.width(); - int areaMaxY = d_ptr->m_viewport.height() - d_ptr->m_secondarySubViewport.y(); - int areaMinY = d_ptr->m_viewport.height() - (d_ptr->m_secondarySubViewport.y() + d_ptr->m_secondarySubViewport.height()); + int areaMaxX = d_ptr->m_viewport.x() + d_ptr->m_secondarySubViewport.x() + d_ptr->m_secondarySubViewport.width(); + int areaMaxY = d_ptr->m_viewport.y() + d_ptr->m_secondarySubViewport.y() + d_ptr->m_secondarySubViewport.height(); + int areaMinY = d_ptr->m_viewport.y() + d_ptr->m_secondarySubViewport.y(); return ( x > areaMinX && x < areaMaxX && y > areaMinY && y < areaMaxY ); } @@ -255,9 +313,12 @@ QRect Q3DScene::secondarySubViewport() const void Q3DScene::setSecondarySubViewport(const QRect &secondarySubViewport) { if (d_ptr->m_secondarySubViewport != secondarySubViewport) { - d_ptr->m_secondarySubViewport = secondarySubViewport; + QRect clipRect = QRect(0, 0, d_ptr->m_viewport.width(), d_ptr->m_viewport.height()); + d_ptr->m_secondarySubViewport = secondarySubViewport.intersected(clipRect); + updateGLSubViewports(); d_ptr->m_changeTracker.secondarySubViewportChanged = true; emit secondarySubViewportChanged(secondarySubViewport); + emit needRender(); } } @@ -309,6 +370,7 @@ void Q3DScene::setSlicingActive(bool isSlicing) if (d_ptr->m_isSlicingActive != isSlicing) { d_ptr->m_isSlicingActive = isSlicing; d_ptr->m_changeTracker.slicingActivatedChanged = true; + calculateSubViewports(); emit slicingActiveChanged(isSlicing); emit needRender(); } @@ -358,11 +420,11 @@ void Q3DScene::setActiveCamera(Q3DCamera *camera) if (camera != d_ptr->m_camera) { if (d_ptr->m_camera) { disconnect(d_ptr->m_camera, &Q3DCamera::xRotationChanged, this, - &Q3DScene::needRender); + &Q3DScene::needRender); disconnect(d_ptr->m_camera, &Q3DCamera::yRotationChanged, this, - &Q3DScene::needRender); + &Q3DScene::needRender); disconnect(d_ptr->m_camera, &Q3DCamera::zoomLevelChanged, this, - &Q3DScene::needRender); + &Q3DScene::needRender); } d_ptr->m_camera = camera; @@ -424,7 +486,9 @@ void Q3DScene::setDevicePixelRatio(float pixelRatio) { if (d_ptr->m_devicePixelRatio != pixelRatio) { d_ptr->m_devicePixelRatio = pixelRatio; + d_ptr->m_changeTracker.devicePixelRatioChanged = true; emit devicePixelRatioChanged(pixelRatio); + updateGLViewport(); } } @@ -445,6 +509,56 @@ void Q3DScene::setLightPositionRelativeToCamera(const QVector3D &relativePositio distanceModifier)); } +/*! + * \internal + * Sets the size of the window being rendered to. With widget based graphs, this + * is equal to the size of the QWindow and is same as the bounding rectangle. + * With declarative graphs this is equal to the size of the QQuickWindow and + * can be different from the bounding rectangle. + */ +void Q3DScene::setWindowSize(const QSize &size) +{ + if (d_ptr->m_windowSize != size) { + d_ptr->m_windowSize = size; + updateGLViewport(); + d_ptr->m_changeTracker.windowSizeChanged = true; + emit windowSizeChanged(size); + emit needRender(); + } +} + +/*! + * \internal + */ +QSize Q3DScene::windowSize() const +{ + return d_ptr->m_windowSize; +} + +/*! + * \internal + */ +QRect Q3DScene::glViewport() +{ + return d_ptr->m_glViewport; +} + +/*! + * \internal + */ +QRect Q3DScene::glPrimarySubViewport() +{ + return d_ptr->m_glPrimarySubViewport; +} + +/*! + * \internal + */ +QRect Q3DScene::glSecondarySubViewport() +{ + return d_ptr->m_glSecondarySubViewport; +} + /*! * \fn Q3DScene::needRender() * \internal @@ -471,6 +585,11 @@ Q3DScenePrivate::~Q3DScenePrivate() // those changes are discarded. void Q3DScenePrivate::sync(Q3DScenePrivate &other) { + if (m_changeTracker.windowSizeChanged) { + other.q_ptr->setWindowSize(q_ptr->windowSize()); + m_changeTracker.windowSizeChanged = false; + other.m_changeTracker.windowSizeChanged = false; + } if (m_changeTracker.viewportChanged) { other.q_ptr->setViewport(q_ptr->viewport()); m_changeTracker.viewportChanged = false; diff --git a/src/datavisualization/engine/q3dscene.h b/src/datavisualization/engine/q3dscene.h index f1b424a6..5231edb2 100644 --- a/src/datavisualization/engine/q3dscene.h +++ b/src/datavisualization/engine/q3dscene.h @@ -33,7 +33,7 @@ class Q3DScenePrivate; class QT_DATAVISUALIZATION_EXPORT Q3DScene : public QObject { Q_OBJECT - Q_PROPERTY(QRect viewport READ viewport WRITE setViewport NOTIFY viewportChanged) + Q_PROPERTY(QRect viewport READ viewport NOTIFY viewportChanged) Q_PROPERTY(QRect primarySubViewport READ primarySubViewport WRITE setPrimarySubViewport NOTIFY primarySubViewportChanged) Q_PROPERTY(QRect secondarySubViewport READ secondarySubViewport WRITE setSecondarySubViewport NOTIFY secondarySubViewportChanged) Q_PROPERTY(QPoint selectionQueryPosition READ selectionQueryPosition WRITE setSelectionQueryPosition NOTIFY selectionQueryPositionChanged) @@ -48,8 +48,6 @@ public: ~Q3DScene(); QRect viewport() const; - void setViewport(const QRect &viewport); - void setViewportSize(int width, int height); QRect primarySubViewport() const; void setPrimarySubViewport(const QRect &primarySubViewport); @@ -81,7 +79,6 @@ public: Q_INVOKABLE void setLightPositionRelativeToCamera(const QVector3D &relativePosition, float fixedRotation = 0.0f, float distanceModifier = 0.0f); - signals: void viewportChanged(QRect viewport); void primarySubViewportChanged(QRect subViewport); @@ -95,10 +92,30 @@ signals: void selectionQueryPositionChanged(const QPoint position); private: +signals: + void windowSizeChanged(const QSize size); + +private: + void setViewport(const QRect &viewport); + void setViewportSize(int width, int height); + void setWindowSize(const QSize &size); + QSize windowSize() const; + void calculateSubViewports(); + void updateGLViewport(); + void updateGLSubViewports(); + + + QRect glViewport(); + QRect glPrimarySubViewport(); + QRect glSecondarySubViewport(); + QScopedPointer d_ptr; Q_DISABLE_COPY(Q3DScene) + friend class AbstractDeclarative; + friend class Q3DWindow; + friend class Abstract3DController; friend class Q3DScenePrivate; friend class Abstract3DRenderer; friend class Bars3DRenderer; diff --git a/src/datavisualization/engine/q3dscene_p.h b/src/datavisualization/engine/q3dscene_p.h index d083b592..1c6ba5ab 100644 --- a/src/datavisualization/engine/q3dscene_p.h +++ b/src/datavisualization/engine/q3dscene_p.h @@ -48,6 +48,7 @@ struct Q3DSceneChangeBitField { bool slicingActivatedChanged : 1; bool devicePixelRatioChanged : 1; bool selectionQueryPositionChanged : 1; + bool windowSizeChanged : 1; Q3DSceneChangeBitField() : viewportChanged(true), @@ -58,7 +59,8 @@ struct Q3DSceneChangeBitField { lightChanged(true), slicingActivatedChanged(true), devicePixelRatioChanged(true), - selectionQueryPositionChanged(false) + selectionQueryPositionChanged(false), + windowSizeChanged(true) { } }; @@ -84,6 +86,10 @@ public: bool m_isUnderSideCameraEnabled; bool m_isSlicingActive; QPoint m_selectionQueryPosition; + QSize m_windowSize; + QRect m_glViewport; + QRect m_glPrimarySubViewport; + QRect m_glSecondarySubViewport; }; QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/engine/q3dsurface.cpp b/src/datavisualization/engine/q3dsurface.cpp index f523de1b..ce738685 100644 --- a/src/datavisualization/engine/q3dsurface.cpp +++ b/src/datavisualization/engine/q3dsurface.cpp @@ -194,16 +194,6 @@ void Q3DSurface::wheelEvent(QWheelEvent *event) dptr()->m_shared->wheelEvent(event); } -/*! - * \internal - */ -void Q3DSurface::resizeEvent(QResizeEvent *event) -{ - Q_UNUSED(event); - dptr()->m_shared->setWidth(width()); - dptr()->m_shared->setHeight(height()); -} - Q3DSurfacePrivate *Q3DSurface::dptr() { return static_cast(d_ptr.data()); diff --git a/src/datavisualization/engine/q3dsurface.h b/src/datavisualization/engine/q3dsurface.h index da0022ee..bdbe65f5 100644 --- a/src/datavisualization/engine/q3dsurface.h +++ b/src/datavisualization/engine/q3dsurface.h @@ -81,7 +81,6 @@ protected: void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void wheelEvent(QWheelEvent *event); - void resizeEvent(QResizeEvent *event); private: Q3DSurfacePrivate *dptr(); diff --git a/src/datavisualization/engine/q3dwindow.cpp b/src/datavisualization/engine/q3dwindow.cpp index 61a7911d..4a31900f 100644 --- a/src/datavisualization/engine/q3dwindow.cpp +++ b/src/datavisualization/engine/q3dwindow.cpp @@ -168,6 +168,18 @@ bool Q3DWindow::event(QEvent *event) } } +/*! + * \internal + */ +void Q3DWindow::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + + Q3DScene *scene = d_ptr->m_visualController->scene(); + scene->setWindowSize(QSize(width(), height())); + scene->setViewport(QRect(x(),y(),width(),height())); +} + /*! * \internal */ diff --git a/src/datavisualization/engine/q3dwindow.h b/src/datavisualization/engine/q3dwindow.h index bacc0976..cdffc6b9 100644 --- a/src/datavisualization/engine/q3dwindow.h +++ b/src/datavisualization/engine/q3dwindow.h @@ -49,6 +49,7 @@ public: protected: bool event(QEvent *event); + void resizeEvent(QResizeEvent *event); void exposeEvent(QExposeEvent *event); private: diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp index 237fb398..6050911c 100644 --- a/src/datavisualization/engine/scatter3drenderer.cpp +++ b/src/datavisualization/engine/scatter3drenderer.cpp @@ -140,8 +140,10 @@ void Scatter3DRenderer::initializeOpenGL() loadLabelMesh(); // Set view port - glViewport(m_mainViewPort.x(), m_mainViewPort.y(), - m_mainViewPort.width(), m_mainViewPort.height()); + glViewport(m_primarySubViewport.x(), + m_primarySubViewport.y(), + m_primarySubViewport.width(), + m_primarySubViewport.height()); // Load background mesh (we need to be initialized first) loadBackgroundMesh(); @@ -213,14 +215,6 @@ void Scatter3DRenderer::updateData() void Scatter3DRenderer::updateScene(Q3DScene *scene) { - // TODO: Move these to more suitable place e.g. controller should be controlling the viewports. - float devicePixelRatio = scene->devicePixelRatio(); - QRect logicalPrimarySubViewport = QRect(m_mainViewPort.x() / devicePixelRatio, - m_mainViewPort.y() / devicePixelRatio, - m_mainViewPort.width() / devicePixelRatio, - m_mainViewPort.height() / devicePixelRatio); - scene->setPrimarySubViewport(logicalPrimarySubViewport); - // TODO: See QTRD-2374 scene->activeCamera()->setMinYRotation(-90.0f); @@ -253,12 +247,14 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) const Q3DCamera *activeCamera = m_cachedScene->activeCamera(); // Specify viewport - glViewport(m_mainViewPort.x(), m_mainViewPort.y(), - m_mainViewPort.width(), m_mainViewPort.height()); + glViewport(m_primarySubViewport.x(), + m_primarySubViewport.y(), + m_primarySubViewport.width(), + m_primarySubViewport.height()); // Set up projection matrix QMatrix4x4 projectionMatrix; - GLfloat viewPortRatio = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height(); + GLfloat viewPortRatio = (GLfloat)m_primarySubViewport.width() / (GLfloat)m_primarySubViewport.height(); projectionMatrix.perspective(45.0f, viewPortRatio, 0.1f, 100.0f); // Calculate view matrix @@ -332,8 +328,8 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) // Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows. glViewport(0, 0, - m_mainViewPort.width() * m_shadowQualityMultiplier, - m_mainViewPort.height() * m_shadowQualityMultiplier); + m_primarySubViewport.width() * m_shadowQualityMultiplier, + m_primarySubViewport.height() * m_shadowQualityMultiplier); // Enable drawing to framebuffer glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer); @@ -431,8 +427,10 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) glCullFace(GL_BACK); // Revert to original viewport - glViewport(m_mainViewPort.x(), m_mainViewPort.y(), - m_mainViewPort.width(), m_mainViewPort.height()); + glViewport(m_primarySubViewport.x(), + m_primarySubViewport.y(), + m_primarySubViewport.width(), + m_primarySubViewport.height()); #if 0 // Use this if you want to see what is being drawn to the framebuffer // You'll also have to comment out GL_COMPARE_R_TO_TEXTURE -line in texturehelper (if using it) @@ -551,7 +549,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) // Read color under cursor QVector3D clickedColor = Utils::getSelection(m_inputPosition, - m_cachedBoundingRect.height()); + m_viewport.height()); int clickedIndex = 0; QScatter3DSeries *clickedSeries = 0; selectionColorToSeriesAndIndex(clickedColor, clickedIndex, clickedSeries); @@ -1544,17 +1542,6 @@ void Scatter3DRenderer::updateSelectedItem(int index, const QScatter3DSeries *se } } -void Scatter3DRenderer::handleResize() -{ - if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0) - return; - - // Set view port - m_mainViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height()); - - Abstract3DRenderer::handleResize(); -} - void Scatter3DRenderer::updateShadowQuality(QDataVis::ShadowQuality quality) { m_cachedShadowQuality = quality; @@ -1699,10 +1686,10 @@ void Scatter3DRenderer::initSelectionBuffer() m_selectionTexture = 0; } - if (m_mainViewPort.size().isEmpty()) + if (m_primarySubViewport.size().isEmpty()) return; - m_selectionTexture = m_textureHelper->createSelectionTexture(m_mainViewPort.size(), + m_selectionTexture = m_textureHelper->createSelectionTexture(m_primarySubViewport.size(), m_selectionFrameBuffer, m_selectionDepthBuffer); } @@ -1724,11 +1711,11 @@ void Scatter3DRenderer::updateDepthBuffer() m_depthTexture = 0; } - if (m_mainViewPort.size().isEmpty()) + if (m_primarySubViewport.size().isEmpty()) return; if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { - m_depthTexture = m_textureHelper->createDepthTextureFrameBuffer(m_mainViewPort.size(), + m_depthTexture = m_textureHelper->createDepthTextureFrameBuffer(m_primarySubViewport.size(), m_depthFrameBuffer, m_shadowQualityMultiplier); if (!m_depthTexture) diff --git a/src/datavisualization/engine/scatter3drenderer_p.h b/src/datavisualization/engine/scatter3drenderer_p.h index 7423488f..30ec7489 100644 --- a/src/datavisualization/engine/scatter3drenderer_p.h +++ b/src/datavisualization/engine/scatter3drenderer_p.h @@ -57,7 +57,6 @@ private: bool m_xFlipped; bool m_zFlipped; bool m_yFlipped; - QRect m_mainViewPort; bool m_updateLabels; ShaderHelper *m_dotShader; ShaderHelper *m_dotGradientShader; @@ -115,7 +114,6 @@ private: virtual void fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh); void drawScene(GLuint defaultFboHandle); - void handleResize(); void loadBackgroundMesh(); void loadGridLineMesh(); diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp index bbd50d4e..66a8ff2b 100644 --- a/src/datavisualization/engine/surface3drenderer.cpp +++ b/src/datavisualization/engine/surface3drenderer.cpp @@ -523,19 +523,6 @@ QRect Surface3DRenderer::calculateSampleRect(const QSurfaceDataArray &array) void Surface3DRenderer::updateScene(Q3DScene *scene) { - // TODO: Move these to more suitable place e.g. controller should be controlling the viewports. - float devicePixelRatio = scene->devicePixelRatio(); - QRect logicalPrimarySubViewport = QRect(m_mainViewPort.x() / devicePixelRatio, - m_mainViewPort.y() / devicePixelRatio, - m_mainViewPort.width() / devicePixelRatio, - m_mainViewPort.height() / devicePixelRatio); - QRect logicalSecondarySubViewport = QRect(m_sliceViewPort.x() / devicePixelRatio, - m_sliceViewPort.y() / devicePixelRatio, - m_sliceViewPort.width() / devicePixelRatio, - m_sliceViewPort.height() / devicePixelRatio); - scene->setPrimarySubViewport(logicalPrimarySubViewport); - scene->setSecondarySubViewport(logicalSecondarySubViewport); - // Set initial camera position // X must be 0 for rotation to work - we can use "setCameraRotation" for setting it later if (m_hasHeightAdjustmentChanged) { @@ -576,13 +563,15 @@ void Surface3DRenderer::drawSlicedScene() QVector3D lightPos; // Specify viewport - glViewport(m_sliceViewPort.x(), m_sliceViewPort.y(), - m_sliceViewPort.width(), m_sliceViewPort.height()); + glViewport(m_secondarySubViewport.x(), + m_secondarySubViewport.y(), + m_secondarySubViewport.width(), + m_secondarySubViewport.height()); // Set up projection matrix QMatrix4x4 projectionMatrix; - GLfloat aspect = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height(); + GLfloat aspect = (GLfloat)m_secondarySubViewport.width() / (GLfloat)m_secondarySubViewport.height(); projectionMatrix.ortho(-sliceUnits * aspect, sliceUnits * aspect, -sliceUnits, sliceUnits, -1.0f, 4.0f); @@ -835,15 +824,17 @@ void Surface3DRenderer::drawSlicedScene() void Surface3DRenderer::drawScene(GLuint defaultFboHandle) { GLfloat backgroundRotation = 0; + glViewport(m_primarySubViewport.x(), + m_primarySubViewport.y(), + m_primarySubViewport.width(), + m_primarySubViewport.height()); // Specify viewport - glViewport(m_mainViewPort.x(), m_mainViewPort.y(), - m_mainViewPort.width(), m_mainViewPort.height()); // Set up projection matrix QMatrix4x4 projectionMatrix; - projectionMatrix.perspective(45.0f, (GLfloat)m_mainViewPort.width() - / (GLfloat)m_mainViewPort.height(), 0.1f, 100.0f); + projectionMatrix.perspective(45.0f, (GLfloat)m_primarySubViewport.width() + / (GLfloat)m_primarySubViewport.height(), 0.1f, 100.0f); // Calculate view matrix QMatrix4x4 viewMatrix = m_cachedScene->activeCamera()->viewMatrix(); @@ -895,8 +886,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) // Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows. glViewport(0, 0, - m_mainViewPort.width() * m_shadowQualityMultiplier, - m_mainViewPort.height() * m_shadowQualityMultiplier); + m_primarySubViewport.width() * m_shadowQualityMultiplier, + m_primarySubViewport.height() * m_shadowQualityMultiplier); // Get the depth view matrix // It may be possible to hack lightPos here if we want to make some tweaks to shadow @@ -910,8 +901,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) // Set the depth projection matrix #ifndef USE_WIDER_SHADOWS // Use this for perspective shadows - depthProjectionMatrix.perspective(10.0f, (GLfloat)m_mainViewPort.width() - / (GLfloat)m_mainViewPort.height(), 3.0f, 100.0f); + depthProjectionMatrix.perspective(10.0f, (GLfloat)m_primarySubViewport.width() + / (GLfloat)m_primarySubViewport.height(), 3.0f, 100.0f); #else // Use these for orthographic shadows depthProjectionMatrix.ortho(-2.0f * 2.0f, 2.0f * 2.0f, @@ -965,8 +956,10 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); // Revert to original viewport - glViewport(m_mainViewPort.x(), m_mainViewPort.y(), - m_mainViewPort.width(), m_mainViewPort.height()); + glViewport(m_primarySubViewport.x(), + m_primarySubViewport.y(), + m_primarySubViewport.width(), + m_primarySubViewport.height()); // Reset culling to normal glEnable(GL_CULL_FACE); @@ -1020,7 +1013,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) glEnable(GL_DITHER); GLubyte pixel[4] = {0, 0, 0, 0}; - glReadPixels(m_inputPosition.x(), m_cachedBoundingRect.height() - m_inputPosition.y(), + glReadPixels(m_inputPosition.x(), m_viewport.height() - m_inputPosition.y(), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void *)pixel); glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); @@ -1761,7 +1754,7 @@ void Surface3DRenderer::initSelectionBuffer() m_selectionResultTexture = 0; } - m_selectionResultTexture = m_textureHelper->createSelectionTexture(m_mainViewPort.size(), + m_selectionResultTexture = m_textureHelper->createSelectionTexture(m_primarySubViewport.size(), m_selectionFrameBuffer, m_selectionDepthBuffer); } @@ -1885,16 +1878,6 @@ void Surface3DRenderer::loadGridLineMesh() m_gridLineObj->load(); } -void Surface3DRenderer::handleResize() -{ - if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0) - return; - - setViewPorts(); - - Abstract3DRenderer::handleResize(); -} - void Surface3DRenderer::surfacePointSelected(const QPoint &point) { int row = point.x(); @@ -1911,20 +1894,20 @@ void Surface3DRenderer::surfacePointSelected(const QPoint &point) pos = m_sliceSurfaceObj->vertexAt(column, 0); pos *= QVector3D(m_surfaceScaleX, 1.0f, 0.0f); pos += QVector3D(m_surfaceOffsetX, 0.0f, 0.0f); - m_selectionPointer->updateBoundingRect(m_sliceViewPort); + m_selectionPointer->updateBoundingRect(m_secondarySubViewport); m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment); } else if (m_cachedSelectionMode.testFlag(QDataVis::SelectionColumn)) { pos = m_sliceSurfaceObj->vertexAt(row, 0); pos *= QVector3D(m_surfaceScaleZ, 1.0f, 0.0f); pos += QVector3D(-m_surfaceOffsetZ, 0.0f, 0.0f); - m_selectionPointer->updateBoundingRect(m_sliceViewPort); + m_selectionPointer->updateBoundingRect(m_secondarySubViewport); m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment); } } else { pos = m_surfaceObj->vertexAt(column, row); pos *= QVector3D(m_surfaceScaleX, 1.0f, m_surfaceScaleZ);; pos += QVector3D(m_surfaceOffsetX, 0.0f, m_surfaceOffsetZ); - m_selectionPointer->updateBoundingRect(m_mainViewPort); + m_selectionPointer->updateBoundingRect(m_primarySubViewport); m_selectionPointer->updateSliceData(false, m_autoScaleAdjustment); } @@ -2040,8 +2023,6 @@ void Surface3DRenderer::updateSlicingActive(bool isSlicing) m_cachedIsSlicingActivated = isSlicing; - setViewPorts(); - if (!m_cachedIsSlicingActivated) initSelectionBuffer(); // We need to re-init selection buffer in case there has been a resize @@ -2052,26 +2033,6 @@ void Surface3DRenderer::updateSlicingActive(bool isSlicing) m_selectionDirty = true; } -void Surface3DRenderer::setViewPorts() -{ - // Update view ports - if (m_cachedIsSlicingActivated) { - m_mainViewPort = QRect(0, - m_cachedBoundingRect.height() - - (m_cachedBoundingRect.height() / subViewDivider), - m_cachedBoundingRect.width() / subViewDivider, - m_cachedBoundingRect.height() / subViewDivider); - m_sliceViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height()); - if (m_selectionPointer) - m_selectionPointer->updateBoundingRect(m_sliceViewPort); - } else { - m_mainViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height()); - m_sliceViewPort = QRect(0, 0, 0, 0); - if (m_selectionPointer) - m_selectionPointer->updateBoundingRect(m_mainViewPort); - } -} - void Surface3DRenderer::loadLabelMesh() { if (m_labelObj) @@ -2172,15 +2133,15 @@ void Surface3DRenderer::updateDepthBuffer() m_depthTexture = 0; } - if (m_mainViewPort.size().isEmpty()) + if (m_primarySubViewport.size().isEmpty()) return; if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { - m_depthTexture = m_textureHelper->createDepthTextureFrameBuffer(m_mainViewPort.size(), + m_depthTexture = m_textureHelper->createDepthTextureFrameBuffer(m_primarySubViewport.size(), m_depthFrameBuffer, m_shadowQualityMultiplier); - m_textureHelper->fillDepthTexture(m_depthTexture, m_mainViewPort.size(), m_shadowQualityMultiplier, 1.0f); - m_depthModelTexture = m_textureHelper->createDepthTexture(m_mainViewPort.size(), + m_textureHelper->fillDepthTexture(m_depthTexture, m_primarySubViewport.size(), m_shadowQualityMultiplier, 1.0f); + m_depthModelTexture = m_textureHelper->createDepthTexture(m_primarySubViewport.size(), m_shadowQualityMultiplier); if (!m_depthTexture || !m_depthModelTexture) lowerShadowQuality(); diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h index f1eeb088..f70fde9b 100644 --- a/src/datavisualization/engine/surface3drenderer_p.h +++ b/src/datavisualization/engine/surface3drenderer_p.h @@ -69,8 +69,6 @@ private: bool m_cachedIsSlicingActivated; // Internal attributes purely related to how the scene is drawn with GL. - QRect m_mainViewPort; - QRect m_sliceViewPort; ShaderHelper *m_shader; ShaderHelper *m_depthShader; ShaderHelper *m_backgroundShader; @@ -154,7 +152,6 @@ signals: void flatShadingSupportedChanged(bool supported); private: - void setViewPorts(); void updateSliceDataModel(const QPoint &point); void updateShadowQuality(QDataVis::ShadowQuality quality); void updateTextures(); @@ -166,7 +163,6 @@ private: void loadSurfaceObj(); void loadSliceSurfaceObj(); void drawScene(GLuint defaultFboHandle); - void handleResize(); void calculateSceneScalingFactors(); void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader); void initLabelShaders(const QString &vertexShader, const QString &fragmentShader); diff --git a/src/datavisualizationqml2/abstractdeclarative.cpp b/src/datavisualizationqml2/abstractdeclarative.cpp index 1bfa2911..0d6d7526 100644 --- a/src/datavisualizationqml2/abstractdeclarative.cpp +++ b/src/datavisualizationqml2/abstractdeclarative.cpp @@ -17,17 +17,19 @@ ****************************************************************************/ #include "abstractdeclarative_p.h" -#include "declarativerenderer_p.h" #include "q3dvalueaxis.h" +#include +#include QT_DATAVISUALIZATION_BEGIN_NAMESPACE AbstractDeclarative::AbstractDeclarative(QQuickItem *parent) : QQuickItem(parent), m_controller(0), - m_initialisedSize(0, 0), - m_devicePixelRatio(1.0) + m_isFirstRender(true) { + connect(this, &QQuickItem::windowChanged, this, &AbstractDeclarative::handleWindowChanged); + setAntialiasing(true); } AbstractDeclarative::~AbstractDeclarative() @@ -83,32 +85,91 @@ void AbstractDeclarative::setSharedController(Abstract3DController *controller) &AbstractDeclarative::selectionModeChanged); } -QSGNode *AbstractDeclarative::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) +void AbstractDeclarative::synchDataToRenderer() { - qreal devicePixelRatio = window()->devicePixelRatio(); + m_controller->initializeOpenGL(); + m_controller->synchDataToRenderer(); +} + +void AbstractDeclarative::handleWindowChanged(QQuickWindow *window) +{ + if (!window) + return; + + // Disable clearing of the window as we render underneath + window->setClearBeforeRendering(false); + + connect(window, &QQuickWindow::beforeSynchronizing, this, + &AbstractDeclarative::synchDataToRenderer, Qt::DirectConnection); + connect(window, &QQuickWindow::beforeRendering, this, + &AbstractDeclarative::render, Qt::DirectConnection); + connect(m_controller, &Abstract3DController::needRender, window, + &QQuickWindow::update); + + updateWindowParameters(); +} - // If old node exists and has right size and right device pixel ratio, reuse it. - if (oldNode && m_initialisedSize == boundingRect().size().toSize() && devicePixelRatio == m_devicePixelRatio) { - // Update bounding rectangle (that has same size as before). - static_cast(oldNode)->setRect(boundingRect()); - return oldNode; +void AbstractDeclarative::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + QQuickItem::geometryChanged(newGeometry, oldGeometry); + + m_cachedGeometry = newGeometry; + + updateWindowParameters(); +} + +void AbstractDeclarative::itemChange(ItemChange change, const ItemChangeData & value) +{ + QQuickItem::itemChange(change, value); + + updateWindowParameters(); +} + +void AbstractDeclarative::updateWindowParameters() +{ + // Update the device pixel ratio, window size and bounding box + QQuickWindow *win = window(); + Q3DScene *scene = m_controller->scene(); + if (win) { + if (win->devicePixelRatio() != scene->devicePixelRatio()) + scene->setDevicePixelRatio(win->devicePixelRatio()); + + if (win->size() != scene->windowSize()) + scene->setWindowSize(QSize(win->width(), win->height())); + + QPointF point = QQuickItem::mapToScene(QPointF(m_cachedGeometry.x(), m_cachedGeometry.y())); + if (m_controller) { + scene->setViewport(QRect(point.x(), point.y(), m_cachedGeometry.width(), m_cachedGeometry.height())); + } + + } +} + +void AbstractDeclarative::render() +{ + // Needed to catch the window size change upon first render call + if (m_isFirstRender) { + m_isFirstRender = false; + updateWindowParameters(); } - // Create a new render node when size changes or if there is no node yet - m_initialisedSize = boundingRect().size().toSize(); - m_devicePixelRatio = devicePixelRatio; + // Clear the background as that is not done by default + glViewport(0, 0, window()->width(), window()->height()); + QColor clearColor = window()->color(); + glClearColor(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + // TODO: Store the state of these and restore before returning + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glDisable(GL_BLEND); - // Delete old node - if (oldNode) - delete oldNode; + m_controller->render(); - // Create a new one and set it's bounding rectangle - DeclarativeRenderer *node = new DeclarativeRenderer(window(), m_controller); - node->setDevicePixelRatio(float(m_devicePixelRatio)); - node->setRect(boundingRect()); - m_controller->scene()->setDevicePixelRatio(m_devicePixelRatio); - m_controller->setBoundingRect(boundingRect().toRect()); - return node; + glEnable(GL_BLEND); } QAbstract3DInputHandler* AbstractDeclarative::inputHandler() const @@ -135,21 +196,18 @@ void AbstractDeclarative::touchEvent(QTouchEvent *event) void AbstractDeclarative::mousePressEvent(QMouseEvent *event) { QPoint mousePos = event->pos(); - //mousePos.setY(height() - mousePos.y()); m_controller->mousePressEvent(event, mousePos); } void AbstractDeclarative::mouseReleaseEvent(QMouseEvent *event) { QPoint mousePos = event->pos(); - //mousePos.setY(height() - mousePos.y()); m_controller->mouseReleaseEvent(event, mousePos); } void AbstractDeclarative::mouseMoveEvent(QMouseEvent *event) { QPoint mousePos = event->pos(); - //mousePos.setY(height() - mousePos.y()); m_controller->mouseMoveEvent(event, mousePos); } diff --git a/src/datavisualizationqml2/abstractdeclarative_p.h b/src/datavisualizationqml2/abstractdeclarative_p.h index aa3cf498..65017b05 100644 --- a/src/datavisualizationqml2/abstractdeclarative_p.h +++ b/src/datavisualizationqml2/abstractdeclarative_p.h @@ -64,10 +64,15 @@ public: virtual void setSelectionMode(QDataVis::SelectionFlags mode); virtual QDataVis::SelectionFlags selectionMode() const; + virtual void geometryChanged(const QRectF & newGeometry, const QRectF & oldGeometry); + virtual void setShadowQuality(QDataVis::ShadowQuality quality); virtual QDataVis::ShadowQuality shadowQuality() const; void setSharedController(Abstract3DController *controller); + // Used to synch up data model from controller to renderer while main thread is locked + void synchDataToRenderer(); + void render(); protected: virtual void mouseDoubleClickEvent(QMouseEvent *event); @@ -76,7 +81,9 @@ protected: virtual void mouseReleaseEvent(QMouseEvent *event); virtual void mouseMoveEvent(QMouseEvent *event); virtual void wheelEvent(QWheelEvent *event); - virtual QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *); + virtual void handleWindowChanged(QQuickWindow *win); + virtual void itemChange(ItemChange change, const ItemChangeData &value); + virtual void updateWindowParameters(); signals: // Signals shadow quality changes. @@ -89,8 +96,8 @@ signals: private: Abstract3DController *m_controller; - QSize m_initialisedSize; - qreal m_devicePixelRatio; + QRectF m_cachedGeometry; + bool m_isFirstRender; }; QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualizationqml2/datavisualizationqml2.pro b/src/datavisualizationqml2/datavisualizationqml2.pro index 938a8a5c..989b52b9 100644 --- a/src/datavisualizationqml2/datavisualizationqml2.pro +++ b/src/datavisualizationqml2/datavisualizationqml2.pro @@ -26,7 +26,6 @@ SOURCES += \ abstractdeclarative.cpp \ colorgradient.cpp \ declarativeseries.cpp \ - declarativerenderer.cpp \ declarativetheme.cpp \ declarativecolor.cpp @@ -38,7 +37,6 @@ HEADERS += \ abstractdeclarative_p.h \ colorgradient_p.h \ declarativeseries_p.h \ - declarativerenderer_p.h \ declarativetheme_p.h \ declarativecolor_p.h diff --git a/src/datavisualizationqml2/declarativebars.cpp b/src/datavisualizationqml2/declarativebars.cpp index 5c64e173..7eab8886 100644 --- a/src/datavisualizationqml2/declarativebars.cpp +++ b/src/datavisualizationqml2/declarativebars.cpp @@ -17,7 +17,6 @@ ****************************************************************************/ #include "declarativebars_p.h" -#include "declarativerenderer_p.h" #include "q3dvalueaxis.h" #include "qitemmodelbardataproxy.h" @@ -27,7 +26,6 @@ DeclarativeBars::DeclarativeBars(QQuickItem *parent) : AbstractDeclarative(parent), m_barsController(0) { - setFlags(QQuickItem::ItemHasContents); setAcceptedMouseButtons(Qt::AllButtons); // TODO: These seem to have no effect; find a way to activate anti-aliasing diff --git a/src/datavisualizationqml2/declarativerenderer.cpp b/src/datavisualizationqml2/declarativerenderer.cpp deleted file mode 100644 index b9c80b1a..00000000 --- a/src/datavisualizationqml2/declarativerenderer.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the QtDataVisualization module. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** -****************************************************************************/ - -#include "declarativerenderer_p.h" - -#include -#include - -QT_DATAVISUALIZATION_BEGIN_NAMESPACE - -DeclarativeRenderer::DeclarativeRenderer(QQuickWindow *window, Abstract3DController *controller) : - m_fbo(0), - m_texture(0), - m_window(window), - m_controller(controller) -{ - connect(m_window, &QQuickWindow::beforeSynchronizing, this, - &DeclarativeRenderer::synchDataToRenderer, Qt::DirectConnection); - connect(m_window, &QQuickWindow::beforeRendering, this, - &DeclarativeRenderer::renderFBO, Qt::DirectConnection); - connect(m_controller.data(), &Abstract3DController::needRender, m_window, - &QQuickWindow::update); -} - -DeclarativeRenderer::~DeclarativeRenderer() -{ - delete m_texture; - delete m_fbo; -} - -void DeclarativeRenderer::synchDataToRenderer() -{ - if (m_controller) { - m_controller->initializeOpenGL(); - m_controller->synchDataToRenderer(); - } -} - -void DeclarativeRenderer::setDevicePixelRatio(float devicePixelRatio ) -{ - m_devicePixelRatio = devicePixelRatio; -} - -void DeclarativeRenderer::renderFBO() -{ - if (m_controller) { - QSize size = rect().size().toSize(); - size.setWidth(size.width() * m_devicePixelRatio); - size.setHeight(size.height() * m_devicePixelRatio); - - // Create FBO - if (!m_fbo) { - QOpenGLFramebufferObjectFormat format; - format.setAttachment(QOpenGLFramebufferObject::Depth); - m_fbo = new QOpenGLFramebufferObject(size, format); - m_texture = m_window->createTextureFromId(m_fbo->texture(), size); - - setTexture(m_texture); - - // Flip texture - // TODO: Can be gotten rid of once support for texture flipping becomes available (in Qt5.2) - QSize ts = m_texture->textureSize(); - QRectF sourceRect(0, 0, ts.width(), ts.height()); - float tmp = sourceRect.top(); - sourceRect.setTop(sourceRect.bottom()); - sourceRect.setBottom(tmp); - QSGGeometry *geometry = this->geometry(); - QSGGeometry::updateTexturedRectGeometry(geometry, rect(), - m_texture->convertToNormalizedSourceRect(sourceRect)); - markDirty(DirtyMaterial); - } - - // Call the graph rendering function - m_fbo->bind(); - - m_controller->render(m_fbo->handle()); - - m_fbo->release(); - } -} - -QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualizationqml2/declarativerenderer_p.h b/src/datavisualizationqml2/declarativerenderer_p.h deleted file mode 100644 index 75f4f290..00000000 --- a/src/datavisualizationqml2/declarativerenderer_p.h +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the QtDataVisualization module. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the QtDataVisualization API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. - -#ifndef ABSTRACTDECLARATIVERENDERER_P_H -#define ABSTRACTDECLARATIVERENDERER_P_H - -#include "datavisualizationglobal_p.h" -#include -#include -#include - -class QOpenGLFramebufferObject; -class QSGTexture; -class QQuickWindow; - -QT_DATAVISUALIZATION_BEGIN_NAMESPACE - -class DeclarativeRenderer : public QObject, public QSGSimpleTextureNode -{ - Q_OBJECT -public: - explicit DeclarativeRenderer(QQuickWindow *window, Abstract3DController *shared); - virtual ~DeclarativeRenderer(); - -public slots: - // Used to synch up data model from controller to renderer while main thread is locked - void synchDataToRenderer(); - // Renders view to FBO before render cycle starts. - void renderFBO(); - void setDevicePixelRatio(float devicePixelRatio); - -private: - QOpenGLFramebufferObject *m_fbo; - QSGTexture *m_texture; - QQuickWindow *m_window; - QPointer m_controller; - float m_devicePixelRatio; -}; - -QT_DATAVISUALIZATION_END_NAMESPACE - -#endif // ABSTRACTDECLARATIVERENDERER_P_H diff --git a/src/datavisualizationqml2/declarativescatter.cpp b/src/datavisualizationqml2/declarativescatter.cpp index 483bb467..5aaa19b6 100644 --- a/src/datavisualizationqml2/declarativescatter.cpp +++ b/src/datavisualizationqml2/declarativescatter.cpp @@ -17,7 +17,6 @@ ****************************************************************************/ #include "declarativescatter_p.h" -#include "declarativerenderer_p.h" #include "qitemmodelscatterdataproxy.h" QT_DATAVISUALIZATION_BEGIN_NAMESPACE @@ -26,7 +25,6 @@ DeclarativeScatter::DeclarativeScatter(QQuickItem *parent) : AbstractDeclarative(parent), m_scatterController(0) { - setFlags(QQuickItem::ItemHasContents); setAcceptedMouseButtons(Qt::AllButtons); // TODO: These seem to have no effect; find a way to activate anti-aliasing diff --git a/src/datavisualizationqml2/declarativesurface.cpp b/src/datavisualizationqml2/declarativesurface.cpp index 7c73d379..3ba5f923 100644 --- a/src/datavisualizationqml2/declarativesurface.cpp +++ b/src/datavisualizationqml2/declarativesurface.cpp @@ -17,7 +17,6 @@ ****************************************************************************/ #include "declarativesurface_p.h" -#include "declarativerenderer_p.h" #include "q3dvalueaxis.h" #include "qitemmodelsurfacedataproxy.h" @@ -27,7 +26,6 @@ DeclarativeSurface::DeclarativeSurface(QQuickItem *parent) : AbstractDeclarative(parent), m_surfaceController(0) { - setFlags(QQuickItem::ItemHasContents); setAcceptedMouseButtons(Qt::AllButtons); // TODO: These seem to have no effect; find a way to activate anti-aliasing diff --git a/tests/qmlcamera/main.cpp b/tests/qmlcamera/main.cpp index 90d81eab..146e91fa 100644 --- a/tests/qmlcamera/main.cpp +++ b/tests/qmlcamera/main.cpp @@ -24,6 +24,19 @@ int main(int argc, char *argv[]) QGuiApplication app(argc, argv); QtQuick2ApplicationViewer viewer; + + // Enable antialiasing + QSurfaceFormat surfaceFormat; + surfaceFormat.setDepthBufferSize(24); +#if !defined(QT_OPENGL_ES_2) + surfaceFormat.setSamples(8); + surfaceFormat.setRenderableType(QSurfaceFormat::OpenGL); +#else + surfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES); +#endif + surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer); + viewer.setFormat(surfaceFormat); + #ifdef Q_OS_ANDROID viewer.addImportPath(QString::fromLatin1("assets:/qml")); viewer.engine()->addPluginPath(QString::fromLatin1("%1/../%2").arg(QDir::homePath(), diff --git a/tests/qmlcamera/qml/qmlcamera/main.qml b/tests/qmlcamera/qml/qmlcamera/main.qml index 3aa0991a..c1266b41 100644 --- a/tests/qmlcamera/qml/qmlcamera/main.qml +++ b/tests/qmlcamera/qml/qmlcamera/main.qml @@ -48,7 +48,7 @@ Item { shadowQuality: Bars3D.ShadowQualityMedium selectionMode: Bars3D.SelectionItem theme: Theme3D { - type: Theme3D.ThemeRetro + type: Theme3D.ThemeDigia font.pointSize: 35 labelBackgroundEnabled: true } -- cgit v1.2.3