From 13d1117087e66c77d2eea2f0a046fc556c19cb3c Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Wed, 30 Apr 2014 15:36:19 +0300 Subject: Scatter data changing optimization. No longer reset the entire render item array if single item changes, significantly speeding up this operation. Task-number: QTRD-2190 Change-Id: Ia3de833b761dc6f24acff581ad79668f51c3e9c5 Reviewed-by: Titta Heikkala Reviewed-by: Mika Salmela --- src/datavisualization/engine/bars3drenderer.cpp | 4 +- src/datavisualization/engine/bars3drenderer_p.h | 2 +- .../engine/scatter3dcontroller.cpp | 42 +++++++++++--- .../engine/scatter3dcontroller_p.h | 10 +++- src/datavisualization/engine/scatter3drenderer.cpp | 67 ++++++++++++++-------- src/datavisualization/engine/scatter3drenderer_p.h | 2 + 6 files changed, 91 insertions(+), 36 deletions(-) (limited to 'src/datavisualization') diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp index ec1f0c7e..ab7bb4ca 100644 --- a/src/datavisualization/engine/bars3drenderer.cpp +++ b/src/datavisualization/engine/bars3drenderer.cpp @@ -342,7 +342,7 @@ void Bars3DRenderer::updateRows(const QVector &rows } } -void Bars3DRenderer::updateItems(const QVector &points) +void Bars3DRenderer::updateItems(const QVector &items) { int minRow = m_axisCacheZ.min(); int maxRow = m_axisCacheZ.max(); @@ -352,7 +352,7 @@ void Bars3DRenderer::updateItems(const QVector &po const QBar3DSeries *prevSeries = 0; const QBarDataArray *dataArray = 0; - foreach (Bars3DController::ChangeItem item, points) { + foreach (Bars3DController::ChangeItem item, items) { const int row = item.point.x(); const int col = item.point.y(); if (row < minRow || row > maxRow || col < minCol || col > maxCol) diff --git a/src/datavisualization/engine/bars3drenderer_p.h b/src/datavisualization/engine/bars3drenderer_p.h index ddea546e..8e39ee11 100644 --- a/src/datavisualization/engine/bars3drenderer_p.h +++ b/src/datavisualization/engine/bars3drenderer_p.h @@ -118,7 +118,7 @@ public: void updateSeries(const QList &seriesList); SeriesRenderCache *createNewCache(QAbstract3DSeries *series); void updateRows(const QVector &rows); - void updateItems(const QVector &points); + void updateItems(const QVector &items); void updateScene(Q3DScene *scene); void render(GLuint defaultFboHandle = 0); diff --git a/src/datavisualization/engine/scatter3dcontroller.cpp b/src/datavisualization/engine/scatter3dcontroller.cpp index 05c0efe7..2d38a4a7 100644 --- a/src/datavisualization/engine/scatter3dcontroller.cpp +++ b/src/datavisualization/engine/scatter3dcontroller.cpp @@ -71,6 +71,12 @@ void Scatter3DController::synchDataToRenderer() Abstract3DController::synchDataToRenderer(); // Notify changes to renderer + if (m_changeTracker.itemChanged) { + m_renderer->updateItems(m_changedItems); + m_changeTracker.itemChanged = false; + m_changedItems.clear(); + } + if (m_changeTracker.selectedItemChanged) { m_renderer->updateSelectedItem(m_selectedItem, m_selectedItemSeries); m_changeTracker.selectedItemChanged = false; @@ -144,17 +150,35 @@ void Scatter3DController::handleItemsAdded(int startIndex, int count) void Scatter3DController::handleItemsChanged(int startIndex, int count) { - Q_UNUSED(startIndex) - Q_UNUSED(count) QScatter3DSeries *series = static_cast(sender())->series(); - if (series->isVisible()) { - adjustAxisRanges(); - m_isDataDirty = true; - series->d_ptr->markItemLabelDirty(); + int oldChangeCount = m_changedItems.size(); + if (!oldChangeCount) + m_changedItems.reserve(count); + + for (int i = 0; i < count; i++) { + bool newItem = true; + int candidate = startIndex + i; + for (int j = 0; j < oldChangeCount; j++) { + const ChangeItem &oldChangeItem = m_changedItems.at(j); + if (oldChangeItem.index == candidate && series == oldChangeItem.series) { + newItem = false; + break; + } + } + if (newItem) { + ChangeItem newChangeItem = {series, candidate}; + m_changedItems.append(newChangeItem); + if (series == m_selectedItemSeries && m_selectedItem == candidate) + series->d_ptr->markItemLabelDirty(); + } + } + + if (count) { + m_changeTracker.itemChanged = true; + if (series->isVisible()) + adjustAxisRanges(); + emitNeedRender(); } - if (!m_changedSeriesList.contains(series)) - m_changedSeriesList.append(series); - emitNeedRender(); } void Scatter3DController::handleItemsRemoved(int startIndex, int count) diff --git a/src/datavisualization/engine/scatter3dcontroller_p.h b/src/datavisualization/engine/scatter3dcontroller_p.h index 1194bc3a..db5a95f5 100644 --- a/src/datavisualization/engine/scatter3dcontroller_p.h +++ b/src/datavisualization/engine/scatter3dcontroller_p.h @@ -40,9 +40,11 @@ class QScatter3DSeries; struct Scatter3DChangeBitField { bool selectedItemChanged : 1; + bool itemChanged : 1; Scatter3DChangeBitField() : - selectedItemChanged(true) + selectedItemChanged(true), + itemChanged(false) { } }; @@ -51,8 +53,14 @@ class QT_DATAVISUALIZATION_EXPORT Scatter3DController : public Abstract3DControl { Q_OBJECT +public: + struct ChangeItem { + QScatter3DSeries *series; + int index; + }; private: Scatter3DChangeBitField m_changeTracker; + QVector m_changedItems; // Rendering Scatter3DRenderer *m_renderer; diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp index 3f91e9c3..c1705179 100644 --- a/src/datavisualization/engine/scatter3drenderer.cpp +++ b/src/datavisualization/engine/scatter3drenderer.cpp @@ -165,12 +165,6 @@ void Scatter3DRenderer::initializeOpenGL() void Scatter3DRenderer::updateData() { calculateSceneScalingFactors(); - float minX = float(m_axisCacheX.min()); - float maxX = float(m_axisCacheX.max()); - float minY = float(m_axisCacheY.min()); - float maxY = float(m_axisCacheY.max()); - float minZ = float(m_axisCacheZ.min()); - float maxZ = float(m_axisCacheZ.max()); int totalDataSize = 0; foreach (SeriesRenderCache *baseCache, m_renderCacheList) { @@ -185,23 +179,8 @@ void Scatter3DRenderer::updateData() if (dataSize != renderArray.size()) renderArray.resize(dataSize); - for (int i = 0; i < dataSize; i++) { - QVector3D dotPos = dataArray.at(i).position(); - ScatterRenderItem &renderItem = renderArray[i]; - if ((dotPos.x() >= minX && dotPos.x() <= maxX ) - && (dotPos.y() >= minY && dotPos.y() <= maxY) - && (dotPos.z() >= minZ && dotPos.z() <= maxZ)) { - renderItem.setPosition(dotPos); - renderItem.setVisible(true); - if (!dataArray.at(i).rotation().isIdentity()) - renderItem.setRotation(dataArray.at(i).rotation().normalized()); - else - renderItem.setRotation(identityQuaternion); - calculateTranslation(renderItem); - } else { - renderItem.setVisible(false); - } - } + for (int i = 0; i < dataSize; i++) + updateRenderItem(dataArray.at(i), renderArray[i]); cache->setDataDirty(false); } } @@ -272,6 +251,30 @@ SeriesRenderCache *Scatter3DRenderer::createNewCache(QAbstract3DSeries *series) return new ScatterSeriesRenderCache(series, this); } +void Scatter3DRenderer::updateItems(const QVector &items) +{ + ScatterSeriesRenderCache *cache = 0; + const QScatter3DSeries *prevSeries = 0; + const QScatterDataArray *dataArray = 0; + + foreach (Scatter3DController::ChangeItem item, items) { + QScatter3DSeries *currentSeries = item.series; + if (currentSeries != prevSeries) { + cache = static_cast(m_renderCacheList.value(currentSeries)); + prevSeries = currentSeries; + dataArray = item.series->dataProxy()->array(); + // Invisible series render caches are not updated, but instead just marked dirty, so that + // they can be completely recalculated when they are turned visible. + if (!cache->isVisible() && !cache->dataDirty()) + cache->setDataDirty(true); + } + if (cache->isVisible()) { + const int index = item.index; + updateRenderItem(dataArray->at(index), cache->renderArray()[index]); + } + } +} + void Scatter3DRenderer::updateScene(Q3DScene *scene) { scene->activeCamera()->d_ptr->setMinYRotation(-90.0f); @@ -1802,6 +1805,24 @@ void Scatter3DRenderer::selectionColorToSeriesAndIndex(const QVector4D &color, series = 0; } +void Scatter3DRenderer::updateRenderItem(const QScatterDataItem &dataItem, ScatterRenderItem &renderItem) +{ + QVector3D dotPos = dataItem.position(); + if ((dotPos.x() >= m_axisCacheX.min() && dotPos.x() <= m_axisCacheX.max() ) + && (dotPos.y() >= m_axisCacheY.min() && dotPos.y() <= m_axisCacheY.max()) + && (dotPos.z() >= m_axisCacheZ.min() && dotPos.z() <= m_axisCacheZ.max())) { + renderItem.setPosition(dotPos); + renderItem.setVisible(true); + if (!dataItem.rotation().isIdentity()) + renderItem.setRotation(dataItem.rotation().normalized()); + else + renderItem.setRotation(identityQuaternion); + calculateTranslation(renderItem); + } else { + renderItem.setVisible(false); + } +} + QVector3D Scatter3DRenderer::convertPositionToTranslation(const QVector3D &position) { float xTrans = m_axisCacheX.positionAt(position.x()); float yTrans = m_axisCacheY.positionAt(position.y()); diff --git a/src/datavisualization/engine/scatter3drenderer_p.h b/src/datavisualization/engine/scatter3drenderer_p.h index 172d0c46..09b8dace 100644 --- a/src/datavisualization/engine/scatter3drenderer_p.h +++ b/src/datavisualization/engine/scatter3drenderer_p.h @@ -105,6 +105,7 @@ public: void updateData(); void updateSeries(const QList &seriesList); SeriesRenderCache *createNewCache(QAbstract3DSeries *series); + void updateItems(const QVector &items); void updateScene(Q3DScene *scene); QVector3D convertPositionToTranslation(const QVector3D &position); @@ -154,6 +155,7 @@ public slots: private: void selectionColorToSeriesAndIndex(const QVector4D &color, int &index, QAbstract3DSeries *&series); + inline void updateRenderItem(const QScatterDataItem &dataItem, ScatterRenderItem &renderItem); }; QT_END_NAMESPACE_DATAVISUALIZATION -- cgit v1.2.3