From ec195a34594dea6145af5e8f2fedc2f9401d0f14 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 19 Jun 2014 09:54:03 +0300 Subject: Polar graph support, phase one - Polar property for toggling the polar mode - Example added. Example docs will be added in another patch once all of the functionality the example needs has been implemented. - Only surface graph supports polar so far. Scatter to be added later. Change-Id: I54d36f764ac1771ac88f73a5f3a2142f2309f6e8 Reviewed-by: Mika Salmela --- ...tdatavisualization-qml-abstractdeclarative.qdoc | 13 + .../engine/abstract3dcontroller.cpp | 22 ++ .../engine/abstract3dcontroller_p.h | 26 +- .../engine/abstract3drenderer.cpp | 152 +++++++- .../engine/abstract3drenderer_p.h | 17 + src/datavisualization/engine/bars3drenderer.cpp | 23 +- src/datavisualization/engine/bars3drenderer_p.h | 1 - src/datavisualization/engine/qabstract3dgraph.cpp | 33 +- src/datavisualization/engine/qabstract3dgraph.h | 5 + src/datavisualization/engine/scatter3drenderer.cpp | 30 +- src/datavisualization/engine/scatter3drenderer_p.h | 1 - src/datavisualization/engine/surface3drenderer.cpp | 403 ++++++++++++--------- src/datavisualization/engine/surface3drenderer_p.h | 2 - .../global/datavisualizationglobal_p.h | 1 + src/datavisualization/theme/q3dtheme.cpp | 2 +- src/datavisualization/utils/surfaceobject.cpp | 79 +++- src/datavisualization/utils/surfaceobject_p.h | 13 +- src/datavisualizationqml2/abstractdeclarative.cpp | 12 + src/datavisualizationqml2/abstractdeclarative_p.h | 5 + .../datavisualizationqml2_plugin.cpp | 6 + 20 files changed, 607 insertions(+), 239 deletions(-) (limited to 'src') diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc index 2cc3eece..5afbc8c7 100644 --- a/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc +++ b/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc @@ -152,6 +152,19 @@ * Add a list of \l{Custom3DItem}s to the graph. Graph takes ownership of the added items. */ +/*! + * \qmlproperty bool AbstractGraph3D::polar + * \since QtDataVisualization 1.2 + * + * If \c {true}, the horizontal axes are changed into polar axes. The X axis becomes the + * angular axis and the Z axis becomes the radial axis. + * Polar mode is not available for bar graphs. + * + * Defaults to \c{false}. + * + * \sa orthoProjection, AbstractAxis3D::gridOffset, radialLabelOffset + */ + /*! * \qmlmethod void AbstractGraph3D::clearSelection() * Clears selection from all attached series. diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp index 30434dca..e4fd0003 100644 --- a/src/datavisualization/engine/abstract3dcontroller.cpp +++ b/src/datavisualization/engine/abstract3dcontroller.cpp @@ -50,6 +50,7 @@ Abstract3DController::Abstract3DController(QRect initialViewport, Q3DScene *scen m_isCustomItemDirty(true), m_isSeriesVisualsDirty(true), m_renderPending(false), + m_isPolar(false), m_measureFps(false), m_numFrames(0), m_currentFps(0.0) @@ -176,6 +177,11 @@ void Abstract3DController::synchDataToRenderer() m_renderer->updateTheme(m_themeManager->activeTheme()); + if (m_changeTracker.polarChanged) { + m_renderer->updatePolar(m_isPolar); + m_changeTracker.polarChanged = false; + } + if (m_changeTracker.shadowQualityChanged) { m_renderer->updateShadowQuality(m_shadowQuality); m_changeTracker.shadowQualityChanged = false; @@ -1521,4 +1527,20 @@ float Abstract3DController::aspectRatio() return m_aspectRatio; } +void Abstract3DController::setPolar(bool enable) +{ + if (enable != m_isPolar) { + m_isPolar = enable; + m_changeTracker.polarChanged = true; + m_isDataDirty = true; + emit polarChanged(m_isPolar); + emitNeedRender(); + } +} + +bool Abstract3DController::isPolar() const +{ + return m_isPolar; +} + QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/engine/abstract3dcontroller_p.h b/src/datavisualization/engine/abstract3dcontroller_p.h index 0e4d1add..7d721b0c 100644 --- a/src/datavisualization/engine/abstract3dcontroller_p.h +++ b/src/datavisualization/engine/abstract3dcontroller_p.h @@ -90,6 +90,7 @@ struct Abstract3DChangeBitField { bool axisXTitleFixedChanged : 1; bool axisYTitleFixedChanged : 1; bool axisZTitleFixedChanged : 1; + bool polarChanged : 1; Abstract3DChangeBitField() : themeChanged(true), @@ -133,7 +134,8 @@ struct Abstract3DChangeBitField { axisZTitleVisibilityChanged(true), axisXTitleFixedChanged(true), axisYTitleFixedChanged(true), - axisZTitleFixedChanged(true) + axisZTitleFixedChanged(true), + polarChanged(true) { } }; @@ -175,6 +177,7 @@ protected: bool m_isCustomItemDirty; bool m_isSeriesVisualsDirty; bool m_renderPending; + bool m_isPolar; QList m_seriesList; @@ -261,6 +264,17 @@ public: void setOrthoProjection(bool enable); bool isOrthoProjection() const; + void setMeasureFps(bool enable); + inline bool measureFps() const { return m_measureFps; } + inline qreal currentFps() const { return m_currentFps; } + + QAbstract3DGraph::ElementType selectedElement() const; + + void setAspectRatio(float ratio); + float aspectRatio(); + void setPolar(bool enable); + bool isPolar() const; + void emitNeedRender(); virtual void clearSelection() = 0; @@ -320,17 +334,8 @@ public slots: // Renderer callback handlers void handleRequestShadowQuality(QAbstract3DGraph::ShadowQuality quality); - void setMeasureFps(bool enable); - inline bool measureFps() const { return m_measureFps; } - inline qreal currentFps() const { return m_currentFps; } - - QAbstract3DGraph::ElementType selectedElement() const; - void updateCustomItem(); - void setAspectRatio(float ratio); - float aspectRatio(); - signals: void shadowQualityChanged(QAbstract3DGraph::ShadowQuality quality); void activeInputHandlerChanged(QAbstract3DInputHandler *inputHandler); @@ -346,6 +351,7 @@ signals: void orthoProjectionChanged(bool enabled); void aspectRatioChanged(float ratio); void optimizationHintsChanged(QAbstract3DGraph::OptimizationHints hints); + void polarChanged(bool enabled); protected: virtual QAbstract3DAxis *createDefaultAxis(QAbstract3DAxis::AxisOrientation orientation); diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp index 132a0514..56a5ba60 100644 --- a/src/datavisualization/engine/abstract3drenderer.cpp +++ b/src/datavisualization/engine/abstract3drenderer.cpp @@ -25,8 +25,16 @@ #include "qcustom3ditem_p.h" #include "qcustom3dlabel_p.h" +#include + QT_BEGIN_NAMESPACE_DATAVISUALIZATION +const qreal doublePi(M_PI * 2.0); +const int polarGridRoundness(64); +const qreal polarGridAngle(doublePi / qreal(polarGridRoundness)); +const float polarGridAngleDegrees(float(360.0 / qreal(polarGridRoundness))); +const qreal polarGridHalfAngle(polarGridAngle / 2.0); + Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller) : QObject(0), m_hasNegativeValues(false), @@ -37,6 +45,7 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller) m_cachedSelectionMode(QAbstract3DGraph::SelectionNone), m_cachedOptimizationHint(QAbstract3DGraph::OptimizationDefault), m_textureHelper(0), + m_depthTexture(0), m_cachedScene(new Q3DScene()), m_selectionDirty(true), m_selectionState(SelectNone), @@ -55,7 +64,15 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller) m_backgroundObj(0), m_gridLineObj(0), m_labelObj(0), - m_graphAspectRatio(2.0f) + m_graphAspectRatio(2.0f), + m_polarGraph(false), + m_xRightAngleRotation(QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 90.0f)), + m_yRightAngleRotation(QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f)), + m_zRightAngleRotation(QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, 90.0f)), + m_xRightAngleRotationNeg(QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, -90.0f)), + m_yRightAngleRotationNeg(QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, -90.0f)), + m_zRightAngleRotationNeg(QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, -90.0f)), + m_xFlipRotation(QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, -180.0f)) { QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Abstract3DRenderer::updateTextures); QObject::connect(this, &Abstract3DRenderer::needRender, controller, @@ -89,7 +106,10 @@ Abstract3DRenderer::~Abstract3DRenderer() ObjectHelper::releaseObjectHelper(this, m_gridLineObj); ObjectHelper::releaseObjectHelper(this, m_labelObj); - delete m_textureHelper; + if (m_textureHelper) { + m_textureHelper->deleteTexture(&m_depthTexture); + delete m_textureHelper; + } } void Abstract3DRenderer::initializeOpenGL() @@ -287,6 +307,14 @@ void Abstract3DRenderer::updateAspectRatio(float ratio) updateCustomItemPositions(); } +void Abstract3DRenderer::updatePolar(bool enable) +{ + m_polarGraph = enable; + foreach (SeriesRenderCache *cache, m_renderCacheList) + cache->setDataDirty(true); + updateCustomItemPositions(); +} + void Abstract3DRenderer::updateOptimizationHint(QAbstract3DGraph::OptimizationHints hint) { m_cachedOptimizationHint = hint; @@ -607,10 +635,9 @@ void Abstract3DRenderer::drawAxisTitleY(const QVector3D &sideLabelRotation, QQuaternion titleRotation; if (m_axisCacheY.isTitleFixed()) { titleRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, yRotation) - * QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, 90.0f); + * m_zRightAngleRotation; } else { - titleRotation = totalRotation - * QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, 90.0f); + titleRotation = totalRotation * m_zRightAngleRotation; } dummyItem.setTranslation(titleTrans + titleOffsetVector); @@ -793,7 +820,6 @@ void Abstract3DRenderer::loadLabelMesh() QStringLiteral(":/defaultMeshes/plane")); } - void Abstract3DRenderer::generateBaseColorTexture(const QColor &color, GLuint *texture) { m_textureHelper->deleteTexture(texture); @@ -1131,4 +1157,118 @@ void Abstract3DRenderer::drawCustomItems(RenderingState state, } } +void Abstract3DRenderer::calculatePolarXZ(const QVector3D &dataPos, float &x, float &z) const +{ + // x is angular, z is radial + qreal angle = m_axisCacheX.formatter()->positionAt(dataPos.x()) * doublePi; + qreal radius = m_axisCacheZ.formatter()->positionAt(dataPos.z()); + + // Convert angle & radius to X and Z coords + x = float(radius * qSin(angle)) * m_graphAspectRatio; + z = -float(radius * qCos(angle)) * m_graphAspectRatio; +} + +void Abstract3DRenderer::drawRadialGrid(ShaderHelper *shader, float yFloorLinePos, + const QMatrix4x4 &projectionViewMatrix, + const QMatrix4x4 &depthMatrix) +{ + static QVector lineRotations; + if (!lineRotations.size()) { + lineRotations.resize(polarGridRoundness); + for (int j = 0; j < polarGridRoundness; j++) { + lineRotations[j] = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, + polarGridAngleDegrees * float(j)); + } + } + int gridLineCount = m_axisCacheZ.gridLineCount(); + const QVector &gridPositions = m_axisCacheZ.formatter()->gridPositions(); + const QVector &subGridPositions = m_axisCacheZ.formatter()->subGridPositions(); + int mainSize = gridPositions.size(); + QVector3D translateVector(0.0f, yFloorLinePos, 0.0f); + for (int i = 0; i < gridLineCount; i++) { + float gridPosition = (i >= mainSize) + ? subGridPositions.at(i - mainSize) : gridPositions.at(i); + float radiusFraction = m_graphAspectRatio * gridPosition; + QVector3D gridLineScaler(radiusFraction * float(qSin(polarGridHalfAngle)), + gridLineWidth, gridLineWidth); + translateVector.setZ(gridPosition * m_graphAspectRatio); + for (int j = 0; j < polarGridRoundness; j++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 itModelMatrix; + modelMatrix.rotate(lineRotations.at(j)); + itModelMatrix.rotate(lineRotations.at(j)); + modelMatrix.translate(translateVector); + modelMatrix.scale(gridLineScaler); + itModelMatrix.scale(gridLineScaler); + modelMatrix.rotate(m_xRightAngleRotationNeg); + itModelMatrix.rotate(m_xRightAngleRotationNeg); + QMatrix4x4 MVPMatrix = projectionViewMatrix * modelMatrix; + + shader->setUniformValue(shader->model(), modelMatrix); + shader->setUniformValue(shader->nModel(), itModelMatrix.inverted().transposed()); + shader->setUniformValue(shader->MVP(), MVPMatrix); +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + // Set shadow shader bindings + QMatrix4x4 depthMVPMatrix = depthMatrix * modelMatrix; + shader->setUniformValue(shader->depth(), depthMVPMatrix); + // Draw the object + m_drawer->drawObject(shader, m_gridLineObj, 0, m_depthTexture); + } else { + // Draw the object + m_drawer->drawObject(shader, m_gridLineObj); + } +#else + m_drawer->drawLine(shader); +#endif + } + } +} + +void Abstract3DRenderer::drawAngularGrid(ShaderHelper *shader, float yFloorLinePos, + const QMatrix4x4 &projectionViewMatrix, + const QMatrix4x4 &depthMatrix) +{ + float halfRatio(m_graphAspectRatio / 2.0f); + QVector3D gridLineScaler(gridLineWidth, gridLineWidth, halfRatio); + int gridLineCount = m_axisCacheX.gridLineCount(); + const QVector &gridPositions = m_axisCacheX.formatter()->gridPositions(); + const QVector &subGridPositions = m_axisCacheX.formatter()->subGridPositions(); + int mainSize = gridPositions.size(); + QVector3D translateVector(0.0f, yFloorLinePos, -halfRatio); + for (int i = 0; i < gridLineCount; i++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 itModelMatrix; + float gridPosition = (i >= mainSize) + ? subGridPositions.at(i - mainSize) : gridPositions.at(i); + QQuaternion lineRotation = QQuaternion::fromAxisAndAngle(upVector, gridPosition * 360.0f); + modelMatrix.rotate(lineRotation); + itModelMatrix.rotate(lineRotation); + modelMatrix.translate(translateVector); + modelMatrix.scale(gridLineScaler); + itModelMatrix.scale(gridLineScaler); + modelMatrix.rotate(m_xRightAngleRotationNeg); + itModelMatrix.rotate(m_xRightAngleRotationNeg); + QMatrix4x4 MVPMatrix = projectionViewMatrix * modelMatrix; + + shader->setUniformValue(shader->model(), modelMatrix); + shader->setUniformValue(shader->nModel(), itModelMatrix.inverted().transposed()); + shader->setUniformValue(shader->MVP(), MVPMatrix); +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + // Set shadow shader bindings + QMatrix4x4 depthMVPMatrix = depthMatrix * modelMatrix; + shader->setUniformValue(shader->depth(), depthMVPMatrix); + // Draw the object + m_drawer->drawObject(shader, m_gridLineObj, 0, m_depthTexture); + } else { + // Draw the object + m_drawer->drawObject(shader, m_gridLineObj); + } +#else + m_drawer->drawLine(shader); +#endif + } +} + QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h index 325ac8e6..33337441 100644 --- a/src/datavisualization/engine/abstract3drenderer_p.h +++ b/src/datavisualization/engine/abstract3drenderer_p.h @@ -125,6 +125,7 @@ public: virtual void updateCustomItem(CustomRenderItem *renderItem); virtual void updateAspectRatio(float ratio); + virtual void updatePolar(bool enable); virtual QVector3D convertPositionToTranslation(const QVector3D &position, bool isAbsolute) = 0; @@ -155,6 +156,7 @@ public: GLuint depthTexture, GLfloat shadowQuality); #endif QVector4D indexToSelectionColor(GLint index); + void calculatePolarXZ(const QVector3D &dataPos, float &x, float &z) const; signals: void needRender(); // Emit this if something in renderer causes need for another render pass. @@ -197,6 +199,11 @@ protected: void loadGridLineMesh(); void loadLabelMesh(); + void drawRadialGrid(ShaderHelper *shader, float yFloorLinePos, + const QMatrix4x4 &projectionViewMatrix, const QMatrix4x4 &depthMatrix); + void drawAngularGrid(ShaderHelper *shader, float yFloorLinePos, + const QMatrix4x4 &projectionViewMatrix, const QMatrix4x4 &depthMatrix); + bool m_hasNegativeValues; Q3DTheme *m_cachedTheme; Drawer *m_drawer; @@ -211,6 +218,7 @@ protected: AxisRenderCache m_axisCacheY; AxisRenderCache m_axisCacheZ; TextureHelper *m_textureHelper; + GLuint m_depthTexture; Q3DScene *m_cachedScene; bool m_selectionDirty; @@ -244,6 +252,15 @@ protected: ObjectHelper *m_labelObj; // Shared reference float m_graphAspectRatio; + bool m_polarGraph; + + QQuaternion m_xRightAngleRotation; + QQuaternion m_yRightAngleRotation; + QQuaternion m_zRightAngleRotation; + QQuaternion m_xRightAngleRotationNeg; + QQuaternion m_yRightAngleRotationNeg; + QQuaternion m_zRightAngleRotationNeg; + QQuaternion m_xFlipRotation; private: friend class Abstract3DController; diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp index f909c7d6..70310c23 100644 --- a/src/datavisualization/engine/bars3drenderer.cpp +++ b/src/datavisualization/engine/bars3drenderer.cpp @@ -31,7 +31,6 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION -const GLfloat gridLineWidth = 0.005f; const bool sliceGridLabels = true; Bars3DRenderer::Bars3DRenderer(Bars3DController *controller) @@ -50,7 +49,6 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller) m_backgroundShader(0), m_labelShader(0), m_bgrTexture(0), - m_depthTexture(0), m_selectionTexture(0), m_depthFrameBuffer(0), m_selectionFrameBuffer(0), @@ -421,7 +419,6 @@ void Bars3DRenderer::drawSlicedScene() GLfloat barPosX = 0; QVector3D lightPos; QVector4D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor()); - static QQuaternion ninetyDegreeRotation = QQuaternion::fromAxisAndAngle(upVector, 90.0f); // Specify viewport glViewport(m_secondarySubViewport.x(), @@ -698,7 +695,7 @@ void Bars3DRenderer::drawSlicedScene() barPosX = item.translation().x(); } else { barPosX = -(item.translation().z()); // flip z; frontmost bar to the left - barRotation *= ninetyDegreeRotation; + barRotation *= m_yRightAngleRotation; } modelMatrix.translate(barPosX, barPosY, 0.0f); @@ -1701,9 +1698,9 @@ void Bars3DRenderer::drawBackground(GLfloat rowScaleFactor, GLfloat columnScaleF modelMatrix.scale(backgroundScaler); if (m_yFlipped) - modelMatrix.rotate(90.0f, 1.0f, 0.0f, 0.0f); + modelMatrix.rotate(m_xRightAngleRotation); else - modelMatrix.rotate(-90.0f, 1.0f, 0.0f, 0.0f); + modelMatrix.rotate(m_xRightAngleRotationNeg); itModelMatrix = modelMatrix; @@ -1835,9 +1832,9 @@ void Bars3DRenderer::drawGridLines(GLfloat rowScaleFactor, GLfloat columnScaleFa QVector3D gridLineScaler(rowScaleFactor, gridLineWidth, gridLineWidth); if (m_yFlipped) - lineRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 90.0f); + lineRotation = m_xRightAngleRotation; else - lineRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, -90.0f); + lineRotation = m_xRightAngleRotationNeg; // Floor lines: rows for (GLfloat row = 0.0f; row <= m_cachedRowCount; row++) { @@ -1879,7 +1876,7 @@ void Bars3DRenderer::drawGridLines(GLfloat rowScaleFactor, GLfloat columnScaleFa // Floor lines: columns #if defined(QT_OPENGL_ES_2) - lineRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f); + lineRotation = m_yRightAngleRotation; #endif gridLineScaler = QVector3D(gridLineWidth, gridLineWidth, columnScaleFactor); for (GLfloat bar = 0.0f; bar <= m_cachedColumnCount; bar++) { @@ -1939,8 +1936,8 @@ void Bars3DRenderer::drawGridLines(GLfloat rowScaleFactor, GLfloat columnScaleFa modelMatrix.scale(gridLineScaler); itModelMatrix.scale(gridLineScaler); if (m_zFlipped) { - modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f); - itModelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f); + modelMatrix.rotate(m_xFlipRotation); + itModelMatrix.rotate(m_xFlipRotation); } MVPMatrix = projectionViewMatrix * modelMatrix; @@ -1973,9 +1970,9 @@ void Bars3DRenderer::drawGridLines(GLfloat rowScaleFactor, GLfloat columnScaleFa xWallLinePosition = -xWallLinePosition; if (m_xFlipped) - lineRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, -90.0f); + lineRotation = m_yRightAngleRotationNeg; else - lineRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f); + lineRotation = m_yRightAngleRotation; gridLineScaler = QVector3D(gridLineWidth, gridLineWidth, columnScaleFactor); for (int line = 0; line < gridLineCount; line++) { diff --git a/src/datavisualization/engine/bars3drenderer_p.h b/src/datavisualization/engine/bars3drenderer_p.h index 29835741..466f7bed 100644 --- a/src/datavisualization/engine/bars3drenderer_p.h +++ b/src/datavisualization/engine/bars3drenderer_p.h @@ -68,7 +68,6 @@ private: ShaderHelper *m_backgroundShader; ShaderHelper *m_labelShader; GLuint m_bgrTexture; - GLuint m_depthTexture; GLuint m_selectionTexture; GLuint m_depthFrameBuffer; GLuint m_selectionFrameBuffer; diff --git a/src/datavisualization/engine/qabstract3dgraph.cpp b/src/datavisualization/engine/qabstract3dgraph.cpp index b8fa92e8..6240f714 100644 --- a/src/datavisualization/engine/qabstract3dgraph.cpp +++ b/src/datavisualization/engine/qabstract3dgraph.cpp @@ -591,8 +591,15 @@ qreal QAbstract3DGraph::currentFps() const * \property QAbstract3DGraph::orthoProjection * \since QtDataVisualization 1.1 * - * If \c {true}, orthographic projection will be used for displaying the graph. Defaults to \c{false}. + * If \c {true}, orthographic projection will be used for displaying the graph. + * \note Orthographic projection can be used to create 2D graphs by replacing the default input + * handler with one that doesn't allow rotating the graph and setting the camera to view the graph + * directly from the side or from the top. Also, axis labels typically need to be rotated when + * viewing the graph from the sides. + * Defaults to \c{false}. * \note Shadows will be disabled when set to \c{true}. + * + * \sa QAbstract3DAxis::labelAutoRotation, Q3DCamera::cameraPreset */ void QAbstract3DGraph::setOrthoProjection(bool enable) { @@ -645,6 +652,28 @@ QAbstract3DGraph::OptimizationHints QAbstract3DGraph::optimizationHints() const return d_ptr->m_visualController->optimizationHints(); } +/*! + * \property QAbstract3DGraph::polar + * \since QtDataVisualization 1.2 + * + * If \c {true}, the horizontal axes are changed into polar axes. The X axis becomes the + * angular axis and the Z axis becomes the radial axis. + * Polar mode is not available for bar graphs. + * + * Defaults to \c{false}. + * + * \sa orthoProjection, QAbstract3DAxis::gridOffset, radialLabelOffset + */ +void QAbstract3DGraph::setPolar(bool enable) +{ + d_ptr->m_visualController->setPolar(enable); +} + +bool QAbstract3DGraph::isPolar() const +{ + return d_ptr->m_visualController->isPolar(); +} + /*! * \internal */ @@ -795,6 +824,8 @@ void QAbstract3DGraphPrivate::setVisualController(Abstract3DController *controll QObject::connect(m_visualController, &Abstract3DController::aspectRatioChanged, q_ptr, &QAbstract3DGraph::aspectRatioChanged); + QObject::connect(m_visualController, &Abstract3DController::polarChanged, q_ptr, + &QAbstract3DGraph::polarChanged); } void QAbstract3DGraphPrivate::handleDevicePixelRatioChange() diff --git a/src/datavisualization/engine/qabstract3dgraph.h b/src/datavisualization/engine/qabstract3dgraph.h index 59f61aae..ca673358 100644 --- a/src/datavisualization/engine/qabstract3dgraph.h +++ b/src/datavisualization/engine/qabstract3dgraph.h @@ -50,6 +50,7 @@ class QT_DATAVISUALIZATION_EXPORT QAbstract3DGraph : public QWindow, protected Q Q_PROPERTY(ElementType selectedElement READ selectedElement NOTIFY selectedElementChanged) Q_PROPERTY(qreal aspectRatio READ aspectRatio WRITE setAspectRatio NOTIFY aspectRatioChanged) Q_PROPERTY(OptimizationHints optimizationHints READ optimizationHints WRITE setOptimizationHints NOTIFY optimizationHintsChanged) + Q_PROPERTY(bool polar READ isPolar WRITE setPolar NOTIFY polarChanged) protected: explicit QAbstract3DGraph(QAbstract3DGraphPrivate *d, const QSurfaceFormat *format, @@ -150,6 +151,9 @@ public: void setOptimizationHints(OptimizationHints hints); OptimizationHints optimizationHints() const; + void setPolar(bool enable); + bool isPolar() const; + protected: bool event(QEvent *event); void resizeEvent(QResizeEvent *event); @@ -173,6 +177,7 @@ signals: void orthoProjectionChanged(bool enabled); void aspectRatioChanged(qreal ratio); void optimizationHintsChanged(QAbstract3DGraph::OptimizationHints hints); + void polarChanged(bool enabled); private: Q_DISABLE_COPY(QAbstract3DGraph) diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp index 7ac81552..f6b044f6 100644 --- a/src/datavisualization/engine/scatter3drenderer.cpp +++ b/src/datavisualization/engine/scatter3drenderer.cpp @@ -38,7 +38,6 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION const GLfloat defaultMinSize = 0.01f; const GLfloat defaultMaxSize = 0.1f; const GLfloat itemScaler = 3.0f; -const GLfloat gridLineWidth = 0.005f; Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller) : Abstract3DRenderer(controller), @@ -54,7 +53,6 @@ Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller) m_backgroundShader(0), m_labelShader(0), m_bgrTexture(0), - m_depthTexture(0), m_selectionTexture(0), m_depthFrameBuffer(0), m_selectionFrameBuffer(0), @@ -1006,7 +1004,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) modelMatrix.scale(bgScale); // If we're viewing from below, background object must be flipped if (m_yFlipped) { - modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0); + modelMatrix.rotate(m_xFlipRotation); modelMatrix.rotate(270.0f - backgroundRotation, 0.0f, 1.0f, 0.0f); } else { modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f); @@ -1095,14 +1093,14 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) QQuaternion lineXRotation; if (m_xFlipped) - lineYRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, -90.0f); + lineYRotation = m_yRightAngleRotationNeg; else - lineYRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f); + lineYRotation = m_yRightAngleRotation; if (m_yFlipped) - lineXRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 90.0f); + lineXRotation = m_xRightAngleRotation; else - lineXRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, -90.0f); + lineXRotation = m_xRightAngleRotationNeg; GLfloat yFloorLinePosition = -1.0f - m_backgroundMargin + gridLineOffset; if (m_yFlipped) @@ -1189,8 +1187,8 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) modelMatrix.rotate(lineYRotation); itModelMatrix.rotate(lineYRotation); #else - modelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f); - itModelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f); + modelMatrix.rotate(m_zRightAngleRotation); + itModelMatrix.rotate(m_zRightAngleRotation); #endif MVPMatrix = projectionViewMatrix * modelMatrix; @@ -1221,7 +1219,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) // Columns (= X) if (m_axisCacheX.segmentCount() > 0) { #if defined(QT_OPENGL_ES_2) - lineXRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f); + lineXRotation = m_yRightAngleRotation; #endif // Floor lines int gridLineCount = m_axisCacheX.gridLineCount(); @@ -1301,12 +1299,12 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) #if !defined(QT_OPENGL_ES_2) if (m_zFlipped) { - modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f); - itModelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f); + modelMatrix.rotate(m_xFlipRotation); + itModelMatrix.rotate(m_xFlipRotation); } #else - modelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f); - itModelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f); + modelMatrix.rotate(m_zRightAngleRotation); + itModelMatrix.rotate(m_zRightAngleRotation); #endif MVPMatrix = projectionViewMatrix * modelMatrix; @@ -1368,8 +1366,8 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) itModelMatrix.scale(gridLineScaler); if (m_zFlipped) { - modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f); - itModelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f); + modelMatrix.rotate(m_xFlipRotation); + itModelMatrix.rotate(m_xFlipRotation); } MVPMatrix = projectionViewMatrix * modelMatrix; diff --git a/src/datavisualization/engine/scatter3drenderer_p.h b/src/datavisualization/engine/scatter3drenderer_p.h index 7f213179..b0b1e411 100644 --- a/src/datavisualization/engine/scatter3drenderer_p.h +++ b/src/datavisualization/engine/scatter3drenderer_p.h @@ -61,7 +61,6 @@ private: ShaderHelper *m_backgroundShader; ShaderHelper *m_labelShader; GLuint m_bgrTexture; - GLuint m_depthTexture; GLuint m_selectionTexture; GLuint m_depthFrameBuffer; GLuint m_selectionFrameBuffer; diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp index 60e57529..60e501f1 100644 --- a/src/datavisualization/engine/surface3drenderer.cpp +++ b/src/datavisualization/engine/surface3drenderer.cpp @@ -33,7 +33,6 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION // Margin for background (1.10 make it 10% larger to avoid // selection ball being drawn inside background) const GLfloat backgroundMargin = 1.1f; -const GLfloat gridLineWidth = 0.005f; const GLfloat sliceZScale = 0.1f; const GLfloat sliceUnits = 2.5f; const uint greenMultiplier = 256; @@ -53,12 +52,10 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller) m_selectionShader(0), m_labelShader(0), m_heightNormalizer(0.0f), - m_scaleFactor(0.0f), m_scaleX(0.0f), m_scaleZ(0.0f), m_scaleXWithBackground(0.0f), m_scaleZWithBackground(0.0f), - m_depthTexture(0), m_depthModelTexture(0), m_depthFrameBuffer(0), m_selectionFrameBuffer(0), @@ -301,10 +298,13 @@ void Surface3DRenderer::updateRows(const QVector srcArray->at(row)->at(j + sampleSpace.x()); } - if (cache->isFlatShadingEnabled()) - cache->surfaceObject()->updateCoarseRow(dstArray, row - sampleSpace.y()); - else - cache->surfaceObject()->updateSmoothRow(dstArray, row - sampleSpace.y()); + if (cache->isFlatShadingEnabled()) { + cache->surfaceObject()->updateCoarseRow(dstArray, row - sampleSpace.y(), + m_polarGraph); + } else { + cache->surfaceObject()->updateSmoothRow(dstArray, row - sampleSpace.y(), + m_polarGraph); + } } if (updateBuffers) cache->surfaceObject()->uploadBuffers(); @@ -343,9 +343,9 @@ void Surface3DRenderer::updateItems(const QVectorat(point.x())->at(point.y()); if (cache->isFlatShadingEnabled()) - cache->surfaceObject()->updateCoarseItem(dstArray, y, x); + cache->surfaceObject()->updateCoarseItem(dstArray, y, x, m_polarGraph); else - cache->surfaceObject()->updateSmoothItem(dstArray, y, x); + cache->surfaceObject()->updateSmoothItem(dstArray, y, x, m_polarGraph); } if (updateBuffers) cache->surfaceObject()->uploadBuffers(); @@ -538,10 +538,12 @@ void Surface3DRenderer::updateSliceObject(SurfaceSeriesRenderCache *cache, const QRect sliceRect(0, 0, sliceRow->size(), 2); if (sliceRow->size() > 0) { - if (cache->isFlatShadingEnabled()) - cache->sliceSurfaceObject()->setUpData(sliceDataArray, sliceRect, true, flipZX); - else - cache->sliceSurfaceObject()->setUpSmoothData(sliceDataArray, sliceRect, true, flipZX); + if (cache->isFlatShadingEnabled()) { + cache->sliceSurfaceObject()->setUpData(sliceDataArray, sliceRect, true, false, flipZX); + } else { + cache->sliceSurfaceObject()->setUpSmoothData(sliceDataArray, sliceRect, true, false, + flipZX); + } } } @@ -902,8 +904,8 @@ void Surface3DRenderer::drawSlicedScene() modelMatrix.scale(gridLineScaleY); itModelMatrix.scale(gridLineScaleY); #if (defined QT_OPENGL_ES_2) - modelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f); - itModelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f); + modelMatrix.rotate(m_zRightAngleRotation); + itModelMatrix.rotate(m_zRightAngleRotation); #endif MVPMatrix = projectionViewMatrix * modelMatrix; @@ -1365,7 +1367,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) // If we're viewing from below, background object must be flipped if (m_yFlipped) { - modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f); + modelMatrix.rotate(m_xFlipRotation); modelMatrix.rotate(270.0f - backgroundRotation, 0.0f, 1.0f, 0.0f); } else { modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f); @@ -1461,205 +1463,213 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) QQuaternion lineXRotation; if (m_xFlipped) - lineYRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, -90.0f); + lineYRotation = m_yRightAngleRotationNeg; else - lineYRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f); + lineYRotation = m_yRightAngleRotation; if (m_yFlipped) - lineXRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 90.0f); + lineXRotation = m_xRightAngleRotation; else - lineXRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, -90.0f); + lineXRotation = m_xRightAngleRotationNeg; - GLfloat yFloorLinePosition = -backgroundMargin + gridLineOffset; + float yFloorLinePosition = -backgroundMargin + gridLineOffset; if (m_yFlipped) yFloorLinePosition = -yFloorLinePosition; // Rows (= Z) if (m_axisCacheZ.segmentCount() > 0) { - // Floor lines int gridLineCount = m_axisCacheZ.gridLineCount(); + // Floor lines + if (m_polarGraph) { + drawRadialGrid(lineShader, yFloorLinePosition, projectionViewMatrix, + depthProjectionViewMatrix); + } else { + for (int line = 0; line < gridLineCount; line++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 itModelMatrix; - for (int line = 0; line < gridLineCount; line++) { - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 itModelMatrix; - - modelMatrix.translate(0.0f, yFloorLinePosition, - m_axisCacheZ.gridLinePosition(line)); + modelMatrix.translate(0.0f, yFloorLinePosition, + m_axisCacheZ.gridLinePosition(line)); - modelMatrix.scale(gridLineScaleX); - itModelMatrix.scale(gridLineScaleX); + modelMatrix.scale(gridLineScaleX); + itModelMatrix.scale(gridLineScaleX); - modelMatrix.rotate(lineXRotation); - itModelMatrix.rotate(lineXRotation); + modelMatrix.rotate(lineXRotation); + itModelMatrix.rotate(lineXRotation); - MVPMatrix = projectionViewMatrix * modelMatrix; + MVPMatrix = projectionViewMatrix * modelMatrix; - // Set the rest of the shader bindings - lineShader->setUniformValue(lineShader->model(), modelMatrix); - lineShader->setUniformValue(lineShader->nModel(), - itModelMatrix.inverted().transposed()); - lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); + // Set the rest of the shader bindings + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { - // Set shadow shader bindings - QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; - lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); - // Draw the object - m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); - } else { - // Draw the object - m_drawer->drawObject(lineShader, m_gridLineObj); - } + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + // Set shadow shader bindings + QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + } else { + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj); + } #else - m_drawer->drawLine(lineShader); + m_drawer->drawLine(lineShader); #endif - } - - // Side wall lines - GLfloat lineXTrans = m_scaleXWithBackground - gridLineOffset; + } + // Side wall lines + GLfloat lineXTrans = m_scaleXWithBackground - gridLineOffset; - if (!m_xFlipped) - lineXTrans = -lineXTrans; + if (!m_xFlipped) + lineXTrans = -lineXTrans; - for (int line = 0; line < gridLineCount; line++) { - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 itModelMatrix; + for (int line = 0; line < gridLineCount; line++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 itModelMatrix; - modelMatrix.translate(lineXTrans, 0.0f, m_axisCacheZ.gridLinePosition(line)); + modelMatrix.translate(lineXTrans, 0.0f, m_axisCacheZ.gridLinePosition(line)); - modelMatrix.scale(gridLineScaleY); - itModelMatrix.scale(gridLineScaleY); + modelMatrix.scale(gridLineScaleY); + itModelMatrix.scale(gridLineScaleY); #if !defined(QT_OPENGL_ES_2) - modelMatrix.rotate(lineYRotation); - itModelMatrix.rotate(lineYRotation); + modelMatrix.rotate(lineYRotation); + itModelMatrix.rotate(lineYRotation); #else - modelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f); - itModelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f); + modelMatrix.rotate(m_zRightAngleRotation); + itModelMatrix.rotate(m_zRightAngleRotation); #endif - MVPMatrix = projectionViewMatrix * modelMatrix; + MVPMatrix = projectionViewMatrix * modelMatrix; - // Set the rest of the shader bindings - lineShader->setUniformValue(lineShader->model(), modelMatrix); - lineShader->setUniformValue(lineShader->nModel(), - itModelMatrix.inverted().transposed()); - lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); + // Set the rest of the shader bindings + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { - // Set shadow shader bindings - QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; - lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); - // Draw the object - m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); - } else { - // Draw the object - m_drawer->drawObject(lineShader, m_gridLineObj); - } + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + // Set shadow shader bindings + QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + } else { + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj); + } #else - m_drawer->drawLine(lineShader); + m_drawer->drawLine(lineShader); #endif + } } } // Columns (= X) if (m_axisCacheX.segmentCount() > 0) { #if defined(QT_OPENGL_ES_2) - lineXRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f); + lineXRotation = m_yRightAngleRotation; #endif // Floor lines int gridLineCount = m_axisCacheX.gridLineCount(); - for (int line = 0; line < gridLineCount; line++) { - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 itModelMatrix; + if (m_polarGraph) { + drawAngularGrid(lineShader, yFloorLinePosition, projectionViewMatrix, + depthProjectionViewMatrix); + } else { + for (int line = 0; line < gridLineCount; line++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 itModelMatrix; - modelMatrix.translate(m_axisCacheX.gridLinePosition(line), yFloorLinePosition, - 0.0f); + modelMatrix.translate(m_axisCacheX.gridLinePosition(line), yFloorLinePosition, + 0.0f); - modelMatrix.scale(gridLineScaleZ); - itModelMatrix.scale(gridLineScaleZ); + modelMatrix.scale(gridLineScaleZ); + itModelMatrix.scale(gridLineScaleZ); - modelMatrix.rotate(lineXRotation); - itModelMatrix.rotate(lineXRotation); + modelMatrix.rotate(lineXRotation); + itModelMatrix.rotate(lineXRotation); - MVPMatrix = projectionViewMatrix * modelMatrix; + MVPMatrix = projectionViewMatrix * modelMatrix; - // Set the rest of the shader bindings - lineShader->setUniformValue(lineShader->model(), modelMatrix); - lineShader->setUniformValue(lineShader->nModel(), - itModelMatrix.inverted().transposed()); - lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); + // Set the rest of the shader bindings + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { - // Set shadow shader bindings - QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; - lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); - // Draw the object - m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); - } else { - // Draw the object - m_drawer->drawObject(lineShader, m_gridLineObj); - } + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + // Set shadow shader bindings + QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + } else { + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj); + } #else - m_drawer->drawLine(lineShader); + m_drawer->drawLine(lineShader); #endif - } + } - // Back wall lines - GLfloat lineZTrans = m_scaleZWithBackground - gridLineOffset; + // Back wall lines + GLfloat lineZTrans = m_scaleZWithBackground - gridLineOffset; - if (!m_zFlipped) - lineZTrans = -lineZTrans; + if (!m_zFlipped) + lineZTrans = -lineZTrans; - for (int line = 0; line < gridLineCount; line++) { - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 itModelMatrix; + for (int line = 0; line < gridLineCount; line++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 itModelMatrix; - modelMatrix.translate(m_axisCacheX.gridLinePosition(line), 0.0f, lineZTrans); + modelMatrix.translate(m_axisCacheX.gridLinePosition(line), 0.0f, lineZTrans); - modelMatrix.scale(gridLineScaleY); - itModelMatrix.scale(gridLineScaleY); + modelMatrix.scale(gridLineScaleY); + itModelMatrix.scale(gridLineScaleY); #if !defined(QT_OPENGL_ES_2) - if (m_zFlipped) { - modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f); - itModelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f); - } + if (m_zFlipped) { + modelMatrix.rotate(m_xFlipRotation); + itModelMatrix.rotate(m_xFlipRotation); + } #else - modelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f); - itModelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f); + modelMatrix.rotate(m_zRightAngleRotation); + itModelMatrix.rotate(m_zRightAngleRotation); #endif - MVPMatrix = projectionViewMatrix * modelMatrix; + MVPMatrix = projectionViewMatrix * modelMatrix; - // Set the rest of the shader bindings - lineShader->setUniformValue(lineShader->model(), modelMatrix); - lineShader->setUniformValue(lineShader->nModel(), - itModelMatrix.inverted().transposed()); - lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); + // Set the rest of the shader bindings + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { - // Set shadow shader bindings - QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; - lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); - // Draw the object - m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); - } else { - // Draw the object - m_drawer->drawObject(lineShader, m_gridLineObj); - } + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + // Set shadow shader bindings + QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + } else { + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj); + } #else - m_drawer->drawLine(lineShader); + m_drawer->drawLine(lineShader); #endif + } } } @@ -1684,8 +1694,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) itModelMatrix.scale(gridLineScaleX); if (m_zFlipped) { - modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f); - itModelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f); + modelMatrix.rotate(m_xFlipRotation); + itModelMatrix.rotate(m_xFlipRotation); } MVPMatrix = projectionViewMatrix * modelMatrix; @@ -1833,8 +1843,15 @@ void Surface3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCa QVector3D positionZComp(0.0f, 0.0f, 0.0f); if (m_axisCacheZ.segmentCount() > 0) { int labelCount = m_axisCacheZ.labelCount(); - GLfloat labelXTrans = m_scaleXWithBackground + labelMargin; - GLfloat labelYTrans = -backgroundMargin; + float labelXTrans = 0.0f; + float labelYTrans = -backgroundMargin; + if (m_polarGraph) { + // TODO optional placement of radial labels - YTrans up only if over background + labelXTrans = m_scaleXWithBackground + labelMargin; + //labelYTrans += gridLineOffset + gridLineWidth; + } else { + labelXTrans = m_scaleXWithBackground + labelMargin; + } Qt::AlignmentFlag alignment = (m_xFlipped == m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight; QVector3D labelRotation; if (m_xFlipped) @@ -1921,10 +1938,17 @@ void Surface3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCa float offsetValue = 0.0f; for (int label = startIndex; label != endIndex; label = label + indexStep) { glPolygonOffset(offsetValue++ / -10.0f, 1.0f); + const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(label); // Draw the label here - labelTrans.setZ(m_axisCacheZ.labelPosition(label)); + if (m_polarGraph) { + float direction = m_zFlipped ? -1.0f : 1.0f; + labelTrans.setZ((m_axisCacheZ.formatter()->labelPositions().at(label) + * -m_graphAspectRatio + + m_drawer->scaledFontSize() + gridLineWidth) * direction); + } else { + labelTrans.setZ(m_axisCacheZ.labelPosition(label)); + } m_dummyRenderItem.setTranslation(labelTrans); - const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(label); if (drawSelection) { QVector4D labelColor = QVector4D(label / 255.0f, 0.0f, 0.0f, @@ -1953,8 +1977,13 @@ void Surface3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCa fractionCamX = activeCamera->xRotation() * labelAngleFraction; int labelCount = m_axisCacheX.labelCount(); - GLfloat labelZTrans = m_scaleZWithBackground + labelMargin; + GLfloat labelZTrans = 0.0f; GLfloat labelYTrans = -backgroundMargin; + if (m_polarGraph) + labelYTrans += gridLineOffset + gridLineWidth; + else + labelZTrans = m_scaleZWithBackground + labelMargin; + Qt::AlignmentFlag alignment = (m_xFlipped != m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight; QVector3D labelRotation; if (m_zFlipped) @@ -2023,7 +2052,14 @@ void Surface3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCa } } } + QQuaternion totalRotation = Utils::calculateRotation(labelRotation); + if (m_polarGraph) { + if (m_zFlipped != m_xFlipped) + totalRotation *= m_zRightAngleRotation; + else + totalRotation *= m_zRightAngleRotationNeg; + } QVector3D labelTrans = QVector3D(0.0f, labelYTrans, @@ -2039,10 +2075,44 @@ void Surface3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCa indexStep = 1; } float offsetValue = 0.0f; + bool showLastLabel = false; + QVector &gridPositions = m_axisCacheX.formatter()->gridPositions(); + int lastGridPosIndex = gridPositions.size() - 1; + if (gridPositions.size() + && (gridPositions.at(lastGridPosIndex) != 1.0f || gridPositions.at(0) != 0.0f)) { + // Avoid overlapping first and last label if they would get on same position + showLastLabel = true; + } + for (int label = startIndex; label != endIndex; label = label + indexStep) { glPolygonOffset(offsetValue++ / -10.0f, 1.0f); // Draw the label here - labelTrans.setX(m_axisCacheX.labelPosition(label)); + if (m_polarGraph) { + // Calculate angular position + if (label == lastGridPosIndex && !showLastLabel) + continue; + float gridPosition = m_axisCacheX.formatter()->gridPositions().at(label); + qreal angle = gridPosition * M_PI * 2.0; + labelTrans.setX((m_graphAspectRatio + labelMargin)* float(qSin(angle))); + labelTrans.setZ(-(m_graphAspectRatio + labelMargin) * float(qCos(angle))); + // Alignment depends on label angular position, as well as flips + Qt::AlignmentFlag vAlignment = Qt::AlignCenter; + Qt::AlignmentFlag hAlignment = Qt::AlignCenter; + const float centerMargin = 0.005f; + if (gridPosition < 0.25f - centerMargin || gridPosition > 0.75f + centerMargin) + vAlignment = m_zFlipped ? Qt::AlignTop : Qt::AlignBottom; + else if (gridPosition > 0.25f + centerMargin && gridPosition < 0.75f - centerMargin) + vAlignment = m_zFlipped ? Qt::AlignBottom : Qt::AlignTop; + + if (gridPosition < 0.50f - centerMargin && gridPosition > centerMargin) + hAlignment = m_zFlipped ? Qt::AlignRight : Qt::AlignLeft; + else if (gridPosition < 1.0f - centerMargin && gridPosition > 0.5f + centerMargin) + hAlignment = m_zFlipped ? Qt::AlignLeft : Qt::AlignRight; + + alignment = Qt::AlignmentFlag(vAlignment | hAlignment); + } else { + labelTrans.setX(m_axisCacheX.labelPosition(label)); + } m_dummyRenderItem.setTranslation(labelTrans); const LabelItem &axisLabelItem = *m_axisCacheX.labelItems().at(label); @@ -2298,13 +2368,18 @@ void Surface3DRenderer::calculateSceneScalingFactors() m_heightNormalizer = GLfloat(m_axisCacheY.max() - m_axisCacheY.min()); m_areaSize.setHeight(m_axisCacheZ.max() - m_axisCacheZ.min()); m_areaSize.setWidth(m_axisCacheX.max() - m_axisCacheX.min()); - m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height()); - m_scaleX = m_graphAspectRatio * m_areaSize.width() / m_scaleFactor; - m_scaleZ = m_graphAspectRatio * m_areaSize.height() / m_scaleFactor; + float scaleFactor = qMax(m_areaSize.width(), m_areaSize.height()); + if (m_polarGraph) { + m_scaleX = m_graphAspectRatio; + m_scaleZ = m_graphAspectRatio; + } else { + m_scaleX = m_graphAspectRatio * m_areaSize.width() / scaleFactor; + m_scaleZ = m_graphAspectRatio * m_areaSize.height() / scaleFactor; + } m_scaleXWithBackground = m_scaleX + backgroundMargin - 1.0f; m_scaleZWithBackground = m_scaleZ + backgroundMargin - 1.0f; - float factorScaler = 2.0f * m_graphAspectRatio / m_scaleFactor; + float factorScaler = 2.0f * m_graphAspectRatio / scaleFactor; m_axisCacheX.setScale(factorScaler * m_areaSize.width()); m_axisCacheZ.setScale(-factorScaler * m_areaSize.height()); m_axisCacheX.setTranslate(-m_axisCacheX.scale() / 2.0f); @@ -2327,10 +2402,12 @@ void Surface3DRenderer::updateObjects(SurfaceSeriesRenderCache *cache, bool dime QSurfaceDataArray &dataArray = cache->dataArray(); const QRect &sampleSpace = cache->sampleSpace(); - if (cache->isFlatShadingEnabled()) - cache->surfaceObject()->setUpData(dataArray, sampleSpace, dimensionChanged); - else - cache->surfaceObject()->setUpSmoothData(dataArray, sampleSpace, dimensionChanged); + if (cache->isFlatShadingEnabled()) { + cache->surfaceObject()->setUpData(dataArray, sampleSpace, dimensionChanged, m_polarGraph); + } else { + cache->surfaceObject()->setUpSmoothData(dataArray, sampleSpace, dimensionChanged, + m_polarGraph); + } } void Surface3DRenderer::updateSelectedPoint(const QPoint &position, QSurface3DSeries *series) diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h index efa8ff7e..a621fae3 100644 --- a/src/datavisualization/engine/surface3drenderer_p.h +++ b/src/datavisualization/engine/surface3drenderer_p.h @@ -57,12 +57,10 @@ private: ShaderHelper *m_selectionShader; ShaderHelper *m_labelShader; GLfloat m_heightNormalizer; - GLfloat m_scaleFactor; GLfloat m_scaleX; GLfloat m_scaleZ; GLfloat m_scaleXWithBackground; GLfloat m_scaleZWithBackground; - GLuint m_depthTexture; GLuint m_depthModelTexture; GLuint m_depthFrameBuffer; GLuint m_selectionFrameBuffer; diff --git a/src/datavisualization/global/datavisualizationglobal_p.h b/src/datavisualization/global/datavisualizationglobal_p.h index abdac998..f1f51309 100644 --- a/src/datavisualization/global/datavisualizationglobal_p.h +++ b/src/datavisualization/global/datavisualizationglobal_p.h @@ -69,6 +69,7 @@ static const GLfloat gradientTextureWidth = 2.0f; static const GLfloat uniformTextureHeight = 64.0f; static const GLfloat uniformTextureWidth = 2.0f; static const GLfloat labelMargin = 0.05f; +static const GLfloat gridLineWidth = 0.005f; QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/theme/q3dtheme.cpp b/src/datavisualization/theme/q3dtheme.cpp index 97ff8f81..70397e23 100644 --- a/src/datavisualization/theme/q3dtheme.cpp +++ b/src/datavisualization/theme/q3dtheme.cpp @@ -679,7 +679,7 @@ QLinearGradient Q3DTheme::multiHighlightGradient() const /*! * \property Q3DTheme::lightStrength * - * Specular light strength for the whole graph. Value must be 0.0f and 10.0f. + * Specular light strength for the whole graph. Value must be between 0.0f and 10.0f. */ void Q3DTheme::setLightStrength(float strength) { diff --git a/src/datavisualization/utils/surfaceobject.cpp b/src/datavisualization/utils/surfaceobject.cpp index d999ba90..f8675912 100644 --- a/src/datavisualization/utils/surfaceobject.cpp +++ b/src/datavisualization/utils/surfaceobject.cpp @@ -30,7 +30,8 @@ SurfaceObject::SurfaceObject(Surface3DRenderer *renderer) m_gridIndexCount(0), m_axisCacheX(renderer->m_axisCacheX), m_axisCacheY(renderer->m_axisCacheY), - m_axisCacheZ(renderer->m_axisCacheZ) + m_axisCacheZ(renderer->m_axisCacheZ), + m_renderer(renderer) { m_indicesType = GL_UNSIGNED_INT; @@ -49,7 +50,7 @@ SurfaceObject::~SurfaceObject() } void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QRect &space, - bool changeGeometry, bool flipXZ) + bool changeGeometry, bool polar, bool flipXZ) { m_columns = space.width(); m_rows = space.height(); @@ -75,9 +76,16 @@ void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QR const QSurfaceDataRow &p = *dataArray.at(i); for (int j = 0; j < m_columns; j++) { const QSurfaceDataItem &data = p.at(j); - float normalizedX = xCache.positionAt(data.x()); + float normalizedX; + float normalizedZ; + if (polar) { + // Slice don't use polar, so don't care about flip + m_renderer->calculatePolarXZ(data.position(), normalizedX, normalizedZ); + } else { + normalizedX = xCache.positionAt(data.x()); + normalizedZ = zCache.positionAt(data.z()); + } float normalizedY = m_axisCacheY.positionAt(data.y()); - float normalizedZ = zCache.positionAt(data.z()); m_vertices[totalIndex] = QVector3D(normalizedX, normalizedY, normalizedZ); if (changeGeometry) uvs[totalIndex] = QVector2D(GLfloat(j) * uvX, GLfloat(i) * uvY); @@ -137,7 +145,7 @@ void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QR createBuffers(m_vertices, uvs, m_normals, 0, changeGeometry); } -void SurfaceObject::updateSmoothRow(const QSurfaceDataArray &dataArray, int rowIndex) +void SurfaceObject::updateSmoothRow(const QSurfaceDataArray &dataArray, int rowIndex, bool polar) { // Update vertices int p = rowIndex * m_columns; @@ -145,9 +153,15 @@ void SurfaceObject::updateSmoothRow(const QSurfaceDataArray &dataArray, int rowI for (int j = 0; j < m_columns; j++) { const QSurfaceDataItem &data = dataRow.at(j); - float normalizedX = m_axisCacheX.positionAt(data.x()); + float normalizedX; + float normalizedZ; + if (polar) { + m_renderer->calculatePolarXZ(data.position(), normalizedX, normalizedZ); + } else { + normalizedX = m_axisCacheX.positionAt(data.x()); + normalizedZ = m_axisCacheZ.positionAt(data.z()); + } float normalizedY = m_axisCacheY.positionAt(data.y()); - float normalizedZ = m_axisCacheZ.positionAt(data.z()); m_vertices[p++] = QVector3D(normalizedX, normalizedY, normalizedZ); } @@ -196,13 +210,20 @@ void SurfaceObject::updateSmoothRow(const QSurfaceDataArray &dataArray, int rowI } } -void SurfaceObject::updateSmoothItem(const QSurfaceDataArray &dataArray, int row, int column) +void SurfaceObject::updateSmoothItem(const QSurfaceDataArray &dataArray, int row, int column, + bool polar) { // Update a vertice const QSurfaceDataItem &data = dataArray.at(row)->at(column); - float normalizedX = m_axisCacheX.positionAt(data.x()); + float normalizedX; + float normalizedZ; + if (polar) { + m_renderer->calculatePolarXZ(data.position(), normalizedX, normalizedZ); + } else { + normalizedX = m_axisCacheX.positionAt(data.x()); + normalizedZ = m_axisCacheZ.positionAt(data.z()); + } float normalizedY = m_axisCacheY.positionAt(data.y()); - float normalizedZ = m_axisCacheZ.positionAt(data.z()); m_vertices[row * m_columns + column] = QVector3D(normalizedX, normalizedY, normalizedZ); // Create normals @@ -331,7 +352,7 @@ void SurfaceObject::createSmoothGridlineIndices(int x, int y, int endX, int endY } void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &space, - bool changeGeometry, bool flipXZ) + bool changeGeometry, bool polar, bool flipXZ) { m_columns = space.width(); m_rows = space.height(); @@ -362,9 +383,16 @@ void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &s const QSurfaceDataRow &row = *dataArray.at(i); for (int j = 0; j < m_columns; j++) { const QSurfaceDataItem &data = row.at(j); - float normalizedX = xCache.positionAt(data.x()); + float normalizedX; + float normalizedZ; + if (polar) { + // Slice don't use polar, so don't care about flip + m_renderer->calculatePolarXZ(data.position(), normalizedX, normalizedZ); + } else { + normalizedX = xCache.positionAt(data.x()); + normalizedZ = zCache.positionAt(data.z()); + } float normalizedY = m_axisCacheY.positionAt(data.y()); - float normalizedZ = zCache.positionAt(data.z()); m_vertices[totalIndex] = QVector3D(normalizedX, normalizedY, normalizedZ); if (changeGeometry) uvs[totalIndex] = QVector2D(GLfloat(j) * uvX, GLfloat(i) * uvY); @@ -438,7 +466,7 @@ void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &s delete[] indices; } -void SurfaceObject::updateCoarseRow(const QSurfaceDataArray &dataArray, int rowIndex) +void SurfaceObject::updateCoarseRow(const QSurfaceDataArray &dataArray, int rowIndex, bool polar) { int colLimit = m_columns - 1; int doubleColumns = m_columns * 2 - 2; @@ -448,9 +476,15 @@ void SurfaceObject::updateCoarseRow(const QSurfaceDataArray &dataArray, int rowI for (int j = 0; j < m_columns; j++) { const QSurfaceDataItem &data = dataRow.at(j); - float normalizedX = m_axisCacheX.positionAt(data.x()); + float normalizedX; + float normalizedZ; + if (polar) { + m_renderer->calculatePolarXZ(data.position(), normalizedX, normalizedZ); + } else { + normalizedX = m_axisCacheX.positionAt(data.x()); + normalizedZ = m_axisCacheZ.positionAt(data.z()); + } float normalizedY = m_axisCacheY.positionAt(data.y()); - float normalizedZ = m_axisCacheZ.positionAt(data.z()); m_vertices[p++] = QVector3D(normalizedX, normalizedY, normalizedZ); if (j > 0 && j < colLimit) { @@ -486,7 +520,8 @@ void SurfaceObject::updateCoarseRow(const QSurfaceDataArray &dataArray, int rowI } } -void SurfaceObject::updateCoarseItem(const QSurfaceDataArray &dataArray, int row, int column) +void SurfaceObject::updateCoarseItem(const QSurfaceDataArray &dataArray, int row, int column, + bool polar) { int colLimit = m_columns - 1; int doubleColumns = m_columns * 2 - 2; @@ -494,9 +529,15 @@ void SurfaceObject::updateCoarseItem(const QSurfaceDataArray &dataArray, int row // Update a vertice int p = row * doubleColumns + column * 2 - (column > 0); const QSurfaceDataItem &data = dataArray.at(row)->at(column); - float normalizedX = m_axisCacheX.positionAt(data.x()); + float normalizedX; + float normalizedZ; + if (polar) { + m_renderer->calculatePolarXZ(data.position(), normalizedX, normalizedZ); + } else { + normalizedX = m_axisCacheX.positionAt(data.x()); + normalizedZ = m_axisCacheZ.positionAt(data.z()); + } float normalizedY = m_axisCacheY.positionAt(data.y()); - float normalizedZ = m_axisCacheZ.positionAt(data.z()); m_vertices[p] = QVector3D(normalizedX, normalizedY, normalizedZ); p++; diff --git a/src/datavisualization/utils/surfaceobject_p.h b/src/datavisualization/utils/surfaceobject_p.h index 9c18dcb2..54e6dec3 100644 --- a/src/datavisualization/utils/surfaceobject_p.h +++ b/src/datavisualization/utils/surfaceobject_p.h @@ -54,13 +54,13 @@ public: ~SurfaceObject(); void setUpData(const QSurfaceDataArray &dataArray, const QRect &space, - bool changeGeometry, bool flipXZ = false); + bool changeGeometry, bool polar, bool flipXZ = false); void setUpSmoothData(const QSurfaceDataArray &dataArray, const QRect &space, - bool changeGeometry, bool flipXZ = false); - void updateCoarseRow(const QSurfaceDataArray &dataArray, int rowIndex); - void updateSmoothRow(const QSurfaceDataArray &dataArray, int startRow); - void updateSmoothItem(const QSurfaceDataArray &dataArray, int row, int column); - void updateCoarseItem(const QSurfaceDataArray &dataArray, int row, int column); + bool changeGeometry, bool polar, bool flipXZ = false); + void updateCoarseRow(const QSurfaceDataArray &dataArray, int rowIndex, bool polar); + void updateSmoothRow(const QSurfaceDataArray &dataArray, int startRow, bool polar); + void updateSmoothItem(const QSurfaceDataArray &dataArray, int row, int column, bool polar); + void updateCoarseItem(const QSurfaceDataArray &dataArray, int row, int column, bool polar); void createSmoothIndices(int x, int y, int endX, int endY); void createCoarseIndices(int x, int y, int columns, int rows); void createSmoothGridlineIndices(int x, int y, int endX, int endY); @@ -90,6 +90,7 @@ private: AxisRenderCache &m_axisCacheX; AxisRenderCache &m_axisCacheY; AxisRenderCache &m_axisCacheZ; + Surface3DRenderer *m_renderer; }; QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualizationqml2/abstractdeclarative.cpp b/src/datavisualizationqml2/abstractdeclarative.cpp index f7ccbf21..30acc9e4 100644 --- a/src/datavisualizationqml2/abstractdeclarative.cpp +++ b/src/datavisualizationqml2/abstractdeclarative.cpp @@ -329,6 +329,8 @@ void AbstractDeclarative::setSharedController(Abstract3DController *controller) &AbstractDeclarative::aspectRatioChanged); QObject::connect(m_controller.data(), &Abstract3DController::optimizationHintsChanged, this, &AbstractDeclarative::handleOptimizationHintChange); + QObject::connect(m_controller.data(), &Abstract3DController::polarChanged, this, + &AbstractDeclarative::polarChanged); } void AbstractDeclarative::activateOpenGLContext(QQuickWindow *window) @@ -724,6 +726,16 @@ AbstractDeclarative::OptimizationHints AbstractDeclarative::optimizationHints() return OptimizationHints(intmode); } +void AbstractDeclarative::setPolar(bool enable) +{ + m_controller->setPolar(enable); +} + +bool AbstractDeclarative::isPolar() const +{ + return m_controller->isPolar(); +} + void AbstractDeclarative::windowDestroyed(QObject *obj) { // Remove destroyed window from window lists diff --git a/src/datavisualizationqml2/abstractdeclarative_p.h b/src/datavisualizationqml2/abstractdeclarative_p.h index dfcd9537..cd3d6134 100644 --- a/src/datavisualizationqml2/abstractdeclarative_p.h +++ b/src/datavisualizationqml2/abstractdeclarative_p.h @@ -72,6 +72,7 @@ class AbstractDeclarative : public QQuickItem Q_PROPERTY(ElementType selectedElement READ selectedElement NOTIFY selectedElementChanged REVISION 1) Q_PROPERTY(qreal aspectRatio READ aspectRatio WRITE setAspectRatio NOTIFY aspectRatioChanged REVISION 1) Q_PROPERTY(OptimizationHints optimizationHints READ optimizationHints WRITE setOptimizationHints NOTIFY optimizationHintsChanged REVISION 1) + Q_PROPERTY(bool polar READ isPolar WRITE setPolar NOTIFY polarChanged REVISION 2) public: enum SelectionFlag { @@ -193,6 +194,9 @@ public: void setOptimizationHints(OptimizationHints hints); OptimizationHints optimizationHints() const; + void setPolar(bool enable); + bool isPolar() const; + public slots: virtual void handleAxisXChanged(QAbstract3DAxis *axis) = 0; virtual void handleAxisYChanged(QAbstract3DAxis *axis) = 0; @@ -230,6 +234,7 @@ signals: Q_REVISION(1) void orthoProjectionChanged(bool enabled); Q_REVISION(1) void aspectRatioChanged(qreal ratio); Q_REVISION(1) void optimizationHintsChanged(AbstractDeclarative::OptimizationHints hints); + Q_REVISION(2) void polarChanged(bool enabled); private: QPointer m_controller; diff --git a/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp b/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp index 09780dc5..c4c0bc70 100644 --- a/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp +++ b/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp @@ -106,6 +106,12 @@ void QtDataVisualizationQml2Plugin::registerTypes(const char *uri) // New metatypes qRegisterMetaType("QAbstract3DGraph::ElementType"); + + // QtDataVisualization 1.2 + + // New revisions + qmlRegisterUncreatableType(uri, 1, 2, "AbstractGraph3D", + QLatin1String("Trying to create uncreatable: AbstractGraph3D.")); } QT_END_NAMESPACE_DATAVISUALIZATION -- cgit v1.2.3