diff options
23 files changed, 904 insertions, 63 deletions
diff --git a/src/datavisualization/data/qabstract3dseries.cpp b/src/datavisualization/data/qabstract3dseries.cpp index 48fbc69a..f8fe6b4f 100644 --- a/src/datavisualization/data/qabstract3dseries.cpp +++ b/src/datavisualization/data/qabstract3dseries.cpp @@ -710,32 +710,48 @@ void QAbstract3DSeriesPrivate::setMesh(QAbstract3DSeries::Mesh mesh) { m_mesh = mesh; m_changeTracker.meshChanged = true; - if (m_controller) + if (m_controller) { m_controller->markSeriesVisualsDirty(); + + if (m_controller->optimizationHints().testFlag(QAbstract3DGraph::OptimizationStatic)) + m_controller->markDataDirty(); + } } void QAbstract3DSeriesPrivate::setMeshSmooth(bool enable) { m_meshSmooth = enable; m_changeTracker.meshSmoothChanged = true; - if (m_controller) + if (m_controller) { m_controller->markSeriesVisualsDirty(); + + if (m_controller->optimizationHints().testFlag(QAbstract3DGraph::OptimizationStatic)) + m_controller->markDataDirty(); + } } void QAbstract3DSeriesPrivate::setMeshRotation(const QQuaternion &rotation) { m_meshRotation = rotation; m_changeTracker.meshRotationChanged = true; - if (m_controller) + if (m_controller) { m_controller->markSeriesVisualsDirty(); + + if (m_controller->optimizationHints().testFlag(QAbstract3DGraph::OptimizationStatic)) + m_controller->markDataDirty(); + } } void QAbstract3DSeriesPrivate::setUserDefinedMesh(const QString &meshFile) { m_userDefinedMesh = meshFile; m_changeTracker.userDefinedMeshChanged = true; - if (m_controller) + if (m_controller) { m_controller->markSeriesVisualsDirty(); + + if (m_controller->optimizationHints().testFlag(QAbstract3DGraph::OptimizationStatic)) + m_controller->markDataDirty(); + } } void QAbstract3DSeriesPrivate::setColorStyle(Q3DTheme::ColorStyle style) diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc index 89d38a3d..ba3173b0 100644 --- a/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc +++ b/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc @@ -28,8 +28,9 @@ Note that this type is uncreatable, but contains properties that are shared between the 3D visualizations. - For AbstractGraph3D enums, see \l QAbstract3DGraph::SelectionFlag, - \l QAbstract3DGraph::ShadowQuality, and \l{QAbstract3DGraph::ElementType}. + For AbstractGraph3D enums, see \l{QAbstract3DGraph::SelectionFlag}, + \l{QAbstract3DGraph::ShadowQuality}, \l{QAbstract3DGraph::ElementType}, and + \l{QAbstract3DGraph::OptimizationHint}. \sa Bars3D, Scatter3D, Surface3D, {Qt Data Visualization C++ Classes} */ @@ -286,3 +287,17 @@ * * \note Has no effect on Bars3D. */ + +/*! + * \qmlproperty AbstractGraph3D.OptimizationHints AbstractGraph3D::optimizationHints + * \since Qt Data Visualization 1.1 + * + * Defines if the rendering optimization is default or static. Default mode provides the full feature set at + * reasonable performance. Static is a beta level feature and currently supports only a subset of the + * features on the Scatter graph. Missing features are object gradient for mesh objects, both gradients + * for points, and diffuse and specular color on rotations. At this point static is intended just for + * introducing a new feature. It optimizes graph rendering and is ideal for large non-changing data + * sets. It is slower with dynamic data changes and item rotations. Selection is not optimized, so using it + * with massive data sets is not advisable. + * Defaults to \c{OptimizationDefault} + */ diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp index df63ea42..8658d463 100644 --- a/src/datavisualization/engine/abstract3dcontroller.cpp +++ b/src/datavisualization/engine/abstract3dcontroller.cpp @@ -38,6 +38,7 @@ Abstract3DController::Abstract3DController(QRect initialViewport, Q3DScene *scen m_shadowQuality(QAbstract3DGraph::ShadowQualityMedium), m_useOrthoProjection(false), m_aspectRatio(2.0f), + m_optimizationHints(QAbstract3DGraph::OptimizationDefault), m_scene(scene), m_activeInputHandler(0), m_axisX(0), @@ -195,6 +196,11 @@ void Abstract3DController::synchDataToRenderer() m_changeTracker.aspectRatioChanged = false; } + if (m_changeTracker.optimizationHintChanged) { + m_renderer->updateOptimizationHint(m_optimizationHints); + m_changeTracker.optimizationHintChanged = false; + } + if (m_changeTracker.axisXFormatterChanged) { m_changeTracker.axisXFormatterChanged = false; if (m_axisX->type() & QAbstract3DAxis::AxisTypeValue) { @@ -862,6 +868,22 @@ QAbstract3DGraph::ShadowQuality Abstract3DController::shadowQuality() const return m_shadowQuality; } +void Abstract3DController::setOptimizationHints(QAbstract3DGraph::OptimizationHints hints) +{ + if (hints != m_optimizationHints) { + m_optimizationHints = hints; + m_changeTracker.optimizationHintChanged = true; + m_isDataDirty = true; + emit optimizationHintsChanged(hints); + emitNeedRender(); + } +} + +QAbstract3DGraph::OptimizationHints Abstract3DController::optimizationHints() const +{ + return m_optimizationHints; +} + bool Abstract3DController::shadowsSupported() const { #if defined(QT_OPENGL_ES_2) diff --git a/src/datavisualization/engine/abstract3dcontroller_p.h b/src/datavisualization/engine/abstract3dcontroller_p.h index f7e8967d..0e4d1add 100644 --- a/src/datavisualization/engine/abstract3dcontroller_p.h +++ b/src/datavisualization/engine/abstract3dcontroller_p.h @@ -51,6 +51,7 @@ struct Abstract3DChangeBitField { bool themeChanged : 1; bool shadowQualityChanged : 1; bool selectionModeChanged : 1; + bool optimizationHintChanged : 1; bool axisXTypeChanged : 1; bool axisYTypeChanged : 1; bool axisZTypeChanged : 1; @@ -94,6 +95,7 @@ struct Abstract3DChangeBitField { themeChanged(true), shadowQualityChanged(true), selectionModeChanged(true), + optimizationHintChanged(true), axisXTypeChanged(true), axisYTypeChanged(true), axisZTypeChanged(true), @@ -155,6 +157,7 @@ private: QAbstract3DGraph::ShadowQuality m_shadowQuality; bool m_useOrthoProjection; float m_aspectRatio; + QAbstract3DGraph::OptimizationHints m_optimizationHints; protected: Q3DScene *m_scene; @@ -231,6 +234,9 @@ public: virtual QAbstract3DGraph::ShadowQuality shadowQuality() const; virtual bool shadowsSupported() const; + void setOptimizationHints(QAbstract3DGraph::OptimizationHints hints); + QAbstract3DGraph::OptimizationHints optimizationHints() const; + bool isSlicingActive() const; void setSlicingActive(bool isSlicing); @@ -339,6 +345,7 @@ signals: void currentFpsChanged(qreal fps); void orthoProjectionChanged(bool enabled); void aspectRatioChanged(float ratio); + void optimizationHintsChanged(QAbstract3DGraph::OptimizationHints hints); protected: virtual QAbstract3DAxis *createDefaultAxis(QAbstract3DAxis::AxisOrientation orientation); diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp index 18719483..5d97a6ca 100644 --- a/src/datavisualization/engine/abstract3drenderer.cpp +++ b/src/datavisualization/engine/abstract3drenderer.cpp @@ -35,6 +35,7 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller) m_cachedShadowQuality(QAbstract3DGraph::ShadowQualityMedium), m_autoScaleAdjustment(1.0f), m_cachedSelectionMode(QAbstract3DGraph::SelectionNone), + m_cachedOptimizationHint(QAbstract3DGraph::OptimizationDefault), m_textureHelper(0), m_cachedScene(new Q3DScene()), m_selectionDirty(true), @@ -286,6 +287,11 @@ void Abstract3DRenderer::updateAspectRatio(float ratio) updateCustomItemPositions(); } +void Abstract3DRenderer::updateOptimizationHint(QAbstract3DGraph::OptimizationHints hint) +{ + m_cachedOptimizationHint = hint; +} + void Abstract3DRenderer::handleResize() { if (m_primarySubViewport.width() == 0 || m_primarySubViewport.height() == 0) diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h index b8aad730..0dfc7367 100644 --- a/src/datavisualization/engine/abstract3drenderer_p.h +++ b/src/datavisualization/engine/abstract3drenderer_p.h @@ -75,6 +75,7 @@ public: virtual void updateTheme(Q3DTheme *theme); virtual void updateSelectionMode(QAbstract3DGraph::SelectionFlags newMode); + virtual void updateOptimizationHint(QAbstract3DGraph::OptimizationHints hint); virtual void updateScene(Q3DScene *scene); virtual void updateTextures() = 0; virtual void initSelectionBuffer() = 0; @@ -194,6 +195,7 @@ protected: GLfloat m_autoScaleAdjustment; QAbstract3DGraph::SelectionFlags m_cachedSelectionMode; + QAbstract3DGraph::OptimizationHints m_cachedOptimizationHint; AxisRenderCache m_axisCacheX; AxisRenderCache m_axisCacheY; diff --git a/src/datavisualization/engine/drawer.cpp b/src/datavisualization/engine/drawer.cpp index 8a8df4fd..b8726840 100644 --- a/src/datavisualization/engine/drawer.cpp +++ b/src/datavisualization/engine/drawer.cpp @@ -22,6 +22,7 @@ #include "utils_p.h" #include "texturehelper_p.h" #include "abstract3drenderer_p.h" +#include "scatterpointbufferhelper_p.h" #include <QtGui/QMatrix4x4> #include <QtCore/qmath.h> @@ -205,6 +206,22 @@ void Drawer::drawPoint(ShaderHelper *shader) glDisableVertexAttribArray(shader->posAtt()); } +void Drawer::drawPoints(ShaderHelper *shader, ScatterPointBufferHelper *object) +{ + // 1st attribute buffer : vertices + glEnableVertexAttribArray(shader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, object->pointBuf()); + glVertexAttribPointer(shader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void*)0); + + // Draw the points + glDrawArrays(GL_POINTS, 0, object->indexCount()); + + // Free buffers + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(shader->posAtt()); +} + void Drawer::drawLine(ShaderHelper *shader) { // Draw a single line diff --git a/src/datavisualization/engine/drawer_p.h b/src/datavisualization/engine/drawer_p.h index 966ccb85..ffcea315 100644 --- a/src/datavisualization/engine/drawer_p.h +++ b/src/datavisualization/engine/drawer_p.h @@ -44,6 +44,7 @@ class SurfaceObject; class TextureHelper; class Q3DCamera; class Abstract3DRenderer; +class ScatterPointBufferHelper; class Drawer : public QObject, public QOpenGLFunctions { @@ -78,6 +79,7 @@ public: void drawSelectionObject(ShaderHelper *shader, AbstractObjectHelper *object); void drawSurfaceGrid(ShaderHelper *shader, SurfaceObject *object); void drawPoint(ShaderHelper *shader); + void drawPoints(ShaderHelper *shader, ScatterPointBufferHelper *object); void drawLine(ShaderHelper *shader); void drawLabel(const AbstractRenderItem &item, const LabelItem &labelItem, const QMatrix4x4 &viewmatrix, const QMatrix4x4 &projectionmatrix, diff --git a/src/datavisualization/engine/qabstract3dgraph.cpp b/src/datavisualization/engine/qabstract3dgraph.cpp index 71ef7dbb..dabec744 100644 --- a/src/datavisualization/engine/qabstract3dgraph.cpp +++ b/src/datavisualization/engine/qabstract3dgraph.cpp @@ -140,6 +140,18 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION */ /*! + \enum QAbstract3DGraph::OptimizationHint + \since Qt Data Visualization 1.1 + + The optimization hint for rendering. + + \value OptimizationDefault + Provides the full feature set at a reasonable performance. + \value OptimizationStatic + Beta level feature. Optimizes the rendering of static data sets at the expense of some features. +*/ + +/*! * \internal */ QAbstract3DGraph::QAbstract3DGraph(QAbstract3DGraphPrivate *d, const QSurfaceFormat *format, @@ -612,6 +624,28 @@ qreal QAbstract3DGraph::aspectRatio() const } /*! + * \property QAbstract3DGraph::optimizationHints + * + * Defines if the rendering optimization is default or static. Default mode provides the full feature set at + * reasonable performance. Static is a beta level feature and currently supports only a subset of the + * features on the Scatter graph. Missing features are object gradient for mesh objects, both gradients + * for points, and diffuse and specular color on rotations. At this point static is intended just for + * introducing a new feature. It optimizes graph rendering and is ideal for large non-changing data + * sets. It is slower with dynamic data changes and item rotations. Selection is not optimized, so using it + * with massive data sets is not advisable. + * Defaults to \c{OptimizationDefault}. + */ +void QAbstract3DGraph::setOptimizationHints(OptimizationHints hints) +{ + d_ptr->m_visualController->setOptimizationHints(hints); +} + +QAbstract3DGraph::OptimizationHints QAbstract3DGraph::optimizationHints() const +{ + return d_ptr->m_visualController->optimizationHints(); +} + +/*! * \internal */ bool QAbstract3DGraph::event(QEvent *event) @@ -736,6 +770,8 @@ void QAbstract3DGraphPrivate::setVisualController(Abstract3DController *controll &QAbstract3DGraph::selectionModeChanged); QObject::connect(m_visualController, &Abstract3DController::shadowQualityChanged, q_ptr, &QAbstract3DGraph::shadowQualityChanged); + QObject::connect(m_visualController, &Abstract3DController::optimizationHintsChanged, q_ptr, + &QAbstract3DGraph::optimizationHintsChanged); QObject::connect(m_visualController, &Abstract3DController::elementSelected, q_ptr, &QAbstract3DGraph::selectedElementChanged); diff --git a/src/datavisualization/engine/qabstract3dgraph.h b/src/datavisualization/engine/qabstract3dgraph.h index 2d4f18da..59f61aae 100644 --- a/src/datavisualization/engine/qabstract3dgraph.h +++ b/src/datavisualization/engine/qabstract3dgraph.h @@ -38,6 +38,7 @@ class QT_DATAVISUALIZATION_EXPORT QAbstract3DGraph : public QWindow, protected Q Q_ENUMS(ShadowQuality) Q_ENUMS(ElementType) Q_FLAGS(SelectionFlag SelectionFlags) + Q_FLAGS(OptimizationHint OptimizationHints) Q_PROPERTY(QAbstract3DInputHandler* activeInputHandler READ activeInputHandler WRITE setActiveInputHandler NOTIFY activeInputHandlerChanged) Q_PROPERTY(Q3DTheme* activeTheme READ activeTheme WRITE setActiveTheme NOTIFY activeThemeChanged) Q_PROPERTY(SelectionFlags selectionMode READ selectionMode WRITE setSelectionMode NOTIFY selectionModeChanged) @@ -48,6 +49,7 @@ class QT_DATAVISUALIZATION_EXPORT QAbstract3DGraph : public QWindow, protected Q Q_PROPERTY(bool orthoProjection READ isOrthoProjection WRITE setOrthoProjection NOTIFY orthoProjectionChanged) 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) protected: explicit QAbstract3DGraph(QAbstract3DGraphPrivate *d, const QSurfaceFormat *format, @@ -87,6 +89,12 @@ public: ElementCustomItem }; + enum OptimizationHint { + OptimizationDefault = 0, + OptimizationStatic = 1 + }; + Q_DECLARE_FLAGS(OptimizationHints, OptimizationHint) + public: virtual ~QAbstract3DGraph(); @@ -139,6 +147,9 @@ public: void setAspectRatio(qreal ratio); qreal aspectRatio() const; + void setOptimizationHints(OptimizationHints hints); + OptimizationHints optimizationHints() const; + protected: bool event(QEvent *event); void resizeEvent(QResizeEvent *event); @@ -161,6 +172,7 @@ signals: void currentFpsChanged(qreal fps); void orthoProjectionChanged(bool enabled); void aspectRatioChanged(qreal ratio); + void optimizationHintsChanged(QAbstract3DGraph::OptimizationHints hints); private: Q_DISABLE_COPY(QAbstract3DGraph) @@ -171,6 +183,7 @@ private: friend class Q3DSurface; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstract3DGraph::SelectionFlags) +Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstract3DGraph::OptimizationHints) QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp index 9a93a7ca..6142f237 100644 --- a/src/datavisualization/engine/scatter3drenderer.cpp +++ b/src/datavisualization/engine/scatter3drenderer.cpp @@ -22,6 +22,8 @@ #include "texturehelper_p.h" #include "utils_p.h" #include "scatterseriesrendercache_p.h" +#include "scatterobjectbufferhelper_p.h" +#include "scatterpointbufferhelper_p.h" #include <QtCore/qmath.h> @@ -63,6 +65,7 @@ Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller) m_scaleFactor(0), m_selectedItemIndex(Scatter3DController::invalidSelectionIndex()), m_selectedSeriesCache(0), + m_oldSelectedSeriesCache(0), m_areaSize(QSizeF(0.0, 0.0)), m_dotSizeScale(1.0f), m_hasHeightAdjustmentChanged(true), @@ -163,6 +166,39 @@ void Scatter3DRenderer::updateData() defaultMaxSize)); } + if (m_cachedOptimizationHint.testFlag(QAbstract3DGraph::OptimizationStatic)) { + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + ScatterSeriesRenderCache *cache = static_cast<ScatterSeriesRenderCache *>(baseCache); + if (cache->isVisible()) { + ScatterRenderItemArray &renderArray = cache->renderArray(); + const int renderArraySize = renderArray.size(); + + if (cache->mesh() == QAbstract3DSeries::MeshPoint) { + ScatterPointBufferHelper *points = cache->bufferPoints(); + if (!points) { + points = new ScatterPointBufferHelper(); + cache->setBufferPoints(points); + } + points->load(cache); + } else { + ScatterObjectBufferHelper *object = cache->bufferObject(); + if (!object) { + object = new ScatterObjectBufferHelper(); + cache->setBufferObject(object); + } + if (renderArraySize != cache->oldArraySize() + || cache->object()->objectFile() != cache->oldMeshFileName()) { + object->fullLoad(cache, m_dotSizeScale); + cache->setOldArraySize(renderArraySize); + cache->setOldMeshFileName(cache->object()->objectFile()); + } else { + object->update(cache, m_dotSizeScale); + } + } + } + } + } + updateSelectedItem(m_selectedItemIndex, m_selectedSeriesCache ? m_selectedSeriesCache->series() : 0); } @@ -291,6 +327,9 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) GLfloat backgroundRotation = 0; GLfloat selectedItemSize = 0.0f; + // Get the optimization flag + const bool optimizationDefault = !m_cachedOptimizationHint.testFlag(QAbstract3DGraph::OptimizationStatic); + const Q3DCamera *activeCamera = m_cachedScene->activeCamera(); QVector4D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor()); @@ -401,19 +440,25 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) glPointSize(itemSize * 100.0f * m_shadowQualityMultiplier); } QVector3D modelScaler(itemSize, itemSize, itemSize); - for (int dot = 0; dot < renderArraySize; dot++) { + + int loopCount = 1; + if (optimizationDefault) + loopCount = renderArraySize; + for (int dot = 0; dot < loopCount; dot++) { const ScatterRenderItem &item = renderArray.at(dot); - if (!item.isVisible()) + if (!item.isVisible() && optimizationDefault) continue; QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; - modelMatrix.translate(item.translation()); - if (!drawingPoints) { - if (!seriesRotation.isIdentity() || !item.rotation().isIdentity()) - modelMatrix.rotate(seriesRotation * item.rotation()); - modelMatrix.scale(modelScaler); + if (optimizationDefault) { + modelMatrix.translate(item.translation()); + if (!drawingPoints) { + if (!seriesRotation.isIdentity() || !item.rotation().isIdentity()) + modelMatrix.rotate(seriesRotation * item.rotation()); + modelMatrix.scale(modelScaler); + } } MVPMatrix = depthProjectionViewMatrix * modelMatrix; @@ -421,26 +466,51 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix); if (drawingPoints) { - m_drawer->drawPoint(m_depthShader); + if (optimizationDefault) + m_drawer->drawPoint(m_depthShader); + else + m_drawer->drawPoints(m_depthShader, cache->bufferPoints()); } else { - // 1st attribute buffer : vertices - glEnableVertexAttribArray(m_depthShader->posAtt()); - glBindBuffer(GL_ARRAY_BUFFER, dotObj->vertexBuf()); - glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, - (void *)0); - - // Index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dotObj->elementBuf()); - - // Draw the triangles - glDrawElements(GL_TRIANGLES, dotObj->indexCount(), GL_UNSIGNED_SHORT, - (void *)0); - - // Free buffers - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glDisableVertexAttribArray(m_depthShader->posAtt()); + if (optimizationDefault) { + // 1st attribute buffer : vertices + glEnableVertexAttribArray(m_depthShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, dotObj->vertexBuf()); + glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, + (void *)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dotObj->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, dotObj->indexCount(), GL_UNSIGNED_SHORT, + (void *)0); + + // Free buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(m_depthShader->posAtt()); + } else { + ScatterObjectBufferHelper *object = cache->bufferObject(); + // 1st attribute buffer : vertices + glEnableVertexAttribArray(m_depthShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, object->vertexBuf()); + glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, + (void *)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, object->indexCount(), object->indicesType(), + (void *)0); + + // Free buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(m_depthShader->posAtt()); + } } } } @@ -672,24 +742,29 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) baseColor = cache->baseColor(); dotColor = baseColor; } - for (int i = 0; i < renderArraySize; i++) { + int loopCount = 1; + if (optimizationDefault) + loopCount = renderArraySize; + for (int i = 0; i < loopCount; i++) { ScatterRenderItem &item = renderArray[i]; - if (!item.isVisible()) + if (!item.isVisible() && optimizationDefault) continue; QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; QMatrix4x4 itModelMatrix; - modelMatrix.translate(item.translation()); - if (!drawingPoints) { - if (!seriesRotation.isIdentity() || !item.rotation().isIdentity()) { - QQuaternion totalRotation = seriesRotation * item.rotation(); - modelMatrix.rotate(totalRotation); - itModelMatrix.rotate(totalRotation); + if (optimizationDefault) { + modelMatrix.translate(item.translation()); + if (!drawingPoints) { + if (!seriesRotation.isIdentity() || !item.rotation().isIdentity()) { + QQuaternion totalRotation = seriesRotation * item.rotation(); + modelMatrix.rotate(totalRotation); + itModelMatrix.rotate(totalRotation); + } + modelMatrix.scale(modelScaler); + itModelMatrix.scale(modelScaler); } - modelMatrix.scale(modelScaler); - itModelMatrix.scale(modelScaler); } #ifdef SHOW_DEPTH_TEXTURE_SCENE MVPMatrix = depthProjectionViewMatrix * modelMatrix; @@ -712,7 +787,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) } GLfloat lightStrength = m_cachedTheme->lightStrength(); - if (selectedSeries && (m_selectedItemIndex == i)) { + if (optimizationDefault && selectedSeries && (m_selectedItemIndex == i)) { if (useColor) dotColor = cache->singleHighlightColor(); else @@ -751,6 +826,106 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) dotShader->setUniformValue(dotShader->lightS(), lightStrength / 10.0f); // Draw the object + if (optimizationDefault) + m_drawer->drawObject(dotShader, dotObj, gradientTexture, m_depthTexture); + else + m_drawer->drawObject(dotShader, cache->bufferObject(), gradientTexture, m_depthTexture); + } else { + // Draw the object + if (optimizationDefault) + m_drawer->drawPoint(dotShader); + else + m_drawer->drawPoints(dotShader, cache->bufferPoints()); + } + } else +#endif + { + if (!drawingPoints) { + // Set shadowless shader bindings + dotShader->setUniformValue(dotShader->lightS(), lightStrength); + // Draw the object + if (optimizationDefault) + m_drawer->drawObject(dotShader, dotObj, gradientTexture); + else + m_drawer->drawObject(dotShader, cache->bufferObject(), gradientTexture); + } else { + // Draw the object + if (optimizationDefault) + m_drawer->drawPoint(dotShader); + else + m_drawer->drawPoints(dotShader, cache->bufferPoints()); + } + } + } + + // Draw the selected item on static optimization + if (!optimizationDefault && selectedSeries + && m_selectedItemIndex != Scatter3DController::invalidSelectionIndex()) { + ScatterRenderItem &item = renderArray[m_selectedItemIndex]; + ObjectHelper *dotObj = cache->object(); + + QMatrix4x4 modelMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(item.translation()); + if (!drawingPoints) { + if (!seriesRotation.isIdentity() || !item.rotation().isIdentity()) { + QQuaternion totalRotation = seriesRotation * item.rotation(); + modelMatrix.rotate(totalRotation); + itModelMatrix.rotate(totalRotation); + } + modelMatrix.scale(modelScaler); + itModelMatrix.scale(modelScaler); + } + + QMatrix4x4 MVPMatrix; +#ifdef SHOW_DEPTH_TEXTURE_SCENE + MVPMatrix = depthProjectionViewMatrix * modelMatrix; +#else + MVPMatrix = projectionViewMatrix * modelMatrix; +#endif + + if (useColor) + dotColor = cache->singleHighlightColor(); + else + gradientTexture = cache->singleHighlightGradientTexture(); + GLfloat lightStrength = m_cachedTheme->highlightLightStrength(); + // Save the reference to the item to be used on label drawing + selectedItem = &item; + dotSelectionFound = true; + // Save selected item size (adjusted with font size) for selection label + // positioning + selectedItemSize = itemSize + (m_cachedTheme->font().pointSizeF() / 500.0f); + + if (!drawingPoints) { + // Set shader bindings + dotShader->setUniformValue(dotShader->model(), modelMatrix); + dotShader->setUniformValue(dotShader->nModel(), + itModelMatrix.inverted().transposed()); + } + + dotShader->setUniformValue(dotShader->MVP(), MVPMatrix); + if (useColor) { + dotShader->setUniformValue(dotShader->color(), dotColor); + } else if (colorStyle == Q3DTheme::ColorStyleRangeGradient) { + dotShader->setUniformValue(dotShader->gradientMin(), + (item.translation().y() + 1.0f) / 2.0f); + } + + if (!drawingPoints) { + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-0.5f, 1.0f); + } + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + if (!drawingPoints) { + // Set shadow shader bindings + QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + dotShader->setUniformValue(dotShader->depth(), depthMVPMatrix); + dotShader->setUniformValue(dotShader->lightS(), lightStrength / 10.0f); + + // Draw the object m_drawer->drawObject(dotShader, dotObj, gradientTexture, m_depthTexture); } else { // Draw the object @@ -769,6 +944,9 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) m_drawer->drawPoint(dotShader); } } + + if (!drawingPoints) + glDisable(GL_POLYGON_OFFSET_FILL); } } } @@ -1697,10 +1875,24 @@ void Scatter3DRenderer::updateSelectedItem(int index, QScatter3DSeries *series) static_cast<ScatterSeriesRenderCache *>(m_renderCacheList.value(series, 0)); m_selectedItemIndex = Scatter3DController::invalidSelectionIndex(); + if (m_cachedOptimizationHint.testFlag(QAbstract3DGraph::OptimizationStatic) + && m_oldSelectedSeriesCache + && m_oldSelectedSeriesCache->mesh() == QAbstract3DSeries::MeshPoint) { + m_oldSelectedSeriesCache->bufferPoints()->popPoint(); + m_oldSelectedSeriesCache = 0; + } + if (m_selectedSeriesCache) { const ScatterRenderItemArray &renderArray = m_selectedSeriesCache->renderArray(); - if (index < renderArray.size() && index >= 0) + if (index < renderArray.size() && index >= 0) { m_selectedItemIndex = index; + + if (m_cachedOptimizationHint.testFlag(QAbstract3DGraph::OptimizationStatic) + && m_selectedSeriesCache->mesh() == QAbstract3DSeries::MeshPoint) { + m_selectedSeriesCache->bufferPoints()->pushPoint(m_selectedItemIndex); + m_oldSelectedSeriesCache = m_selectedSeriesCache; + } + } } } diff --git a/src/datavisualization/engine/scatter3drenderer_p.h b/src/datavisualization/engine/scatter3drenderer_p.h index b6bafb3b..7f213179 100644 --- a/src/datavisualization/engine/scatter3drenderer_p.h +++ b/src/datavisualization/engine/scatter3drenderer_p.h @@ -72,6 +72,7 @@ private: GLfloat m_scaleFactor; int m_selectedItemIndex; ScatterSeriesRenderCache *m_selectedSeriesCache; + ScatterSeriesRenderCache *m_oldSelectedSeriesCache; QSizeF m_areaSize; GLfloat m_dotSizeScale; bool m_hasHeightAdjustmentChanged; diff --git a/src/datavisualization/engine/scatterseriesrendercache.cpp b/src/datavisualization/engine/scatterseriesrendercache.cpp index 5b2cf1ef..e8888d19 100644 --- a/src/datavisualization/engine/scatterseriesrendercache.cpp +++ b/src/datavisualization/engine/scatterseriesrendercache.cpp @@ -17,6 +17,8 @@ ****************************************************************************/ #include "scatterseriesrendercache_p.h" +#include "scatterobjectbufferhelper_p.h" +#include "scatterpointbufferhelper_p.h" QT_BEGIN_NAMESPACE_DATAVISUALIZATION @@ -24,12 +26,18 @@ ScatterSeriesRenderCache::ScatterSeriesRenderCache(QAbstract3DSeries *series, Abstract3DRenderer *renderer) : SeriesRenderCache(series, renderer), m_itemSize(0.0f), - m_selectionIndexOffset(0) + m_selectionIndexOffset(0), + m_oldRenderArraySize(0), + m_oldMeshFileName(QString()), + m_scatterBufferObj(0), + m_scatterBufferPoints(0) { } ScatterSeriesRenderCache::~ScatterSeriesRenderCache() { + delete m_scatterBufferObj; + delete m_scatterBufferPoints; } void ScatterSeriesRenderCache::cleanup(TextureHelper *texHelper) diff --git a/src/datavisualization/engine/scatterseriesrendercache_p.h b/src/datavisualization/engine/scatterseriesrendercache_p.h index b2e2d55f..490e21fb 100644 --- a/src/datavisualization/engine/scatterseriesrendercache_p.h +++ b/src/datavisualization/engine/scatterseriesrendercache_p.h @@ -36,6 +36,9 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION +class ScatterObjectBufferHelper; +class ScatterPointBufferHelper; + class ScatterSeriesRenderCache : public SeriesRenderCache { public: @@ -50,11 +53,23 @@ public: inline float itemSize() const { return m_itemSize; } inline void setSelectionIndexOffset(int offset) { m_selectionIndexOffset = offset; } inline int selectionIndexOffset() const { return m_selectionIndexOffset; } + inline int oldArraySize() const { return m_oldRenderArraySize; } + inline void setOldArraySize(int size) { m_oldRenderArraySize = size; } + inline const QString &oldMeshFileName() const { return m_oldMeshFileName; } + inline void setOldMeshFileName(const QString &meshFileName) { m_oldMeshFileName = meshFileName; } + inline void setBufferObject(ScatterObjectBufferHelper *object) { m_scatterBufferObj = object; } + inline ScatterObjectBufferHelper *bufferObject() const { return m_scatterBufferObj; } + inline void setBufferPoints(ScatterPointBufferHelper *object) { m_scatterBufferPoints = object; } + inline ScatterPointBufferHelper *bufferPoints() const { return m_scatterBufferPoints; } protected: ScatterRenderItemArray m_renderArray; float m_itemSize; int m_selectionIndexOffset; // Temporarily cached value for selection color calculations + int m_oldRenderArraySize; // Used to detect if full buffer change needed + QString m_oldMeshFileName; // Used to detect if full buffer change needed + ScatterObjectBufferHelper *m_scatterBufferObj; + ScatterPointBufferHelper *m_scatterBufferPoints; }; QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/utils/objecthelper.cpp b/src/datavisualization/utils/objecthelper.cpp index 30f119f2..a66e0f7e 100644 --- a/src/datavisualization/utils/objecthelper.cpp +++ b/src/datavisualization/utils/objecthelper.cpp @@ -118,6 +118,10 @@ void ObjectHelper::load() glDeleteBuffers(1, &m_uvbuffer); glDeleteBuffers(1, &m_normalbuffer); glDeleteBuffers(1, &m_elementbuffer); + m_indices.clear(); + m_indexedVertices.clear(); + m_indexedUVs.clear(); + m_indexedNormals.clear(); } QVector<QVector3D> vertices; QVector<QVector2D> uvs; @@ -127,36 +131,32 @@ void ObjectHelper::load() qFatal("loading failed"); // Index vertices - QVector<unsigned short> indices; - QVector<QVector3D> indexed_vertices; - QVector<QVector2D> indexed_uvs; - QVector<QVector3D> indexed_normals; - VertexIndexer::indexVBO(vertices, uvs, normals, indices, indexed_vertices, indexed_uvs, - indexed_normals); + VertexIndexer::indexVBO(vertices, uvs, normals, m_indices, m_indexedVertices, m_indexedUVs, + m_indexedNormals); - m_indexCount = indices.size(); + m_indexCount = m_indices.size(); glGenBuffers(1, &m_vertexbuffer); glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer); - glBufferData(GL_ARRAY_BUFFER, indexed_vertices.size() * sizeof(QVector3D), - &indexed_vertices.at(0), + glBufferData(GL_ARRAY_BUFFER, m_indexedVertices.size() * sizeof(QVector3D), + &m_indexedVertices.at(0), GL_STATIC_DRAW); glGenBuffers(1, &m_normalbuffer); glBindBuffer(GL_ARRAY_BUFFER, m_normalbuffer); - glBufferData(GL_ARRAY_BUFFER, indexed_normals.size() * sizeof(QVector3D), - &indexed_normals.at(0), + glBufferData(GL_ARRAY_BUFFER, m_indexedNormals.size() * sizeof(QVector3D), + &m_indexedNormals.at(0), GL_STATIC_DRAW); glGenBuffers(1, &m_uvbuffer); glBindBuffer(GL_ARRAY_BUFFER, m_uvbuffer); - glBufferData(GL_ARRAY_BUFFER, indexed_uvs.size() * sizeof(QVector2D), - &indexed_uvs.at(0), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, m_indexedUVs.size() * sizeof(QVector2D), + &m_indexedUVs.at(0), GL_STATIC_DRAW); glGenBuffers(1, &m_elementbuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementbuffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned short), - &indices.at(0), GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indices.size() * sizeof(unsigned short), + &m_indices.at(0), GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); diff --git a/src/datavisualization/utils/objecthelper_p.h b/src/datavisualization/utils/objecthelper_p.h index 1c3217b7..c84f53bd 100644 --- a/src/datavisualization/utils/objecthelper_p.h +++ b/src/datavisualization/utils/objecthelper_p.h @@ -46,15 +46,23 @@ public: static void resetObjectHelper(const Abstract3DRenderer *cacheId, ObjectHelper *&obj, const QString &meshFile); static void releaseObjectHelper(const Abstract3DRenderer *cacheId, ObjectHelper *&obj); - inline const QString &objectFile() { return m_objectFile; } + inline const QVector<unsigned short> &indices() const { return m_indices; } + inline const QVector<QVector3D> &indexedvertices() const { return m_indexedVertices; } + inline const QVector<QVector2D> &indexedUVs() const { return m_indexedUVs; } + inline const QVector<QVector3D> &indexedNormals() const { return m_indexedNormals; } + private: static ObjectHelper *getObjectHelper(const Abstract3DRenderer *cacheId, const QString &objectFile); void load(); QString m_objectFile; + QVector<unsigned short> m_indices; + QVector<QVector3D> m_indexedVertices; + QVector<QVector2D> m_indexedUVs; + QVector<QVector3D> m_indexedNormals; }; QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/utils/scatterobjectbufferhelper.cpp b/src/datavisualization/utils/scatterobjectbufferhelper.cpp new file mode 100644 index 00000000..123588f1 --- /dev/null +++ b/src/datavisualization/utils/scatterobjectbufferhelper.cpp @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 "scatterobjectbufferhelper_p.h" +#include "objecthelper_p.h" +#include <QtGui/QVector2D> +#include <QtGui/QMatrix4x4> + +QT_BEGIN_NAMESPACE_DATAVISUALIZATION + +const GLfloat itemScaler = 3.0f; + +ScatterObjectBufferHelper::ScatterObjectBufferHelper() +{ + m_indicesType = GL_UNSIGNED_INT; +} + +ScatterObjectBufferHelper::~ScatterObjectBufferHelper() +{ +} + +void ScatterObjectBufferHelper::fullLoad(ScatterSeriesRenderCache *cache, qreal dotScale) +{ + initializeOpenGLFunctions(); + + ObjectHelper *dotObj = cache->object(); + ScatterRenderItemArray &renderArray = cache->renderArray(); + const uint renderArraySize = renderArray.size(); + uint itemCount = renderArraySize; + QQuaternion seriesRotation(cache->meshRotation()); + + if (m_meshDataLoaded) { + // Delete old data + glDeleteBuffers(1, &m_vertexbuffer); + glDeleteBuffers(1, &m_uvbuffer); + glDeleteBuffers(1, &m_normalbuffer); + glDeleteBuffers(1, &m_elementbuffer); + } + + // Index vertices + const QVector<unsigned short> indices = dotObj->indices(); + const QVector<QVector3D> indexed_vertices = dotObj->indexedvertices(); + const QVector<QVector2D> indexed_uvs = dotObj->indexedUVs(); + const QVector<QVector3D> indexed_normals = dotObj->indexedNormals(); + int indicesCount = indices.count(); + int verticeCount = indexed_vertices.count(); + int uvsCount = indexed_uvs.count(); + int normalsCount = indexed_normals.count(); + + float itemSize = cache->itemSize() / itemScaler; + if (itemSize == 0.0f) + itemSize = dotScale; + QVector3D modelScaler(itemSize, itemSize, itemSize); + QMatrix4x4 modelMatrix; + if (!seriesRotation.isIdentity()) { + QMatrix4x4 matrix; + matrix.rotate(seriesRotation); + modelMatrix = matrix.transposed(); + } + modelMatrix.scale(modelScaler); + + QVector<QVector3D> scaled_vertices; + scaled_vertices.resize(verticeCount); + for (int i = 0; i < verticeCount; i++) + scaled_vertices[i] = indexed_vertices[i] * modelMatrix; + + QVector<GLuint> buffered_indices; + QVector<QVector3D> buffered_vertices; + QVector<QVector2D> buffered_uvs; + QVector<QVector3D> buffered_normals; + + buffered_indices.resize(indicesCount * renderArraySize); + buffered_vertices.resize(verticeCount * renderArraySize); + buffered_uvs.resize(uvsCount * renderArraySize); + buffered_normals.resize(normalsCount * renderArraySize); + uint pos = 0; + for (uint i = 0; i < renderArraySize; i++) { + ScatterRenderItem &item = renderArray[i]; + if (!item.isVisible()) { + itemCount--; + continue; + } + + int offset = pos * verticeCount; + if (item.rotation().isIdentity()) { + for (int j = 0; j < verticeCount; j++) + buffered_vertices[j + offset] = scaled_vertices[j] + item.translation(); + } else { + QMatrix4x4 matrix; + matrix.rotate(seriesRotation * item.rotation()); + modelMatrix = matrix.transposed(); + modelMatrix.scale(modelScaler); + + for (int j = 0; j < verticeCount; j++) + buffered_vertices[j + offset] = indexed_vertices[j] * modelMatrix + + item.translation(); + } + + offset = pos * normalsCount; + for (int j = 0; j < normalsCount; j++) + buffered_normals[j + offset] = indexed_normals[j]; + + offset = pos * uvsCount; + for (int j = 0; j < uvsCount; j++) + buffered_uvs[j + offset] = indexed_uvs[j]; + + int offsetVertice = i * verticeCount; + offset = pos * indicesCount; + for (int j = 0; j < indicesCount; j++) { + buffered_indices[j + offset] = GLuint(indices[j] + offsetVertice); + } + + pos++; + } + + m_indexCount = indicesCount * itemCount; + + glGenBuffers(1, &m_vertexbuffer); + glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer); + glBufferData(GL_ARRAY_BUFFER, verticeCount * itemCount * sizeof(QVector3D), + &buffered_vertices.at(0), + GL_STATIC_DRAW); + + glGenBuffers(1, &m_normalbuffer); + glBindBuffer(GL_ARRAY_BUFFER, m_normalbuffer); + glBufferData(GL_ARRAY_BUFFER, normalsCount * itemCount * sizeof(QVector3D), + &buffered_normals.at(0), + GL_STATIC_DRAW); + + glGenBuffers(1, &m_uvbuffer); + glBindBuffer(GL_ARRAY_BUFFER, m_uvbuffer); + glBufferData(GL_ARRAY_BUFFER, uvsCount * itemCount * sizeof(QVector2D), + &buffered_uvs.at(0), GL_STATIC_DRAW); + + glGenBuffers(1, &m_elementbuffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementbuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesCount * itemCount * sizeof(GLint), + &buffered_indices.at(0), GL_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + m_meshDataLoaded = true; +} + +void ScatterObjectBufferHelper::update(ScatterSeriesRenderCache *cache, qreal dotScale) +{ + initializeOpenGLFunctions(); + + ObjectHelper *dotObj = cache->object(); + ScatterRenderItemArray &renderArray = cache->renderArray(); + const int renderArraySize = renderArray.size(); + QQuaternion seriesRotation(cache->meshRotation()); + + // Index vertices + const QVector<QVector3D> indexed_vertices = dotObj->indexedvertices(); + int verticeCount = indexed_vertices.count(); + + float itemSize = cache->itemSize() / itemScaler; + if (itemSize == 0.0f) + itemSize = dotScale; + QVector3D modelScaler(itemSize, itemSize, itemSize); + QMatrix4x4 modelMatrix; + if (!seriesRotation.isIdentity()) { + QMatrix4x4 matrix; + matrix.rotate(seriesRotation); + modelMatrix = matrix.transposed(); + } + modelMatrix.scale(modelScaler); + + QVector<QVector3D> scaled_vertices; + scaled_vertices.resize(verticeCount); + for (int i = 0; i < verticeCount; i++) + scaled_vertices[i] = indexed_vertices[i] * modelMatrix; + + QVector<QVector3D> buffered_vertices; + + buffered_vertices.resize(verticeCount * renderArraySize); + for (int i = 0; i < renderArraySize; i++) { + ScatterRenderItem &item = renderArray[i]; + if (!item.isVisible()) + continue; + + const int offset = i * verticeCount; + if (item.rotation().isIdentity()) { + for (int j = 0; j < verticeCount; j++) + buffered_vertices[j + offset] = scaled_vertices[j] + item.translation(); + } else { + QMatrix4x4 matrix; + matrix.rotate(seriesRotation * item.rotation()); + modelMatrix = matrix.transposed(); + modelMatrix.scale(modelScaler); + + for (int j = 0; j < verticeCount; j++) + buffered_vertices[j + offset] = indexed_vertices[j] * modelMatrix + + item.translation(); + } + } + + glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer); + glBufferData(GL_ARRAY_BUFFER, buffered_vertices.size() * sizeof(QVector3D), + &buffered_vertices.at(0), + GL_DYNAMIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + m_meshDataLoaded = true; +} + +QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/utils/scatterobjectbufferhelper_p.h b/src/datavisualization/utils/scatterobjectbufferhelper_p.h new file mode 100644 index 00000000..0bba45f5 --- /dev/null +++ b/src/datavisualization/utils/scatterobjectbufferhelper_p.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 SCATTEROBJECTBUFFERHELPER_P_H +#define SCATTEROBJECTBUFFERHELPER_P_H + +#include "datavisualizationglobal_p.h" +#include "abstractobjecthelper_p.h" +#include "scatterseriesrendercache_p.h" +#include <QtGui/QOpenGLFunctions> + +QT_BEGIN_NAMESPACE_DATAVISUALIZATION + +class ScatterObjectBufferHelper : public AbstractObjectHelper +{ +public: + ScatterObjectBufferHelper(); + ~ScatterObjectBufferHelper(); + + void fullLoad(ScatterSeriesRenderCache *cache, qreal dotScale); + void update(ScatterSeriesRenderCache *cache, qreal dotScale); +}; + +QT_END_NAMESPACE_DATAVISUALIZATION + +#endif diff --git a/src/datavisualization/utils/scatterpointbufferhelper.cpp b/src/datavisualization/utils/scatterpointbufferhelper.cpp new file mode 100644 index 00000000..0f290aeb --- /dev/null +++ b/src/datavisualization/utils/scatterpointbufferhelper.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 "scatterpointbufferhelper_p.h" + +QT_BEGIN_NAMESPACE_DATAVISUALIZATION + +const GLfloat itemScaler = 3.0f; +const QVector3D hiddenPos(-1000.0f, -1000.0f, -1000.0f); + +ScatterPointBufferHelper::ScatterPointBufferHelper() + : m_pointbuffer(0), + m_oldRemoveIndex(0), + m_oldRemove(false) +{ + m_indicesType = GL_UNSIGNED_INT; +} + +ScatterPointBufferHelper::~ScatterPointBufferHelper() +{ + if (QOpenGLContext::currentContext()) + glDeleteBuffers(1, &m_pointbuffer); +} + +GLuint ScatterPointBufferHelper::pointBuf() +{ + if (!m_meshDataLoaded) + qFatal("No loaded object"); + return m_pointbuffer; +} + +void ScatterPointBufferHelper::pushPoint(uint pointIndex) +{ + glBindBuffer(GL_ARRAY_BUFFER, m_pointbuffer); + + if (m_oldRemove && m_oldRemoveIndex < pointIndex) { + glBufferSubData(GL_ARRAY_BUFFER, m_oldRemoveIndex * sizeof(QVector3D), + sizeof(QVector3D), &m_bufferedPoints.at(m_oldRemoveIndex)); + } + + glBufferSubData(GL_ARRAY_BUFFER, pointIndex * sizeof(QVector3D), + sizeof(QVector3D), + &hiddenPos); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + m_oldRemoveIndex = pointIndex; + m_oldRemove = true; +} + +void ScatterPointBufferHelper::popPoint() +{ + if (m_oldRemove) { + glBindBuffer(GL_ARRAY_BUFFER, m_pointbuffer); + glBufferSubData(GL_ARRAY_BUFFER, m_oldRemoveIndex * sizeof(QVector3D), + sizeof(QVector3D), &m_bufferedPoints.at(m_oldRemoveIndex)); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + + m_oldRemoveIndex = 0; + m_oldRemove = false; +} + +void ScatterPointBufferHelper::load(ScatterSeriesRenderCache *cache) +{ + initializeOpenGLFunctions(); + + ScatterRenderItemArray &renderArray = cache->renderArray(); + const int renderArraySize = renderArray.size(); + + if (m_meshDataLoaded) { + // Delete old data + glDeleteBuffers(1, &m_pointbuffer); + m_bufferedPoints.clear(); + } + + m_bufferedPoints.resize(renderArraySize); + for (int i = 0; i < renderArraySize; i++) { + ScatterRenderItem &item = renderArray[i]; + if (!item.isVisible()) + m_bufferedPoints[i] = hiddenPos; + else + m_bufferedPoints[i] = item.translation(); + } + + m_indexCount = renderArraySize; + + glGenBuffers(1, &m_pointbuffer); + glBindBuffer(GL_ARRAY_BUFFER, m_pointbuffer); + glBufferData(GL_ARRAY_BUFFER, m_bufferedPoints.size() * sizeof(QVector3D), + &m_bufferedPoints.at(0), + GL_DYNAMIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + m_meshDataLoaded = true; +} + +QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/utils/scatterpointbufferhelper_p.h b/src/datavisualization/utils/scatterpointbufferhelper_p.h new file mode 100644 index 00000000..39903b1a --- /dev/null +++ b/src/datavisualization/utils/scatterpointbufferhelper_p.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2014 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 SCATTERPOINTBUFFERHELPER_P_H +#define SCATTERPOINTBUFFERHELPER_P_H + +#include "datavisualizationglobal_p.h" +#include "abstractobjecthelper_p.h" +#include "scatterseriesrendercache_p.h" +#include <QtGui/QOpenGLFunctions> + +QT_BEGIN_NAMESPACE_DATAVISUALIZATION + +class ScatterPointBufferHelper : public AbstractObjectHelper +{ +public: + ScatterPointBufferHelper(); + ~ScatterPointBufferHelper(); + + GLuint pointBuf(); + + void pushPoint(uint pointIndex); + void popPoint(); + void load(ScatterSeriesRenderCache *cache); + +public: + GLuint m_pointbuffer; + +private: + QVector<QVector3D> m_bufferedPoints; + uint m_oldRemoveIndex; + bool m_oldRemove; +}; + +QT_END_NAMESPACE_DATAVISUALIZATION + +#endif diff --git a/src/datavisualization/utils/utils.pri b/src/datavisualization/utils/utils.pri index 8ce8794e..30bfb156 100644 --- a/src/datavisualization/utils/utils.pri +++ b/src/datavisualization/utils/utils.pri @@ -7,7 +7,9 @@ HEADERS += $$PWD/meshloader_p.h \ $$PWD/utils_p.h \ $$PWD/abstractobjecthelper_p.h \ $$PWD/surfaceobject_p.h \ - $$PWD/qutils.h + $$PWD/qutils.h \ + $$PWD/scatterobjectbufferhelper_p.h \ + $$PWD/scatterpointbufferhelper_p.h SOURCES += $$PWD/meshloader.cpp \ $$PWD/vertexindexer.cpp \ @@ -17,4 +19,6 @@ SOURCES += $$PWD/meshloader.cpp \ $$PWD/texturehelper.cpp \ $$PWD/utils.cpp \ $$PWD/abstractobjecthelper.cpp \ - $$PWD/surfaceobject.cpp + $$PWD/surfaceobject.cpp \ + $$PWD/scatterobjectbufferhelper.cpp \ + $$PWD/scatterpointbufferhelper.cpp diff --git a/src/datavisualizationqml2/abstractdeclarative.cpp b/src/datavisualizationqml2/abstractdeclarative.cpp index 04c41964..a6dee6eb 100644 --- a/src/datavisualizationqml2/abstractdeclarative.cpp +++ b/src/datavisualizationqml2/abstractdeclarative.cpp @@ -699,6 +699,18 @@ qreal AbstractDeclarative::aspectRatio() const return m_controller->aspectRatio(); } +void AbstractDeclarative::setOptimizationHints(OptimizationHints hints) +{ + int intmode = int(hints); + m_controller->setOptimizationHints(QAbstract3DGraph::OptimizationHints(intmode)); +} + +AbstractDeclarative::OptimizationHints AbstractDeclarative::optimizationHints() const +{ + int intmode = int(m_controller->optimizationHints()); + return OptimizationHints(intmode); +} + 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 ce19edd2..ebe8b49c 100644 --- a/src/datavisualizationqml2/abstractdeclarative_p.h +++ b/src/datavisualizationqml2/abstractdeclarative_p.h @@ -56,6 +56,7 @@ class AbstractDeclarative : public QQuickItem Q_ENUMS(RenderingMode) Q_ENUMS(ElementType) Q_FLAGS(SelectionFlag SelectionFlags) + Q_FLAGS(OptimizationHint OptimizationHints) Q_PROPERTY(SelectionFlags selectionMode READ selectionMode WRITE setSelectionMode NOTIFY selectionModeChanged) Q_PROPERTY(ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality NOTIFY shadowQualityChanged) Q_PROPERTY(bool shadowsSupported READ shadowsSupported NOTIFY shadowsSupportedChanged) @@ -70,6 +71,7 @@ class AbstractDeclarative : public QQuickItem Q_PROPERTY(bool orthoProjection READ isOrthoProjection WRITE setOrthoProjection NOTIFY orthoProjectionChanged REVISION 1) 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) public: enum SelectionFlag { @@ -111,6 +113,12 @@ public: RenderIndirect }; + enum OptimizationHint { + OptimizationDefault = 0, + OptimizationStatic = 1 + }; + Q_DECLARE_FLAGS(OptimizationHints, OptimizationHint) + public: explicit AbstractDeclarative(QQuickItem *parent = 0); virtual ~AbstractDeclarative(); @@ -182,6 +190,9 @@ public: void setAspectRatio(qreal ratio); qreal aspectRatio() const; + void setOptimizationHints(OptimizationHints hints); + OptimizationHints optimizationHints() const; + public slots: virtual void handleAxisXChanged(QAbstract3DAxis *axis) = 0; virtual void handleAxisYChanged(QAbstract3DAxis *axis) = 0; @@ -216,6 +227,7 @@ signals: Q_REVISION(1) void selectedElementChanged(QAbstract3DGraph::ElementType type); Q_REVISION(1) void orthoProjectionChanged(bool enabled); Q_REVISION(1) void aspectRatioChanged(qreal ratio); + Q_REVISION(1) void optimizationHintsChanged(QAbstract3DGraph::OptimizationHints hints); private: QPointer<Abstract3DController> m_controller; @@ -236,6 +248,7 @@ private: bool m_runningInDesigner; }; Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractDeclarative::SelectionFlags) +Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractDeclarative::OptimizationHints) QT_END_NAMESPACE_DATAVISUALIZATION |