diff options
39 files changed, 1619 insertions, 1210 deletions
diff --git a/src/datavisualization/data/barrenderitem.cpp b/src/datavisualization/data/barrenderitem.cpp index 50d2a4b4..2d9d3daa 100644 --- a/src/datavisualization/data/barrenderitem.cpp +++ b/src/datavisualization/data/barrenderitem.cpp @@ -24,8 +24,7 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION BarRenderItem::BarRenderItem() : AbstractRenderItem(), m_value(0), - m_height(0.0f), - m_seriesIndex(0) + m_height(0.0f) { } @@ -35,7 +34,6 @@ BarRenderItem::BarRenderItem(const BarRenderItem &other) m_value = other.m_value; m_position = other.m_position; m_height = other.m_height; - m_seriesIndex = other.m_seriesIndex; } BarRenderItem::~BarRenderItem() @@ -67,7 +65,6 @@ void BarRenderSliceItem::setItem(const BarRenderItem &renderItem) m_value = renderItem.value(); m_position = renderItem.position(); m_height = renderItem.height(); - m_seriesIndex = renderItem.seriesIndex(); m_sliceLabel = QString(); m_sliceLabelItem = 0; } diff --git a/src/datavisualization/data/barrenderitem_p.h b/src/datavisualization/data/barrenderitem_p.h index 1122053d..97c069e2 100644 --- a/src/datavisualization/data/barrenderitem_p.h +++ b/src/datavisualization/data/barrenderitem_p.h @@ -54,16 +54,10 @@ public: inline void setHeight(GLfloat height) { m_height = height; } inline GLfloat height() const { return m_height; } - // Series index in visual series that this item belongs to. - // This is only utilized by slicing, so it may not be up to date on all items. - inline void setSeriesIndex(int seriesIndex) { m_seriesIndex = seriesIndex; } - inline int seriesIndex() const { return m_seriesIndex; } - protected: float m_value; QPoint m_position; // x = row, y = column GLfloat m_height; - int m_seriesIndex; friend class QBarDataItem; }; diff --git a/src/datavisualization/data/qabstract3dseries_p.h b/src/datavisualization/data/qabstract3dseries_p.h index 530afe5e..e62543af 100644 --- a/src/datavisualization/data/qabstract3dseries_p.h +++ b/src/datavisualization/data/qabstract3dseries_p.h @@ -52,6 +52,7 @@ struct QAbstract3DSeriesChangeBitField { bool nameChanged : 1; bool itemLabelChanged : 1; bool itemLabelVisibilityChanged : 1; + bool visibilityChanged : 1; QAbstract3DSeriesChangeBitField() : meshChanged(true), @@ -67,7 +68,8 @@ struct QAbstract3DSeriesChangeBitField { multiHighlightGradientChanged(true), nameChanged(true), itemLabelChanged(true), - itemLabelVisibilityChanged(true) + itemLabelVisibilityChanged(true), + visibilityChanged(true) { } }; diff --git a/src/datavisualization/data/scatterrenderitem.cpp b/src/datavisualization/data/scatterrenderitem.cpp index 3b2e64c5..33df4d28 100644 --- a/src/datavisualization/data/scatterrenderitem.cpp +++ b/src/datavisualization/data/scatterrenderitem.cpp @@ -29,10 +29,10 @@ ScatterRenderItem::ScatterRenderItem() } ScatterRenderItem::ScatterRenderItem(const ScatterRenderItem &other) - : AbstractRenderItem(other), - m_visible(false) + : AbstractRenderItem(other) { m_position = other.m_position; + m_visible = other.m_visible; } ScatterRenderItem::~ScatterRenderItem() diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp index 9283ccb4..885904d4 100644 --- a/src/datavisualization/engine/abstract3dcontroller.cpp +++ b/src/datavisualization/engine/abstract3dcontroller.cpp @@ -50,7 +50,6 @@ Abstract3DController::Abstract3DController(QRect initialViewport, Q3DScene *scen m_axisZ(0), m_renderer(0), m_isDataDirty(true), - m_isSeriesVisibilityDirty(true), m_isSeriesVisualsDirty(true), m_renderPending(false), m_measureFps(false), @@ -146,7 +145,7 @@ void Abstract3DController::removeSeries(QAbstract3DSeries *series) this, &Abstract3DController::handleSeriesVisibilityChanged); series->d_ptr->setController(0); m_isDataDirty = true; - m_isSeriesVisibilityDirty = true; + m_isSeriesVisualsDirty = true; emitNeedRender(); } } @@ -354,9 +353,13 @@ void Abstract3DController::synchDataToRenderer() } } - if (m_isSeriesVisibilityDirty || m_isSeriesVisualsDirty) { - m_renderer->updateSeries(m_seriesList, m_isSeriesVisibilityDirty); - m_isSeriesVisibilityDirty = false; + if (m_changedSeriesList.size()) { + m_renderer->modifiedSeriesList(m_changedSeriesList); + m_changedSeriesList.clear(); + } + + if (m_isSeriesVisualsDirty) { + m_renderer->updateSeries(m_seriesList); m_isSeriesVisualsDirty = false; } @@ -1018,10 +1021,14 @@ void Abstract3DController::handleAxisFormatterDirtyBySender(QObject *sender) void Abstract3DController::handleSeriesVisibilityChangedBySender(QObject *sender) { - Q_UNUSED(sender) + QAbstract3DSeries *series = static_cast<QAbstract3DSeries *>(sender); + series->d_ptr->m_changeTracker.visibilityChanged = true; m_isDataDirty = true; - m_isSeriesVisibilityDirty = true; + m_isSeriesVisualsDirty = true; + + adjustAxisRanges(); + emitNeedRender(); } diff --git a/src/datavisualization/engine/abstract3dcontroller_p.h b/src/datavisualization/engine/abstract3dcontroller_p.h index f18ed452..4f597769 100644 --- a/src/datavisualization/engine/abstract3dcontroller_p.h +++ b/src/datavisualization/engine/abstract3dcontroller_p.h @@ -155,7 +155,6 @@ protected: QList<QAbstract3DAxis *> m_axes; // List of all added axes Abstract3DRenderer *m_renderer; bool m_isDataDirty; - bool m_isSeriesVisibilityDirty; bool m_isSeriesVisualsDirty; bool m_renderPending; @@ -166,6 +165,8 @@ protected: int m_numFrames; qreal m_currentFps; + QVector<QAbstract3DSeries *> m_changedSeriesList; + explicit Abstract3DController(QRect initialViewport, Q3DScene *scene, QObject *parent = 0); public: @@ -247,6 +248,7 @@ public: virtual void handleAxisFormatterDirtyBySender(QObject *sender); virtual void handleSeriesVisibilityChangedBySender(QObject *sender); virtual void handlePendingClick() = 0; + virtual void adjustAxisRanges() = 0; void markSeriesItemLabelsDirty(); diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp index 0b8ac8d1..f70d128b 100644 --- a/src/datavisualization/engine/abstract3drenderer.cpp +++ b/src/datavisualization/engine/abstract3drenderer.cpp @@ -47,7 +47,8 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller) m_clickPending(false), m_clickedSeries(0), m_clickedType(QAbstract3DGraph::ElementNone), - m_selectionLabelItem(0) + m_selectionLabelItem(0), + m_visibleSeriesCount(0) { QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Abstract3DRenderer::updateTextures); @@ -59,14 +60,17 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller) Abstract3DRenderer::~Abstract3DRenderer() { - for (int i = 0; i < m_visibleSeriesList.size(); i++) - m_visibleSeriesList[i].cleanup(m_textureHelper); - delete m_drawer; delete m_textureHelper; delete m_cachedScene; delete m_cachedTheme; delete m_selectionLabelItem; + + foreach (SeriesRenderCache *cache, m_renderCacheList) { + cache->cleanup(m_textureHelper); + delete cache; + } + m_renderCacheList.clear(); } void Abstract3DRenderer::initializeOpenGL() @@ -285,6 +289,9 @@ void Abstract3DRenderer::updateAxisRange(QAbstract3DAxis::AxisOrientation orient AxisRenderCache &cache = axisCacheForOrientation(orientation); cache.setMin(min); cache.setMax(max); + + foreach (SeriesRenderCache *cache, m_renderCacheList) + cache->setDataDirty(true); } void Abstract3DRenderer::updateAxisSegmentCount(QAbstract3DAxis::AxisOrientation orientation, @@ -318,6 +325,18 @@ void Abstract3DRenderer::updateAxisFormatter(QAbstract3DAxis::AxisOrientation or } formatter->d_ptr->populateCopy(*(cache.formatter())); cache.markPositionsDirty(); + + foreach (SeriesRenderCache *cache, m_renderCacheList) + cache->setDataDirty(true); +} + +void Abstract3DRenderer::modifiedSeriesList(const QVector<QAbstract3DSeries *> &seriesList) +{ + foreach (QAbstract3DSeries *series, seriesList) { + SeriesRenderCache *cache = m_renderCacheList.value(series, 0); + if (cache) + cache->setDataDirty(true); + } } void Abstract3DRenderer::fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh) @@ -327,33 +346,45 @@ void Abstract3DRenderer::fixMeshFileName(QString &fileName, QAbstract3DSeries::M Q_UNUSED(mesh) } -void Abstract3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList, - bool updateVisibility) +void Abstract3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList) { - int visibleCount = 0; - if (updateVisibility) { - int oldSize = m_visibleSeriesList.size(); - foreach (QAbstract3DSeries *current, seriesList) { - if (current->isVisible()) - visibleCount++; + foreach (SeriesRenderCache *cache, m_renderCacheList) + cache->setValid(false); + + m_visibleSeriesCount = 0; + int seriesCount = seriesList.size(); + for (int i = 0; i < seriesCount; i++) { + QAbstract3DSeries *series = seriesList.at(i); + SeriesRenderCache *cache = m_renderCacheList.value(series); + bool newSeries = false; + if (!cache) { + cache = createNewCache(series); + m_renderCacheList[series] = cache; + newSeries = true; } + cache->setValid(true); + cache->populate(newSeries); + if (cache->isVisible()) + m_visibleSeriesCount++; + } - // Clean up series caches that are about to be permanently deleted. - // Can't just use cache destructor, as resize will call that to all items. - if (visibleCount < oldSize) { - for (int i = visibleCount; i < oldSize; i++) - m_visibleSeriesList[i].cleanup(m_textureHelper); - } + // Remove non-valid objects from the cache list + foreach (SeriesRenderCache *cache, m_renderCacheList) { + if (!cache->isValid()) + cleanCache(cache); + } +} - if (visibleCount != oldSize) - m_visibleSeriesList.resize(visibleCount); +SeriesRenderCache *Abstract3DRenderer::createNewCache(QAbstract3DSeries *series) +{ + return new SeriesRenderCache(series, this); +} - visibleCount = 0; - } - foreach (QAbstract3DSeries *current, seriesList) { - if (current->isVisible()) - m_visibleSeriesList[visibleCount++].populate(current, this); - } +void Abstract3DRenderer::cleanCache(SeriesRenderCache *cache) +{ + m_renderCacheList.remove(cache->series()); + cache->cleanup(m_textureHelper); + delete cache; } AxisRenderCache &Abstract3DRenderer::axisCacheForOrientation( diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h index f5ca8d02..ce21deff 100644 --- a/src/datavisualization/engine/abstract3drenderer_p.h +++ b/src/datavisualization/engine/abstract3drenderer_p.h @@ -61,8 +61,9 @@ public: virtual ~Abstract3DRenderer(); virtual void updateData() = 0; - virtual void updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility); - + virtual void updateSeries(const QList<QAbstract3DSeries *> &seriesList); + virtual SeriesRenderCache *createNewCache(QAbstract3DSeries *series); + virtual void cleanCache(SeriesRenderCache *cache); virtual void render(GLuint defaultFboHandle); virtual void updateTheme(Q3DTheme *theme); @@ -96,6 +97,7 @@ public: const QString &format); virtual void updateAxisFormatter(QAbstract3DAxis::AxisOrientation orientation, QValue3DAxisFormatter *formatter); + virtual void modifiedSeriesList(const QVector<QAbstract3DSeries *> &seriesList); virtual void fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh); void generateBaseColorTexture(const QColor &color, GLuint *texture); @@ -147,7 +149,7 @@ protected: bool m_selectionDirty; SelectionState m_selectionState; QPoint m_inputPosition; - QVector<SeriesRenderCache> m_visibleSeriesList; + QHash<QAbstract3DSeries *, SeriesRenderCache *> m_renderCacheList; QRect m_primarySubViewport; QRect m_secondarySubViewport; float m_devicePixelRatio; @@ -158,6 +160,7 @@ protected: QString m_selectionLabel; LabelItem *m_selectionLabelItem; + int m_visibleSeriesCount; }; QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/engine/bars3dcontroller.cpp b/src/datavisualization/engine/bars3dcontroller.cpp index 49b6f383..38870115 100644 --- a/src/datavisualization/engine/bars3dcontroller.cpp +++ b/src/datavisualization/engine/bars3dcontroller.cpp @@ -108,6 +108,8 @@ void Bars3DController::handleArrayReset() m_isDataDirty = true; series->d_ptr->markItemLabelDirty(); } + if (!m_changedSeriesList.contains(series)) + m_changedSeriesList.append(series); // Clear selection unless still valid setSelectedBar(m_selectedBar, m_selectedBarSeries, false); emitNeedRender(); @@ -122,6 +124,8 @@ void Bars3DController::handleRowsAdded(int startIndex, int count) adjustAxisRanges(); m_isDataDirty = true; } + if (!m_changedSeriesList.contains(series)) + m_changedSeriesList.append(series); emitNeedRender(); } @@ -135,6 +139,8 @@ void Bars3DController::handleRowsChanged(int startIndex, int count) m_isDataDirty = true; series->d_ptr->markItemLabelDirty(); } + if (!m_changedSeriesList.contains(series)) + m_changedSeriesList.append(series); emitNeedRender(); } @@ -161,6 +167,8 @@ void Bars3DController::handleRowsRemoved(int startIndex, int count) adjustAxisRanges(); m_isDataDirty = true; } + if (!m_changedSeriesList.contains(series)) + m_changedSeriesList.append(series); emitNeedRender(); } @@ -183,6 +191,8 @@ void Bars3DController::handleRowsInserted(int startIndex, int count) adjustAxisRanges(); m_isDataDirty = true; } + if (!m_changedSeriesList.contains(series)) + m_changedSeriesList.append(series); emitNeedRender(); } @@ -197,6 +207,8 @@ void Bars3DController::handleItemChanged(int rowIndex, int columnIndex) m_isDataDirty = true; series->d_ptr->markItemLabelDirty(); } + if (!m_changedSeriesList.contains(series)) + m_changedSeriesList.append(series); emitNeedRender(); } @@ -240,8 +252,6 @@ void Bars3DController::handleSeriesVisibilityChangedBySender(QObject *sender) { Abstract3DController::handleSeriesVisibilityChangedBySender(sender); - adjustAxisRanges(); - // Visibility changes may require disabling slicing, // so just reset selection to ensure everything is still valid. setSelectedBar(m_selectedBar, m_selectedBarSeries, false); @@ -341,9 +351,6 @@ void Bars3DController::insertSeries(int index, QAbstract3DSeries *series) Abstract3DController::insertSeries(index, series); if (oldSize != m_seriesList.size()) { - if (series->isVisible()) - adjustAxisRanges(); - QBar3DSeries *barSeries = static_cast<QBar3DSeries *>(series); if (!oldSize) { m_primarySeries = barSeries; diff --git a/src/datavisualization/engine/bars3dcontroller_p.h b/src/datavisualization/engine/bars3dcontroller_p.h index 9ea59c89..33928306 100644 --- a/src/datavisualization/engine/bars3dcontroller_p.h +++ b/src/datavisualization/engine/bars3dcontroller_p.h @@ -118,6 +118,7 @@ public: virtual QList<QBar3DSeries *> barSeriesList(); virtual void handleAxisRangeChangedBySender(QObject *sender); + virtual void adjustAxisRanges(); public slots: void handleArrayReset(); @@ -137,11 +138,9 @@ protected: virtual QAbstract3DAxis *createDefaultAxis(QAbstract3DAxis::AxisOrientation orientation); private: - void adjustAxisRanges(); void adjustSelectionPosition(QPoint &pos, const QBar3DSeries *series); Q_DISABLE_COPY(Bars3DController) - }; QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp index 46df6464..6102adde 100644 --- a/src/datavisualization/engine/bars3drenderer.cpp +++ b/src/datavisualization/engine/bars3drenderer.cpp @@ -27,6 +27,7 @@ #include "qbardataitem.h" #include "q3dlight.h" #include "qbar3dseries_p.h" +#include "barseriesrendercache_p.h" #include <QtGui/QMatrix4x4> #include <QtGui/QMouseEvent> @@ -83,17 +84,18 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller) m_scaleFactor(0), m_maxSceneSize(40.0f), m_visualSelectedBarPos(Bars3DController::invalidSelectionPosition()), - m_visualSelectedBarSeriesIndex(-1), m_resetCameraBaseOrientation(true), m_selectedBarPos(Bars3DController::invalidSelectionPosition()), - m_selectedBarSeries(0), + m_selectedSeriesCache(0), m_noZeroInRange(false), m_seriesScaleX(0.0f), m_seriesScaleZ(0.0f), m_seriesStep(0.0f), m_seriesStart(0.0f), m_clickedPosition(Bars3DController::invalidSelectionPosition()), - m_keepSeriesUniform(false) + m_keepSeriesUniform(false), + m_haveUniformColorSeries(false), + m_haveGradientSeries(false) { m_axisCacheY.setScale(2.0f); m_axisCacheY.setTranslate(-1.0f); @@ -151,7 +153,6 @@ void Bars3DRenderer::initializeOpenGL() void Bars3DRenderer::updateData() { - int seriesCount = m_visibleSeriesList.size(); int minRow = m_axisCacheZ.min(); int maxRow = m_axisCacheZ.max(); int minCol = m_axisCacheX.min(); @@ -162,12 +163,9 @@ void Bars3DRenderer::updateData() int dataRowCount = 0; int maxDataRowCount = 0; - if (m_renderingArrays.size() != seriesCount) { - m_renderingArrays.resize(seriesCount); - m_seriesScaleX = 1.0f / float(seriesCount); - m_seriesStep = 1.0f / float(seriesCount); - m_seriesStart = -((float(seriesCount) - 1.0f) / 2.0f) * m_seriesStep; - } + m_seriesScaleX = 1.0f / float(m_visibleSeriesCount); + m_seriesStep = 1.0f / float(m_visibleSeriesCount); + m_seriesStart = -((float(m_visibleSeriesCount) - 1.0f) / 2.0f) * m_seriesStep; if (m_keepSeriesUniform) m_seriesScaleZ = m_seriesScaleX; @@ -178,7 +176,6 @@ void Bars3DRenderer::updateData() // Force update for selection related items m_sliceCache = 0; m_sliceTitleItem = 0; - m_sliceSelection.clear(); m_cachedColumnCount = newColumns; m_cachedRowCount = newRows; @@ -192,95 +189,121 @@ void Bars3DRenderer::updateData() const QValue3DAxisFormatter *axisFormatter = m_axisCacheY.formatter(); float zeroPosition = axisFormatter->positionAt(0.0f); - for (int series = 0; series < seriesCount; series++) { - BarRenderItemArray &renderArray = m_renderingArrays[series]; - if (newRows != renderArray.size() - || newColumns != renderArray.at(0).size()) { - // Destroy old render items and reallocate new array - renderArray.resize(newRows); - for (int i = 0; i < newRows; i++) - renderArray[i].resize(newColumns); - } - // Update cached data window - QBarDataProxy *dataProxy = - static_cast<QBar3DSeries *>(m_visibleSeriesList.at(series).series())->dataProxy(); - dataRowCount = dataProxy->rowCount(); - if (maxDataRowCount < dataRowCount) - maxDataRowCount = qMin(dataRowCount, newRows); - int dataRowIndex = minRow; - GLfloat heightValue = 0.0f; - for (int i = 0; i < newRows; i++) { - int j = 0; - BarRenderItemRow &renderRow = renderArray[i]; - if (dataRowIndex < dataRowCount) { - const QBarDataRow *dataRow = dataProxy->rowAt(dataRowIndex); - updateSize = qMin((dataRow->size() - minCol), renderRow.size()); - if (dataRow) { - int dataColIndex = minCol; - for (; j < updateSize ; j++) { - float value = dataRow->at(dataColIndex).value(); - heightValue = axisFormatter->positionAt(value); - if (m_noZeroInRange) { - if (m_hasNegativeValues) { - heightValue = -1.0f + heightValue; - if (heightValue > 0.0f) - heightValue = 0.0f; - } else { - if (heightValue < 0.0f) - heightValue = 0.0f; + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + BarSeriesRenderCache *cache = static_cast<BarSeriesRenderCache *>(baseCache); + if (cache->isVisible()) { + const QBar3DSeries *currentSeries = cache->series(); + BarRenderItemArray &renderArray = cache->renderArray(); + bool dimensionsChanged = false; + if (newRows != renderArray.size() + || newColumns != renderArray.at(0).size()) { + // Destroy old render items and reallocate new array + dimensionsChanged = true; + renderArray.resize(newRows); + for (int i = 0; i < newRows; i++) + renderArray[i].resize(newColumns); + cache->sliceArray().clear(); + } + + if (cache->dataDirty() || dimensionsChanged) { + QBarDataProxy *dataProxy = currentSeries->dataProxy(); + dataRowCount = dataProxy->rowCount(); + if (maxDataRowCount < dataRowCount) + maxDataRowCount = qMin(dataRowCount, newRows); + int dataRowIndex = minRow; + GLfloat heightValue = 0.0f; + for (int i = 0; i < newRows; i++) { + int j = 0; + BarRenderItemRow &renderRow = renderArray[i]; + if (dataRowIndex < dataRowCount) { + const QBarDataRow *dataRow = dataProxy->rowAt(dataRowIndex); + updateSize = qMin((dataRow->size() - minCol), renderRow.size()); + if (dataRow) { + int dataColIndex = minCol; + for (; j < updateSize ; j++) { + float value = dataRow->at(dataColIndex).value(); + heightValue = axisFormatter->positionAt(value); + if (m_noZeroInRange) { + if (m_hasNegativeValues) { + heightValue = -1.0f + heightValue; + if (heightValue > 0.0f) + heightValue = 0.0f; + } else { + if (heightValue < 0.0f) + heightValue = 0.0f; + } + } else { + heightValue -= zeroPosition; + } + renderRow[j].setValue(value); + renderRow[j].setHeight(heightValue); + + float angle = dataRow->at(dataColIndex).rotation(); + if (angle) { + renderRow[j].setRotation( + QQuaternion::fromAxisAndAngle( + upVector, angle)); + } else { + renderRow[j].setRotation(identityQuaternion); + } + dataColIndex++; } - } else { - heightValue -= zeroPosition; - } - renderRow[j].setValue(value); - renderRow[j].setHeight(heightValue); - - float angle = dataRow->at(dataColIndex).rotation(); - if (angle) { - renderRow[j].setRotation( - QQuaternion::fromAxisAndAngle( - upVector, angle)); - } else { - renderRow[j].setRotation(identityQuaternion); } - dataColIndex++; } + for (; j < newColumns; j++) { + renderRow[j].setValue(0.0f); + renderRow[j].setHeight(0.0f); + renderRow[j].setRotation(identityQuaternion); + } + dataRowIndex++; } + cache->setDataDirty(false); } - for (; j < m_renderingArrays.at(series).at(i).size(); j++) { - renderRow[j].setValue(0.0f); - renderRow[j].setHeight(0.0f); - renderRow[j].setRotation(identityQuaternion); - } - dataRowIndex++; } } // Reset selected bar to update selection - updateSelectedBar(m_selectedBarPos, m_selectedBarSeries); + updateSelectedBar(m_selectedBarPos, + m_selectedSeriesCache ? m_selectedSeriesCache->series() : 0); } -void Bars3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList, - bool updateVisibility) +void Bars3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList) { - Abstract3DRenderer::updateSeries(seriesList, updateVisibility); + Abstract3DRenderer::updateSeries(seriesList); bool noSelection = true; - int seriesCount = m_visibleSeriesList.size(); - for (int i = 0; i < seriesCount; i++) { - QBar3DSeries *barSeries = static_cast<QBar3DSeries *>(m_visibleSeriesList.at(i).series()); - if (noSelection - && barSeries->selectedBar() != QBar3DSeries::invalidSelectionPosition() - && selectionLabel() != m_visibleSeriesList.at(i).itemLabel()) { - m_selectionLabelDirty = true; - noSelection = false; + int seriesCount = seriesList.size(); + int visualIndex = 0; + m_haveUniformColorSeries = false; + m_haveGradientSeries = false; + for (int i = 0 ; i < seriesCount; i++) { + QBar3DSeries *barSeries = static_cast<QBar3DSeries *>(seriesList[i]); + if (barSeries->isVisible()) { + BarSeriesRenderCache *cache = + static_cast<BarSeriesRenderCache *>(m_renderCacheList.value(barSeries)); + if (noSelection + && barSeries->selectedBar() != QBar3DSeries::invalidSelectionPosition() + && selectionLabel() != cache->itemLabel()) { + m_selectionLabelDirty = true; + noSelection = false; + } + cache->setVisualIndex(visualIndex++); + if (cache->colorStyle() == Q3DTheme::ColorStyleUniform) + m_haveUniformColorSeries = true; + else + m_haveGradientSeries = true; } } if (noSelection && !selectionLabel().isEmpty()) m_selectionLabelDirty = true; } +SeriesRenderCache *Bars3DRenderer::createNewCache(QAbstract3DSeries *series) +{ + return new BarSeriesRenderCache(series, this); +} + void Bars3DRenderer::updateScene(Q3DScene *scene) { if (m_hasNegativeValues) @@ -506,7 +529,6 @@ void Bars3DRenderer::drawSlicedScene() ShaderHelper *barShader = m_barShader; barShader->bind(); - int currentSeriesIndex = -1; Q3DTheme::ColorStyle previousColorStyle = Q3DTheme::ColorStyleUniform; Q3DTheme::ColorStyle colorStyle = Q3DTheme::ColorStyleUniform; ObjectHelper *barObj = 0; @@ -514,29 +536,31 @@ void Bars3DRenderer::drawSlicedScene() QVector3D baseColor; GLuint highlightGradientTexture = 0; GLuint baseGradientTexture = 0; - const SeriesRenderCache *currentSeries = 0; bool colorStyleIsUniform = true; + int firstVisualIndex = m_renderCacheList.size(); + QVector<BarRenderSliceItem> *firstVisualSliceArray = 0; + BarRenderSliceItem *selectedItem = 0; + + QQuaternion seriesRotation; + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + if (baseCache->isVisible()) { + BarSeriesRenderCache *cache = static_cast<BarSeriesRenderCache *>(baseCache); + QVector<BarRenderSliceItem> &sliceArray = cache->sliceArray(); + int sliceCount = sliceArray.size(); + if (firstVisualIndex > cache->visualIndex()) { + firstVisualIndex = cache->visualIndex(); + firstVisualSliceArray = &sliceArray; + } - int sliceItemCount = m_sliceSelection.size(); - for (int bar = 0; bar < sliceItemCount; bar++) { - const BarRenderSliceItem &item = m_sliceSelection.at(bar); - if (!item.value()) - continue; - - QQuaternion seriesRotation; - - if (item.seriesIndex() != currentSeriesIndex) { - currentSeriesIndex = item.seriesIndex(); - currentSeries = &(m_visibleSeriesList.at(currentSeriesIndex)); - barObj = currentSeries->object(); - colorStyle = currentSeries->colorStyle(); + barObj = cache->object(); + colorStyle = cache->colorStyle(); colorStyleIsUniform = (colorStyle == Q3DTheme::ColorStyleUniform); if (colorStyleIsUniform) { - highlightColor = currentSeries->singleHighlightColor(); - baseColor = currentSeries->baseColor(); + highlightColor = cache->singleHighlightColor(); + baseColor = cache->baseColor(); } else { - highlightGradientTexture = currentSeries->singleHighlightGradientTexture(); - baseGradientTexture = currentSeries->baseGradientTexture(); + highlightGradientTexture = cache->singleHighlightGradientTexture(); + baseGradientTexture = cache->baseGradientTexture(); } // Rebind shader if it has changed @@ -555,76 +579,88 @@ void Bars3DRenderer::drawSlicedScene() } previousColorStyle = colorStyle; - seriesRotation = currentSeries->meshRotation(); - } + seriesRotation = cache->meshRotation(); + bool selectedSeries = (cache == m_selectedSeriesCache); + + for (int bar = 0; bar < sliceCount; bar++) { + BarRenderSliceItem &item = cache->sliceArray()[bar]; + if (selectedSeries && itemMode && sliceGridLabels + && m_visualSelectedBarPos.x() == item.position().x() + && m_visualSelectedBarPos.y() == item.position().y()) { + selectedItem = &item; + } + if (!item.value()) + continue; - if (item.height() < 0) - glCullFace(GL_FRONT); - else - glCullFace(GL_BACK); + if (item.height() < 0) + glCullFace(GL_FRONT); + else + glCullFace(GL_BACK); - QMatrix4x4 MVPMatrix; - QMatrix4x4 modelMatrix; - QMatrix4x4 itModelMatrix; - QQuaternion barRotation = item.rotation(); - GLfloat barPosY = item.translation().y() + barPosYAdjustment - zeroPosAdjustment; - - if (rowMode) { - barPosX = item.translation().x(); - } else { - barPosX = -(item.translation().z()); // flip z; frontmost bar to the left - barRotation *= ninetyDegreeRotation; - } + QMatrix4x4 MVPMatrix; + QMatrix4x4 modelMatrix; + QMatrix4x4 itModelMatrix; + QQuaternion barRotation = item.rotation(); + GLfloat barPosY = item.translation().y() + barPosYAdjustment - zeroPosAdjustment; - modelMatrix.translate(barPosX, barPosY, 0.0f); - modelMatrixScaler.setY(item.height()); + if (rowMode) { + barPosX = item.translation().x(); + } else { + barPosX = -(item.translation().z()); // flip z; frontmost bar to the left + barRotation *= ninetyDegreeRotation; + } - if (!seriesRotation.isIdentity()) - barRotation *= seriesRotation; + modelMatrix.translate(barPosX, barPosY, 0.0f); + modelMatrixScaler.setY(item.height()); - if (!barRotation.isIdentity()) { - modelMatrix.rotate(barRotation); - itModelMatrix.rotate(barRotation); - } + if (!seriesRotation.isIdentity()) + barRotation *= seriesRotation; - modelMatrix.scale(modelMatrixScaler); - itModelMatrix.scale(modelMatrixScaler); + if (!barRotation.isIdentity()) { + modelMatrix.rotate(barRotation); + itModelMatrix.rotate(barRotation); + } - MVPMatrix = projectionViewMatrix * modelMatrix; + modelMatrix.scale(modelMatrixScaler); + itModelMatrix.scale(modelMatrixScaler); - QVector3D barColor; - GLuint gradientTexture = 0; + MVPMatrix = projectionViewMatrix * modelMatrix; - if (itemMode && m_visualSelectedBarPos.x() == item.position().x() - && m_visualSelectedBarPos.y() == item.position().y()) { - if (colorStyleIsUniform) - barColor = highlightColor; - else - gradientTexture = highlightGradientTexture; - } else { - if (colorStyleIsUniform) - barColor = baseColor; - else - gradientTexture = baseGradientTexture; - } + QVector3D barColor; + GLuint gradientTexture = 0; - if (item.height() != 0) { - // Set shader bindings - barShader->setUniformValue(barShader->model(), modelMatrix); - barShader->setUniformValue(barShader->nModel(), - itModelMatrix.inverted().transposed()); - barShader->setUniformValue(barShader->MVP(), MVPMatrix); - if (colorStyleIsUniform) { - barShader->setUniformValue(barShader->color(), barColor); - } else if (colorStyle == Q3DTheme::ColorStyleRangeGradient) { - barShader->setUniformValue(barShader->gradientHeight(), - (qAbs(item.height()) / m_gradientFraction)); - } + if (itemMode && m_visualSelectedBarPos.x() == item.position().x() + && m_visualSelectedBarPos.y() == item.position().y()) { + if (colorStyleIsUniform) + barColor = highlightColor; + else + gradientTexture = highlightGradientTexture; + } else { + if (colorStyleIsUniform) + barColor = baseColor; + else + gradientTexture = baseGradientTexture; + } - // Draw the object - m_drawer->drawObject(barShader, - barObj, - gradientTexture); + if (item.height() != 0) { + // Set shader bindings + barShader->setUniformValue(barShader->model(), modelMatrix); + barShader->setUniformValue(barShader->nModel(), + itModelMatrix.inverted().transposed()); + barShader->setUniformValue(barShader->MVP(), MVPMatrix); + if (colorStyleIsUniform) { + barShader->setUniformValue(barShader->color(), barColor); + } else if (colorStyle == Q3DTheme::ColorStyleRangeGradient) { + barShader->setUniformValue(barShader->gradientHeight(), + (qAbs(item.height()) / m_gradientFraction)); + } + + // Draw the object + m_drawer->drawObject(barShader, + barObj, + gradientTexture); + } + } } } @@ -644,11 +680,11 @@ void Bars3DRenderer::drawSlicedScene() QVector3D sliceValueRotation(0.0f, 0.0f, 90.0f); QVector3D sliceLabelRotation(0.0f, 0.0f, -45.0f); - int lastLabel = m_sliceCache->labelItems().size() - 1; + int labelCount = m_sliceCache->labelItems().size(); - for (int labelNo = 0; labelNo <= lastLabel; labelNo++) { + for (int labelNo = 0; labelNo < labelCount; labelNo++) { // Get labels from first series only - const BarRenderSliceItem &item = m_sliceSelection.at(labelNo); + const BarRenderSliceItem &item = firstVisualSliceArray->at(labelNo); m_dummyBarRenderItem.setTranslation(QVector3D(item.translation().x(), barLabelYPos, item.translation().z())); @@ -660,60 +696,63 @@ void Bars3DRenderer::drawSlicedScene() Qt::AlignRight, true); } - for (int col = 0; col < sliceItemCount; col++) { - BarRenderSliceItem &item = m_sliceSelection[col]; - - if (!sliceGridLabels) { - // Draw values - if (item.height() != 0.0f || (!m_noZeroInRange && item.value() == 0.0f)) { - // Create label texture if we need it - if (item.sliceLabel().isNull() || m_updateLabels) { - QString valueLabelText = m_axisCacheY.formatter()->stringForValue( - qreal(item.value()), m_axisCacheY.labelFormat()); - item.setSliceLabel(valueLabelText); - m_drawer->generateLabelItem(item.sliceLabelItem(), item.sliceLabel()); - m_updateLabels = false; - } - Qt::AlignmentFlag alignment = (item.height() < 0) ? Qt::AlignBottom : Qt::AlignTop; - Drawer::LabelPosition labelPos = (item.height() < 0) ? Drawer::LabelBelow : Drawer::LabelOver; - m_dummyBarRenderItem.setTranslation(QVector3D(item.translation().x(), - barPosYAdjustment - zeroPosAdjustment - + item.height(), - item.translation().z())); - - m_drawer->drawLabel(m_dummyBarRenderItem, item.sliceLabelItem(), viewMatrix, - projectionMatrix, zeroVector, sliceValueRotation, - item.height(), m_cachedSelectionMode, m_labelShader, - m_labelObj, activeCamera, false, false, labelPos, - alignment, true); - } - } else { - // Only draw value for selected item when grid labels are on - if (itemMode && m_visualSelectedBarPos.x() == item.position().x() - && m_visualSelectedBarPos.y() == item.position().y() - && item.seriesIndex() == m_visualSelectedBarSeriesIndex) { - // Create label texture if we need it - if (item.sliceLabel().isNull() || m_updateLabels) { - QString valueLabelText = m_axisCacheY.formatter()->stringForValue( - qreal(item.value()), m_axisCacheY.labelFormat()); - item.setSliceLabel(valueLabelText); - m_drawer->generateLabelItem(item.sliceLabelItem(), item.sliceLabel()); - m_updateLabels = false; + if (!sliceGridLabels) { + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + if (baseCache->isVisible()) { + BarSeriesRenderCache *cache = static_cast<BarSeriesRenderCache *>(baseCache); + QVector<BarRenderSliceItem> &sliceArray = cache->sliceArray(); + int sliceCount = sliceArray.size(); + for (int col = 0; col < sliceCount; col++) { + BarRenderSliceItem &item = sliceArray[col]; + + // Draw values + if (item.height() != 0.0f || (!m_noZeroInRange && item.value() == 0.0f)) { + // Create label texture if we need it + if (item.sliceLabel().isNull() || m_updateLabels) { + QString valueLabelText = m_axisCacheY.formatter()->stringForValue( + qreal(item.value()), m_axisCacheY.labelFormat()); + item.setSliceLabel(valueLabelText); + m_drawer->generateLabelItem(item.sliceLabelItem(), item.sliceLabel()); + m_updateLabels = false; + } + Qt::AlignmentFlag alignment = (item.height() < 0) ? Qt::AlignBottom : Qt::AlignTop; + Drawer::LabelPosition labelPos = (item.height() < 0) ? Drawer::LabelBelow : Drawer::LabelOver; + m_dummyBarRenderItem.setTranslation(QVector3D(item.translation().x(), + barPosYAdjustment - zeroPosAdjustment + + item.height(), + item.translation().z())); + + m_drawer->drawLabel(m_dummyBarRenderItem, item.sliceLabelItem(), viewMatrix, + projectionMatrix, zeroVector, sliceValueRotation, + item.height(), m_cachedSelectionMode, m_labelShader, + m_labelObj, activeCamera, false, false, labelPos, + alignment, true); + } } - Qt::AlignmentFlag alignment = (item.height() < 0) ? Qt::AlignBottom : Qt::AlignTop; - Drawer::LabelPosition labelPos = (item.height() < 0) ? Drawer::LabelBelow : Drawer::LabelOver; - m_dummyBarRenderItem.setTranslation(QVector3D(item.translation().x(), - barPosYAdjustment - zeroPosAdjustment - + item.height(), - item.translation().z())); - - m_drawer->drawLabel(m_dummyBarRenderItem, item.sliceLabelItem(), viewMatrix, - projectionMatrix, zeroVector, sliceValueRotation, - item.height(), m_cachedSelectionMode, m_labelShader, - m_labelObj, activeCamera, false, false, labelPos, - alignment, true); } } + } else { + // Only draw value for selected item when grid labels are on + // Create label texture if we need it + if (selectedItem->sliceLabel().isNull() || m_updateLabels) { + QString valueLabelText = m_axisCacheY.formatter()->stringForValue( + qreal(selectedItem->value()), m_axisCacheY.labelFormat()); + selectedItem->setSliceLabel(valueLabelText); + m_drawer->generateLabelItem(selectedItem->sliceLabelItem(), selectedItem->sliceLabel()); + m_updateLabels = false; + } + Qt::AlignmentFlag alignment = (selectedItem->height() < 0) ? Qt::AlignBottom : Qt::AlignTop; + Drawer::LabelPosition labelPos = (selectedItem->height() < 0) ? Drawer::LabelBelow : Drawer::LabelOver; + m_dummyBarRenderItem.setTranslation(QVector3D(selectedItem->translation().x(), + barPosYAdjustment - zeroPosAdjustment + + selectedItem->height(), + selectedItem->translation().z())); + + m_drawer->drawLabel(m_dummyBarRenderItem, selectedItem->sliceLabelItem(), viewMatrix, + projectionMatrix, zeroVector, sliceValueRotation, + selectedItem->height(), m_cachedSelectionMode, m_labelShader, + m_labelObj, activeCamera, false, false, labelPos, + alignment, true); } // Draw labels for axes @@ -773,8 +812,6 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) QVector3D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor()); - int seriesCount = m_visibleSeriesList.size(); - const Q3DCamera *activeCamera = m_cachedScene->activeCamera(); glViewport(m_primarySubViewport.x(), @@ -880,70 +917,74 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) // Draw bars to depth buffer QVector3D shadowScaler(m_scaleX * m_seriesScaleX * 0.9f, 0.0f, m_scaleZ * m_seriesScaleZ * 0.9f); - float seriesPos = m_seriesStart; - for (int series = 0; series < seriesCount; series++) { - ObjectHelper *barObj = m_visibleSeriesList.at(series).object(); - QQuaternion seriesRotation(m_visibleSeriesList.at(series).meshRotation()); - for (int row = startRow; row != stopRow; row += stepRow) { - for (int bar = startBar; bar != stopBar; bar += stepBar) { - GLfloat shadowOffset = 0.0f; - const BarRenderItem &item = m_renderingArrays.at(series).at(row).at(bar); - if (!item.value()) - continue; - // Set front face culling for negative valued bars and back face culling for - // positive valued bars to remove peter-panning issues - if (item.height() > 0) { - glCullFace(GL_BACK); - if (m_yFlipped) - shadowOffset = 0.015f; - } else { - glCullFace(GL_FRONT); - if (!m_yFlipped) - shadowOffset = -0.015f; - } + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + if (baseCache->isVisible()) { + BarSeriesRenderCache *cache = static_cast<BarSeriesRenderCache *>(baseCache); + float seriesPos = m_seriesStart + m_seriesStep * cache->visualIndex() + 0.5f; + ObjectHelper *barObj = cache->object(); + QQuaternion seriesRotation(cache->meshRotation()); + const BarRenderItemArray &renderArray = cache->renderArray(); + for (int row = startRow; row != stopRow; row += stepRow) { + const BarRenderItemRow &renderRow = renderArray.at(row); + for (int bar = startBar; bar != stopBar; bar += stepBar) { + const BarRenderItem &item = renderRow.at(bar); + if (!item.value()) + continue; + GLfloat shadowOffset = 0.0f; + // Set front face culling for negative valued bars and back face culling + // for positive valued bars to remove peter-panning issues + if (item.height() > 0) { + glCullFace(GL_BACK); + if (m_yFlipped) + shadowOffset = 0.015f; + } else { + glCullFace(GL_FRONT); + if (!m_yFlipped) + shadowOffset = -0.015f; + } - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; - colPos = (bar + 0.5f + seriesPos) * (m_cachedBarSpacing.width()); - rowPos = (row + 0.5f) * (m_cachedBarSpacing.height()); + colPos = (bar + seriesPos) * (m_cachedBarSpacing.width()); + rowPos = (row + 0.5f) * (m_cachedBarSpacing.height()); - // Draw shadows for bars "on the other side" a bit off ground to avoid seeing - // shadows through the ground - modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor, - item.height() + shadowOffset, - (m_columnDepth - rowPos) / m_scaleFactor); - // Scale the bars down in X and Z to reduce self-shadowing issues - shadowScaler.setY(item.height()); - if (!seriesRotation.isIdentity() || !item.rotation().isIdentity()) - modelMatrix.rotate(seriesRotation * item.rotation()); - modelMatrix.scale(shadowScaler); + // Draw shadows for bars "on the other side" a bit off ground to avoid + // seeing shadows through the ground + modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor, + item.height() + shadowOffset, + (m_columnDepth - rowPos) / m_scaleFactor); + // Scale the bars down in X and Z to reduce self-shadowing issues + shadowScaler.setY(item.height()); + if (!seriesRotation.isIdentity() || !item.rotation().isIdentity()) + modelMatrix.rotate(seriesRotation * item.rotation()); + modelMatrix.scale(shadowScaler); - MVPMatrix = depthProjectionViewMatrix * modelMatrix; + MVPMatrix = depthProjectionViewMatrix * modelMatrix; - m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix); + m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix); - // 1st attribute buffer : vertices - glEnableVertexAttribArray(m_depthShader->posAtt()); - glBindBuffer(GL_ARRAY_BUFFER, barObj->vertexBuf()); - glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, - (void *)0); + // 1st attribute buffer : vertices + glEnableVertexAttribArray(m_depthShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, barObj->vertexBuf()); + glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, + (void *)0); - // Index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, barObj->elementBuf()); + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, barObj->elementBuf()); - // Draw the triangles - glDrawElements(GL_TRIANGLES, barObj->indexCount(), GL_UNSIGNED_SHORT, - (void *)0); + // Draw the triangles + glDrawElements(GL_TRIANGLES, barObj->indexCount(), GL_UNSIGNED_SHORT, + (void *)0); - // Free buffers - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); + // Free buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); - glDisableVertexAttribArray(m_depthShader->posAtt()); + glDisableVertexAttribArray(m_depthShader->posAtt()); + } } } - seriesPos += m_seriesStep; } // Disable drawing to depth framebuffer (= enable drawing to screen) @@ -962,7 +1003,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) // Skip selection mode drawing if we're slicing or have no selection mode if (!m_cachedIsSlicingActivated && m_cachedSelectionMode > QAbstract3DGraph::SelectionNone - && m_selectionState == SelectOnScene && seriesCount > 0) { + && m_selectionState == SelectOnScene && m_visibleSeriesCount > 0) { // Bind selection shader m_selectionShader->bind(); @@ -976,50 +1017,54 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Set clear color to white (= selectionSkipColor) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled - float seriesPos = m_seriesStart; - for (int series = 0; series < seriesCount; series++) { - ObjectHelper *barObj = m_visibleSeriesList.at(series).object(); - QQuaternion seriesRotation(m_visibleSeriesList.at(series).meshRotation()); - for (int row = startRow; row != stopRow; row += stepRow) { - for (int bar = startBar; bar != stopBar; bar += stepBar) { - const BarRenderItem &item = m_renderingArrays.at(series).at(row).at(bar); - if (!item.value()) - continue; - - if (item.height() < 0) - glCullFace(GL_FRONT); - else - glCullFace(GL_BACK); + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + if (baseCache->isVisible()) { + BarSeriesRenderCache *cache = static_cast<BarSeriesRenderCache *>(baseCache); + float seriesPos = m_seriesStart + m_seriesStep * cache->visualIndex() + 0.5f; + ObjectHelper *barObj = cache->object(); + QQuaternion seriesRotation(cache->meshRotation()); + const BarRenderItemArray &renderArray = cache->renderArray(); + for (int row = startRow; row != stopRow; row += stepRow) { + const BarRenderItemRow &renderRow = renderArray.at(row); + for (int bar = startBar; bar != stopBar; bar += stepBar) { + const BarRenderItem &item = renderRow.at(bar); + if (!item.value()) + continue; + + if (item.height() < 0) + glCullFace(GL_FRONT); + else + glCullFace(GL_BACK); - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; - colPos = (bar + 0.5f + seriesPos) * (m_cachedBarSpacing.width()); - rowPos = (row + 0.5f) * (m_cachedBarSpacing.height()); + colPos = (bar + seriesPos) * (m_cachedBarSpacing.width()); + rowPos = (row + 0.5f) * (m_cachedBarSpacing.height()); - modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor, - item.height(), - (m_columnDepth - rowPos) / m_scaleFactor); - if (!seriesRotation.isIdentity() || !item.rotation().isIdentity()) - modelMatrix.rotate(seriesRotation * item.rotation()); - modelMatrix.scale(QVector3D(m_scaleX * m_seriesScaleX, - item.height(), - m_scaleZ * m_seriesScaleZ)); + modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor, + item.height(), + (m_columnDepth - rowPos) / m_scaleFactor); + if (!seriesRotation.isIdentity() || !item.rotation().isIdentity()) + modelMatrix.rotate(seriesRotation * item.rotation()); + modelMatrix.scale(QVector3D(m_scaleX * m_seriesScaleX, + item.height(), + m_scaleZ * m_seriesScaleZ)); - MVPMatrix = projectionViewMatrix * modelMatrix; + MVPMatrix = projectionViewMatrix * modelMatrix; - QVector4D barColor = QVector4D(GLfloat(row) / 255.0f, - GLfloat(bar) / 255.0f, - GLfloat(series) / 255.0f, - itemAlpha); + QVector4D barColor = QVector4D(GLfloat(row) / 255.0f, + GLfloat(bar) / 255.0f, + GLfloat(cache->visualIndex()) / 255.0f, + itemAlpha); - m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix); - m_selectionShader->setUniformValue(m_selectionShader->color(), barColor); + m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix); + m_selectionShader->setUniformValue(m_selectionShader->color(), barColor); - m_drawer->drawSelectionObject(m_selectionShader, barObj); + m_drawer->drawSelectionObject(m_selectionShader, barObj); + } } } - seriesPos += m_seriesStep; } glCullFace(GL_BACK); drawLabels(true, activeCamera, viewMatrix, projectionMatrix, rowScaleFactor, @@ -1048,18 +1093,9 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) ShaderHelper *barShader = 0; GLuint gradientTexture = 0; Q3DTheme::ColorStyle previousColorStyle = Q3DTheme::ColorStyleUniform; - bool haveUniformColorSeries = false; - bool haveGradientSeries = false; - - for (int i = 0; i < seriesCount; i++) { - if (m_visibleSeriesList.at(i).colorStyle() == Q3DTheme::ColorStyleUniform) - haveUniformColorSeries = true; - else - haveGradientSeries = true; - } // Set unchanging shader bindings - if (haveGradientSeries) { + if (m_haveGradientSeries) { m_barGradientShader->bind(); m_barGradientShader->setUniformValue(m_barGradientShader->lightP(), lightPos); m_barGradientShader->setUniformValue(m_barGradientShader->view(), viewMatrix); @@ -1069,7 +1105,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) m_barGradientShader->setUniformValue(m_barGradientShader->lightColor(), lightColor); } - if (haveUniformColorSeries) { + if (m_haveUniformColorSeries) { m_barShader->bind(); m_barShader->setUniformValue(m_barShader->lightP(), lightPos); m_barShader->setUniformValue(m_barShader->view(), viewMatrix); @@ -1082,17 +1118,13 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) previousColorStyle = Q3DTheme::ColorStyleRangeGradient; } + int sliceReserveAmount = 0; if (m_selectionDirty && m_cachedIsSlicingActivated) { // Slice doesn't own its items, no need to delete them - just clear - m_sliceSelection.clear(); - int reserveAmount; if (rowMode) - reserveAmount = m_cachedColumnCount; + sliceReserveAmount = m_cachedColumnCount; else - reserveAmount = m_cachedRowCount; - if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionMultiSeries)) - reserveAmount *= m_visibleSeriesList.size(); - m_sliceSelection.resize(reserveAmount); + sliceReserveAmount = m_cachedRowCount; // Set slice cache, i.e. axis cache from where slice labels are taken if (rowMode) @@ -1115,225 +1147,220 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) QVector3D barColor; QVector3D modelScaler(m_scaleX * m_seriesScaleX, 0.0f, m_scaleZ * m_seriesScaleZ); bool somethingSelected = (m_visualSelectedBarPos != Bars3DController::invalidSelectionPosition()); - float seriesPos = m_seriesStart; - for (int series = 0; series < seriesCount; series++) { - const SeriesRenderCache ¤tSeries = m_visibleSeriesList.at(series); - QQuaternion seriesRotation(currentSeries.meshRotation()); - ObjectHelper *barObj = currentSeries.object(); - Q3DTheme::ColorStyle colorStyle = currentSeries.colorStyle(); - bool colorStyleIsUniform = (colorStyle == Q3DTheme::ColorStyleUniform); - - // Rebind shader if it has changed - if (colorStyleIsUniform != (previousColorStyle == Q3DTheme::ColorStyleUniform)) { - if (colorStyleIsUniform) - barShader = m_barShader; - else - barShader = m_barGradientShader; - barShader->bind(); - } + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + if (baseCache->isVisible()) { + BarSeriesRenderCache *cache = static_cast<BarSeriesRenderCache *>(baseCache); + float seriesPos = m_seriesStart + m_seriesStep * cache->visualIndex() + 0.5f; + ObjectHelper *barObj = cache->object(); + QQuaternion seriesRotation(cache->meshRotation()); + Q3DTheme::ColorStyle colorStyle = cache->colorStyle(); + BarRenderItemArray &renderArray = cache->renderArray(); + bool colorStyleIsUniform = (colorStyle == Q3DTheme::ColorStyleUniform); + if (sliceReserveAmount) + cache->sliceArray().resize(sliceReserveAmount); - if (colorStyleIsUniform) { - baseColor = currentSeries.baseColor(); - } else if ((previousColorStyle != colorStyle) - && (colorStyle == Q3DTheme::ColorStyleObjectGradient)) { - m_barGradientShader->setUniformValue(m_barGradientShader->gradientHeight(), 0.5f); - } + // Rebind shader if it has changed + if (colorStyleIsUniform != (previousColorStyle == Q3DTheme::ColorStyleUniform)) { + if (colorStyleIsUniform) + barShader = m_barShader; + else + barShader = m_barGradientShader; + barShader->bind(); + } - // Always use base color when no selection mode - if (m_cachedSelectionMode == QAbstract3DGraph::SelectionNone) { - if (colorStyleIsUniform) - barColor = baseColor; - else - gradientTexture = currentSeries.baseGradientTexture(); - } + if (colorStyleIsUniform) { + baseColor = cache->baseColor(); + } else if ((previousColorStyle != colorStyle) + && (colorStyle == Q3DTheme::ColorStyleObjectGradient)) { + m_barGradientShader->setUniformValue(m_barGradientShader->gradientHeight(), 0.5f); + } - previousColorStyle = colorStyle; - int sliceSeriesAdjust = 0; - if (m_selectionDirty && m_cachedIsSlicingActivated) { - int seriesMultiplier = 0; - if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionMultiSeries)) - seriesMultiplier = series; - if (rowMode) - sliceSeriesAdjust = seriesMultiplier * m_cachedColumnCount; - else - sliceSeriesAdjust = seriesMultiplier * m_cachedRowCount; - } + // Always use base color when no selection mode + if (m_cachedSelectionMode == QAbstract3DGraph::SelectionNone) { + if (colorStyleIsUniform) + barColor = baseColor; + else + gradientTexture = cache->baseGradientTexture(); + } - for (int row = startRow; row != stopRow; row += stepRow) { - for (int bar = startBar; bar != stopBar; bar += stepBar) { - BarRenderItem &item = m_renderingArrays[series][row][bar]; + previousColorStyle = colorStyle; - if (item.height() < 0) - glCullFace(GL_FRONT); - else - glCullFace(GL_BACK); + for (int row = startRow; row != stopRow; row += stepRow) { + BarRenderItemRow &renderRow = renderArray[row]; + for (int bar = startBar; bar != stopBar; bar += stepBar) { + BarRenderItem &item = renderRow[bar]; + if (item.height() < 0) + glCullFace(GL_FRONT); + else + glCullFace(GL_BACK); - QMatrix4x4 modelMatrix; - QMatrix4x4 itModelMatrix; - QMatrix4x4 MVPMatrix; + QMatrix4x4 modelMatrix; + QMatrix4x4 itModelMatrix; + QMatrix4x4 MVPMatrix; - colPos = (bar + 0.5f + seriesPos) * (m_cachedBarSpacing.width()); - rowPos = (row + 0.5f) * (m_cachedBarSpacing.height()); - - modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor, - item.height(), - (m_columnDepth - rowPos) / m_scaleFactor); - modelScaler.setY(item.height()); - if (!seriesRotation.isIdentity() || !item.rotation().isIdentity()) { - QQuaternion totalRotation = seriesRotation * item.rotation(); - modelMatrix.rotate(totalRotation); - itModelMatrix.rotate(totalRotation); - } - modelMatrix.scale(modelScaler); - itModelMatrix.scale(modelScaler); + colPos = (bar + seriesPos) * (m_cachedBarSpacing.width()); + rowPos = (row + 0.5f) * (m_cachedBarSpacing.height()); + + modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor, + item.height(), + (m_columnDepth - rowPos) / m_scaleFactor); + modelScaler.setY(item.height()); + if (!seriesRotation.isIdentity() || !item.rotation().isIdentity()) { + QQuaternion totalRotation = seriesRotation * item.rotation(); + modelMatrix.rotate(totalRotation); + itModelMatrix.rotate(totalRotation); + } + modelMatrix.scale(modelScaler); + itModelMatrix.scale(modelScaler); #ifdef SHOW_DEPTH_TEXTURE_SCENE - MVPMatrix = depthProjectionViewMatrix * modelMatrix; + MVPMatrix = depthProjectionViewMatrix * modelMatrix; #else - MVPMatrix = projectionViewMatrix * modelMatrix; + MVPMatrix = projectionViewMatrix * modelMatrix; #endif - GLfloat lightStrength = m_cachedTheme->lightStrength(); - GLfloat shadowLightStrength = adjustedLightStrength; - - if (m_cachedSelectionMode > QAbstract3DGraph::SelectionNone) { - Bars3DController::SelectionType selectionType = Bars3DController::SelectionNone; - if (somethingSelected) - selectionType = isSelected(row, bar, series); - - switch (selectionType) { - case Bars3DController::SelectionItem: { - if (colorStyleIsUniform) - barColor = currentSeries.singleHighlightColor(); - else - gradientTexture = currentSeries.singleHighlightGradientTexture(); - - lightStrength = m_cachedTheme->highlightLightStrength(); - shadowLightStrength = adjustedHighlightStrength; - // Insert position data into render item. We have no ownership, don't delete the previous one - if (!m_cachedIsSlicingActivated - && m_visualSelectedBarSeriesIndex == series) { - selectedBar = &item; - selectedBar->setPosition(QPoint(row, bar)); - item.setTranslation(modelMatrix.column(3).toVector3D()); - barSelectionFound = true; - } - if (m_selectionDirty && m_cachedIsSlicingActivated) { - QVector3D translation = modelMatrix.column(3).toVector3D(); - if (m_cachedSelectionMode & QAbstract3DGraph::SelectionColumn - && seriesCount > 1) { - translation.setZ((m_columnDepth - ((row + 0.5f + seriesPos) - * (m_cachedBarSpacing.height()))) - / m_scaleFactor); - } - item.setTranslation(translation); - item.setPosition(QPoint(row, bar)); - item.setSeriesIndex(series); - if (rowMode) - m_sliceSelection[sliceSeriesAdjust + bar].setItem(item); + GLfloat lightStrength = m_cachedTheme->lightStrength(); + GLfloat shadowLightStrength = adjustedLightStrength; + + if (m_cachedSelectionMode > QAbstract3DGraph::SelectionNone) { + Bars3DController::SelectionType selectionType = + Bars3DController::SelectionNone; + if (somethingSelected) + selectionType = isSelected(row, bar, cache); + + switch (selectionType) { + case Bars3DController::SelectionItem: { + if (colorStyleIsUniform) + barColor = cache->singleHighlightColor(); else - m_sliceSelection[sliceSeriesAdjust + row].setItem(item); - } - break; - } - case Bars3DController::SelectionRow: { - // Current bar is on the same row as the selected bar - if (colorStyleIsUniform) - barColor = currentSeries.multiHighlightColor(); - else - gradientTexture = currentSeries.multiHighlightGradientTexture(); - - lightStrength = m_cachedTheme->highlightLightStrength(); - shadowLightStrength = adjustedHighlightStrength; - if (m_cachedIsSlicingActivated) { - item.setTranslation(modelMatrix.column(3).toVector3D()); - item.setPosition(QPoint(row, bar)); - if (m_selectionDirty) { - item.setSeriesIndex(series); - if (!m_sliceTitleItem && m_axisCacheZ.labelItems().size() > row) - m_sliceTitleItem = m_axisCacheZ.labelItems().at(row); - m_sliceSelection[sliceSeriesAdjust + bar].setItem(item); + gradientTexture = cache->singleHighlightGradientTexture(); + + lightStrength = m_cachedTheme->highlightLightStrength(); + shadowLightStrength = adjustedHighlightStrength; + // Insert position data into render item + // We have no ownership, don't delete the previous one + if (!m_cachedIsSlicingActivated + && m_selectedSeriesCache == cache) { + selectedBar = &item; + selectedBar->setPosition(QPoint(row, bar)); + item.setTranslation(modelMatrix.column(3).toVector3D()); + barSelectionFound = true; + } + if (m_selectionDirty && m_cachedIsSlicingActivated) { + QVector3D translation = modelMatrix.column(3).toVector3D(); + if (m_cachedSelectionMode & QAbstract3DGraph::SelectionColumn + && m_visibleSeriesCount > 1) { + translation.setZ((m_columnDepth + - ((row + seriesPos) + * (m_cachedBarSpacing.height()))) + / m_scaleFactor); + } + item.setTranslation(translation); + item.setPosition(QPoint(row, bar)); + if (rowMode) + cache->sliceArray()[bar].setItem(item); + else + cache->sliceArray()[row].setItem(item); } + break; } - break; - } - case Bars3DController::SelectionColumn: { - // Current bar is on the same column as the selected bar - if (colorStyleIsUniform) - barColor = currentSeries.multiHighlightColor(); - else - gradientTexture = currentSeries.multiHighlightGradientTexture(); - - lightStrength = m_cachedTheme->highlightLightStrength(); - shadowLightStrength = adjustedHighlightStrength; - if (m_cachedIsSlicingActivated) { - QVector3D translation = modelMatrix.column(3).toVector3D(); - if (seriesCount > 1) { - translation.setZ((m_columnDepth - ((row + 0.5f + seriesPos) - * (m_cachedBarSpacing.height()))) - / m_scaleFactor); + case Bars3DController::SelectionRow: { + // Current bar is on the same row as the selected bar + if (colorStyleIsUniform) + barColor = cache->multiHighlightColor(); + else + gradientTexture = cache->multiHighlightGradientTexture(); + + lightStrength = m_cachedTheme->highlightLightStrength(); + shadowLightStrength = adjustedHighlightStrength; + if (m_cachedIsSlicingActivated) { + item.setTranslation(modelMatrix.column(3).toVector3D()); + item.setPosition(QPoint(row, bar)); + if (m_selectionDirty) { + if (!m_sliceTitleItem && m_axisCacheZ.labelItems().size() > row) + m_sliceTitleItem = m_axisCacheZ.labelItems().at(row); + cache->sliceArray()[bar].setItem(item); + } } - item.setTranslation(translation); - item.setPosition(QPoint(row, bar)); - if (m_selectionDirty) { - item.setSeriesIndex(series); - if (!m_sliceTitleItem && m_axisCacheX.labelItems().size() > bar) - m_sliceTitleItem = m_axisCacheX.labelItems().at(bar); - m_sliceSelection[sliceSeriesAdjust + row].setItem(item); + break; + } + case Bars3DController::SelectionColumn: { + // Current bar is on the same column as the selected bar + if (colorStyleIsUniform) + barColor = cache->multiHighlightColor(); + else + gradientTexture = cache->multiHighlightGradientTexture(); + + lightStrength = m_cachedTheme->highlightLightStrength(); + shadowLightStrength = adjustedHighlightStrength; + if (m_cachedIsSlicingActivated) { + QVector3D translation = modelMatrix.column(3).toVector3D(); + if (m_visibleSeriesCount > 1) { + translation.setZ((m_columnDepth - ((row + seriesPos) + * (m_cachedBarSpacing.height()))) + / m_scaleFactor); + } + item.setTranslation(translation); + item.setPosition(QPoint(row, bar)); + if (m_selectionDirty) { + if (!m_sliceTitleItem && m_axisCacheX.labelItems().size() > bar) + m_sliceTitleItem = m_axisCacheX.labelItems().at(bar); + cache->sliceArray()[row].setItem(item); + } } + break; + } + case Bars3DController::SelectionNone: { + // Current bar is not selected, nor on a row or column + if (colorStyleIsUniform) + barColor = baseColor; + else + gradientTexture = cache->baseGradientTexture(); + break; + } } - break; - } - case Bars3DController::SelectionNone: { - // Current bar is not selected, nor on a row or column - if (colorStyleIsUniform) - barColor = baseColor; - else - gradientTexture = currentSeries.baseGradientTexture(); - break; - } } - } - // Skip drawing of 0-height bars - if (item.height() != 0) { - // Set shader bindings - barShader->setUniformValue(barShader->model(), modelMatrix); - barShader->setUniformValue(barShader->nModel(), - itModelMatrix.transposed().inverted()); - barShader->setUniformValue(barShader->MVP(), MVPMatrix); - if (colorStyleIsUniform) { - barShader->setUniformValue(barShader->color(), barColor); - } else if (colorStyle == Q3DTheme::ColorStyleRangeGradient) { - barShader->setUniformValue(barShader->gradientHeight(), - qAbs(item.height()) / m_gradientFraction); - } + // Skip drawing of 0-height bars + if (item.height() != 0) { + // Set shader bindings + barShader->setUniformValue(barShader->model(), modelMatrix); + barShader->setUniformValue(barShader->nModel(), + itModelMatrix.transposed().inverted()); + barShader->setUniformValue(barShader->MVP(), MVPMatrix); + if (colorStyleIsUniform) { + barShader->setUniformValue(barShader->color(), barColor); + } else if (colorStyle == Q3DTheme::ColorStyleRangeGradient) { + barShader->setUniformValue(barShader->gradientHeight(), + qAbs(item.height()) / m_gradientFraction); + } #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { - // Set shadow shader bindings - QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; - barShader->setUniformValue(barShader->shadowQ(), m_shadowQualityToShader); - barShader->setUniformValue(barShader->depth(), depthMVPMatrix); - barShader->setUniformValue(barShader->lightS(), shadowLightStrength); - barShader->setUniformValue(barShader->lightColor(), lightColor); - - // Draw the object - m_drawer->drawObject(barShader, barObj, gradientTexture, m_depthTexture); - } else + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + // Set shadow shader bindings + QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + barShader->setUniformValue(barShader->shadowQ(), m_shadowQualityToShader); + barShader->setUniformValue(barShader->depth(), depthMVPMatrix); + barShader->setUniformValue(barShader->lightS(), shadowLightStrength); + barShader->setUniformValue(barShader->lightColor(), lightColor); + + // Draw the object + m_drawer->drawObject(barShader, barObj, gradientTexture, m_depthTexture); + } else #else - Q_UNUSED(shadowLightStrength); + Q_UNUSED(shadowLightStrength); #endif - { - // Set shadowless shader bindings - barShader->setUniformValue(barShader->lightS(), lightStrength); + { + // Set shadowless shader bindings + barShader->setUniformValue(barShader->lightS(), lightStrength); - // Draw the object - m_drawer->drawObject(barShader, barObj, gradientTexture); + // Draw the object + m_drawer->drawObject(barShader, barObj, gradientTexture); + } } } } } - seriesPos += m_seriesStep; } + glDisable(GL_POLYGON_OFFSET_FILL); // Bind background shader @@ -1676,7 +1703,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle) || m_selectionLabelDirty) { QString labelText = selectionLabel(); if (labelText.isNull() || m_selectionLabelDirty) { - labelText = m_visibleSeriesList[m_visualSelectedBarSeriesIndex].itemLabel(); + labelText = m_selectedSeriesCache->itemLabel(); setSelectionLabel(labelText); m_selectionLabelDirty = false; } @@ -1891,7 +1918,7 @@ void Bars3DRenderer::updateMultiSeriesScaling(bool uniform) m_keepSeriesUniform = uniform; // Recalculate scale factors - m_seriesScaleX = 1.0f / float(m_visibleSeriesList.size()); + m_seriesScaleX = 1.0f / float(m_visibleSeriesCount); if (m_keepSeriesUniform) m_seriesScaleZ = m_seriesScaleX; else @@ -1943,30 +1970,24 @@ void Bars3DRenderer::updateAxisRange(QAbstract3DAxis::AxisOrientation orientatio } } -void Bars3DRenderer::updateSelectedBar(const QPoint &position, const QBar3DSeries *series) +void Bars3DRenderer::updateSelectedBar(const QPoint &position, QBar3DSeries *series) { m_selectedBarPos = position; - m_selectedBarSeries = series; + m_selectedSeriesCache = static_cast<BarSeriesRenderCache *>(m_renderCacheList.value(series, 0)); m_selectionDirty = true; m_selectionLabelDirty = true; - m_visualSelectedBarSeriesIndex = -1; - if (m_renderingArrays.isEmpty()) { + if (!m_selectedSeriesCache + || !m_selectedSeriesCache->isVisible() + || m_selectedSeriesCache->renderArray().isEmpty()) { m_visualSelectedBarPos = Bars3DController::invalidSelectionPosition(); return; } int adjustedZ = m_selectedBarPos.x() - int(m_axisCacheZ.min()); int adjustedX = m_selectedBarPos.y() - int(m_axisCacheX.min()); - int maxZ = m_renderingArrays.at(0).size() - 1; - int maxX = maxZ >= 0 ? m_renderingArrays.at(0).at(0).size() - 1 : -1; - - for (int i = 0; i < m_visibleSeriesList.size(); i++) { - if (m_visibleSeriesList.at(i).series() == series) { - m_visualSelectedBarSeriesIndex = i; - break; - } - } + int maxZ = m_selectedSeriesCache->renderArray().size() - 1; + int maxX = maxZ >= 0 ? m_selectedSeriesCache->renderArray().at(0).size() - 1 : -1; if (m_selectedBarPos == Bars3DController::invalidSelectionPosition() || adjustedZ < 0 || adjustedZ > maxZ @@ -2113,13 +2134,13 @@ void Bars3DRenderer::calculateHeightAdjustment() } } -Bars3DController::SelectionType Bars3DRenderer::isSelected(int row, int bar, int seriesIndex) +Bars3DController::SelectionType Bars3DRenderer::isSelected(int row, int bar, + const BarSeriesRenderCache *cache) { Bars3DController::SelectionType isSelectedType = Bars3DController::SelectionNone; if ((m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionMultiSeries) - && m_visualSelectedBarSeriesIndex >= 0) - || seriesIndex == m_visualSelectedBarSeriesIndex) { + && m_selectedSeriesCache) || cache == m_selectedSeriesCache) { if (row == m_visualSelectedBarPos.x() && bar == m_visualSelectedBarPos.y() && (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionItem))) { isSelectedType = Bars3DController::SelectionItem; @@ -2174,10 +2195,17 @@ QPoint Bars3DRenderer::selectionColorToArrayPosition(const QVector4D &selectionC QBar3DSeries *Bars3DRenderer::selectionColorToSeries(const QVector4D &selectionColor) { - if (selectionColor == selectionSkipColor) + if (selectionColor == selectionSkipColor) { return 0; - else - return static_cast<QBar3DSeries *>(m_visibleSeriesList.at(int(selectionColor.z())).series()); + } else { + int seriesIndexFromColor(selectionColor.z()); + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + BarSeriesRenderCache *cache = static_cast<BarSeriesRenderCache *>(baseCache); + if (cache->visualIndex() == seriesIndexFromColor) + return cache->series(); + } + } + return 0; } void Bars3DRenderer::updateSlicingActive(bool isSlicing) diff --git a/src/datavisualization/engine/bars3drenderer_p.h b/src/datavisualization/engine/bars3drenderer_p.h index fba5d830..549a63f6 100644 --- a/src/datavisualization/engine/bars3drenderer_p.h +++ b/src/datavisualization/engine/bars3drenderer_p.h @@ -45,6 +45,7 @@ class ShaderHelper; class ObjectHelper; class LabelItem; class Q3DScene; +class BarSeriesRenderCache; class QT_DATAVISUALIZATION_EXPORT Bars3DRenderer : public Abstract3DRenderer { @@ -60,7 +61,6 @@ private: // Internal state BarRenderItem *m_selectedBar; // points to renderitem array - QVector<BarRenderSliceItem> m_sliceSelection; AxisRenderCache *m_sliceCache; // not owned const LabelItem *m_sliceTitleItem; // not owned bool m_xFlipped; @@ -95,12 +95,10 @@ private: GLfloat m_scaleFactor; GLfloat m_maxSceneSize; QPoint m_visualSelectedBarPos; - int m_visualSelectedBarSeriesIndex; bool m_resetCameraBaseOrientation; QPoint m_selectedBarPos; - const QBar3DSeries *m_selectedBarSeries; + BarSeriesRenderCache *m_selectedSeriesCache; BarRenderItem m_dummyBarRenderItem; - QVector<BarRenderItemArray> m_renderingArrays; bool m_noZeroInRange; float m_seriesScaleX; float m_seriesScaleZ; @@ -108,13 +106,16 @@ private: float m_seriesStart; QPoint m_clickedPosition; bool m_keepSeriesUniform; + bool m_haveUniformColorSeries; + bool m_haveGradientSeries; public: explicit Bars3DRenderer(Bars3DController *controller); ~Bars3DRenderer(); void updateData(); - void updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility); + void updateSeries(const QList<QAbstract3DSeries *> &seriesList); + SeriesRenderCache *createNewCache(QAbstract3DSeries *series); void updateScene(Q3DScene *scene); void render(GLuint defaultFboHandle = 0); @@ -127,7 +128,7 @@ public slots: const QSizeF &spacing = QSizeF(1.0, 1.0), bool relative = true); void updateSlicingActive(bool isSlicing); - void updateSelectedBar(const QPoint &position, const QBar3DSeries *series); + void updateSelectedBar(const QPoint &position, QBar3DSeries *series); inline QPoint clickedPosition() const { return m_clickedPosition; } void resetClickedStatus(); @@ -161,7 +162,8 @@ private: #endif void calculateSceneScalingFactors(); void calculateHeightAdjustment(); - Abstract3DController::SelectionType isSelected(int row, int bar, int seriesIndex); + Abstract3DController::SelectionType isSelected(int row, int bar, + const BarSeriesRenderCache *cache); QPoint selectionColorToArrayPosition(const QVector4D &selectionColor); QBar3DSeries *selectionColorToSeries(const QVector4D &selectionColor); diff --git a/src/datavisualization/engine/barseriesrendercache.cpp b/src/datavisualization/engine/barseriesrendercache.cpp new file mode 100644 index 00000000..83d3e366 --- /dev/null +++ b/src/datavisualization/engine/barseriesrendercache.cpp @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** 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 "barseriesrendercache_p.h" +#include "bars3drenderer_p.h" + +QT_BEGIN_NAMESPACE_DATAVISUALIZATION + +BarSeriesRenderCache::BarSeriesRenderCache(QAbstract3DSeries *series, + Abstract3DRenderer *renderer) + : SeriesRenderCache(series, renderer), + m_visualIndex(-1) +{ +} + +BarSeriesRenderCache::~BarSeriesRenderCache() +{ +} + +void BarSeriesRenderCache::cleanup(TextureHelper *texHelper) +{ + m_renderArray.clear(); + m_sliceArray.clear(); + + SeriesRenderCache::cleanup(texHelper); +} + +QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/engine/barseriesrendercache_p.h b/src/datavisualization/engine/barseriesrendercache_p.h new file mode 100644 index 00000000..4e169300 --- /dev/null +++ b/src/datavisualization/engine/barseriesrendercache_p.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** 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 BARSERIESRENDERCACHE_P_H +#define BARSERIESRENDERCACHE_P_H + +#include "datavisualizationglobal_p.h" +#include "seriesrendercache_p.h" +#include "qbar3dseries_p.h" +#include "barrenderitem_p.h" + +QT_BEGIN_NAMESPACE_DATAVISUALIZATION + +class BarSeriesRenderCache : public SeriesRenderCache +{ +public: + BarSeriesRenderCache(QAbstract3DSeries *series, Abstract3DRenderer *renderer); + virtual ~BarSeriesRenderCache(); + + void cleanup(TextureHelper *texHelper); + + inline BarRenderItemArray &renderArray() { return m_renderArray; } + inline QBar3DSeries *series() const { return static_cast<QBar3DSeries *>(m_series); } + inline QVector<BarRenderSliceItem> &sliceArray() { return m_sliceArray; } + inline void setVisualIndex(int index) { m_visualIndex = index; } + inline int visualIndex() {return m_visualIndex; } + +protected: + BarRenderItemArray m_renderArray; + QVector<BarRenderSliceItem> m_sliceArray; + int m_visualIndex; // order of the series is relevant +}; + +QT_END_NAMESPACE_DATAVISUALIZATION + +#endif diff --git a/src/datavisualization/engine/engine.pri b/src/datavisualization/engine/engine.pri index 9c2e71e4..96fa7fa9 100644 --- a/src/datavisualization/engine/engine.pri +++ b/src/datavisualization/engine/engine.pri @@ -26,7 +26,9 @@ HEADERS += $$PWD/qabstract3dgraph_p.h \ $$PWD/q3dobject.h \ $$PWD/q3dobject_p.h \ $$PWD/q3dscene_p.h \ - $$PWD/surfaceseriesrendercache_p.h + $$PWD/surfaceseriesrendercache_p.h \ + $$PWD/barseriesrendercache_p.h \ + $$PWD/scatterseriesrendercache_p.h SOURCES += $$PWD/qabstract3dgraph.cpp \ $$PWD/q3dbars.cpp \ @@ -48,7 +50,9 @@ SOURCES += $$PWD/qabstract3dgraph.cpp \ $$PWD/q3dlight.cpp \ $$PWD/q3dobject.cpp \ $$PWD/q3dscene.cpp \ - $$PWD/surfaceseriesrendercache.cpp + $$PWD/surfaceseriesrendercache.cpp \ + $$PWD/barseriesrendercache.cpp \ + $$PWD/scatterseriesrendercache.cpp RESOURCES += engine/engine.qrc diff --git a/src/datavisualization/engine/scatter3dcontroller.cpp b/src/datavisualization/engine/scatter3dcontroller.cpp index b45a956d..05c0efe7 100644 --- a/src/datavisualization/engine/scatter3dcontroller.cpp +++ b/src/datavisualization/engine/scatter3dcontroller.cpp @@ -83,9 +83,6 @@ void Scatter3DController::addSeries(QAbstract3DSeries *series) Abstract3DController::addSeries(series); - if (series->isVisible()) - adjustValueAxisRange(); - QScatter3DSeries *scatterSeries = static_cast<QScatter3DSeries *>(series); if (scatterSeries->selectedItem() != invalidSelectionIndex()) setSelectedItem(scatterSeries->selectedItem(), scatterSeries); @@ -101,7 +98,7 @@ void Scatter3DController::removeSeries(QAbstract3DSeries *series) setSelectedItem(invalidSelectionIndex(), 0); if (wasVisible) - adjustValueAxisRange(); + adjustAxisRanges(); } QList<QScatter3DSeries *> Scatter3DController::scatterSeriesList() @@ -121,9 +118,11 @@ void Scatter3DController::handleArrayReset() { QScatter3DSeries *series = static_cast<QScatterDataProxy *>(sender())->series(); if (series->isVisible()) { - adjustValueAxisRange(); + adjustAxisRanges(); m_isDataDirty = true; } + if (!m_changedSeriesList.contains(series)) + m_changedSeriesList.append(series); setSelectedItem(m_selectedItem, m_selectedItemSeries); series->d_ptr->markItemLabelDirty(); emitNeedRender(); @@ -135,9 +134,11 @@ void Scatter3DController::handleItemsAdded(int startIndex, int count) Q_UNUSED(count) QScatter3DSeries *series = static_cast<QScatterDataProxy *>(sender())->series(); if (series->isVisible()) { - adjustValueAxisRange(); + adjustAxisRanges(); m_isDataDirty = true; } + if (!m_changedSeriesList.contains(series)) + m_changedSeriesList.append(series); emitNeedRender(); } @@ -147,10 +148,12 @@ void Scatter3DController::handleItemsChanged(int startIndex, int count) Q_UNUSED(count) QScatter3DSeries *series = static_cast<QScatterDataProxy *>(sender())->series(); if (series->isVisible()) { - adjustValueAxisRange(); + adjustAxisRanges(); m_isDataDirty = true; series->d_ptr->markItemLabelDirty(); } + if (!m_changedSeriesList.contains(series)) + m_changedSeriesList.append(series); emitNeedRender(); } @@ -173,9 +176,11 @@ void Scatter3DController::handleItemsRemoved(int startIndex, int count) } if (series->isVisible()) { - adjustValueAxisRange(); + adjustAxisRanges(); m_isDataDirty = true; } + if (!m_changedSeriesList.contains(series)) + m_changedSeriesList.append(series); if (m_recordInsertsAndRemoves) { InsertRemoveRecord record(false, startIndex, count, series); @@ -200,9 +205,11 @@ void Scatter3DController::handleItemsInserted(int startIndex, int count) } if (series->isVisible()) { - adjustValueAxisRange(); + adjustAxisRanges(); m_isDataDirty = true; } + if (!m_changedSeriesList.contains(series)) + m_changedSeriesList.append(series); if (m_recordInsertsAndRemoves) { InsertRemoveRecord record(true, startIndex, count, series); @@ -231,7 +238,7 @@ void Scatter3DController::handleAxisAutoAdjustRangeChangedInOrientation( { Q_UNUSED(orientation) Q_UNUSED(autoAdjust) - adjustValueAxisRange(); + adjustAxisRanges(); } void Scatter3DController::handleAxisRangeChangedBySender(QObject *sender) @@ -242,13 +249,6 @@ void Scatter3DController::handleAxisRangeChangedBySender(QObject *sender) setSelectedItem(m_selectedItem, m_selectedItemSeries); } -void Scatter3DController::handleSeriesVisibilityChangedBySender(QObject *sender) -{ - Abstract3DController::handleSeriesVisibilityChangedBySender(sender); - - adjustValueAxisRange(); -} - void Scatter3DController::handlePendingClick() { int index = m_renderer->clickedIndex(); @@ -333,7 +333,7 @@ void Scatter3DController::clearSelection() setSelectedItem(invalidSelectionIndex(), 0); } -void Scatter3DController::adjustValueAxisRange() +void Scatter3DController::adjustAxisRanges() { QValue3DAxis *valueAxisX = static_cast<QValue3DAxis *>(m_axisX); QValue3DAxis *valueAxisY = static_cast<QValue3DAxis *>(m_axisY); diff --git a/src/datavisualization/engine/scatter3dcontroller_p.h b/src/datavisualization/engine/scatter3dcontroller_p.h index 53d24549..1194bc3a 100644 --- a/src/datavisualization/engine/scatter3dcontroller_p.h +++ b/src/datavisualization/engine/scatter3dcontroller_p.h @@ -108,8 +108,8 @@ public: virtual void handleAxisAutoAdjustRangeChangedInOrientation( QAbstract3DAxis::AxisOrientation orientation, bool autoAdjust); virtual void handleAxisRangeChangedBySender(QObject *sender); - virtual void handleSeriesVisibilityChangedBySender(QObject *sender); virtual void handlePendingClick(); + virtual void adjustAxisRanges(); public slots: void handleArrayReset(); @@ -125,7 +125,6 @@ protected: virtual void startRecordingRemovesAndInserts(); private: - void adjustValueAxisRange(); Q_DISABLE_COPY(Scatter3DController) }; diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp index f5336832..c6e243a1 100644 --- a/src/datavisualization/engine/scatter3drenderer.cpp +++ b/src/datavisualization/engine/scatter3drenderer.cpp @@ -26,6 +26,7 @@ #include "utils_p.h" #include "q3dlight.h" #include "qscatter3dseries_p.h" +#include "scatterseriesrendercache_p.h" #include <QtGui/QMatrix4x4> #include <QtGui/QMouseEvent> @@ -83,15 +84,17 @@ Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller) m_heightNormalizer(1.0f), m_scaleFactor(0), m_selectedItemIndex(Scatter3DController::invalidSelectionIndex()), - m_selectedItemTotalIndex(Scatter3DController::invalidSelectionIndex()), - m_selectedItemSeriesIndex(Scatter3DController::invalidSelectionIndex()), - m_selectedSeries(0), + m_selectedSeriesCache(0), m_areaSize(QSizeF(0.0, 0.0)), m_dotSizeScale(1.0f), m_hasHeightAdjustmentChanged(true), m_backgroundMargin(defaultMaxSize), m_maxItemSize(0.0f), - m_clickedIndex(Scatter3DController::invalidSelectionIndex()) + m_clickedIndex(Scatter3DController::invalidSelectionIndex()), + m_havePointSeries(false), + m_haveMeshSeries(false), + m_haveUniformColorMeshSeries(false), + m_haveGradientMeshSeries(false) { m_axisCacheY.setScale(2.0f); m_axisCacheY.setTranslate(-1.0f); @@ -159,32 +162,99 @@ void Scatter3DRenderer::initializeOpenGL() loadBackgroundMesh(); } -void Scatter3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList, - bool updateVisibility) +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) { + ScatterSeriesRenderCache *cache = static_cast<ScatterSeriesRenderCache *>(baseCache); + if (cache->isVisible() && cache->dataDirty()) { + const QScatter3DSeries *currentSeries = cache->series(); + ScatterRenderItemArray &renderArray = cache->renderArray(); + QScatterDataProxy *dataProxy = currentSeries->dataProxy(); + const QScatterDataArray &dataArray = *dataProxy->array(); + int dataSize = dataArray.size(); + totalDataSize += dataSize; + 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); + } + } + cache->setDataDirty(false); + } + } + + if (totalDataSize) { + m_dotSizeScale = GLfloat(qBound(defaultMinSize, 2.0f / float(qSqrt(qreal(totalDataSize))), + defaultMaxSize)); + } + + updateSelectedItem(m_selectedItemIndex, + m_selectedSeriesCache ? m_selectedSeriesCache->series() : 0); +} + +void Scatter3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList) { - Abstract3DRenderer::updateSeries(seriesList, updateVisibility); + Abstract3DRenderer::updateSeries(seriesList); - int seriesCount = m_visibleSeriesList.size(); + int seriesCount = seriesList.size(); float maxItemSize = 0.0f; float itemSize = 0.0f; + bool noSelection = true; - if (m_cachedItemSize.size() != seriesCount) - m_cachedItemSize.resize(seriesCount); + m_havePointSeries = false; + m_haveMeshSeries = false; + m_haveUniformColorMeshSeries = false; + m_haveGradientMeshSeries = false; - bool noSelection = true; - for (int series = 0; series < seriesCount; series++) { - QScatter3DSeries *scatterSeries = - static_cast<QScatter3DSeries *>(m_visibleSeriesList.at(series).series()); - itemSize = scatterSeries->itemSize(); - if (maxItemSize < itemSize) - maxItemSize = itemSize; - if (m_cachedItemSize.at(series) != itemSize) - m_cachedItemSize[series] = itemSize; - if (noSelection - && scatterSeries->selectedItem() != QScatter3DSeries::invalidSelectionIndex() - && m_selectionLabel != m_visibleSeriesList.at(series).itemLabel()) { - m_selectionLabelDirty = true; - noSelection = false; + for (int i = 0; i < seriesCount; i++) { + QScatter3DSeries *scatterSeries = static_cast<QScatter3DSeries *>(seriesList[i]); + if (scatterSeries->isVisible()) { + ScatterSeriesRenderCache *cache = + static_cast<ScatterSeriesRenderCache *>(m_renderCacheList.value(scatterSeries)); + itemSize = scatterSeries->itemSize(); + if (maxItemSize < itemSize) + maxItemSize = itemSize; + if (cache->itemSize() != itemSize) + cache->setItemSize(itemSize); + if (noSelection + && scatterSeries->selectedItem() != QScatter3DSeries::invalidSelectionIndex() + && m_selectionLabel != cache->itemLabel()) { + m_selectionLabelDirty = true; + noSelection = false; + } + + if (cache->mesh() == QAbstract3DSeries::MeshPoint) { + m_havePointSeries = true; + } else { + m_haveMeshSeries = true; + if (cache->colorStyle() == Q3DTheme::ColorStyleUniform) + m_haveUniformColorMeshSeries = true; + else + m_haveGradientMeshSeries = true; + } } } m_maxItemSize = maxItemSize; @@ -197,53 +267,9 @@ void Scatter3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesLis m_selectionLabelDirty = true; } -void Scatter3DRenderer::updateData() +SeriesRenderCache *Scatter3DRenderer::createNewCache(QAbstract3DSeries *series) { - int seriesCount = m_visibleSeriesList.size(); - 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; - - if (m_renderingArrays.size() != seriesCount) - m_renderingArrays.resize(seriesCount); - - for (int series = 0; series < seriesCount; series++) { - QScatterDataProxy *dataProxy = - static_cast<QScatter3DSeries *>(m_visibleSeriesList.at(series).series())->dataProxy(); - const QScatterDataArray &dataArray = *dataProxy->array(); - int dataSize = dataArray.size(); - totalDataSize += dataSize; - - if (dataSize != m_renderingArrays.at(series).size()) - m_renderingArrays[series].resize(dataSize); - - for (int i = 0; i < dataSize; i++) { - QVector3D dotPos = dataArray.at(i).position(); - ScatterRenderItem &renderItem = m_renderingArrays[series][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); - } - } - } - m_dotSizeScale = GLfloat(qBound(defaultMinSize, 2.0f / float(qSqrt(qreal(totalDataSize))), - defaultMaxSize)); - - updateSelectedItem(m_selectedItemIndex, m_selectedSeries); + return new ScatterSeriesRenderCache(series, this); } void Scatter3DRenderer::updateScene(Q3DScene *scene) @@ -306,8 +332,6 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) QMatrix4x4 viewMatrix = activeCamera->d_ptr->viewMatrix(); QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix; - int seriesCount = m_visibleSeriesList.size(); - // Calculate label flipping if (viewMatrix.row(0).x() > 0) m_zFlipped = false; @@ -342,25 +366,8 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) QMatrix4x4 depthProjectionMatrix; QMatrix4x4 depthProjectionViewMatrix; - // Check if we have any series with points - bool havePointSeries = false; - bool haveMeshSeries = false; - bool haveUniformColorMeshSeries = false; - bool haveGradientMeshSeries = false; - for (int i = 0; i < seriesCount; i++) { - if (m_visibleSeriesList.at(i).mesh() == QAbstract3DSeries::MeshPoint) { - havePointSeries = true; - } else { - haveMeshSeries = true; - if (m_visibleSeriesList.at(i).colorStyle() == Q3DTheme::ColorStyleUniform) - haveUniformColorMeshSeries = true; - else - haveGradientMeshSeries = true; - } - } - #if !defined(QT_OPENGL_ES_2) - if (havePointSeries) { + if (m_havePointSeries) { glEnable(GL_POINT_SMOOTH); glEnable(GL_PROGRAM_POINT_SIZE); } @@ -401,60 +408,63 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) depthProjectionViewMatrix = depthProjectionMatrix * depthViewMatrix; // Draw dots to depth buffer - for (int series = 0; series < seriesCount; series++) { - ObjectHelper *dotObj = m_visibleSeriesList.at(series).object(); - QQuaternion seriesRotation = m_visibleSeriesList.at(series).meshRotation(); - bool drawingPoints = (m_visibleSeriesList.at(series).mesh() == QAbstract3DSeries::MeshPoint); - - float itemSize = m_cachedItemSize.at(series) / itemScaler; - if (itemSize == 0.0f) - itemSize = m_dotSizeScale; - if (drawingPoints) { - // Scale points based on shadow quality for shadows, not by zoom level - glPointSize(itemSize * 100.0f * m_shadowQualityMultiplier); - } - QVector3D modelScaler(itemSize, itemSize, itemSize); - - for (int dot = 0; dot < m_renderingArrays.at(series).size(); dot++) { - const ScatterRenderItem &item = m_renderingArrays.at(series).at(dot); - if (!item.isVisible()) - 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); - } - - MVPMatrix = depthProjectionViewMatrix * modelMatrix; - - m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix); - + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + if (baseCache->isVisible()) { + ScatterSeriesRenderCache *cache = static_cast<ScatterSeriesRenderCache *>(baseCache); + ObjectHelper *dotObj = cache->object(); + QQuaternion seriesRotation(cache->meshRotation()); + const ScatterRenderItemArray &renderArray = cache->renderArray(); + const int renderArraySize = renderArray.size(); + bool drawingPoints = (cache->mesh() == QAbstract3DSeries::MeshPoint); + float itemSize = cache->itemSize() / itemScaler; + if (itemSize == 0.0f) + itemSize = m_dotSizeScale; if (drawingPoints) { - m_drawer->drawPoint(m_depthShader); - } 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()); + // Scale points based on shadow quality for shadows, not by zoom level + glPointSize(itemSize * 100.0f * m_shadowQualityMultiplier); + } + QVector3D modelScaler(itemSize, itemSize, itemSize); + for (int dot = 0; dot < renderArraySize; dot++) { + const ScatterRenderItem &item = renderArray.at(dot); + if (!item.isVisible()) + 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); + } + + MVPMatrix = depthProjectionViewMatrix * modelMatrix; + + m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix); + + if (drawingPoints) { + m_drawer->drawPoint(m_depthShader); + } 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()); + } } } } @@ -481,7 +491,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) // Skip selection mode drawing if we have no selection mode if (m_cachedSelectionMode > QAbstract3DGraph::SelectionNone - && SelectOnScene == m_selectionState && seriesCount > 0) { + && SelectOnScene == m_selectionState && m_visibleSeriesCount > 0) { // Draw dots to selection buffer glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer); glViewport(0, 0, @@ -493,70 +503,67 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled - int arraySize = 0; - int totalArraySize = 0; - int dotNo = 0; - - // Init previous to opposite of first to ensure we change binding for first series - bool previousDrawingPoints = (m_visibleSeriesList.at(0).mesh() != QAbstract3DSeries::MeshPoint); - for (int series = 0; series < seriesCount; series++) { - ObjectHelper *dotObj = m_visibleSeriesList.at(series).object(); - QQuaternion seriesRotation = m_visibleSeriesList.at(series).meshRotation(); - bool drawingPoints = (m_visibleSeriesList.at(series).mesh() == QAbstract3DSeries::MeshPoint); - - float itemSize = m_cachedItemSize.at(series) / itemScaler; - if (itemSize == 0.0f) - itemSize = m_dotSizeScale; + bool previousDrawingPoints = false; + int totalIndex = 0; + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + if (baseCache->isVisible()) { + ScatterSeriesRenderCache *cache = + static_cast<ScatterSeriesRenderCache *>(baseCache); + ObjectHelper *dotObj = cache->object(); + QQuaternion seriesRotation(cache->meshRotation()); + const ScatterRenderItemArray &renderArray = cache->renderArray(); + const int renderArraySize = renderArray.size(); + bool drawingPoints = (cache->mesh() == QAbstract3DSeries::MeshPoint); + float itemSize = cache->itemSize() / itemScaler; + if (itemSize == 0.0f) + itemSize = m_dotSizeScale; #if !defined(QT_OPENGL_ES_2) - if (drawingPoints) - glPointSize(itemSize * activeCamera->zoomLevel()); // Scale points based on zoom -#endif - QVector3D modelScaler(itemSize, itemSize, itemSize); - - // Rebind selection shader if it has changed - if (drawingPoints != previousDrawingPoints) { - previousDrawingPoints = drawingPoints; if (drawingPoints) - selectionShader = pointSelectionShader; - else - selectionShader = m_selectionShader; - - selectionShader->bind(); - } - arraySize = m_renderingArrays.at(series).size(); - totalArraySize += arraySize; + glPointSize(itemSize * activeCamera->zoomLevel()); // Scale points based on zoom +#endif + QVector3D modelScaler(itemSize, itemSize, itemSize); - if (totalArraySize > 0xfffffe) // Max possible different selection colors, 0xffffff being skipColor - qFatal("Too many objects"); + // Rebind selection shader if it has changed + if (!totalIndex || drawingPoints != previousDrawingPoints) { + previousDrawingPoints = drawingPoints; + if (drawingPoints) + selectionShader = pointSelectionShader; + else + selectionShader = m_selectionShader; - for (int dot = 0; dot < arraySize; dot++) { - const ScatterRenderItem &item = m_renderingArrays.at(series).at(dot); - if (!item.isVisible()) - 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); + selectionShader->bind(); + } + cache->setSelectionIndexOffset(totalIndex); + for (int dot = 0; dot < renderArraySize; dot++) { + const ScatterRenderItem &item = renderArray.at(dot); + if (!item.isVisible()) { + totalIndex++; + 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); + } + + MVPMatrix = projectionViewMatrix * modelMatrix; + + QVector4D dotColor = indexToSelectionColor(totalIndex++); + dotColor /= 255.0f; + + selectionShader->setUniformValue(selectionShader->MVP(), MVPMatrix); + selectionShader->setUniformValue(selectionShader->color(), dotColor); + + if (drawingPoints) + m_drawer->drawPoint(selectionShader); + else + m_drawer->drawSelectionObject(selectionShader, dotObj); } - - MVPMatrix = projectionViewMatrix * modelMatrix; - - QVector4D dotColor = indexToSelectionColor(dotNo); - dotColor /= 255.0f; - - selectionShader->setUniformValue(selectionShader->MVP(), MVPMatrix); - selectionShader->setUniformValue(selectionShader->color(), dotColor); - - if (drawingPoints) - m_drawer->drawPoint(selectionShader); - else - m_drawer->drawSelectionObject(selectionShader, dotObj); - dotNo++; } } @@ -584,15 +591,14 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) GLuint gradientTexture = 0; bool dotSelectionFound = false; ScatterRenderItem *selectedItem(0); - int dotNo = 0; QVector3D baseColor; QVector3D dotColor; bool previousDrawingPoints = false; Q3DTheme::ColorStyle previousMeshColorStyle = Q3DTheme::ColorStyleUniform; - if (haveMeshSeries) { + if (m_haveMeshSeries) { // Set unchanging shader bindings - if (haveGradientMeshSeries) { + if (m_haveGradientMeshSeries) { m_dotGradientShader->bind(); m_dotGradientShader->setUniformValue(m_dotGradientShader->lightP(), lightPos); m_dotGradientShader->setUniformValue(m_dotGradientShader->view(), viewMatrix); @@ -600,7 +606,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) m_cachedTheme->ambientLightStrength()); m_dotGradientShader->setUniformValue(m_dotGradientShader->lightColor(), lightColor); } - if (haveUniformColorMeshSeries) { + if (m_haveUniformColorMeshSeries) { m_dotShader->bind(); m_dotShader->setUniformValue(m_dotShader->lightP(), lightPos); m_dotShader->setUniformValue(m_dotShader->view(), viewMatrix); @@ -620,160 +626,170 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) dotShader->bind(); } - for (int series = 0; series < seriesCount; series++) { - const SeriesRenderCache ¤tSeries = m_visibleSeriesList.at(series); - QQuaternion seriesRotation = currentSeries.meshRotation(); - ObjectHelper *dotObj = currentSeries.object(); - bool drawingPoints = (currentSeries.mesh() == QAbstract3DSeries::MeshPoint); - Q3DTheme::ColorStyle colorStyle = currentSeries.colorStyle(); - bool colorStyleIsUniform = (colorStyle == Q3DTheme::ColorStyleUniform); - bool useColor = colorStyleIsUniform || drawingPoints; - - float itemSize = m_cachedItemSize.at(series) / itemScaler; - if (itemSize == 0.0f) - itemSize = m_dotSizeScale; + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + if (baseCache->isVisible()) { + ScatterSeriesRenderCache *cache = + static_cast<ScatterSeriesRenderCache *>(baseCache); + ObjectHelper *dotObj = cache->object(); + QQuaternion seriesRotation(cache->meshRotation()); + ScatterRenderItemArray &renderArray = cache->renderArray(); + const int renderArraySize = renderArray.size(); + bool selectedSeries = m_cachedSelectionMode > QAbstract3DGraph::SelectionNone + && (m_selectedSeriesCache == cache); + bool drawingPoints = (cache->mesh() == QAbstract3DSeries::MeshPoint); + Q3DTheme::ColorStyle colorStyle = cache->colorStyle(); + bool colorStyleIsUniform = (colorStyle == Q3DTheme::ColorStyleUniform); + bool useColor = colorStyleIsUniform || drawingPoints; + bool rangeGradientPoints = drawingPoints + && (colorStyle == Q3DTheme::ColorStyleRangeGradient); + float itemSize = cache->itemSize() / itemScaler; + if (itemSize == 0.0f) + itemSize = m_dotSizeScale; #if !defined(QT_OPENGL_ES_2) - if (drawingPoints) - glPointSize(itemSize * activeCamera->zoomLevel()); // Scale points based on zoom + if (drawingPoints) + glPointSize(itemSize * activeCamera->zoomLevel()); // Scale points based on zoom #endif - QVector3D modelScaler(itemSize, itemSize, itemSize); - - // Rebind shader if it has changed - if (drawingPoints != previousDrawingPoints - || (!drawingPoints && - (colorStyleIsUniform != (previousMeshColorStyle == Q3DTheme::ColorStyleUniform)))) { - previousDrawingPoints = drawingPoints; - if (drawingPoints) { - dotShader = pointSelectionShader; - } else { - if (colorStyleIsUniform) - dotShader = m_dotShader; - else - dotShader = m_dotGradientShader; + QVector3D modelScaler(itemSize, itemSize, itemSize); + + // Rebind shader if it has changed + if (drawingPoints != previousDrawingPoints + || (!drawingPoints && + (colorStyleIsUniform != (previousMeshColorStyle + == Q3DTheme::ColorStyleUniform)))) { + previousDrawingPoints = drawingPoints; + if (drawingPoints) { + dotShader = pointSelectionShader; + } else { + if (colorStyleIsUniform) + dotShader = m_dotShader; + else + dotShader = m_dotGradientShader; + } + dotShader->bind(); } - dotShader->bind(); - } - if (!drawingPoints && !colorStyleIsUniform && previousMeshColorStyle != colorStyle) { - if (colorStyle == Q3DTheme::ColorStyleObjectGradient) { - m_dotGradientShader->setUniformValue(m_dotGradientShader->gradientMin(), 0.0f); - m_dotGradientShader->setUniformValue(m_dotGradientShader->gradientHeight(), 0.5f); - } else { - // Each ball is of uniform color according to its Y-coordinate - m_dotGradientShader->setUniformValue(m_dotGradientShader->gradientHeight(), 0.0f); + if (!drawingPoints && !colorStyleIsUniform && previousMeshColorStyle != colorStyle) { + if (colorStyle == Q3DTheme::ColorStyleObjectGradient) { + m_dotGradientShader->setUniformValue(m_dotGradientShader->gradientMin(), 0.0f); + m_dotGradientShader->setUniformValue(m_dotGradientShader->gradientHeight(), + 0.5f); + } else { + // Each dot is of uniform color according to its Y-coordinate + m_dotGradientShader->setUniformValue(m_dotGradientShader->gradientHeight(), + 0.0f); + } } - } - if (!drawingPoints) - previousMeshColorStyle = colorStyle; + if (!drawingPoints) + previousMeshColorStyle = colorStyle; - if (useColor) { - baseColor = currentSeries.baseColor(); - dotColor = baseColor; - } + if (useColor) { + baseColor = cache->baseColor(); + dotColor = baseColor; + } + for (int i = 0; i < renderArraySize; i++) { + ScatterRenderItem &item = renderArray[i]; + if (!item.isVisible()) + continue; - int seriesSize = m_renderingArrays.at(series).size(); - for (int dot = 0; dot < seriesSize; dot++) { - ScatterRenderItem &item = m_renderingArrays[series][dot]; - if (!item.isVisible()) - 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); + 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); + } + modelMatrix.scale(modelScaler); + itModelMatrix.scale(modelScaler); } - modelMatrix.scale(modelScaler); - itModelMatrix.scale(modelScaler); - } #ifdef SHOW_DEPTH_TEXTURE_SCENE - MVPMatrix = depthProjectionViewMatrix * modelMatrix; + MVPMatrix = depthProjectionViewMatrix * modelMatrix; #else - MVPMatrix = projectionViewMatrix * modelMatrix; + MVPMatrix = projectionViewMatrix * modelMatrix; #endif - if (useColor) - dotColor = baseColor; - else - gradientTexture = currentSeries.baseGradientTexture(); - - GLfloat lightStrength = m_cachedTheme->lightStrength(); - if (m_cachedSelectionMode > QAbstract3DGraph::SelectionNone - && (m_selectedItemTotalIndex == dotNo)) { - if (useColor) - dotColor = currentSeries.singleHighlightColor(); - else - gradientTexture = currentSeries.singleHighlightGradientTexture(); - lightStrength = m_cachedTheme->highlightLightStrength(); - // Insert data to ScatterRenderItem. We have no ownership, don't delete the previous one - 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()); - } + if (useColor) { + if (rangeGradientPoints) { + // Drawing points with range gradient + // Get color from gradient based on items y position converted to percent + int position = int(item.translation().y() * 50.0f) + 50; + dotColor = Utils::vectorFromColor( + cache->gradientImage().pixel(0, position)); + } else { + dotColor = baseColor; + } + } else { + gradientTexture = cache->baseGradientTexture(); + } - dotShader->setUniformValue(dotShader->MVP(), MVPMatrix); - if (useColor) { - if (colorStyle == Q3DTheme::ColorStyleRangeGradient && - (m_selectedItemTotalIndex != dotNo)) { - // Drawing points with range gradient - // Get color from gradient based on items y position converted to percents - int position = int(item.translation().y() * 50.0f) + 50; - dotColor = Utils::vectorFromColor( - currentSeries.gradientImage().pixel(0, position)); + GLfloat lightStrength = m_cachedTheme->lightStrength(); + if (selectedSeries && (m_selectedItemIndex == i)) { + if (useColor) + dotColor = cache->singleHighlightColor(); + else + gradientTexture = cache->singleHighlightGradientTexture(); + lightStrength = m_cachedTheme->highlightLightStrength(); + // Insert data to ScatterRenderItem + // We don't have ownership, so don't delete the previous one + selectedItem = &item; + dotSelectionFound = true; + // Save selected item size (adjusted with font size) for selection label + // positioning + selectedItemSize = itemSize + (m_cachedTheme->font().pointSizeF() / 500.0f); } - dotShader->setUniformValue(dotShader->color(), dotColor); - } else if (colorStyle == Q3DTheme::ColorStyleRangeGradient) { - dotShader->setUniformValue(dotShader->gradientMin(), - (item.translation().y() + 1.0f) / 2.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->shadowQ(), m_shadowQualityToShader); - dotShader->setUniformValue(dotShader->depth(), depthMVPMatrix); - dotShader->setUniformValue(dotShader->lightS(), lightStrength / 10.0f); + // Set shader bindings + dotShader->setUniformValue(dotShader->model(), modelMatrix); + dotShader->setUniformValue(dotShader->nModel(), + itModelMatrix.inverted().transposed()); + } - // Draw the object - m_drawer->drawObject(dotShader, dotObj, gradientTexture, m_depthTexture); - } else { - // Draw the object - m_drawer->drawPoint(dotShader); + 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); } - } else +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + if (!drawingPoints) { + // Set shadow shader bindings + QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + dotShader->setUniformValue(dotShader->shadowQ(), m_shadowQualityToShader); + 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 + m_drawer->drawPoint(dotShader); + } + } else #endif - { - if (!drawingPoints) { - // Set shadowless shader bindings - dotShader->setUniformValue(dotShader->lightS(), lightStrength); - // Draw the object - m_drawer->drawObject(dotShader, dotObj, gradientTexture); - } else { - // Draw the object - m_drawer->drawPoint(dotShader); + { + if (!drawingPoints) { + // Set shadowless shader bindings + dotShader->setUniformValue(dotShader->lightS(), lightStrength); + // Draw the object + m_drawer->drawObject(dotShader, dotObj, gradientTexture); + } else { + // Draw the object + m_drawer->drawPoint(dotShader); + } } } - dotNo++; } } #if !defined(QT_OPENGL_ES_2) - if (havePointSeries) { + if (m_havePointSeries) { glDisable(GL_POINT_SMOOTH); glDisable(GL_PROGRAM_POINT_SIZE); } @@ -1263,7 +1279,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) || !labelItem.textureId() || m_selectionLabelDirty) { QString labelText = selectionLabel(); if (labelText.isNull() || m_selectionLabelDirty) { - labelText = m_visibleSeriesList[m_selectedItemSeriesIndex].itemLabel(); + labelText = m_selectedSeriesCache->itemLabel(); setSelectionLabel(labelText); m_selectionLabelDirty = false; } @@ -1505,26 +1521,18 @@ void Scatter3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCa glDisable(GL_POLYGON_OFFSET_FILL); } -void Scatter3DRenderer::updateSelectedItem(int index, const QScatter3DSeries *series) +void Scatter3DRenderer::updateSelectedItem(int index, QScatter3DSeries *series) { m_selectionDirty = true; m_selectionLabelDirty = true; - m_selectedSeries = series; + m_selectedSeriesCache = + static_cast<ScatterSeriesRenderCache *>(m_renderCacheList.value(series, 0)); m_selectedItemIndex = Scatter3DController::invalidSelectionIndex(); - m_selectedItemTotalIndex = Scatter3DController::invalidSelectionIndex(); - m_selectedItemSeriesIndex = Scatter3DController::invalidSelectionIndex(); - if (!m_renderingArrays.isEmpty() && index != Scatter3DController::invalidSelectionIndex()) { - int totalIndex = 0; - for (int i = 0; i < m_visibleSeriesList.size(); i++) { - if (m_visibleSeriesList.at(i).series() == series) { - m_selectedItemSeriesIndex = i; - m_selectedItemIndex = index; - m_selectedItemTotalIndex = index + totalIndex; - break; - } - totalIndex += m_renderingArrays.at(i).size(); - } + if (m_selectedSeriesCache) { + const ScatterRenderItemArray &renderArray = m_selectedSeriesCache->renderArray(); + if (index < renderArray.size() && index >= 0) + m_selectedItemIndex = index; } } @@ -1767,17 +1775,22 @@ void Scatter3DRenderer::selectionColorToSeriesAndIndex(const QVector4D &color, index = Scatter3DController::invalidSelectionIndex(); m_clickedType = QAbstract3DGraph::ElementAxisYLabel; } else { - index = int(color.x()) + int totalIndex = int(color.x()) + (int(color.y()) << 8) + (int(color.z()) << 16); // Find the series and adjust the index accordingly - for (int i = 0; i < m_renderingArrays.size(); i++) { - if (index < m_renderingArrays.at(i).size()) { - series = m_visibleSeriesList.at(i).series(); - m_clickedType = QAbstract3DGraph::ElementSeries; - return; // Valid found and already set to return parameters, so we can return - } else { - index -= m_renderingArrays.at(i).size(); + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + if (baseCache->isVisible()) { + ScatterSeriesRenderCache *cache = + static_cast<ScatterSeriesRenderCache *>(baseCache); + int offset = cache->selectionIndexOffset(); + if (totalIndex >= offset + && totalIndex < (offset + cache->renderArray().size())) { + index = totalIndex - offset; + series = cache->series(); + m_clickedType = QAbstract3DGraph::ElementSeries; + return; + } } } } diff --git a/src/datavisualization/engine/scatter3drenderer_p.h b/src/datavisualization/engine/scatter3drenderer_p.h index 8b4d0759..ab45381e 100644 --- a/src/datavisualization/engine/scatter3drenderer_p.h +++ b/src/datavisualization/engine/scatter3drenderer_p.h @@ -46,6 +46,7 @@ class ObjectHelper; class LabelItem; class Q3DScene; class QAbstractAxisPrivate; +class ScatterSeriesRenderCache; class QT_DATAVISUALIZATION_EXPORT Scatter3DRenderer : public Abstract3DRenderer { @@ -83,26 +84,27 @@ private: GLfloat m_heightNormalizer; GLfloat m_scaleFactor; int m_selectedItemIndex; - int m_selectedItemTotalIndex; - int m_selectedItemSeriesIndex; - const QScatter3DSeries *m_selectedSeries; + ScatterSeriesRenderCache *m_selectedSeriesCache; QSizeF m_areaSize; GLfloat m_dotSizeScale; QVector3D m_translationOffset; bool m_hasHeightAdjustmentChanged; ScatterRenderItem m_dummyRenderItem; - QVector<ScatterRenderItemArray> m_renderingArrays; GLfloat m_backgroundMargin; GLfloat m_maxItemSize; - QVector<float> m_cachedItemSize; int m_clickedIndex; + bool m_havePointSeries; + bool m_haveMeshSeries; + bool m_haveUniformColorMeshSeries; + bool m_haveGradientMeshSeries; public: explicit Scatter3DRenderer(Scatter3DController *controller); ~Scatter3DRenderer(); - void updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility); void updateData(); + void updateSeries(const QList<QAbstract3DSeries *> &seriesList); + SeriesRenderCache *createNewCache(QAbstract3DSeries *series); void updateScene(Q3DScene *scene); inline int clickedIndex() const { return m_clickedIndex; } @@ -145,7 +147,7 @@ private: friend class ScatterRenderItem; public slots: - void updateSelectedItem(int index, const QScatter3DSeries *series); + void updateSelectedItem(int index, QScatter3DSeries *series); private: QVector4D indexToSelectionColor(GLint index); diff --git a/src/datavisualization/engine/scatterseriesrendercache.cpp b/src/datavisualization/engine/scatterseriesrendercache.cpp new file mode 100644 index 00000000..2a2c5393 --- /dev/null +++ b/src/datavisualization/engine/scatterseriesrendercache.cpp @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** 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 "scatterseriesrendercache_p.h" +#include "scatter3drenderer_p.h" + +QT_BEGIN_NAMESPACE_DATAVISUALIZATION + +ScatterSeriesRenderCache::ScatterSeriesRenderCache(QAbstract3DSeries *series, + Abstract3DRenderer *renderer) + : SeriesRenderCache(series, renderer), + m_itemSize(0.0f), + m_selectionIndexOffset(0) +{ +} + +ScatterSeriesRenderCache::~ScatterSeriesRenderCache() +{ +} + +void ScatterSeriesRenderCache::cleanup(TextureHelper *texHelper) +{ + m_renderArray.clear(); + + SeriesRenderCache::cleanup(texHelper); +} + +QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/engine/scatterseriesrendercache_p.h b/src/datavisualization/engine/scatterseriesrendercache_p.h new file mode 100644 index 00000000..b2e2d55f --- /dev/null +++ b/src/datavisualization/engine/scatterseriesrendercache_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 SCATTERSERIESRENDERCACHE_P_H +#define SCATTERSERIESRENDERCACHE_P_H + +#include "datavisualizationglobal_p.h" +#include "seriesrendercache_p.h" +#include "qscatter3dseries_p.h" +#include "scatterrenderitem_p.h" + +QT_BEGIN_NAMESPACE_DATAVISUALIZATION + +class ScatterSeriesRenderCache : public SeriesRenderCache +{ +public: + ScatterSeriesRenderCache(QAbstract3DSeries *series, Abstract3DRenderer *renderer); + virtual ~ScatterSeriesRenderCache(); + + void cleanup(TextureHelper *texHelper); + + inline ScatterRenderItemArray &renderArray() { return m_renderArray; } + inline QScatter3DSeries *series() const { return static_cast<QScatter3DSeries *>(m_series); } + inline void setItemSize(float size) { m_itemSize = size; } + inline float itemSize() const { return m_itemSize; } + inline void setSelectionIndexOffset(int offset) { m_selectionIndexOffset = offset; } + inline int selectionIndexOffset() const { return m_selectionIndexOffset; } + +protected: + ScatterRenderItemArray m_renderArray; + float m_itemSize; + int m_selectionIndexOffset; // Temporarily cached value for selection color calculations +}; + +QT_END_NAMESPACE_DATAVISUALIZATION + +#endif diff --git a/src/datavisualization/engine/seriesrendercache.cpp b/src/datavisualization/engine/seriesrendercache.cpp index 7e51df1e..e674ae43 100644 --- a/src/datavisualization/engine/seriesrendercache.cpp +++ b/src/datavisualization/engine/seriesrendercache.cpp @@ -26,15 +26,19 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION const QString smoothString(QStringLiteral("Smooth")); -SeriesRenderCache::SeriesRenderCache() - : m_series(0), +SeriesRenderCache::SeriesRenderCache(QAbstract3DSeries *series, Abstract3DRenderer *renderer) + : m_series(series), m_object(0), m_mesh(QAbstract3DSeries::MeshCube), m_baseUniformTexture(0), m_baseGradientTexture(0), m_gradientImage(0), m_singleHighlightGradientTexture(0), - m_multiHighlightGradientTexture(0) + m_multiHighlightGradientTexture(0), + m_valid(false), + m_visible(false), + m_renderer(renderer), + m_objectDirty(true) { } @@ -42,22 +46,13 @@ SeriesRenderCache::~SeriesRenderCache() { } -void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer *renderer) +void SeriesRenderCache::populate(bool newSeries) { - Q_ASSERT(series); + QAbstract3DSeriesChangeBitField &changeTracker = m_series->d_ptr->m_changeTracker; - bool seriesChanged = false; - - if (m_series != series) { - m_series = series; - seriesChanged = true; - } - - QAbstract3DSeriesChangeBitField &changeTracker = series->d_ptr->m_changeTracker; - - if (seriesChanged || changeTracker.meshChanged || changeTracker.meshSmoothChanged + if (newSeries || changeTracker.meshChanged || changeTracker.meshSmoothChanged || changeTracker.userDefinedMeshChanged) { - m_mesh = series->mesh(); + m_mesh = m_series->mesh(); changeTracker.meshChanged = false; changeTracker.meshSmoothChanged = false; changeTracker.userDefinedMeshChanged = false; @@ -67,7 +62,7 @@ void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer * // Compose mesh filename if (m_mesh == QAbstract3DSeries::MeshUserDefined) { // Always use the supplied mesh directly - meshFileName = series->userDefinedMesh(); + meshFileName = m_series->userDefinedMesh(); } else { switch (m_mesh) { case QAbstract3DSeries::MeshBar: @@ -107,11 +102,11 @@ void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer * break; } - if (series->isMeshSmooth() && m_mesh != QAbstract3DSeries::MeshPoint) + if (m_series->isMeshSmooth() && m_mesh != QAbstract3DSeries::MeshPoint) meshFileName += smoothString; // Give renderer an opportunity to customize the mesh - renderer->fixMeshFileName(meshFileName, m_mesh); + m_renderer->fixMeshFileName(meshFileName, m_mesh); } delete m_object; @@ -123,8 +118,8 @@ void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer * } } - if (seriesChanged || changeTracker.meshRotationChanged) { - m_meshRotation = series->meshRotation().normalized(); + if (newSeries || changeTracker.meshRotationChanged) { + m_meshRotation = m_series->meshRotation().normalized(); if (m_series->type() == QAbstract3DSeries::SeriesTypeBar && (m_meshRotation.x() || m_meshRotation.z())) { m_meshRotation = identityQuaternion; @@ -132,63 +127,68 @@ void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer * changeTracker.meshRotationChanged = false; } - if (seriesChanged || changeTracker.colorStyleChanged) { - m_colorStyle = series->colorStyle(); + if (newSeries || changeTracker.colorStyleChanged) { + m_colorStyle = m_series->colorStyle(); changeTracker.colorStyleChanged = false; } - if (seriesChanged || changeTracker.baseColorChanged) { - m_baseColor = Utils::vectorFromColor(series->baseColor()); + if (newSeries || changeTracker.baseColorChanged) { + m_baseColor = Utils::vectorFromColor(m_series->baseColor()); if (m_series->type() == QAbstract3DSeries::SeriesTypeSurface) - renderer->generateBaseColorTexture(series->baseColor(), &m_baseUniformTexture); + m_renderer->generateBaseColorTexture(m_series->baseColor(), &m_baseUniformTexture); changeTracker.baseColorChanged = false; } - if (seriesChanged || changeTracker.baseGradientChanged) { - QLinearGradient gradient = series->baseGradient(); + if (newSeries || changeTracker.baseGradientChanged) { + QLinearGradient gradient = m_series->baseGradient(); m_gradientImage = Utils::getGradientImage(gradient); - renderer->fixGradientAndGenerateTexture(&gradient, &m_baseGradientTexture); + m_renderer->fixGradientAndGenerateTexture(&gradient, &m_baseGradientTexture); changeTracker.baseGradientChanged = false; } - if (seriesChanged || changeTracker.singleHighlightColorChanged) { - m_singleHighlightColor = Utils::vectorFromColor(series->singleHighlightColor()); + if (newSeries || changeTracker.singleHighlightColorChanged) { + m_singleHighlightColor = Utils::vectorFromColor(m_series->singleHighlightColor()); changeTracker.singleHighlightColorChanged = false; } - if (seriesChanged || changeTracker.singleHighlightGradientChanged) { - QLinearGradient gradient = series->singleHighlightGradient(); - renderer->fixGradientAndGenerateTexture(&gradient, &m_singleHighlightGradientTexture); + if (newSeries || changeTracker.singleHighlightGradientChanged) { + QLinearGradient gradient = m_series->singleHighlightGradient(); + m_renderer->fixGradientAndGenerateTexture(&gradient, &m_singleHighlightGradientTexture); changeTracker.singleHighlightGradientChanged = false; } - if (seriesChanged || changeTracker.multiHighlightColorChanged) { - m_multiHighlightColor = Utils::vectorFromColor(series->multiHighlightColor()); + if (newSeries || changeTracker.multiHighlightColorChanged) { + m_multiHighlightColor = Utils::vectorFromColor(m_series->multiHighlightColor()); changeTracker.multiHighlightColorChanged = false; } - if (seriesChanged || changeTracker.multiHighlightGradientChanged) { - QLinearGradient gradient = series->multiHighlightGradient(); - renderer->fixGradientAndGenerateTexture(&gradient, &m_multiHighlightGradientTexture); + if (newSeries || changeTracker.multiHighlightGradientChanged) { + QLinearGradient gradient = m_series->multiHighlightGradient(); + m_renderer->fixGradientAndGenerateTexture(&gradient, &m_multiHighlightGradientTexture); changeTracker.multiHighlightGradientChanged = false; } - if (seriesChanged || changeTracker.nameChanged) { - m_name = series->name(); + if (newSeries || changeTracker.nameChanged) { + m_name = m_series->name(); changeTracker.nameChanged = false; } - if (seriesChanged || changeTracker.itemLabelChanged + if (newSeries || changeTracker.itemLabelChanged || changeTracker.itemLabelVisibilityChanged) { changeTracker.itemLabelChanged = false; changeTracker.itemLabelVisibilityChanged = false; // series->itemLabel() call resolves the item label and emits the changed signal // if it is dirty, so we need to call it even if m_itemLabel is eventually set // to an empty string. - m_itemLabel = series->itemLabel(); - if (!series->isItemLabelVisible()) + m_itemLabel = m_series->itemLabel(); + if (!m_series->isItemLabelVisible()) m_itemLabel = QString(); } + + if (newSeries || changeTracker.visibilityChanged) { + m_visible = m_series->isVisible(); + changeTracker.visibilityChanged = false; + } } void SeriesRenderCache::cleanup(TextureHelper *texHelper) diff --git a/src/datavisualization/engine/seriesrendercache_p.h b/src/datavisualization/engine/seriesrendercache_p.h index a6ae03cf..8536d501 100644 --- a/src/datavisualization/engine/seriesrendercache_p.h +++ b/src/datavisualization/engine/seriesrendercache_p.h @@ -41,10 +41,10 @@ class TextureHelper; class SeriesRenderCache { public: - SeriesRenderCache(); + SeriesRenderCache(QAbstract3DSeries *series, Abstract3DRenderer *renderer); virtual ~SeriesRenderCache(); - void populate(QAbstract3DSeries *series, Abstract3DRenderer *renderer); + virtual void populate(bool newSeries); virtual void cleanup(TextureHelper *texHelper); // NOTE: Series pointer can only be used to access the series when syncing with controller. @@ -66,6 +66,11 @@ public: inline const GLuint &multiHighlightGradientTexture() const { return m_multiHighlightGradientTexture; } inline const QString &name() const { return m_name; } inline const QString &itemLabel() const { return m_itemLabel; } + inline void setValid(bool valid) { m_valid = valid; } + inline bool isValid() const { return m_valid; } + inline bool isVisible() const { return m_visible; } + inline void setDataDirty(bool state) { m_objectDirty = state; } + inline bool dataDirty() const { return m_objectDirty; } protected: QAbstract3DSeries *m_series; @@ -85,6 +90,10 @@ protected: QString m_name; QString m_itemLabel; + bool m_valid; + bool m_visible; + Abstract3DRenderer *m_renderer; + bool m_objectDirty; }; QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/engine/surface3dcontroller.cpp b/src/datavisualization/engine/surface3dcontroller.cpp index 683a214a..591cbdda 100644 --- a/src/datavisualization/engine/surface3dcontroller.cpp +++ b/src/datavisualization/engine/surface3dcontroller.cpp @@ -66,11 +66,6 @@ void Surface3DController::synchDataToRenderer() if (!isInitialized()) return; - if (m_changedSeriesList.size()) { - m_renderer->modifiedSeriesList(m_changedSeriesList); - m_changedSeriesList.clear(); - } - Abstract3DController::synchDataToRenderer(); // Notify changes to renderer @@ -98,7 +93,7 @@ void Surface3DController::handleAxisAutoAdjustRangeChangedInOrientation( Q_UNUSED(orientation) Q_UNUSED(autoAdjust) - adjustValueAxisRange(); + adjustAxisRanges(); } void Surface3DController::handleAxisRangeChangedBySender(QObject *sender) @@ -113,8 +108,6 @@ void Surface3DController::handleSeriesVisibilityChangedBySender(QObject *sender) { Abstract3DController::handleSeriesVisibilityChangedBySender(sender); - adjustValueAxisRange(); - // Visibility changes may require disabling slicing, // so just reset selection to ensure everything is still valid. setSelectedPoint(m_selectedPoint, m_selectedSeries, false); @@ -150,9 +143,6 @@ void Surface3DController::addSeries(QAbstract3DSeries *series) Abstract3DController::addSeries(series); - if (series->isVisible()) - adjustValueAxisRange(); - QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(series); if (surfaceSeries->selectedPoint() != invalidSelectionPosition()) setSelectedPoint(surfaceSeries->selectedPoint(), surfaceSeries, false); @@ -168,7 +158,7 @@ void Surface3DController::removeSeries(QAbstract3DSeries *series) setSelectedPoint(invalidSelectionPosition(), 0, false); if (wasVisible) - adjustValueAxisRange(); + adjustAxisRanges(); } QList<QSurface3DSeries *> Surface3DController::surfaceSeriesList() @@ -292,11 +282,12 @@ void Surface3DController::handleArrayReset() { QSurface3DSeries *series = static_cast<QSurfaceDataProxy *>(sender())->series(); if (series->isVisible()) { - adjustValueAxisRange(); - if (!m_changedSeriesList.contains(series)) - m_changedSeriesList.append(series); + adjustAxisRanges(); m_isDataDirty = true; } + if (!m_changedSeriesList.contains(series)) + m_changedSeriesList.append(series); + // Clear selection unless still valid setSelectedPoint(m_selectedPoint, m_selectedSeries, false); series->d_ptr->markItemLabelDirty(); @@ -345,7 +336,7 @@ void Surface3DController::handleRowsChanged(int startIndex, int count) if (m_changedRows.size()) { m_changeTracker.rowsChanged = true; - adjustValueAxisRange(); + adjustAxisRanges(); // Clear selection unless still valid setSelectedPoint(m_selectedPoint, m_selectedSeries, false); emitNeedRender(); @@ -373,7 +364,7 @@ void Surface3DController::handleItemChanged(int rowIndex, int columnIndex) if (series == m_selectedSeries && m_selectedPoint == candidate) series->d_ptr->markItemLabelDirty(); - adjustValueAxisRange(); + adjustAxisRanges(); // Clear selection unless still valid setSelectedPoint(m_selectedPoint, m_selectedSeries, false); emitNeedRender(); @@ -386,11 +377,11 @@ void Surface3DController::handleRowsAdded(int startIndex, int count) Q_UNUSED(count) QSurface3DSeries *series = static_cast<QSurfaceDataProxy *>(sender())->series(); if (series->isVisible()) { - adjustValueAxisRange(); + adjustAxisRanges(); m_isDataDirty = true; - if (!m_changedSeriesList.contains(series)) - m_changedSeriesList.append(series); } + if (!m_changedSeriesList.contains(series)) + m_changedSeriesList.append(series); emitNeedRender(); } @@ -409,11 +400,11 @@ void Surface3DController::handleRowsInserted(int startIndex, int count) } if (series->isVisible()) { - adjustValueAxisRange(); + adjustAxisRanges(); m_isDataDirty = true; - if (!m_changedSeriesList.contains(series)) - m_changedSeriesList.append(series); } + if (!m_changedSeriesList.contains(series)) + m_changedSeriesList.append(series); emitNeedRender(); } @@ -437,16 +428,16 @@ void Surface3DController::handleRowsRemoved(int startIndex, int count) } if (series->isVisible()) { - adjustValueAxisRange(); + adjustAxisRanges(); m_isDataDirty = true; - if (!m_changedSeriesList.contains(series)) - m_changedSeriesList.append(series); } + if (!m_changedSeriesList.contains(series)) + m_changedSeriesList.append(series); emitNeedRender(); } -void Surface3DController::adjustValueAxisRange() +void Surface3DController::adjustAxisRanges() { QValue3DAxis *valueAxisX = static_cast<QValue3DAxis *>(m_axisX); QValue3DAxis *valueAxisY = static_cast<QValue3DAxis *>(m_axisY); diff --git a/src/datavisualization/engine/surface3dcontroller_p.h b/src/datavisualization/engine/surface3dcontroller_p.h index 14c0dd40..b742b6bb 100644 --- a/src/datavisualization/engine/surface3dcontroller_p.h +++ b/src/datavisualization/engine/surface3dcontroller_p.h @@ -77,7 +77,6 @@ private: bool m_flatShadingSupported; QVector<ChangeItem> m_changedItems; QVector<ChangeRow> m_changedRows; - QVector<QSurface3DSeries *> m_changedSeriesList; public: explicit Surface3DController(QRect rect, Q3DScene *scene = 0); @@ -97,6 +96,7 @@ public: virtual void handleAxisRangeChangedBySender(QObject *sender); virtual void handleSeriesVisibilityChangedBySender(QObject *sender); virtual void handlePendingClick(); + virtual void adjustAxisRanges(); static QPoint invalidSelectionPosition(); bool isFlatShadingSupported(); @@ -119,8 +119,6 @@ signals: void selectedSeriesChanged(QSurface3DSeries *series); private: - void adjustValueAxisRange(); - Q_DISABLE_COPY(Surface3DController) }; diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp index 9e591383..9e5f0b37 100644 --- a/src/datavisualization/engine/surface3drenderer.cpp +++ b/src/datavisualization/engine/surface3drenderer.cpp @@ -144,12 +144,6 @@ Surface3DRenderer::~Surface3DRenderer() delete m_gridLineObj; #endif delete m_labelObj; - - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { - cache->cleanup(m_textureHelper); - delete cache; - } - m_renderCacheList.clear(); } void Surface3DRenderer::initializeOpenGL() @@ -194,22 +188,25 @@ void Surface3DRenderer::updateData() { calculateSceneScalingFactors(); - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { - const QSurface3DSeries *currentSeries = cache->series(); - QSurfaceDataProxy *dataProxy = currentSeries->dataProxy(); - const QSurfaceDataArray &array = *dataProxy->array(); + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache); + if (cache->isVisible() && cache->dataDirty()) { + const QSurface3DSeries *currentSeries = cache->series(); + QSurfaceDataProxy *dataProxy = currentSeries->dataProxy(); + const QSurfaceDataArray &array = *dataProxy->array(); + QSurfaceDataArray &dataArray = cache->dataArray(); + QRect sampleSpace; - // Need minimum of 2x2 array to draw a surface - if (array.size() >= 2 && array.at(0)->size() >= 2) { - QRect sampleSpace = calculateSampleRect(array); + // Need minimum of 2x2 array to draw a surface + if (array.size() >= 2 && array.at(0)->size() >= 2) + sampleSpace = calculateSampleRect(array); - QSurfaceDataArray &dataArray = cache->dataArray(); - bool dimensionChanged = false; + bool dimensionsChanged = false; if (cache->sampleSpace() != sampleSpace) { if (sampleSpace.width() >= 2) m_selectionTexturesDirty = true; - dimensionChanged = true; + dimensionsChanged = true; cache->setSampleSpace(sampleSpace); for (int i = 0; i < dataArray.size(); i++) @@ -218,7 +215,7 @@ void Surface3DRenderer::updateData() } if (sampleSpace.width() >= 2 && sampleSpace.height() >= 2) { - if (dimensionChanged) { + if (dimensionsChanged) { dataArray.reserve(sampleSpace.height()); for (int i = 0; i < sampleSpace.height(); i++) dataArray << new QSurfaceDataRow(sampleSpace.width()); @@ -230,13 +227,13 @@ void Surface3DRenderer::updateData() } } - if (dataArray.size() > 0 && (cache->objectDirty() || dimensionChanged)) { - checkFlatSupport(cache); - updateObjects(cache, dimensionChanged); - cache->setObjectDirty(false); - cache->setFlatStatusDirty(false); - } + checkFlatSupport(cache); + updateObjects(cache, dimensionsChanged); + cache->setFlatStatusDirty(false); + } else { + cache->surfaceObject()->clear(); } + cache->setDataDirty(false); } } @@ -246,26 +243,15 @@ void Surface3DRenderer::updateData() updateSelectedPoint(m_selectedPoint, m_selectedSeries); } -void Surface3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList, - bool updateVisibility) +void Surface3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList) { - Q_UNUSED(updateVisibility); - - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) - cache->setValid(false); + Abstract3DRenderer::updateSeries(seriesList); bool noSelection = true; foreach (QAbstract3DSeries *series, seriesList) { QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(series); - SurfaceSeriesRenderCache *cache = m_renderCacheList.value(surfaceSeries); - if (!cache) { - cache = new SurfaceSeriesRenderCache(this); - m_renderCacheList[surfaceSeries] = cache; - m_selectionTexturesDirty = true; - } - cache->setValid(true); - cache->populate(surfaceSeries, this); - + SurfaceSeriesRenderCache *cache = + static_cast<SurfaceSeriesRenderCache *>( m_renderCacheList.value(series)); if (noSelection && surfaceSeries->selectedPoint() != QSurface3DSeries::invalidSelectionPosition() && selectionLabel() != cache->itemLabel()) { @@ -280,26 +266,15 @@ void Surface3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesLis } } - if (noSelection && !selectionLabel().isEmpty()) + if (noSelection && !selectionLabel().isEmpty()) { m_selectionLabelDirty = true; - - // Remove non-valid objects from the cache list - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { - if (!cache->isValid()) { - if (cache->series() == m_selectedSeries) - updateSelectedPoint(Surface3DController::invalidSelectionPosition(), 0); - - m_renderCacheList.remove(cache->series()); - cache->cleanup(m_textureHelper); - delete cache; - - m_selectionTexturesDirty = true; - } + updateSelectedPoint(Surface3DController::invalidSelectionPosition(), 0); } // Selection pointer issues if (m_selectedSeries) { - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache); QVector3D highlightColor = Utils::vectorFromColor(cache->series()->singleHighlightColor()); SelectionPointer *slicePointer = cache->sliceSelectionPointer(); @@ -318,19 +293,23 @@ void Surface3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesLis } } -void Surface3DRenderer::modifiedSeriesList(const QVector<QSurface3DSeries *> &seriesList) +SeriesRenderCache *Surface3DRenderer::createNewCache(QAbstract3DSeries *series) { - foreach (QSurface3DSeries *series, seriesList) { - SurfaceSeriesRenderCache *cache = m_renderCacheList.value(series); - if (cache) - cache->setObjectDirty(true); - } + m_selectionTexturesDirty = true; + return new SurfaceSeriesRenderCache(series, this); +} + +void Surface3DRenderer::cleanCache(SeriesRenderCache *cache) +{ + Abstract3DRenderer::cleanCache(cache); + m_selectionTexturesDirty = true; } void Surface3DRenderer::updateRows(const QVector<Surface3DController::ChangeRow> &rows) { foreach (Surface3DController::ChangeRow item, rows) { - SurfaceSeriesRenderCache *cache = m_renderCacheList.value(item.series); + SurfaceSeriesRenderCache *cache = + static_cast<SurfaceSeriesRenderCache *>(m_renderCacheList.value(item.series)); QSurfaceDataArray &dstArray = cache->dataArray(); const QRect &sampleSpace = cache->sampleSpace(); @@ -367,7 +346,8 @@ void Surface3DRenderer::updateRows(const QVector<Surface3DController::ChangeRow> void Surface3DRenderer::updateItem(const QVector<Surface3DController::ChangeItem> &points) { foreach (Surface3DController::ChangeItem item, points) { - SurfaceSeriesRenderCache *cache = m_renderCacheList.value(item.series); + SurfaceSeriesRenderCache *cache = + static_cast<SurfaceSeriesRenderCache *>(m_renderCacheList.value(item.series)); QSurfaceDataArray &dstArray = cache->dataArray(); const QRect &sampleSpace = cache->sampleSpace(); @@ -404,38 +384,22 @@ void Surface3DRenderer::updateItem(const QVector<Surface3DController::ChangeItem updateSelectedPoint(m_selectedPoint, m_selectedSeries); } -void Surface3DRenderer::updateAxisRange(QAbstract3DAxis::AxisOrientation orientation, float min, - float max) -{ - Abstract3DRenderer::updateAxisRange(orientation, min, max); - - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) - cache->setObjectDirty(true); -} - -void Surface3DRenderer::updateAxisFormatter(QAbstract3DAxis::AxisOrientation orientation, - QValue3DAxisFormatter *formatter) -{ - Abstract3DRenderer::updateAxisFormatter(orientation, formatter); - - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) - cache->setObjectDirty(true); -} - void Surface3DRenderer::updateSliceDataModel(const QPoint &point) { - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) - cache->sliceSurfaceObject()->clear(); + foreach (SeriesRenderCache *baseCache, m_renderCacheList) + static_cast<SurfaceSeriesRenderCache *>(baseCache)->sliceSurfaceObject()->clear(); if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionMultiSeries)) { // Find axis coordinates for the selected point - SurfaceSeriesRenderCache *selectedCache = + SeriesRenderCache *selectedCache = m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries)); - QSurfaceDataArray &dataArray = selectedCache->dataArray(); + QSurfaceDataArray &dataArray = + static_cast<SurfaceSeriesRenderCache *>(selectedCache)->dataArray(); QSurfaceDataItem item = dataArray.at(point.x())->at(point.y()); QPointF coords(item.x(), item.z()); - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache); if (cache->series() != m_selectedSeries) { QPoint mappedPoint = mapCoordsToSampleSpace(cache, coords); updateSliceObject(cache, mappedPoint); @@ -446,9 +410,10 @@ void Surface3DRenderer::updateSliceDataModel(const QPoint &point) } else { if (m_selectedSeries) { SurfaceSeriesRenderCache *cache = - m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries)); + static_cast<SurfaceSeriesRenderCache *>( + m_renderCacheList.value(m_selectedSeries)); if (cache) - updateSliceObject(cache, point); + updateSliceObject(static_cast<SurfaceSeriesRenderCache *>(cache), point); } } } @@ -728,7 +693,8 @@ void Surface3DRenderer::render(GLuint defaultFboHandle) // Render selection ball if (m_selectionActive && m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionItem)) { - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache); if (cache->slicePointerActive() && cache->renderable() && m_cachedIsSlicingActivated ) { cache->sliceSelectionPointer()->render(defaultFboHandle); @@ -780,7 +746,8 @@ void Surface3DRenderer::drawSlicedScene() if (m_renderCacheList.size()) { bool drawGrid = false; - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache); if (cache->sliceSurfaceObject()->indexCount() && cache->renderable()) { if (!drawGrid && cache->surfaceGridVisible()) { glEnable(GL_POLYGON_OFFSET_FILL); @@ -838,10 +805,13 @@ void Surface3DRenderer::drawSlicedScene() m_surfaceGridShader->bind(); m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(), Utils::vectorFromColor(m_cachedTheme->gridLineColor())); - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { - if (cache->sliceSurfaceObject()->indexCount() && cache->isSeriesVisible() && + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + SurfaceSeriesRenderCache *cache = + static_cast<SurfaceSeriesRenderCache *>(baseCache); + if (cache->sliceSurfaceObject()->indexCount() && cache->isVisible() && cache->surfaceGridVisible()) { - m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), cache->MVPMatrix()); + m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), + cache->MVPMatrix()); m_drawer->drawSurfaceGrid(m_surfaceGridShader, cache->sliceSurfaceObject()); } } @@ -1101,9 +1071,10 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) glDisable(GL_CULL_FACE); - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache); SurfaceObject *object = cache->surfaceObject(); - if (object->indexCount() && cache->surfaceVisible() && cache->isSeriesVisible() + if (object->indexCount() && cache->surfaceVisible() && cache->isVisible() && cache->sampleSpace().width() >= 2 && cache->sampleSpace().height() >= 2) { QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; @@ -1134,9 +1105,10 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) m_depthModelTexture, 0); glClear(GL_DEPTH_BUFFER_BIT); - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache); SurfaceObject *object = cache->surfaceObject(); - if (object->indexCount() && cache->surfaceVisible() && cache->isSeriesVisible() + if (object->indexCount() && cache->surfaceVisible() && cache->isVisible() && cache->sampleSpace().width() >= 2 && cache->sampleSpace().height() >= 2) { m_depthShader->setUniformValue(m_depthShader->MVP(), cache->MVPMatrix()); @@ -1195,7 +1167,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) glDisable(GL_CULL_FACE); - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache); if (cache->surfaceObject()->indexCount() && cache->renderable()) { QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; @@ -1242,7 +1215,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) bool drawGrid = false; - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache); QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; QMatrix4x4 itModelMatrix; @@ -1255,7 +1229,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) cache->setMVPMatrix(MVPMatrix); const QRect &sampleSpace = cache->sampleSpace(); - if (cache->surfaceObject()->indexCount() && cache->isSeriesVisible() && + if (cache->surfaceObject()->indexCount() && cache->isVisible() && sampleSpace.width() >= 2 && sampleSpace.height() >= 2) { noShadows = false; if (!drawGrid && cache->surfaceGridVisible()) { @@ -1318,13 +1292,18 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) glDisable(GL_POLYGON_OFFSET_FILL); m_surfaceGridShader->bind(); m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(), - Utils::vectorFromColor(m_cachedTheme->gridLineColor())); - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { - m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), cache->MVPMatrix()); + Utils::vectorFromColor( + m_cachedTheme->gridLineColor())); + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + SurfaceSeriesRenderCache *cache = + static_cast<SurfaceSeriesRenderCache *>(baseCache); + m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), + cache->MVPMatrix()); const QRect &sampleSpace = cache->sampleSpace(); - if (cache->surfaceObject()->indexCount() && cache->surfaceGridVisible() && - cache->isSeriesVisible() && sampleSpace.width() >= 2 && sampleSpace.height() >= 2) { + if (cache->surfaceObject()->indexCount() && cache->surfaceGridVisible() + && cache->isVisible() && sampleSpace.width() >= 2 + && sampleSpace.height() >= 2) { m_drawer->drawSurfaceGrid(m_surfaceGridShader, cache->surfaceObject()); } } @@ -1746,7 +1725,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) QPoint visiblePoint = Surface3DController::invalidSelectionPosition(); if (m_selectedSeries) { SurfaceSeriesRenderCache *cache = - m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries)); + static_cast<SurfaceSeriesRenderCache *>( + m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries))); if (cache && m_selectedPoint != Surface3DController::invalidSelectionPosition()) { const QRect &sampleSpace = cache->sampleSpace(); int x = m_selectedPoint.x() - sampleSpace.y(); @@ -1985,7 +1965,9 @@ void Surface3DRenderer::updateSelectionTextures() { uint lastSelectionId = 1; - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + SurfaceSeriesRenderCache *cache = + static_cast<SurfaceSeriesRenderCache *>(baseCache); GLuint texture = cache->selectionTexture(); m_textureHelper->deleteTexture(&texture); createSelectionTexture(cache, lastSelectionId); @@ -2113,14 +2095,13 @@ void Surface3DRenderer::updateObjects(SurfaceSeriesRenderCache *cache, bool dime QSurfaceDataArray &dataArray = cache->dataArray(); const QRect &sampleSpace = cache->sampleSpace(); - if (cache->isFlatShadingEnabled()) cache->surfaceObject()->setUpData(dataArray, sampleSpace, dimensionChanged); else cache->surfaceObject()->setUpSmoothData(dataArray, sampleSpace, dimensionChanged); } -void Surface3DRenderer::updateSelectedPoint(const QPoint &position, const QSurface3DSeries *series) +void Surface3DRenderer::updateSelectedPoint(const QPoint &position, QSurface3DSeries *series) { m_selectedPoint = position; m_selectedSeries = series; @@ -2153,7 +2134,9 @@ void Surface3DRenderer::loadGridLineMesh() void Surface3DRenderer::surfacePointSelected(const QPoint &point) { - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + SurfaceSeriesRenderCache *cache = + static_cast<SurfaceSeriesRenderCache *>(baseCache); cache->setSlicePointerActivity(false); cache->setMainPointerActivity(false); } @@ -2161,12 +2144,15 @@ void Surface3DRenderer::surfacePointSelected(const QPoint &point) if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionMultiSeries)) { // Find axis coordinates for the selected point SurfaceSeriesRenderCache *selectedCache = - m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries)); + static_cast<SurfaceSeriesRenderCache *>( + m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries))); QSurfaceDataArray &dataArray = selectedCache->dataArray(); QSurfaceDataItem item = dataArray.at(point.x())->at(point.y()); QPointF coords(item.x(), item.z()); - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + SurfaceSeriesRenderCache *cache = + static_cast<SurfaceSeriesRenderCache *>(baseCache); if (cache->series() != m_selectedSeries) { QPoint mappedPoint = mapCoordsToSampleSpace(cache, coords); updateSelectionPoint(cache, mappedPoint, false); @@ -2177,7 +2163,8 @@ void Surface3DRenderer::surfacePointSelected(const QPoint &point) } else { if (m_selectedSeries) { SurfaceSeriesRenderCache *cache = - m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries)); + static_cast<SurfaceSeriesRenderCache *>( + m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries))); if (cache) updateSelectionPoint(cache, point, true); } @@ -2262,7 +2249,8 @@ QPoint Surface3DRenderer::selectionIdToSurfacePoint(uint id) // Not a label selection SurfaceSeriesRenderCache *selectedCache = 0; - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache); if (cache->isWithinIdRange(id)) { selectedCache = cache; break; @@ -2346,7 +2334,8 @@ void Surface3DRenderer::updateSlicingActive(bool isSlicing) m_selectionDirty = true; - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + foreach (SeriesRenderCache *baseCache, m_renderCacheList) { + SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache); if (cache->mainSelectionPointer()) cache->mainSelectionPointer()->updateBoundingRect(m_primarySubViewport); } diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h index 39e96f55..e1147e3c 100644 --- a/src/datavisualization/engine/surface3drenderer_p.h +++ b/src/datavisualization/engine/surface3drenderer_p.h @@ -95,9 +95,8 @@ private: QSizeF m_areaSize; bool m_hasHeightAdjustmentChanged; QPoint m_selectedPoint; - const QSurface3DSeries *m_selectedSeries; + QSurface3DSeries *m_selectedSeries; QPoint m_clickedPosition; - QHash<QSurface3DSeries *, SurfaceSeriesRenderCache *> m_renderCacheList; bool m_selectionTexturesDirty; GLuint m_noShadowTexture; @@ -106,17 +105,15 @@ public: ~Surface3DRenderer(); void updateData(); - void updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility); + void updateSeries(const QList<QAbstract3DSeries *> &seriesList); + SeriesRenderCache *createNewCache(QAbstract3DSeries *series); + void cleanCache(SeriesRenderCache *cache); void updateSelectionMode(QAbstract3DGraph::SelectionFlags mode); - void modifiedSeriesList(const QVector<QSurface3DSeries *> &seriesList); void updateRows(const QVector<Surface3DController::ChangeRow> &rows); void updateItem(const QVector<Surface3DController::ChangeItem> &points); - void updateAxisRange(QAbstract3DAxis::AxisOrientation orientation, float min, float max); - void updateAxisFormatter(QAbstract3DAxis::AxisOrientation orientation, - QValue3DAxisFormatter *formatter); void updateScene(Q3DScene *scene); void updateSlicingActive(bool isSlicing); - void updateSelectedPoint(const QPoint &position, const QSurface3DSeries *series); + void updateSelectedPoint(const QPoint &position, QSurface3DSeries *series); inline QPoint clickedPosition() const { return m_clickedPosition; } void resetClickedStatus(); diff --git a/src/datavisualization/engine/surfaceseriesrendercache.cpp b/src/datavisualization/engine/surfaceseriesrendercache.cpp index ad81f714..db3fa9f7 100644 --- a/src/datavisualization/engine/surfaceseriesrendercache.cpp +++ b/src/datavisualization/engine/surfaceseriesrendercache.cpp @@ -19,16 +19,18 @@ #include "seriesrendercache_p.h" #include "surfaceseriesrendercache_p.h" #include "objecthelper_p.h" -#include "abstract3drenderer_p.h" +#include "surface3drenderer_p.h" #include "texturehelper_p.h" #include "utils_p.h" QT_BEGIN_NAMESPACE_DATAVISUALIZATION -SurfaceSeriesRenderCache::SurfaceSeriesRenderCache(Surface3DRenderer *renderer) - : m_surfaceVisible(false), +SurfaceSeriesRenderCache::SurfaceSeriesRenderCache(QAbstract3DSeries *series, + Surface3DRenderer *renderer) + : SeriesRenderCache(series, renderer), + m_surfaceVisible(false), m_surfaceGridVisible(false), - m_surfaceFlatShading(true), + m_surfaceFlatShading(false), m_surfaceObj(new SurfaceObject(renderer)), m_sliceSurfaceObj(new SurfaceObject(renderer)), m_sampleSpace(QRect(0, 0, 0 , 0)), @@ -36,13 +38,11 @@ SurfaceSeriesRenderCache::SurfaceSeriesRenderCache(Surface3DRenderer *renderer) m_selectionIdStart(0), m_selectionIdEnd(0), m_flatChangeAllowed(true), - m_flatStatusDirty(false), + m_flatStatusDirty(true), m_sliceSelectionPointer(0), m_mainSelectionPointer(0), m_slicePointerActive(false), - m_mainPointerActive(false), - m_valid(false), - m_objectDirty(true) + m_mainPointerActive(false) { } @@ -50,17 +50,15 @@ SurfaceSeriesRenderCache::~SurfaceSeriesRenderCache() { } -void SurfaceSeriesRenderCache::populate(QSurface3DSeries *series, Abstract3DRenderer *renderer) +void SurfaceSeriesRenderCache::populate(bool newSeries) { - Q_ASSERT(series); + SeriesRenderCache::populate(newSeries); - SeriesRenderCache::populate(series, renderer); - - QSurface3DSeries::DrawFlags drawMode = series->drawMode(); + QSurface3DSeries::DrawFlags drawMode = series()->drawMode(); m_surfaceVisible = drawMode.testFlag(QSurface3DSeries::DrawSurface); m_surfaceGridVisible = drawMode.testFlag(QSurface3DSeries::DrawWireframe); - if (m_flatChangeAllowed && m_surfaceFlatShading != series->isFlatShadingEnabled()) { - m_surfaceFlatShading = series->isFlatShadingEnabled(); + if (m_flatChangeAllowed && m_surfaceFlatShading != series()->isFlatShadingEnabled()) { + m_surfaceFlatShading = series()->isFlatShadingEnabled(); m_flatStatusDirty = true; } } diff --git a/src/datavisualization/engine/surfaceseriesrendercache_p.h b/src/datavisualization/engine/surfaceseriesrendercache_p.h index bab16201..9d373812 100644 --- a/src/datavisualization/engine/surfaceseriesrendercache_p.h +++ b/src/datavisualization/engine/surfaceseriesrendercache_p.h @@ -48,10 +48,10 @@ class TextureHelper; class SurfaceSeriesRenderCache : public SeriesRenderCache { public: - SurfaceSeriesRenderCache(Surface3DRenderer *renderer); + SurfaceSeriesRenderCache(QAbstract3DSeries *series, Surface3DRenderer *renderer); virtual ~SurfaceSeriesRenderCache(); - void populate(QSurface3DSeries *series, Abstract3DRenderer *renderer); + virtual void populate(bool newSeries); virtual void cleanup(TextureHelper *texHelper); inline bool surfaceVisible() const { return m_surfaceVisible; } @@ -59,8 +59,6 @@ public: inline bool isFlatShadingEnabled() const { return m_surfaceFlatShading; } inline void setFlatShadingEnabled(bool enabled) { m_surfaceFlatShading = enabled; } inline void setFlatChangeAllowed(bool allowed) { m_flatChangeAllowed = allowed; } - inline void setValid(bool valid) { m_valid = valid; } - inline bool isValid() const { return m_valid; } inline SurfaceObject *surfaceObject() { return m_surfaceObj; } inline SurfaceObject *sliceSurfaceObject() { return m_sliceSurfaceObj; } inline const QRect &sampleSpace() const { return m_sampleSpace; } @@ -68,11 +66,8 @@ public: inline QSurface3DSeries *series() const { return static_cast<QSurface3DSeries *>(m_series); } inline QSurfaceDataArray &dataArray() { return m_dataArray; } inline QSurfaceDataArray &sliceDataArray() { return m_sliceDataArray; } - inline bool isSeriesVisible() const { return m_series->isVisible(); } - inline bool renderable() const { return m_series->isVisible() && (m_surfaceVisible || - m_surfaceGridVisible); } - inline void setObjectDirty(bool state) { m_objectDirty = state; } - inline bool objectDirty() const { return m_objectDirty; } + inline bool renderable() const { return m_visible && (m_surfaceVisible || + m_surfaceGridVisible); } inline void setSelectionTexture(GLuint texture) { m_selectionTexture = texture; } inline GLuint selectionTexture() const { return m_selectionTexture; } inline void setSelectionIdRange(uint start, uint end) { m_selectionIdStart = start; @@ -82,7 +77,6 @@ public: selection <= m_selectionIdEnd; } inline bool isFlatStatusDirty() const { return m_flatStatusDirty; } inline void setFlatStatusDirty(bool status) { m_flatStatusDirty = status; } - // m_MVPMatrix is volatile, used only for optimizing rendering a bit inline void setMVPMatrix(const QMatrix4x4 &matrix) { m_MVPMatrix = matrix; } inline const QMatrix4x4 &MVPMatrix() { return m_MVPMatrix; } @@ -115,9 +109,6 @@ protected: SelectionPointer *m_mainSelectionPointer; bool m_slicePointerActive; bool m_mainPointerActive; - - bool m_valid; - bool m_objectDirty; }; QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/utils/surfaceobject.cpp b/src/datavisualization/utils/surfaceobject.cpp index b21961cb..96d04094 100644 --- a/src/datavisualization/utils/surfaceobject.cpp +++ b/src/datavisualization/utils/surfaceobject.cpp @@ -673,6 +673,8 @@ void SurfaceObject::clear() m_gridIndexCount = 0; m_indexCount = 0; m_surfaceType = Undefined; + m_vertices.clear(); + m_normals.clear(); } QVector3D SurfaceObject::normal(const QVector3D &a, const QVector3D &b, const QVector3D &c) diff --git a/tests/barstest/chart.cpp b/tests/barstest/chart.cpp index 0a8bef55..2c095cf8 100644 --- a/tests/barstest/chart.cpp +++ b/tests/barstest/chart.cpp @@ -71,7 +71,8 @@ GraphModifier::GraphModifier(Q3DBars *barchart, QColorDialog *colorDialog) m_defaultInputHandler(0), m_ownTheme(0), m_builtinTheme(new Q3DTheme(Q3DTheme::ThemeStoneMoss)), - m_customInputHandler(new CustomInputHandler) + m_customInputHandler(new CustomInputHandler), + m_extraSeries(0) { m_temperatureData->setObjectName("m_temperatureData"); m_temperatureData2->setObjectName("m_temperatureData2"); @@ -1149,6 +1150,67 @@ void GraphModifier::changeLogBase(const QString &text) formatter->setBase(qreal(text.toDouble())); } +void GraphModifier::addRemoveSeries() +{ + static int counter = 0; + + switch (counter) { + case 0: { + qDebug() << __FUNCTION__ << counter << "New series"; + m_extraSeries = new QBar3DSeries; + m_graph->addSeries(m_extraSeries); + QObject::connect(m_extraSeries, &QBar3DSeries::selectedBarChanged, this, + &GraphModifier::handleSelectionChange); + } + break; + case 1: { + qDebug() << __FUNCTION__ << counter << "Add data to series"; + QBarDataArray *array = new QBarDataArray; + array->reserve(5); + for (int i = 0; i < 5; i++) { + array->append(new QBarDataRow(10)); + for (int j = 0; j < 10; j++) + (*array->at(i))[j].setValue(i * j); + } + m_extraSeries->dataProxy()->resetArray(array); + } + break; + case 2: { + qDebug() << __FUNCTION__ << counter << "Hide series"; + m_extraSeries->setVisible(false); + } + break; + case 3: { + qDebug() << __FUNCTION__ << counter << "Modify data when hidden"; + QBarDataArray array; + array.reserve(5); + for (int i = 0; i < 5; i++) { + array.append(new QBarDataRow(10)); + for (int j = 0; j < 10; j++) + (*array.at(i))[j].setValue(2 * i * j); + } + m_extraSeries->dataProxy()->addRows(array); + } + break; + case 4: { + qDebug() << __FUNCTION__ << counter << "Show series again"; + m_extraSeries->setVisible(true); + } + break; + case 5: { + qDebug() << __FUNCTION__ << counter << "Remove series"; + m_graph->removeSeries(m_extraSeries); + delete m_extraSeries; + m_extraSeries = 0; + } + break; + default: + qDebug() << __FUNCTION__ << "Resetting test"; + counter = -1; + } + counter++; +} + void GraphModifier::changeValueAxisSegments(int value) { qDebug() << __FUNCTION__ << value; diff --git a/tests/barstest/chart.h b/tests/barstest/chart.h index 214c4e17..e64b282a 100644 --- a/tests/barstest/chart.h +++ b/tests/barstest/chart.h @@ -91,6 +91,7 @@ public: void changeValueAxisFormat(const QString & text); void changeLogBase(const QString & text); void setFpsLabel(QLabel *fpsLabel) { m_fpsLabel = fpsLabel; } + void addRemoveSeries(); public slots: void flipViews(); @@ -162,6 +163,7 @@ private: QTimer m_selectionTimer; QTimer m_rotationTimer; QLabel *m_fpsLabel; + QBar3DSeries *m_extraSeries; }; #endif diff --git a/tests/barstest/main.cpp b/tests/barstest/main.cpp index b1589e0f..e02bddce 100644 --- a/tests/barstest/main.cpp +++ b/tests/barstest/main.cpp @@ -66,6 +66,10 @@ int main(int argc, char **argv) hLayout->addLayout(vLayout); hLayout->addLayout(vLayout2); + QPushButton *addSeriesButton = new QPushButton(widget); + addSeriesButton->setText(QStringLiteral("Add / Remove a series")); + addSeriesButton->setEnabled(true); + QPushButton *addDataButton = new QPushButton(widget); addDataButton->setText(QStringLiteral("Add a row of data")); addDataButton->setEnabled(false); @@ -305,6 +309,7 @@ int main(int argc, char **argv) valueAxisSegmentsSpin->setMaximum(100); valueAxisSegmentsSpin->setValue(10); + vLayout->addWidget(addSeriesButton, 0, Qt::AlignTop); vLayout->addWidget(addDataButton, 0, Qt::AlignTop); vLayout->addWidget(addMultiDataButton, 0, Qt::AlignTop); vLayout->addWidget(insertDataButton, 0, Qt::AlignTop); @@ -419,6 +424,7 @@ int main(int argc, char **argv) QObject::connect(labelButton, &QPushButton::clicked, modifier, &GraphModifier::changeLabelStyle); QObject::connect(addDataButton, &QPushButton::clicked, modifier, &GraphModifier::addRow); + QObject::connect(addSeriesButton, &QPushButton::clicked, modifier, &GraphModifier::addRemoveSeries); QObject::connect(addMultiDataButton, &QPushButton::clicked, modifier, &GraphModifier::addRows); QObject::connect(insertDataButton, &QPushButton::clicked, modifier, &GraphModifier::insertRow); QObject::connect(insertMultiDataButton, &QPushButton::clicked, modifier, &GraphModifier::insertRows); diff --git a/tests/scattertest/main.cpp b/tests/scattertest/main.cpp index fbe257f5..2bd60aff 100644 --- a/tests/scattertest/main.cpp +++ b/tests/scattertest/main.cpp @@ -102,6 +102,9 @@ int main(int argc, char **argv) QPushButton *setSelectedItemButton = new QPushButton(widget); setSelectedItemButton->setText(QStringLiteral("Select/deselect item 3")); + QPushButton *clearSeriesDataButton = new QPushButton(widget); + clearSeriesDataButton->setText(QStringLiteral("Clear series data")); + QPushButton *addSeriesButton = new QPushButton(widget); addSeriesButton->setText(QStringLiteral("Add Series")); @@ -220,6 +223,7 @@ int main(int argc, char **argv) vLayout->addWidget(removeOneButton, 0, Qt::AlignTop); vLayout->addWidget(removeBunchButton, 0, Qt::AlignTop); vLayout->addWidget(setSelectedItemButton, 0, Qt::AlignTop); + vLayout->addWidget(clearSeriesDataButton, 0, Qt::AlignTop); vLayout->addWidget(addSeriesButton, 0, Qt::AlignTop); vLayout->addWidget(removeSeriesButton, 0, Qt::AlignTop); vLayout->addWidget(toggleSeriesVisibilityButton, 0, Qt::AlignTop); @@ -280,6 +284,8 @@ int main(int argc, char **argv) &ScatterDataModifier::removeBunch); QObject::connect(setSelectedItemButton, &QPushButton::clicked, modifier, &ScatterDataModifier::selectItem); + QObject::connect(clearSeriesDataButton, &QPushButton::clicked, modifier, + &ScatterDataModifier::clearSeriesData); QObject::connect(addSeriesButton, &QPushButton::clicked, modifier, &ScatterDataModifier::addSeries); QObject::connect(removeSeriesButton, &QPushButton::clicked, modifier, diff --git a/tests/scattertest/scatterchart.cpp b/tests/scattertest/scatterchart.cpp index a589919f..2e208926 100644 --- a/tests/scattertest/scatterchart.cpp +++ b/tests/scattertest/scatterchart.cpp @@ -459,6 +459,12 @@ void ScatterDataModifier::setGradient() } } +void ScatterDataModifier::clearSeriesData() +{ + if (m_targetSeries) + m_targetSeries->dataProxy()->resetArray(0); +} + void ScatterDataModifier::addSeries() { QScatter3DSeries *series = createAndAddSeries(); diff --git a/tests/scattertest/scatterchart.h b/tests/scattertest/scatterchart.h index 23071c85..1470f07b 100644 --- a/tests/scattertest/scatterchart.h +++ b/tests/scattertest/scatterchart.h @@ -71,6 +71,7 @@ public slots: void selectItem(); void handleSelectionChange(int index); void setGradient(); + void clearSeriesData(); void addSeries(); void removeSeries(); void toggleSeriesVisibility(); diff --git a/tests/surfacetest/graphmodifier.cpp b/tests/surfacetest/graphmodifier.cpp index e1fed76a..c87eb2fc 100644 --- a/tests/surfacetest/graphmodifier.cpp +++ b/tests/surfacetest/graphmodifier.cpp @@ -1093,6 +1093,44 @@ void GraphModifier::removeRow() m_zCount--; } +void GraphModifier::resetArray() +{ + qDebug() << "Reset series data array"; + int rows = 10; + int columns = 10; + float randFactor = float(rand() % 100) / 100.0f; + QSurfaceDataArray *planeArray = new QSurfaceDataArray; + planeArray->reserve(rows); + + for (int i = 0; i < rows; i++) { + planeArray->append(new QSurfaceDataRow); + (*planeArray)[i]->resize(columns); + for (int j = 0; j < columns; j++) { + (*planeArray->at(i))[j].setX(float(j) * randFactor); + (*planeArray->at(i))[j].setY(float(i - j) * randFactor); + (*planeArray->at(i))[j].setZ(float(i)); + } + } + +#ifdef MULTI_SERIES + int series = rand() % 4; + m_multiseries[series]->dataProxy()->resetArray(planeArray); +#else + m_theSeries->dataProxy()->resetArray(planeArray); +#endif +} + +void GraphModifier::resetArrayEmpty() +{ + QSurfaceDataArray *emptryArray = new QSurfaceDataArray; +#ifdef MULTI_SERIES + int series = rand() % 4; + m_multiseries[series]->dataProxy()->resetArray(emptryArray); +#else + m_theSeries->dataProxy()->resetArray(emptryArray); +#endif +} + void GraphModifier::changeMesh() { static int model = 0; diff --git a/tests/surfacetest/graphmodifier.h b/tests/surfacetest/graphmodifier.h index 9fd0360b..5c4ed033 100644 --- a/tests/surfacetest/graphmodifier.h +++ b/tests/surfacetest/graphmodifier.h @@ -105,6 +105,8 @@ public: void insertRow(); void insertRows(); void removeRow(); + void resetArray(); + void resetArrayEmpty(); public slots: void changeShadowQuality(int quality); diff --git a/tests/surfacetest/main.cpp b/tests/surfacetest/main.cpp index 6b54b8dd..bddb2d11 100644 --- a/tests/surfacetest/main.cpp +++ b/tests/surfacetest/main.cpp @@ -338,6 +338,12 @@ int main(int argc, char *argv[]) QPushButton *removeRowButton = new QPushButton(widget); removeRowButton->setText(QStringLiteral("Remove a row")); + QPushButton *resetArrayButton = new QPushButton(widget); + resetArrayButton->setText(QStringLiteral("Reset Series Array to plane")); + + QPushButton *resetArrayEmptyButton = new QPushButton(widget); + resetArrayEmptyButton->setText(QStringLiteral("Reset Series Array to empty")); + QFrame* line = new QFrame(); line->setFrameShape(QFrame::HLine); line->setFrameShadow(QFrame::Sunken); @@ -423,6 +429,8 @@ int main(int argc, char *argv[]) vLayout2->addWidget(insertRowButton); vLayout2->addWidget(insertRowsButton); vLayout2->addWidget(removeRowButton); + vLayout2->addWidget(resetArrayButton); + vLayout2->addWidget(resetArrayEmptyButton); widget->show(); @@ -574,6 +582,10 @@ int main(int argc, char *argv[]) modifier, &GraphModifier::insertRows); QObject::connect(removeRowButton,&QPushButton::clicked, modifier, &GraphModifier::removeRow); + QObject::connect(resetArrayButton,&QPushButton::clicked, + modifier, &GraphModifier::resetArray); + QObject::connect(resetArrayEmptyButton,&QPushButton::clicked, + modifier, &GraphModifier::resetArrayEmpty); #ifdef MULTI_SERIES modifier->setSeries1CB(series1CB); |