summaryrefslogtreecommitdiffstats
path: root/src/datavisualization
diff options
context:
space:
mode:
authorMika Salmela <mika.salmela@digia.com>2014-06-05 10:32:24 +0300
committerMika Salmela <mika.salmela@digia.com>2014-06-05 10:36:02 +0300
commit2299481acb0b36d76414ed9e0ae2b2d110ff13d8 (patch)
treec7e4412dcea928b428a2abb7116009b3a4fbce43 /src/datavisualization
parentf8e9d36ce868adaade5aaa6769ba681763d16874 (diff)
Scatter perf improvement
Task-number: QTRD-3148 Change-Id: I2c9efa84184819aaac123ee29685bc3a9e35bfe6 Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com> Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
Diffstat (limited to 'src/datavisualization')
-rw-r--r--src/datavisualization/data/qabstract3dseries.cpp24
-rw-r--r--src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc19
-rw-r--r--src/datavisualization/engine/abstract3dcontroller.cpp22
-rw-r--r--src/datavisualization/engine/abstract3dcontroller_p.h7
-rw-r--r--src/datavisualization/engine/abstract3drenderer.cpp6
-rw-r--r--src/datavisualization/engine/abstract3drenderer_p.h2
-rw-r--r--src/datavisualization/engine/drawer.cpp17
-rw-r--r--src/datavisualization/engine/drawer_p.h2
-rw-r--r--src/datavisualization/engine/qabstract3dgraph.cpp36
-rw-r--r--src/datavisualization/engine/qabstract3dgraph.h13
-rw-r--r--src/datavisualization/engine/scatter3drenderer.cpp268
-rw-r--r--src/datavisualization/engine/scatter3drenderer_p.h1
-rw-r--r--src/datavisualization/engine/scatterseriesrendercache.cpp10
-rw-r--r--src/datavisualization/engine/scatterseriesrendercache_p.h15
-rw-r--r--src/datavisualization/utils/objecthelper.cpp30
-rw-r--r--src/datavisualization/utils/objecthelper_p.h10
-rw-r--r--src/datavisualization/utils/scatterobjectbufferhelper.cpp226
-rw-r--r--src/datavisualization/utils/scatterobjectbufferhelper_p.h51
-rw-r--r--src/datavisualization/utils/scatterpointbufferhelper.cpp113
-rw-r--r--src/datavisualization/utils/scatterpointbufferhelper_p.h62
-rw-r--r--src/datavisualization/utils/utils.pri8
21 files changed, 879 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