From e91237b54c2f58eaa8a2ce36bf016e2d8e8588f2 Mon Sep 17 00:00:00 2001 From: Mika Salmela Date: Thu, 6 Feb 2014 12:56:54 +0200 Subject: Multiseries support for surface Task-number: QTRD-2767 Change-Id: Ifa7ca07f2afdb27974ad20819f0a4646293764b0 Reviewed-by: Miikka Heikkinen --- src/datavisualization/data/qabstract3dseries.h | 1 + .../engine/abstract3drenderer.cpp | 13 +- .../engine/abstract3drenderer_p.h | 1 + src/datavisualization/engine/engine.pri | 6 +- src/datavisualization/engine/seriesrendercache.cpp | 4 + src/datavisualization/engine/seriesrendercache_p.h | 2 + .../engine/surface3dcontroller.cpp | 25 +- .../engine/surface3dcontroller_p.h | 1 + src/datavisualization/engine/surface3drenderer.cpp | 751 +++++++++++---------- src/datavisualization/engine/surface3drenderer_p.h | 24 +- .../engine/surfaceseriesrendercache.cpp | 73 ++ .../engine/surfaceseriesrendercache_p.h | 101 +++ .../global/datavisualizationglobal_p.h | 2 + src/datavisualization/utils/surfaceobject.cpp | 7 + src/datavisualization/utils/surfaceobject_p.h | 13 +- src/datavisualization/utils/texturehelper.cpp | 12 + src/datavisualization/utils/texturehelper_p.h | 1 + tests/surfacetest/graphmodifier.cpp | 333 ++++++++- tests/surfacetest/graphmodifier.h | 39 ++ tests/surfacetest/main.cpp | 200 +++++- 20 files changed, 1219 insertions(+), 390 deletions(-) create mode 100644 src/datavisualization/engine/surfaceseriesrendercache.cpp create mode 100644 src/datavisualization/engine/surfaceseriesrendercache_p.h diff --git a/src/datavisualization/data/qabstract3dseries.h b/src/datavisualization/data/qabstract3dseries.h index ebb22b7f..c45bb801 100644 --- a/src/datavisualization/data/qabstract3dseries.h +++ b/src/datavisualization/data/qabstract3dseries.h @@ -142,6 +142,7 @@ private: friend class Abstract3DController; friend class Bars3DController; friend class Surface3DController; + friend class Surface3DRenderer; friend class Scatter3DController; friend class QBar3DSeries; friend class SeriesRenderCache; diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp index e3ec7c9a..e62f2a00 100644 --- a/src/datavisualization/engine/abstract3drenderer.cpp +++ b/src/datavisualization/engine/abstract3drenderer.cpp @@ -426,8 +426,17 @@ void Abstract3DRenderer::lowerShadowQuality() updateShadowQuality(newQuality); } -void Abstract3DRenderer::fixGradientAndGenerateTexture(QLinearGradient *gradient, - GLuint *gradientTexture) +void Abstract3DRenderer::generateBaseColorTexture(const QColor &color, GLuint *texture) +{ + if (*texture) { + m_textureHelper->deleteTexture(texture); + *texture = 0; + } + + *texture = m_textureHelper->createUniformTexture(color); +} + +void Abstract3DRenderer::fixGradientAndGenerateTexture(QLinearGradient *gradient, GLuint *gradientTexture) { // Readjust start/stop to match gradient texture size gradient->setStart(qreal(gradientTextureWidth), qreal(gradientTextureHeight)); diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h index e7591a10..a381adf8 100644 --- a/src/datavisualization/engine/abstract3drenderer_p.h +++ b/src/datavisualization/engine/abstract3drenderer_p.h @@ -94,6 +94,7 @@ public: virtual void updateAxisLabelFormat(QAbstract3DAxis::AxisOrientation orientation, const QString &format); virtual void fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh); + void generateBaseColorTexture(const QColor &color, GLuint *texture); void fixGradientAndGenerateTexture(QLinearGradient *gradient, GLuint *gradientTexture); inline bool isClickPending() { return m_clickPending; } diff --git a/src/datavisualization/engine/engine.pri b/src/datavisualization/engine/engine.pri index e13a9a04..b686397c 100644 --- a/src/datavisualization/engine/engine.pri +++ b/src/datavisualization/engine/engine.pri @@ -26,7 +26,8 @@ HEADERS += $$PWD/qabstract3dgraph_p.h \ $$PWD/q3dbox.h \ $$PWD/q3dobject.h \ $$PWD/q3dobject_p.h \ - $$PWD/q3dscene_p.h + $$PWD/q3dscene_p.h \ + $$PWD/surfaceseriesrendercache_p.h SOURCES += $$PWD/qabstract3dgraph.cpp \ $$PWD/q3dbars.cpp \ @@ -48,6 +49,7 @@ SOURCES += $$PWD/qabstract3dgraph.cpp \ $$PWD/q3dlight.cpp \ $$PWD/q3dbox.cpp \ $$PWD/q3dobject.cpp \ - $$PWD/q3dscene.cpp + $$PWD/q3dscene.cpp \ + $$PWD/surfaceseriesrendercache.cpp RESOURCES += engine/engine.qrc diff --git a/src/datavisualization/engine/seriesrendercache.cpp b/src/datavisualization/engine/seriesrendercache.cpp index fe2db319..5d20e761 100644 --- a/src/datavisualization/engine/seriesrendercache.cpp +++ b/src/datavisualization/engine/seriesrendercache.cpp @@ -30,6 +30,7 @@ SeriesRenderCache::SeriesRenderCache() : m_series(0), m_object(0), m_mesh(QAbstract3DSeries::MeshCube), + m_baseUniformTexture(0), m_baseGradientTexture(0), m_singleHighlightGradientTexture(0), m_multiHighlightGradientTexture(0) @@ -138,6 +139,8 @@ void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer * if (seriesChanged || changeTracker.baseColorChanged) { m_baseColor = Utils::vectorFromColor(series->baseColor()); + if (m_series->type() == QAbstract3DSeries::SeriesTypeSurface) + renderer->generateBaseColorTexture(series->baseColor(), &m_baseUniformTexture); changeTracker.baseColorChanged = false; } @@ -178,6 +181,7 @@ void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer * void SeriesRenderCache::cleanup(TextureHelper *texHelper) { delete m_object; + texHelper->deleteTexture(&m_baseUniformTexture); texHelper->deleteTexture(&m_baseGradientTexture); texHelper->deleteTexture(&m_singleHighlightGradientTexture); texHelper->deleteTexture(&m_multiHighlightGradientTexture); diff --git a/src/datavisualization/engine/seriesrendercache_p.h b/src/datavisualization/engine/seriesrendercache_p.h index 82f69ccd..7994339a 100644 --- a/src/datavisualization/engine/seriesrendercache_p.h +++ b/src/datavisualization/engine/seriesrendercache_p.h @@ -58,6 +58,7 @@ public: inline ObjectHelper *object() const { return m_object; } inline const Q3DTheme::ColorStyle &colorStyle() const { return m_colorStyle; } inline const QVector3D &baseColor() const { return m_baseColor; } + inline const GLuint &baseUniformTexture() const { return m_baseUniformTexture; } inline const GLuint &baseGradientTexture() const { return m_baseGradientTexture; } inline const QVector3D &singleHighlightColor() const { return m_singleHighlightColor; } inline const GLuint &singleHighlightGradientTexture() const { return m_singleHighlightGradientTexture; } @@ -74,6 +75,7 @@ protected: Q3DTheme::ColorStyle m_colorStyle; QVector3D m_baseColor; + GLuint m_baseUniformTexture; GLuint m_baseGradientTexture; QVector3D m_singleHighlightColor; GLuint m_singleHighlightGradientTexture; diff --git a/src/datavisualization/engine/surface3dcontroller.cpp b/src/datavisualization/engine/surface3dcontroller.cpp index 664c4a71..553166e1 100644 --- a/src/datavisualization/engine/surface3dcontroller.cpp +++ b/src/datavisualization/engine/surface3dcontroller.cpp @@ -68,6 +68,11 @@ void Surface3DController::synchDataToRenderer() if (!isInitialized()) return; + if (m_changedSeriesList.size()) { + m_renderer->modifiedSeriesList(m_changedSeriesList); + m_changedSeriesList.clear(); + } + Abstract3DController::synchDataToRenderer(); // Notify changes to renderer @@ -143,14 +148,10 @@ void Surface3DController::addSeries(QAbstract3DSeries *series) { Q_ASSERT(series && series->type() == QAbstract3DSeries::SeriesTypeSurface); - if (!m_seriesList.size()) { - Abstract3DController::addSeries(series); + Abstract3DController::addSeries(series); - if (series->isVisible()) - adjustValueAxisRange(); - } else { - qWarning("Surface graph only supports a single series."); - } + if (series->isVisible()) + adjustValueAxisRange(); QSurface3DSeries *surfaceSeries = static_cast(series); if (surfaceSeries->selectedPoint() != invalidSelectionPosition()) @@ -260,7 +261,7 @@ void Surface3DController::setSelectedPoint(const QPoint &position, QSurface3DSer emitNeedRender(); } - if (pos != m_selectedPoint) { + if (pos != m_selectedPoint || series != m_selectedSeries) { m_selectedPoint = pos; m_selectedSeries = series; m_changeTracker.selectedPointChanged = true; @@ -288,6 +289,8 @@ void Surface3DController::handleArrayReset() QSurface3DSeries *series = static_cast(sender())->series(); if (series->isVisible()) { adjustValueAxisRange(); + if (!m_changedSeriesList.contains(series)) + m_changedSeriesList.append(series); m_isDataDirty = true; } // Clear selection unless still valid @@ -375,6 +378,8 @@ void Surface3DController::handleRowsAdded(int startIndex, int count) if (series->isVisible()) { adjustValueAxisRange(); m_isDataDirty = true; + if (!m_changedSeriesList.contains(series)) + m_changedSeriesList.append(series); } emitNeedRender(); } @@ -396,6 +401,8 @@ void Surface3DController::handleRowsInserted(int startIndex, int count) if (series->isVisible()) { adjustValueAxisRange(); m_isDataDirty = true; + if (!m_changedSeriesList.contains(series)) + m_changedSeriesList.append(series); } emitNeedRender(); @@ -422,6 +429,8 @@ void Surface3DController::handleRowsRemoved(int startIndex, int count) if (series->isVisible()) { adjustValueAxisRange(); m_isDataDirty = true; + if (!m_changedSeriesList.contains(series)) + m_changedSeriesList.append(series); } emitNeedRender(); diff --git a/src/datavisualization/engine/surface3dcontroller_p.h b/src/datavisualization/engine/surface3dcontroller_p.h index 4ca9c8e2..64a57b3b 100644 --- a/src/datavisualization/engine/surface3dcontroller_p.h +++ b/src/datavisualization/engine/surface3dcontroller_p.h @@ -67,6 +67,7 @@ private: bool m_flatShadingSupported; QVector m_changedItems; QVector m_changedRows; + QVector m_changedSeriesList; public: explicit Surface3DController(QRect rect, Q3DScene *scene = 0); diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp index 4dbd48ba..48d10932 100644 --- a/src/datavisualization/engine/surface3drenderer.cpp +++ b/src/datavisualization/engine/surface3drenderer.cpp @@ -60,7 +60,8 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller) m_cachedIsSlicingActivated(false), m_depthShader(0), m_backgroundShader(0), - m_surfaceShader(0), + m_surfaceFlatShader(0), + m_surfaceSmoothShader(0), m_surfaceGridShader(0), m_selectionShader(0), m_labelShader(0), @@ -84,19 +85,15 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller) m_gridLineObj(0), m_labelObj(0), m_surfaceObj(0), - m_sliceSurfaceObj(0), m_depthTexture(0), m_depthModelTexture(0), m_depthFrameBuffer(0), m_selectionFrameBuffer(0), m_selectionDepthBuffer(0), - m_selectionTexture(0), m_selectionResultTexture(0), m_shadowQualityToShader(33.3f), m_cachedFlatShading(false), m_flatSupported(true), - m_cachedSurfaceVisible(true), - m_cachedSurfaceGridOn(true), m_selectionPointer(0), m_selectionActive(false), m_xFlipped(false), @@ -108,8 +105,8 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller) m_hasHeightAdjustmentChanged(true), m_selectedPoint(Surface3DController::invalidSelectionPosition()), m_selectedSeries(0), - m_uniformGradientTexture(0), - m_clickedPosition(Surface3DController::invalidSelectionPosition()) + m_clickedPosition(Surface3DController::invalidSelectionPosition()), + m_selectionTexturesDirty(false) { // Check if flat feature is supported ShaderHelper tester(this, QStringLiteral(":/shaders/vertexSurfaceFlat"), @@ -125,9 +122,6 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller) initializeOpenGLFunctions(); initializeOpenGL(); - - // Create initial uniform gradient - generateUniformGradient(m_uniformGradientTextureColor); } Surface3DRenderer::~Surface3DRenderer() @@ -139,32 +133,29 @@ Surface3DRenderer::~Surface3DRenderer() m_textureHelper->deleteTexture(&m_depthTexture); m_textureHelper->deleteTexture(&m_depthModelTexture); - m_textureHelper->deleteTexture(&m_selectionTexture); m_textureHelper->deleteTexture(&m_selectionResultTexture); - m_textureHelper->deleteTexture(&m_uniformGradientTexture); + foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + GLuint texture = cache->selectionTexture(); + m_textureHelper->deleteTexture(&texture); + } } delete m_depthShader; delete m_backgroundShader; delete m_selectionShader; - delete m_surfaceShader; + delete m_surfaceFlatShader; + delete m_surfaceSmoothShader; delete m_surfaceGridShader; delete m_labelShader; delete m_backgroundObj; - delete m_surfaceObj; - delete m_sliceSurfaceObj; delete m_gridLineObj; delete m_labelObj; delete m_selectionPointer; - for (int i = 0; i < m_dataArray.size(); i++) - delete m_dataArray.at(i); - m_dataArray.clear(); - - for (int i = 0; i < m_sliceDataArray.size(); i++) - delete m_sliceDataArray.at(i); - m_sliceDataArray.clear(); + foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) + delete cache; + m_renderCacheList.clear(); } void Surface3DRenderer::initializeOpenGL() @@ -200,77 +191,56 @@ void Surface3DRenderer::initializeOpenGL() void Surface3DRenderer::updateData() { - // Surface only supports single series for now, so we are only interested in the first series - const QSurfaceDataArray *array = 0; - if (m_visibleSeriesList.size()) { - QSurface3DSeries *firstSeries = static_cast(m_visibleSeriesList.at(0).series()); - QSurfaceDataProxy *dataProxy = firstSeries->dataProxy(); - if (dataProxy) - array = dataProxy->array(); - } - calculateSceneScalingFactors(); - // Need minimum of 2x2 array to draw a surface - if (array && array->size() >= 2 && array->at(0)->size() >= 2) { - QRect sampleSpace = calculateSampleRect(*array); + foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + const QSurface3DSeries *currentSeries = cache->series(); + QSurfaceDataProxy *dataProxy = currentSeries->dataProxy(); + const QSurfaceDataArray &array = *dataProxy->array(); - bool dimensionChanged = false; - if (m_sampleSpace != sampleSpace) { - dimensionChanged = true; - m_sampleSpace = sampleSpace; + // Need minimum of 2x2 array to draw a surface + if (array.size() >= 2 && array.at(0)->size() >= 2) { + QRect sampleSpace = calculateSampleRect(array); - for (int i = 0; i < m_dataArray.size(); i++) - delete m_dataArray.at(i); - m_dataArray.clear(); - } + QSurfaceDataArray &dataArray = cache->dataArray(); + bool dimensionChanged = false; + if (cache->sampleSpace() != sampleSpace) { + if (cache->sampleSpace().width()) + m_selectionTexturesDirty = true; - if (sampleSpace.width() >= 2 && sampleSpace.height() >= 2) { - if (dimensionChanged) { - m_dataArray.reserve(sampleSpace.height()); - for (int i = 0; i < sampleSpace.height(); i++) - m_dataArray << new QSurfaceDataRow(sampleSpace.width()); - } - for (int i = 0; i < sampleSpace.height(); i++) { - for (int j = 0; j < sampleSpace.width(); j++) - (*(m_dataArray.at(i)))[j] = array->at(i + sampleSpace.y())->at( - j + sampleSpace.x()); - } + dimensionChanged = true; + cache->setSampleSpace(sampleSpace); - if (m_dataArray.size() > 0) { - if (!m_surfaceObj) - loadSurfaceObj(); + for (int i = 0; i < dataArray.size(); i++) + delete dataArray.at(i); + dataArray.clear(); + } - // Note: Data setup can change sample space (as min width/height is 1) - if (!m_cachedFlatShading) { - m_surfaceObj->setUpSmoothData(m_dataArray, m_sampleSpace, m_heightNormalizer, - m_axisCacheY.min(), dimensionChanged); - } else { - m_surfaceObj->setUpData(m_dataArray, m_sampleSpace, m_heightNormalizer, - m_axisCacheY.min(), dimensionChanged); + if (sampleSpace.width() >= 2 && sampleSpace.height() >= 2) { + if (dimensionChanged) { + dataArray.reserve(sampleSpace.height()); + for (int i = 0; i < sampleSpace.height(); i++) + dataArray << new QSurfaceDataRow(sampleSpace.width()); + } + for (int i = 0; i < sampleSpace.height(); i++) { + for (int j = 0; j < sampleSpace.width(); j++) { + (*(dataArray.at(i)))[j] = array.at(i + sampleSpace.y())->at( + j + sampleSpace.x()); + } } - if (dimensionChanged) - updateSelectionTexture(); + if (dataArray.size() > 0 && (cache->objectDirty() || dimensionChanged)) { + checkFlatSupport(cache); + updateObjects(cache, dimensionChanged); + cache->setObjectDirty(false); + cache->setFlatStatusDirty(false); + } } } - } else { - for (int i = 0; i < m_dataArray.size(); i++) - delete m_dataArray.at(i); - m_dataArray.clear(); - m_sampleSpace = QRect(); - - delete m_surfaceObj; - m_surfaceObj = 0; -#if !defined(QT_OPENGL_ES_2) - m_textureHelper->fillDepthTexture(m_depthTexture, m_primarySubViewport.size(), - m_shadowQualityMultiplier, 1.0f); -#endif } - for (int i = 0; i < m_sliceDataArray.size(); i++) - delete m_sliceDataArray.at(i); - m_sliceDataArray.clear(); + if (m_selectionTexturesDirty && m_cachedSelectionMode > QAbstract3DGraph::SelectionNone) + updateSelectionTextures(); updateSelectedPoint(m_selectedPoint, m_selectedSeries); } @@ -278,35 +248,69 @@ void Surface3DRenderer::updateData() void Surface3DRenderer::updateSeries(const QList &seriesList, bool updateVisibility) { - Abstract3DRenderer::updateSeries(seriesList, updateVisibility); + Q_UNUSED(updateVisibility); - if (m_visibleSeriesList.size()) { - QSurface3DSeries *series = static_cast(m_visibleSeriesList.at(0).series()); - updateFlatStatus(series->isFlatShadingEnabled()); + foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) + cache->setValid(false); - QSurface3DSeries::DrawFlags drawMode = series->drawMode(); - m_cachedSurfaceVisible = drawMode.testFlag(QSurface3DSeries::DrawSurface); -#if !defined(QT_OPENGL_ES_2) - if (!m_cachedSurfaceVisible) { - m_textureHelper->fillDepthTexture(m_depthTexture, m_primarySubViewport.size(), - m_shadowQualityMultiplier, 1.0f); + foreach (QAbstract3DSeries *series, seriesList) { + // Item selection label may need update + if (series->d_ptr->m_changeTracker.nameChanged + || series->d_ptr->m_changeTracker.itemLabelFormatChanged) { + m_selectionLabelDirty = true; } -#endif - m_cachedSurfaceGridOn = drawMode.testFlag(QSurface3DSeries::DrawWireframe); - QVector3D seriesColor = Utils::vectorFromColor(series->baseColor()); - if (m_uniformGradientTextureColor != seriesColor) - generateUniformGradient(seriesColor); - if (m_selectionPointer) { + QSurface3DSeries *surfaceSeries = static_cast(series); + SurfaceSeriesRenderCache *cache = m_renderCacheList.value(surfaceSeries); + if (!cache) { + cache = new SurfaceSeriesRenderCache; + m_renderCacheList[surfaceSeries] = cache; + + m_selectionTexturesDirty = true; + } + cache->setValid(true); + cache->populate(surfaceSeries, this); + if (cache->isFlatStatusDirty() && cache->sampleSpace().width()) { + checkFlatSupport(cache); + updateObjects(cache, true); + cache->setFlatStatusDirty(false); + } + } + + foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + if (!cache->isValid()) { + if (cache->series() == m_selectedSeries) + updateSelectedPoint(Surface3DController::invalidSelectionPosition(), 0); + + m_renderCacheList.remove(cache->series()); + delete cache; + + m_selectionTexturesDirty = true; + } + } + + if (m_selectionPointer && m_selectedSeries) { + SurfaceSeriesRenderCache *cache = + m_renderCacheList.value(const_cast(m_selectedSeries)); + if (cache) { m_selectionPointer->setHighlightColor( - Utils::vectorFromColor(series->singleHighlightColor())); + Utils::vectorFromColor(m_selectedSeries->singleHighlightColor())); // Make sure selection pointer object reference is still good - m_selectionPointer->setPointerObject(m_visibleSeriesList.at(0).object()); - m_selectionPointer->setRotation(m_visibleSeriesList.at(0).meshRotation()); + m_selectionPointer->setPointerObject(cache->object()); + m_selectionPointer->setRotation(cache->meshRotation()); } } } +void Surface3DRenderer::modifiedSeriesList(const QVector &seriesList) +{ + foreach (QSurface3DSeries *series, seriesList) { + SurfaceSeriesRenderCache *cache = m_renderCacheList.value(series); + if (cache) + cache->setObjectDirty(true); + } +} + void Surface3DRenderer::updateRows(const QVector &rows) { // Surface only supports single series for now, so we are only interested in the first series @@ -392,52 +396,53 @@ void Surface3DRenderer::updateSliceDataModel(const QPoint &point) int column = point.y(); int row = point.x(); - for (int i = 0; i < m_sliceDataArray.size(); i++) - delete m_sliceDataArray.at(i); - m_sliceDataArray.clear(); - - m_sliceDataArray.reserve(2); - QSurfaceDataRow *sliceRow; - - float adjust = (0.025f * m_heightNormalizer) / 2.0f; - float stepDown = 2.0f * adjust; - if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow)) { - QSurfaceDataRow *src = m_dataArray.at(row); - sliceRow = new QSurfaceDataRow(src->size()); - for (int i = 0; i < sliceRow->size(); i++) - (*sliceRow)[i].setPosition(QVector3D(src->at(i).x(), src->at(i).y() + adjust, -1.0f)); - } else { - sliceRow = new QSurfaceDataRow(m_sampleSpace.height()); - for (int i = 0; i < m_sampleSpace.height(); i++) { - (*sliceRow)[i].setPosition(QVector3D(m_dataArray.at(i)->at(column).z(), - m_dataArray.at(i)->at(column).y() + adjust, - -1.0f)); + foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + QSurfaceDataArray &sliceDataArray = cache->sliceDataArray(); + for (int i = 0; i < sliceDataArray.size(); i++) + delete sliceDataArray.at(i); + sliceDataArray.clear(); + sliceDataArray.reserve(2); + + QSurfaceDataRow *sliceRow; + QSurfaceDataArray &dataArray = cache->dataArray(); + float adjust = (0.025f * m_heightNormalizer) / 2.0f; + float stepDown = 2.0f * adjust; + if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow)) { + QSurfaceDataRow *src = dataArray.at(row); + sliceRow = new QSurfaceDataRow(src->size()); + for (int i = 0; i < sliceRow->size(); i++) + (*sliceRow)[i].setPosition(QVector3D(src->at(i).x(), src->at(i).y() + adjust, -1.0f)); + } else { + QRect sampleSpace = cache->sampleSpace(); + sliceRow = new QSurfaceDataRow(sampleSpace.height()); + for (int i = 0; i < sampleSpace.height(); i++) { + (*sliceRow)[i].setPosition(QVector3D(dataArray.at(i)->at(column).z(), + dataArray.at(i)->at(column).y() + adjust, + -1.0f)); + } } - } - m_sliceDataArray << sliceRow; + sliceDataArray << sliceRow; - // Make a duplicate, so that we get a little bit depth - QSurfaceDataRow *duplicateRow = new QSurfaceDataRow(*sliceRow); - for (int i = 0; i < sliceRow->size(); i++) { - (*sliceRow)[i].setPosition(QVector3D(sliceRow->at(i).x(), sliceRow->at(i).y() - stepDown, - 1.0f)); - } - - m_sliceDataArray << duplicateRow; + // Make a duplicate, so that we get a little bit depth + QSurfaceDataRow *duplicateRow = new QSurfaceDataRow(*sliceRow); + for (int i = 0; i < sliceRow->size(); i++) { + (*sliceRow)[i].setPosition(QVector3D(sliceRow->at(i).x(), sliceRow->at(i).y() - stepDown, + 1.0f)); + } - QRect sliceRect(0, 0, sliceRow->size(), 2); + sliceDataArray << duplicateRow; - if (sliceRow->size() > 0) { - if (!m_sliceSurfaceObj) - loadSliceSurfaceObj(); + QRect sliceRect(0, 0, sliceRow->size(), 2); - if (!m_cachedFlatShading) { - m_sliceSurfaceObj->setUpSmoothData(m_sliceDataArray, sliceRect, m_heightNormalizer, - m_axisCacheY.min(), true); - } else { - m_sliceSurfaceObj->setUpData(m_sliceDataArray, sliceRect, m_heightNormalizer, - m_axisCacheY.min(), true); + if (sliceRow->size() > 0) { + if (cache->isFlatShadingEnabled()) { + cache->sliceSurfaceObject()->setUpData(sliceDataArray, sliceRect, m_heightNormalizer, + m_axisCacheY.min(), true); + } else { + cache->sliceSurfaceObject()->setUpSmoothData(sliceDataArray, sliceRect, m_heightNormalizer, + m_axisCacheY.min(), true); + } } } } @@ -612,13 +617,11 @@ void Surface3DRenderer::drawSlicedScene() offset = -m_surfaceOffsetZ; } - if (m_surfaceObj) { + if (m_renderCacheList.size()) { QMatrix4x4 MVPMatrix; QMatrix4x4 modelMatrix; QMatrix4x4 itModelMatrix; - const SeriesRenderCache &series = m_visibleSeriesList.at(0); - modelMatrix.translate(offset, 0.0f, 0.0f); QVector3D scaling(scaleX, 1.0f, sliceZScale); modelMatrix.scale(scaling); @@ -626,41 +629,49 @@ void Surface3DRenderer::drawSlicedScene() MVPMatrix = projectionViewMatrix * modelMatrix; - if (m_cachedSurfaceVisible) { - if (m_cachedSurfaceGridOn) { - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(0.5f, 1.0f); - } + bool drawGrid = false; + + foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + if (cache->surfaceVisible()) { + if (cache->surfaceGridVisible()) { + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(0.5f, 1.0f); + drawGrid = true; + } - ShaderHelper *surfaceShader = m_surfaceShader; - surfaceShader->bind(); - - GLuint baseGradientTexture = m_uniformGradientTexture; - if (series.colorStyle() != Q3DTheme::ColorStyleUniform) - baseGradientTexture = series.baseGradientTexture(); - - // Set shader bindings - surfaceShader->setUniformValue(surfaceShader->lightP(), lightPos); - surfaceShader->setUniformValue(surfaceShader->view(), viewMatrix); - surfaceShader->setUniformValue(surfaceShader->model(), modelMatrix); - surfaceShader->setUniformValue(surfaceShader->nModel(), - itModelMatrix.inverted().transposed()); - surfaceShader->setUniformValue(surfaceShader->MVP(), MVPMatrix); - surfaceShader->setUniformValue(surfaceShader->lightS(), 0.15f); - surfaceShader->setUniformValue(surfaceShader->ambientS(), - m_cachedTheme->ambientLightStrength() * 2.3f); - surfaceShader->setUniformValue(surfaceShader->lightColor(), lightColor); - - m_drawer->drawObject(surfaceShader, m_sliceSurfaceObj, baseGradientTexture); + ShaderHelper *surfaceShader = m_surfaceFlatShader; + surfaceShader->bind(); + + GLuint colorTexture = cache->baseUniformTexture();; + if (cache->colorStyle() != Q3DTheme::ColorStyleUniform) + colorTexture = cache->baseGradientTexture(); + + // Set shader bindings + surfaceShader->setUniformValue(surfaceShader->lightP(), lightPos); + surfaceShader->setUniformValue(surfaceShader->view(), viewMatrix); + surfaceShader->setUniformValue(surfaceShader->model(), modelMatrix); + surfaceShader->setUniformValue(surfaceShader->nModel(), + itModelMatrix.inverted().transposed()); + surfaceShader->setUniformValue(surfaceShader->MVP(), MVPMatrix); + surfaceShader->setUniformValue(surfaceShader->lightS(), 0.15f); + surfaceShader->setUniformValue(surfaceShader->ambientS(), + m_cachedTheme->ambientLightStrength() * 2.3f); + surfaceShader->setUniformValue(surfaceShader->lightColor(), lightColor); + + m_drawer->drawObject(surfaceShader, cache->sliceSurfaceObject(), colorTexture); + } } // Draw surface grid - if (m_cachedSurfaceGridOn) { + if (drawGrid) { m_surfaceGridShader->bind(); m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(), Utils::vectorFromColor(m_cachedTheme->gridLineColor())); m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), MVPMatrix); - m_drawer->drawSurfaceGrid(m_surfaceGridShader, m_sliceSurfaceObj); + foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + if (cache->surfaceGridVisible()) + m_drawer->drawSurfaceGrid(m_surfaceGridShader, cache->sliceSurfaceObject()); + } glDisable(GL_POLYGON_OFFSET_FILL); } @@ -849,8 +860,6 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) m_primarySubViewport.width(), m_primarySubViewport.height()); - // Specify viewport - // Set up projection matrix QMatrix4x4 projectionMatrix; projectionMatrix.perspective(45.0f, (GLfloat)m_primarySubViewport.width() @@ -893,8 +902,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) // Draw depth buffer #if !defined(QT_OPENGL_ES_2) GLfloat adjustedLightStrength = m_cachedTheme->lightStrength() / 10.0f; - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone && m_surfaceObj - && m_cachedSurfaceVisible) { + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone && m_renderCacheList.size()) { // Render scene into a depth texture for using with shadow mapping // Enable drawing to depth framebuffer glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer); @@ -943,18 +951,23 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix); - // 1st attribute buffer : vertices - glEnableVertexAttribArray(m_depthShader->posAtt()); - glBindBuffer(GL_ARRAY_BUFFER, m_surfaceObj->vertexBuf()); - glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, - (void *)0); - - // Index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_surfaceObj->elementBuf()); - - // Draw the triangles - glDrawElements(GL_TRIANGLES, m_surfaceObj->indexCount(), m_surfaceObj->indicesType(), - (void *)0); + foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + if (cache->surfaceVisible() && cache->isSeriesVisible()) { + SurfaceObject *object = cache->surfaceObject(); + // 1st attribute buffer : vertices + glEnableVertexAttribArray(m_depthShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, object->vertexBuf()); + glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, + (void *)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, object->indexCount(), + object->indicesType(), (void *)0); + } + } glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); @@ -963,9 +976,23 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) m_depthModelTexture, 0); glClear(GL_DEPTH_BUFFER_BIT); - // Draw the triangles - glDrawElements(GL_TRIANGLES, m_surfaceObj->indexCount(), m_surfaceObj->indicesType(), - (void *)0); + foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + if (cache->surfaceVisible() && cache->isSeriesVisible()) { + SurfaceObject *object = cache->surfaceObject(); + // 1st attribute buffer : vertices + glEnableVertexAttribArray(m_depthShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, object->vertexBuf()); + glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, + (void *)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, object->indexCount(), + object->indicesType(), (void *)0); + } + } // Free buffers glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -991,10 +1018,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) glEnable(GL_TEXTURE_2D); // Draw selection buffer - if (!m_cachedIsSlicingActivated && m_surfaceObj && m_selectionState == SelectOnScene - && m_cachedSelectionMode > QAbstract3DGraph::SelectionNone - && (m_cachedSurfaceVisible || m_cachedSurfaceGridOn) - && m_visibleSeriesList.size() > 0) { + if (!m_cachedIsSlicingActivated && m_renderCacheList.size() && m_selectionState == SelectOnScene + && m_cachedSelectionMode > QAbstract3DGraph::SelectionNone) { m_selectionShader->bind(); glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer); glViewport(0, @@ -1019,7 +1044,12 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix); - m_drawer->drawObject(m_selectionShader, m_surfaceObj, m_selectionTexture); + foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + if (cache->surfaceVisible() && cache->isSeriesVisible()) { + m_drawer->drawObject(m_selectionShader, cache->surfaceObject(), + cache->selectionTexture()); + } + } glEnable(GL_DITHER); @@ -1037,7 +1067,6 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) #endif m_clickedPosition = selectionIdToSurfacePoint(selectionId); - m_clickedSeries = m_visibleSeriesList.at(0).series(); emit needRender(); @@ -1049,14 +1078,9 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) } // Draw the surface - if (m_surfaceObj && m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) { - m_surfaceShader->bind(); + if (m_renderCacheList.size()) { // For surface we can see climpses from underneath glDisable(GL_CULL_FACE); - if (m_cachedSurfaceGridOn) { - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(0.5f, 1.0f); - } QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; @@ -1071,57 +1095,77 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) #else MVPMatrix = projectionViewMatrix * modelMatrix; #endif + bool drawGrid = false; + + foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + QRect sampleSpace = cache->sampleSpace(); + if (cache->isSeriesVisible() && sampleSpace.width() >= 2 && sampleSpace.height() >= 2) { + if (cache->surfaceGridVisible()) { + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(0.5f, 1.0f); + drawGrid = true; + } - if (m_cachedSurfaceVisible) { - // Set shader bindings - m_surfaceShader->setUniformValue(m_surfaceShader->lightP(), lightPos); - m_surfaceShader->setUniformValue(m_surfaceShader->view(), viewMatrix); - m_surfaceShader->setUniformValue(m_surfaceShader->model(), modelMatrix); - m_surfaceShader->setUniformValue(m_surfaceShader->nModel(), - itModelMatrix.inverted().transposed()); - m_surfaceShader->setUniformValue(m_surfaceShader->MVP(), MVPMatrix); - m_surfaceShader->setUniformValue(m_surfaceShader->ambientS(), - m_cachedTheme->ambientLightStrength()); - m_surfaceShader->setUniformValue(m_surfaceShader->lightColor(), lightColor); - - GLuint gradientTexture; - if (m_visibleSeriesList.at(0).colorStyle() == Q3DTheme::ColorStyleUniform) - gradientTexture = m_uniformGradientTexture; - else - gradientTexture = m_visibleSeriesList.at(0).baseGradientTexture(); - -#if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { - // Set shadow shader bindings - QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; - m_surfaceShader->setUniformValue(m_surfaceShader->shadowQ(), - m_shadowQualityToShader); - m_surfaceShader->setUniformValue(m_surfaceShader->depth(), depthMVPMatrix); - m_surfaceShader->setUniformValue(m_surfaceShader->lightS(), adjustedLightStrength); - - // Draw the object - m_drawer->drawObject(m_surfaceShader, m_surfaceObj, gradientTexture, - m_depthModelTexture); - } else -#endif - { - // Set shadowless shader bindings - m_surfaceShader->setUniformValue(m_surfaceShader->lightS(), - m_cachedTheme->lightStrength()); - - // Draw the object - m_drawer->drawObject(m_surfaceShader, m_surfaceObj, gradientTexture); + if (cache->surfaceVisible()) { + ShaderHelper *shader = m_surfaceFlatShader; + if (!cache->isFlatShadingEnabled()) + shader = m_surfaceSmoothShader; + shader->bind(); + + // Set shader bindings + shader->setUniformValue(shader->lightP(), lightPos); + shader->setUniformValue(shader->view(), viewMatrix); + shader->setUniformValue(shader->model(), modelMatrix); + shader->setUniformValue(shader->nModel(), + itModelMatrix.inverted().transposed()); + shader->setUniformValue(shader->MVP(), MVPMatrix); + shader->setUniformValue(shader->ambientS(), + m_cachedTheme->ambientLightStrength()); + shader->setUniformValue(shader->lightColor(), lightColor); + + GLuint gradientTexture; + if (cache->colorStyle() == Q3DTheme::ColorStyleUniform) + gradientTexture = cache->baseUniformTexture(); + else + gradientTexture = cache->baseGradientTexture(); + + #if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + // Set shadow shader bindings + QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + shader->setUniformValue(shader->shadowQ(), m_shadowQualityToShader); + shader->setUniformValue(shader->depth(), depthMVPMatrix); + shader->setUniformValue(shader->lightS(), adjustedLightStrength); + + // Draw the objects + m_drawer->drawObject(shader, cache->surfaceObject(), gradientTexture, m_depthModelTexture); + } else + #endif + { + // Set shadowless shader bindings + shader->setUniformValue(shader->lightS(), + m_cachedTheme->lightStrength()); + + // Draw the objects + m_drawer->drawObject(shader, cache->surfaceObject(), gradientTexture); + } + } } - glEnable(GL_CULL_FACE); } + glEnable(GL_CULL_FACE); // Draw surface grid - if (m_cachedSurfaceGridOn) { + if (drawGrid) { m_surfaceGridShader->bind(); m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(), Utils::vectorFromColor(m_cachedTheme->gridLineColor())); m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), MVPMatrix); - m_drawer->drawSurfaceGrid(m_surfaceGridShader, m_surfaceObj); + foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + QRect sampleSpace = cache->sampleSpace(); + if (cache->surfaceGridVisible() && cache->isSeriesVisible() && + sampleSpace.width() >= 2 && sampleSpace.height() >= 2) + m_drawer->drawSurfaceGrid(m_surfaceGridShader, cache->surfaceObject()); + } glDisable(GL_POLYGON_OFFSET_FILL); } @@ -1699,12 +1743,17 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) // Selection handling if (m_selectionDirty || m_selectionLabelDirty) { QPoint visiblePoint = Surface3DController::invalidSelectionPosition(); - if (m_selectedPoint != Surface3DController::invalidSelectionPosition()) { - int x = m_selectedPoint.x() - m_sampleSpace.y(); - int y = m_selectedPoint.y() - m_sampleSpace.x(); - if (x >= 0 && y >= 0 && x < m_sampleSpace.height() && y < m_sampleSpace.width() - && m_dataArray.size()) { - visiblePoint = QPoint(x, y); + if (m_selectedSeries) { + SurfaceSeriesRenderCache *cache = + m_renderCacheList.value(const_cast(m_selectedSeries)); + if (cache && m_selectedPoint != Surface3DController::invalidSelectionPosition()) { + QRect sampleSpace = cache->sampleSpace(); + int x = m_selectedPoint.x() - sampleSpace.y(); + int y = m_selectedPoint.y() - sampleSpace.x(); + if (x >= 0 && y >= 0 && x < sampleSpace.height() && y < sampleSpace.width() + && cache->dataArray().size()) { + visiblePoint = QPoint(x, y); + } } } @@ -1723,47 +1772,64 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) } } -// This one needs to be called when the data size changes -void Surface3DRenderer::updateSelectionTexture() +void Surface3DRenderer::updateSelectionMode(QAbstract3DGraph::SelectionFlags mode) +{ + Abstract3DRenderer::updateSelectionMode(mode); + + if (m_cachedSelectionMode > QAbstract3DGraph::SelectionNone) + updateSelectionTextures(); +} + +void Surface3DRenderer::updateSelectionTextures() +{ + uint lastSelectionId = 1; + + foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + GLuint texture = cache->selectionTexture(); + m_textureHelper->deleteTexture(&texture); + createSelectionTexture(cache, lastSelectionId); + } + m_selectionTexturesDirty = false; +} + +void Surface3DRenderer::createSelectionTexture(SurfaceSeriesRenderCache *cache, uint &lastSelectionId) { // Create the selection ID image. Each grid corner gets 2x2 pixel area of // ID color so that each vertex (data point) has 4x4 pixel area of ID color - int idImageWidth = (m_sampleSpace.width() - 1) * 4; - int idImageHeight = (m_sampleSpace.height() - 1) * 4; + QRect sampleSpace = cache->sampleSpace(); + int idImageWidth = (sampleSpace.width() - 1) * 4; + int idImageHeight = (sampleSpace.height() - 1) * 4; int stride = idImageWidth * 4 * sizeof(uchar); // 4 = number of color components (rgba) + uint idStart = lastSelectionId; uchar *bits = new uchar[idImageWidth * idImageHeight * 4 * sizeof(uchar)]; - uint id = 1; for (int i = 0; i < idImageHeight; i += 4) { for (int j = 0; j < idImageWidth; j += 4) { int p = (i * idImageWidth + j) * 4; uchar r, g, b, a; - idToRGBA(id, &r, &g, &b, &a); + idToRGBA(lastSelectionId, &r, &g, &b, &a); fillIdCorner(&bits[p], r, g, b, a, stride); - idToRGBA(id + 1, &r, &g, &b, &a); + idToRGBA(lastSelectionId + 1, &r, &g, &b, &a); fillIdCorner(&bits[p + 8], r, g, b, a, stride); - idToRGBA(id + m_sampleSpace.width(), &r, &g, &b, &a); + idToRGBA(lastSelectionId + sampleSpace.width(), &r, &g, &b, &a); fillIdCorner(&bits[p + 2 * stride], r, g, b, a, stride); - idToRGBA(id + m_sampleSpace.width() + 1, &r, &g, &b, &a); + idToRGBA(lastSelectionId + sampleSpace.width() + 1, &r, &g, &b, &a); fillIdCorner(&bits[p + 2 * stride + 8], r, g, b, a, stride); - id++; + lastSelectionId++; } - id++; - } - - // If old texture exists, delete it - if (m_selectionTexture) { - m_textureHelper->deleteTexture(&m_selectionTexture); - m_selectionTexture = 0; + lastSelectionId++; } + lastSelectionId += sampleSpace.width(); + cache->setSelectionIdRange(idStart, lastSelectionId - 1); // Move the ID image (bits) to the texture QImage image = QImage(bits, idImageWidth, idImageHeight, QImage::Format_RGB32); - m_selectionTexture = m_textureHelper->create2DTexture(image, false, false, false); + GLuint selectionTexture = m_textureHelper->create2DTexture(image, false, false, false); + cache->setSelectionTexture(selectionTexture); // Release the temp bits allocation delete[] bits; @@ -1823,33 +1889,29 @@ void Surface3DRenderer::calculateSceneScalingFactors() m_scaleZWithBackground = m_scaleZ * backgroundMargin; } -bool Surface3DRenderer::updateFlatStatus(bool enable) +void Surface3DRenderer::checkFlatSupport(SurfaceSeriesRenderCache *cache) { - if (enable && !m_flatSupported) { + bool flatEnable = cache->isFlatShadingEnabled(); + if (flatEnable && !m_flatSupported) { qWarning() << "Warning: Flat qualifier not supported on your platform's GLSL language." " Requires at least GLSL version 1.2 with GL_EXT_gpu_shader4 extension."; - enable = false; + cache->setFlatShadingEnabled(false); + cache->setFlatChangeAllowed(false); } +} - bool changed = false; - if (enable != m_cachedFlatShading) { - m_cachedFlatShading = enable; - changed = true; - initSurfaceShaders(); - } +void Surface3DRenderer::updateObjects(SurfaceSeriesRenderCache *cache, bool dimensionChanged) +{ + QSurfaceDataArray &dataArray = cache->dataArray(); + const QRect sampleSpace = cache->sampleSpace(); - // If no surface object created yet, don't try to update the object - if (m_surfaceObj && changed && m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) { - if (!m_cachedFlatShading) { - m_surfaceObj->setUpSmoothData(m_dataArray, m_sampleSpace, m_heightNormalizer, - m_axisCacheY.min(), true); - } else { - m_surfaceObj->setUpData(m_dataArray, m_sampleSpace, m_heightNormalizer, - m_axisCacheY.min(), true); - } + if (cache->isFlatShadingEnabled()) { + cache->surfaceObject()->setUpData(dataArray, sampleSpace, m_heightNormalizer, + m_axisCacheY.min(), dimensionChanged); + } else { + cache->surfaceObject()->setUpSmoothData(dataArray, sampleSpace, m_heightNormalizer, + m_axisCacheY.min(), dimensionChanged); } - - return m_cachedFlatShading; } void Surface3DRenderer::updateSelectedPoint(const QPoint &position, const QSurface3DSeries *series) @@ -1865,11 +1927,6 @@ void Surface3DRenderer::resetClickedStatus() m_clickedSeries = 0; } -void Surface3DRenderer::updateSurfaceGridStatus(bool enable) -{ - m_cachedSurfaceGridOn = enable; -} - void Surface3DRenderer::loadBackgroundMesh() { if (m_backgroundObj) @@ -1878,20 +1935,6 @@ void Surface3DRenderer::loadBackgroundMesh() m_backgroundObj->load(); } -void Surface3DRenderer::loadSurfaceObj() -{ - if (m_surfaceObj) - delete m_surfaceObj; - m_surfaceObj = new SurfaceObject(); -} - -void Surface3DRenderer::loadSliceSurfaceObj() -{ - if (m_sliceSurfaceObj) - delete m_sliceSurfaceObj; - m_sliceSurfaceObj = new SurfaceObject(); -} - void Surface3DRenderer::loadGridLineMesh() { if (m_gridLineObj) @@ -1905,7 +1948,9 @@ void Surface3DRenderer::surfacePointSelected(const QPoint &point) int row = point.x(); int column = point.y(); - float value = m_dataArray.at(row)->at(column).y(); + SurfaceSeriesRenderCache *cache = m_renderCacheList.value(const_cast(m_selectedSeries)); + QSurfaceDataArray &dataArray = cache->dataArray(); + float value = dataArray.at(row)->at(column).y(); if (!m_selectionPointer) m_selectionPointer = new SelectionPointer(m_drawer); @@ -1913,20 +1958,20 @@ void Surface3DRenderer::surfacePointSelected(const QPoint &point) QVector3D pos; if (m_cachedIsSlicingActivated) { if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow)) { - pos = m_sliceSurfaceObj->vertexAt(column, 0); + pos = cache->sliceSurfaceObject()->vertexAt(column, 0); pos *= QVector3D(m_surfaceScaleX, 1.0f, 0.0f); pos += QVector3D(m_surfaceOffsetX, 0.0f, 0.0f); m_selectionPointer->updateBoundingRect(m_secondarySubViewport); m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment); } else if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionColumn)) { - pos = m_sliceSurfaceObj->vertexAt(row, 0); + pos = cache->sliceSurfaceObject()->vertexAt(row, 0); pos *= QVector3D(m_surfaceScaleZ, 1.0f, 0.0f); pos += QVector3D(-m_surfaceOffsetZ, 0.0f, 0.0f); m_selectionPointer->updateBoundingRect(m_secondarySubViewport); m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment); } } else { - pos = m_surfaceObj->vertexAt(column, row); + pos = cache->surfaceObject()->vertexAt(column, row); pos *= QVector3D(m_surfaceScaleX, 1.0f, m_surfaceScaleZ);; pos += QVector3D(m_surfaceOffsetX, 0.0f, m_surfaceOffsetZ); m_selectionPointer->updateBoundingRect(m_primarySubViewport); @@ -1935,23 +1980,42 @@ void Surface3DRenderer::surfacePointSelected(const QPoint &point) m_selectionPointer->setPosition(pos); m_selectionPointer->setLabel(createSelectionLabel(value, column, row)); - m_selectionPointer->setPointerObject(m_visibleSeriesList.at(0).object()); - m_selectionPointer->setHighlightColor(m_visibleSeriesList.at(0).singleHighlightColor()); + m_selectionPointer->setPointerObject(cache->object()); + m_selectionPointer->setHighlightColor(cache->singleHighlightColor()); m_selectionPointer->updateScene(m_cachedScene); - m_selectionPointer->setRotation(m_visibleSeriesList.at(0).meshRotation()); + m_selectionPointer->setRotation(cache->meshRotation()); } // Maps selection Id to surface point in data array QPoint Surface3DRenderer::selectionIdToSurfacePoint(uint id) { - int column = ((id - 1) % m_sampleSpace.width()) + m_sampleSpace.x(); - int row = ((id - 1) / m_sampleSpace.width()) + m_sampleSpace.y(); + SurfaceSeriesRenderCache *selectedCache = 0; + foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + if (cache->isWithinIdRange(id)) { + selectedCache = cache; + break; + } + } + if (!selectedCache) { + m_clickedSeries = 0; + return Surface3DController::invalidSelectionPosition(); + } + + uint idInSeries = id - selectedCache->selectionIdStart() + 1; + QRect sampleSpace = selectedCache->sampleSpace(); + int column = ((idInSeries - 1) % sampleSpace.width()) + sampleSpace.x(); + int row = ((idInSeries - 1) / sampleSpace.width()) + sampleSpace.y(); + + m_clickedSeries = selectedCache->series(); return QPoint(row, column); } QString Surface3DRenderer::createSelectionLabel(float value, int column, int row) { - QString labelText = m_visibleSeriesList[0].itemLabelFormat(); + SurfaceSeriesRenderCache *cache = + m_renderCacheList.value(const_cast(m_selectedSeries)); + QSurfaceDataArray &dataArray = cache->dataArray(); + QString labelText = cache->itemLabelFormat(); static const QString xTitleTag(QStringLiteral("@xTitle")); static const QString yTitleTag(QStringLiteral("@yTitle")); static const QString zTitleTag(QStringLiteral("@zTitle")); @@ -1969,7 +2033,7 @@ QString Surface3DRenderer::createSelectionLabel(float value, int column, int row if (labelFormat.isEmpty()) labelFormat = Utils::defaultLabelFormat(); QString valueLabelText = generateValueLabel(labelFormat, - m_dataArray.at(row)->at(column).x()); + dataArray.at(row)->at(column).x()); labelText.replace(xLabelTag, valueLabelText); } if (labelText.contains(yLabelTag)) { @@ -1984,11 +2048,11 @@ QString Surface3DRenderer::createSelectionLabel(float value, int column, int row if (labelFormat.isEmpty()) labelFormat = Utils::defaultLabelFormat(); QString valueLabelText = generateValueLabel(labelFormat, - m_dataArray.at(row)->at(column).z()); + dataArray.at(row)->at(column).z()); labelText.replace(zLabelTag, valueLabelText); } - labelText.replace(seriesNameTag, m_visibleSeriesList[0].name()); + labelText.replace(seriesNameTag, cache->name()); m_selectionLabelDirty = false; @@ -2073,31 +2137,34 @@ void Surface3DRenderer::initShaders(const QString &vertexShader, const QString & Q_UNUSED(fragmentShader); // draw the shader for the surface according to smooth status, shadow and uniform color - if (m_surfaceShader) - delete m_surfaceShader; + if (m_surfaceFlatShader) + delete m_surfaceFlatShader; + if (m_surfaceSmoothShader) + delete m_surfaceSmoothShader; + #if !defined(QT_OPENGL_ES_2) - if (!m_cachedFlatShading) { - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { - m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentSurfaceShadowNoTex")); - } else { - m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragmentSurface")); - } + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + m_surfaceSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentSurfaceShadowNoTex")); } else { - if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { - m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceShadowFlat"), + m_surfaceSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragmentSurface")); + } + if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) { + m_surfaceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceShadowFlat"), QStringLiteral(":/shaders/fragmentSurfaceShadowFlat")); - } else { - m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"), + } else { + m_surfaceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"), QStringLiteral(":/shaders/fragmentSurfaceFlat")); - } } #else - m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragmentSurfaceES2")); + m_surfaceSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragmentSurfaceES2")); + m_surfaceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragmentSurfaceES2")); #endif - m_surfaceShader->initialize(); + m_surfaceSmoothShader->initialize(); + m_surfaceFlatShader->initialize(); } void Surface3DRenderer::initBackgroundShaders(const QString &vertexShader, @@ -2177,16 +2244,4 @@ void Surface3DRenderer::updateDepthBuffer() } #endif -void Surface3DRenderer::generateUniformGradient(const QVector3D newColor) -{ - if (m_visibleSeriesList.size()) { - QColor newQColor = Utils::colorFromVector(newColor); - m_uniformGradientTextureColor = newColor; - QLinearGradient newGradient; - newGradient.setColorAt(0.0, newQColor); - newGradient.setColorAt(1.0, newQColor); - fixGradientAndGenerateTexture(&newGradient, &m_uniformGradientTexture); - } -} - QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h index 06973f43..5f4e70ec 100644 --- a/src/datavisualization/engine/surface3drenderer_p.h +++ b/src/datavisualization/engine/surface3drenderer_p.h @@ -34,6 +34,7 @@ #include "abstract3drenderer_p.h" #include "scatterrenderitem_p.h" #include "qsurfacedataproxy.h" +#include "surfaceseriesrendercache_p.h" QT_BEGIN_NAMESPACE_DATAVISUALIZATION @@ -60,7 +61,8 @@ private: // Internal attributes purely related to how the scene is drawn with GL. ShaderHelper *m_depthShader; ShaderHelper *m_backgroundShader; - ShaderHelper *m_surfaceShader; + ShaderHelper *m_surfaceFlatShader; + ShaderHelper *m_surfaceSmoothShader; ShaderHelper *m_surfaceGridShader; ShaderHelper *m_selectionShader; ShaderHelper *m_labelShader; @@ -84,19 +86,15 @@ private: ObjectHelper *m_gridLineObj; ObjectHelper *m_labelObj; SurfaceObject *m_surfaceObj; - SurfaceObject *m_sliceSurfaceObj; GLuint m_depthTexture; GLuint m_depthModelTexture; GLuint m_depthFrameBuffer; GLuint m_selectionFrameBuffer; GLuint m_selectionDepthBuffer; - GLuint m_selectionTexture; GLuint m_selectionResultTexture; GLfloat m_shadowQualityToShader; bool m_cachedFlatShading; bool m_flatSupported; - bool m_cachedSurfaceVisible; - bool m_cachedSurfaceGridOn; SelectionPointer *m_selectionPointer; bool m_selectionActive; bool m_xFlipped; @@ -104,7 +102,6 @@ private: bool m_yFlipped; AbstractRenderItem m_dummyRenderItem; QSurfaceDataArray m_dataArray; - QSurfaceDataArray m_sliceDataArray; QRect m_sampleSpace; GLint m_shadowQualityMultiplier; QSizeF m_areaSize; @@ -112,9 +109,10 @@ private: bool m_hasHeightAdjustmentChanged; QPoint m_selectedPoint; const QSurface3DSeries *m_selectedSeries; - GLuint m_uniformGradientTexture; QVector3D m_uniformGradientTextureColor; QPoint m_clickedPosition; + QHash m_renderCacheList; + bool m_selectionTexturesDirty; public: explicit Surface3DRenderer(Surface3DController *controller); @@ -122,11 +120,11 @@ public: void updateData(); void updateSeries(const QList &seriesList, bool updateVisibility); + void updateSelectionMode(QAbstract3DGraph::SelectionFlags mode); + void modifiedSeriesList(const QVector &seriesList); void updateRows(const QVector &rows); void updateItem(const QVector &points); void updateScene(Q3DScene *scene); - bool updateFlatStatus(bool enable); - void updateSurfaceGridStatus(bool enable); void updateSlicingActive(bool isSlicing); void updateSelectedPoint(const QPoint &position, const QSurface3DSeries *series); inline QPoint clickedPosition() const { return m_clickedPosition; } @@ -142,6 +140,8 @@ signals: void flatShadingSupportedChanged(bool supported); private: + void checkFlatSupport(SurfaceSeriesRenderCache *cache); + void updateObjects(SurfaceSeriesRenderCache *cache, bool dimensionChanged); void updateSliceDataModel(const QPoint &point); void updateShadowQuality(QAbstract3DGraph::ShadowQuality quality); void updateTextures(); @@ -150,8 +150,6 @@ private: void loadBackgroundMesh(); void loadGridLineMesh(); void loadLabelMesh(); - void loadSurfaceObj(); - void loadSliceSurfaceObj(); void drawScene(GLuint defaultFboHandle); void calculateSceneScalingFactors(); void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader); @@ -160,7 +158,8 @@ private: void initSurfaceShaders(); void initSelectionBuffer(); void initDepthShader(); - void updateSelectionTexture(); + void updateSelectionTextures(); + void createSelectionTexture(SurfaceSeriesRenderCache *cache, uint &lastSelectionId); void idToRGBA(uint id, uchar *r, uchar *g, uchar *b, uchar *a); void fillIdCorner(uchar *p, uchar r, uchar g, uchar b, uchar a, int stride); void surfacePointSelected(const QPoint &point); @@ -170,7 +169,6 @@ private: void updateDepthBuffer(); #endif void emitSelectedPointChanged(QPoint position); - void generateUniformGradient(const QVector3D newColor); Q_DISABLE_COPY(Surface3DRenderer) }; diff --git a/src/datavisualization/engine/surfaceseriesrendercache.cpp b/src/datavisualization/engine/surfaceseriesrendercache.cpp new file mode 100644 index 00000000..e6243472 --- /dev/null +++ b/src/datavisualization/engine/surfaceseriesrendercache.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 "seriesrendercache_p.h" +#include "surfaceseriesrendercache_p.h" +#include "objecthelper_p.h" +#include "abstract3drenderer_p.h" +#include "texturehelper_p.h" +#include "utils_p.h" + +QT_BEGIN_NAMESPACE_DATAVISUALIZATION + +SurfaceSeriesRenderCache::SurfaceSeriesRenderCache() + : m_surfaceVisible(false), + m_surfaceGridVisible(false), + m_surfaceFlatShading(true), + m_surfaceObj(new SurfaceObject), + m_sliceSurfaceObj(new SurfaceObject), + m_sampleSpace(QRect(0, 0, 0 , 0)), + m_selectionTexture(0), + m_selectionIdStart(0), + m_selectionIdEnd(0), + m_flatChangeAllowed(true), + m_flatStatusDirty(false), + m_valid(false), + m_objectDirty(true) +{ +} + +SurfaceSeriesRenderCache::~SurfaceSeriesRenderCache() +{ + delete m_surfaceObj; + delete m_sliceSurfaceObj; + for (int i = 0; i < m_dataArray.size(); i++) + delete m_dataArray.at(i); + m_dataArray.clear(); + + for (int i = 0; i < m_sliceDataArray.size(); i++) + delete m_sliceDataArray.at(i); + m_sliceDataArray.clear(); +} + +void SurfaceSeriesRenderCache::populate(QSurface3DSeries *series, Abstract3DRenderer *renderer) +{ + Q_ASSERT(series); + + SeriesRenderCache::populate(series, renderer); + + 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(); + m_flatStatusDirty = true; + } +} + +QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/engine/surfaceseriesrendercache_p.h b/src/datavisualization/engine/surfaceseriesrendercache_p.h new file mode 100644 index 00000000..a0d23e45 --- /dev/null +++ b/src/datavisualization/engine/surfaceseriesrendercache_p.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** 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 SURFACESERIESRENDERCACHE_P_H +#define SURFACESERIESRENDERCACHE_P_H + +#include "datavisualizationglobal_p.h" +#include "seriesrendercache_p.h" +#include "qabstract3dseries_p.h" +#include "qsurface3dseries_p.h" +#include "surfaceobject_p.h" + +QT_BEGIN_NAMESPACE_DATAVISUALIZATION + +class Abstract3DRenderer; +class ObjectHelper; +class TextureHelper; + +class SurfaceSeriesRenderCache : public SeriesRenderCache +{ +public: + SurfaceSeriesRenderCache(); + virtual ~SurfaceSeriesRenderCache(); + + void populate(QSurface3DSeries *series, Abstract3DRenderer *renderer); + void cleanup(TextureHelper *texHelper); + + inline bool surfaceVisible() const { return m_surfaceVisible; } + inline bool surfaceGridVisible() const { return m_surfaceGridVisible; } + 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; } + inline void setSampleSpace(const QRect &sampleSpace) { m_sampleSpace = sampleSpace; } + inline QSurface3DSeries *series() const { return static_cast(m_series); } + inline QSurfaceDataArray &dataArray() { return m_dataArray; } + inline QSurfaceDataArray &sliceDataArray() { return m_sliceDataArray; } + inline bool isSeriesVisible() const { return m_series->isVisible(); } + inline void setObjectDirty(bool state) { m_objectDirty = state; } + inline bool objectDirty() const { return m_objectDirty; } + 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; + m_selectionIdEnd = end; } + inline uint selectionIdStart() const { return m_selectionIdStart; } + inline bool isWithinIdRange(uint selection) const { return selection >= m_selectionIdStart && + selection <= m_selectionIdEnd; } + inline bool isFlatStatusDirty() const { return m_flatStatusDirty; } + inline void setFlatStatusDirty(bool status) { m_flatStatusDirty = status; } + +protected: + bool m_surfaceVisible; + bool m_surfaceGridVisible; + bool m_surfaceFlatShading; + SurfaceObject *m_surfaceObj; + SurfaceObject *m_sliceSurfaceObj; + QRect m_sampleSpace; + QSurfaceDataArray m_dataArray; + QSurfaceDataArray m_sliceDataArray; + GLuint m_selectionTexture; + uint m_selectionIdStart; + uint m_selectionIdEnd; + bool m_flatChangeAllowed; + bool m_flatStatusDirty; + + bool m_valid; + bool m_objectDirty; +}; + +QT_END_NAMESPACE_DATAVISUALIZATION + +#endif diff --git a/src/datavisualization/global/datavisualizationglobal_p.h b/src/datavisualization/global/datavisualizationglobal_p.h index 83af408a..2cfa559c 100644 --- a/src/datavisualization/global/datavisualizationglobal_p.h +++ b/src/datavisualization/global/datavisualizationglobal_p.h @@ -55,6 +55,8 @@ static const QVector3D selectionSkipColor = QVector3D(255.0f, 255.0f, 255.0f); static const QVector3D invalidColorVector = QVector3D(-1.0f, -1.0f, -1.0f); static const GLfloat gradientTextureHeight = 1024.0f; static const GLfloat gradientTextureWidth = 2.0f; +static const GLfloat uniformTextureHeight = 64.0f; +static const GLfloat uniformTextureWidth = 2.0f; QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/utils/surfaceobject.cpp b/src/datavisualization/utils/surfaceobject.cpp index b0cd6c82..cfaab09c 100644 --- a/src/datavisualization/utils/surfaceobject.cpp +++ b/src/datavisualization/utils/surfaceobject.cpp @@ -25,6 +25,10 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION SurfaceObject::SurfaceObject() + : m_surfaceType(Undefined), + m_columns(0), + m_rows(0), + m_gridIndexCount(0) { m_indicesType = GL_UNSIGNED_INT; initializeOpenGLFunctions(); @@ -668,6 +672,9 @@ GLuint SurfaceObject::gridIndexCount() QVector3D SurfaceObject::vertexAt(int column, int row) { int pos = 0; + if (m_surfaceType == Undefined || !m_vertices.size()) + return zeroVector; + if (m_surfaceType == SurfaceFlat) pos = row * (m_columns * 2 - 2) + column * 2 - (column > 0); else diff --git a/src/datavisualization/utils/surfaceobject_p.h b/src/datavisualization/utils/surfaceobject_p.h index ec1a30bd..f51c2909 100644 --- a/src/datavisualization/utils/surfaceobject_p.h +++ b/src/datavisualization/utils/surfaceobject_p.h @@ -39,6 +39,13 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION class SurfaceObject : public AbstractObjectHelper { +public: + enum SurfaceType { + SurfaceSmooth, + SurfaceFlat, + Undefined + }; + public: SurfaceObject(); ~SurfaceObject(); @@ -71,11 +78,7 @@ private: bool changeGeometry); private: - enum SurfaceType { - SurfaceSmooth, - SurfaceFlat - }; - int m_surfaceType; + SurfaceType m_surfaceType; int m_columns; int m_rows; GLuint m_gridElementbuffer; diff --git a/src/datavisualization/utils/texturehelper.cpp b/src/datavisualization/utils/texturehelper.cpp index 91d70946..0f5c8313 100644 --- a/src/datavisualization/utils/texturehelper.cpp +++ b/src/datavisualization/utils/texturehelper.cpp @@ -151,6 +151,18 @@ GLuint TextureHelper::createSelectionTexture(const QSize &size, GLuint &frameBuf return textureid; } +GLuint TextureHelper::createUniformTexture(const QColor &color) +{ + QImage image(QSize(int(uniformTextureWidth), int(uniformTextureHeight)), + QImage::Format_RGB32); + QPainter pmp(&image); + pmp.setBrush(QBrush(color)); + pmp.setPen(Qt::NoPen); + pmp.drawRect(0, 0, int(uniformTextureWidth), int(uniformTextureHeight)); + + return create2DTexture(image, false, true, false, true); +} + GLuint TextureHelper::createGradientTexture(const QLinearGradient &gradient) { QImage image(QSize(int(gradientTextureWidth), int(gradientTextureHeight)), diff --git a/src/datavisualization/utils/texturehelper_p.h b/src/datavisualization/utils/texturehelper_p.h index 17553f30..f9a23a08 100644 --- a/src/datavisualization/utils/texturehelper_p.h +++ b/src/datavisualization/utils/texturehelper_p.h @@ -48,6 +48,7 @@ class TextureHelper : protected QOpenGLFunctions GLuint createCubeMapTexture(const QImage &image, bool useTrilinearFiltering = false); // Returns selection texture and inserts generated framebuffers to framebuffer parameters GLuint createSelectionTexture(const QSize &size, GLuint &frameBuffer, GLuint &depthBuffer); + GLuint createUniformTexture(const QColor &color); GLuint createGradientTexture(const QLinearGradient &gradient); #if !defined(QT_OPENGL_ES_2) GLuint createDepthTexture(const QSize &size, GLuint textureSize); diff --git a/tests/surfacetest/graphmodifier.cpp b/tests/surfacetest/graphmodifier.cpp index 528a803b..c6247bb5 100644 --- a/tests/surfacetest/graphmodifier.cpp +++ b/tests/surfacetest/graphmodifier.cpp @@ -34,14 +34,18 @@ using namespace QtDataVisualization; GraphModifier::GraphModifier(Q3DSurface *graph) : m_graph(graph), + m_series1(new QSurface3DSeries), + m_series2(new QSurface3DSeries), + m_series3(new QSurface3DSeries), + m_series4(new QSurface3DSeries), m_gridSliderX(0), m_gridSliderZ(0), m_axisRangeSliderX(0), m_axisRangeSliderZ(0), m_axisMinSliderX(0), m_axisMinSliderZ(0), - m_xCount(50), - m_zCount(50), + m_xCount(24), + m_zCount(24), m_activeSample(0), m_fontSize(40), m_rangeX(16.0), @@ -53,15 +57,32 @@ GraphModifier::GraphModifier(Q3DSurface *graph) m_insertTestIndexPos(1), m_planeArray(0), m_theSeries(new QSurface3DSeries), - m_drawMode(QSurface3DSeries::DrawSurfaceAndWireframe) + m_drawMode(QSurface3DSeries::DrawSurfaceAndWireframe), + m_drawMode2(QSurface3DSeries::DrawSurfaceAndWireframe), + m_drawMode3(QSurface3DSeries::DrawSurfaceAndWireframe), + m_drawMode4(QSurface3DSeries::DrawSurfaceAndWireframe) { m_graph->setAxisX(new QValue3DAxis); m_graph->setAxisY(new QValue3DAxis); m_graph->setAxisZ(new QValue3DAxis); +#ifdef MULTI_SERIES + m_limitX = float(m_xCount) / 2.0f; + m_limitZ = float(m_zCount) / 2.0f; + m_graph->axisX()->setRange(-m_limitX, m_limitX); + m_graph->axisY()->setRange(-1.0f, 4.5f); + m_graph->axisZ()->setRange(-m_limitZ, m_limitZ); +#else m_graph->axisX()->setRange(m_minX, m_minX + m_rangeX); m_graph->axisZ()->setRange(m_minZ, m_minZ + m_rangeZ); m_graph->addSeries(m_theSeries); +#endif + + for (int i = 0; i < 4; i++) { + m_multiseries[i] = new QSurface3DSeries; + m_multiseries[i]->setItemLabelFormat(QStringLiteral("@seriesName: (@xLabel, @zLabel): @yLabel")); + } + fillSeries(); changeStyle(); m_theSeries->setItemLabelFormat(QStringLiteral("@seriesName: (@xLabel, @zLabel): @yLabel")); @@ -82,10 +103,100 @@ GraphModifier::~GraphModifier() delete m_graph; } +void GraphModifier::fillSeries() +{ + int full = m_limitX * m_limitZ; + + QSurfaceDataArray *dataArray1 = new QSurfaceDataArray; + dataArray1->reserve(m_zCount); + QSurfaceDataArray *dataArray2 = new QSurfaceDataArray; + dataArray2->reserve(m_zCount); + QSurfaceDataArray *dataArray3 = new QSurfaceDataArray; + dataArray3->reserve(m_zCount); + QSurfaceDataArray *dataArray4 = new QSurfaceDataArray; + dataArray4->reserve(m_zCount); + + for (int i = 0; i < m_zCount; i++) { + QSurfaceDataRow *newRow1 = new QSurfaceDataRow(m_xCount); + QSurfaceDataRow *newRow2 = new QSurfaceDataRow(m_xCount); + QSurfaceDataRow *newRow3 = new QSurfaceDataRow(m_xCount); + QSurfaceDataRow *newRow4 = new QSurfaceDataRow(m_xCount); + + for (int j = 0; j < m_xCount; j++) { + float x = float(j) - m_limitX + 0.5f; + float z = float(i) - m_limitZ + 0.5f; + float angle = (z * x) / float(full) * 1.57f; + (*newRow1)[j].setPosition(QVector3D(x, qSin(angle), z)); + angle *= 1.3f; + (*newRow2)[j].setPosition(QVector3D(x, qSin(angle) + 1.1f, z)); + angle *= 1.3f; + (*newRow3)[j].setPosition(QVector3D(x, qSin(angle) + 2.2f, z)); + angle *= 1.3f; + (*newRow4)[j].setPosition(QVector3D(x, qSin(angle) + 3.3f, z)); + } + *dataArray1 << newRow1; + *dataArray2 << newRow2; + *dataArray3 << newRow3; + *dataArray4 << newRow4; + } + + m_multiseries[0]->dataProxy()->resetArray(dataArray1); + m_multiseries[1]->dataProxy()->resetArray(dataArray2); + m_multiseries[2]->dataProxy()->resetArray(dataArray3); + m_multiseries[3]->dataProxy()->resetArray(dataArray4); +} + +void GraphModifier::toggleSeries1(bool enabled) +{ + qDebug() << __FUNCTION__ << " enabled = " << enabled; + + if (enabled) { + m_graph->addSeries(m_multiseries[0]); + } else { + m_graph->removeSeries(m_multiseries[0]); + } +} + +void GraphModifier::toggleSeries2(bool enabled) +{ + qDebug() << __FUNCTION__ << " enabled = " << enabled; + + if (enabled) { + m_graph->addSeries(m_multiseries[1]); + } else { + m_graph->removeSeries(m_multiseries[1]); + } +} + +void GraphModifier::toggleSeries3(bool enabled) +{ + qDebug() << __FUNCTION__ << " enabled = " << enabled; + + if (enabled) { + m_graph->addSeries(m_multiseries[2]); + } else { + m_graph->removeSeries(m_multiseries[2]); + } +} + +void GraphModifier::toggleSeries4(bool enabled) +{ + qDebug() << __FUNCTION__ << " enabled = " << enabled; + + if (enabled) { + m_graph->addSeries(m_multiseries[3]); + } else { + m_graph->removeSeries(m_multiseries[3]); + } +} + void GraphModifier::toggleSmooth(bool enabled) { qDebug() << "GraphModifier::toggleSmooth " << enabled; m_theSeries->setFlatShadingEnabled(enabled); +#ifdef MULTI_SERIES + m_multiseries[0]->setFlatShadingEnabled(enabled); +#endif } void GraphModifier::toggleSurfaceGrid(bool enable) @@ -97,6 +208,9 @@ void GraphModifier::toggleSurfaceGrid(bool enable) m_drawMode &= ~QSurface3DSeries::DrawWireframe; m_theSeries->setDrawMode(m_drawMode); +#ifdef MULTI_SERIES + m_multiseries[0]->setDrawMode(m_drawMode); +#endif } void GraphModifier::toggleSurface(bool enable) @@ -108,11 +222,119 @@ void GraphModifier::toggleSurface(bool enable) m_drawMode &= ~QSurface3DSeries::DrawSurface; m_theSeries->setDrawMode(m_drawMode); +#ifdef MULTI_SERIES + m_multiseries[0]->setDrawMode(m_drawMode); +#endif } void GraphModifier::toggleSeriesVisible(bool enable) { m_theSeries->setVisible(enable); +#ifdef MULTI_SERIES + m_multiseries[0]->setVisible(enable); +#endif +} + +void GraphModifier::toggleSmoothS2(bool enabled) +{ + qDebug() << __FUNCTION__ << enabled; + m_multiseries[1]->setFlatShadingEnabled(enabled); +} + +void GraphModifier::toggleSurfaceGridS2(bool enable) +{ + qDebug() << __FUNCTION__ << enable; + if (enable) + m_drawMode2 |= QSurface3DSeries::DrawWireframe; + else + m_drawMode2 &= ~QSurface3DSeries::DrawWireframe; + + m_multiseries[1]->setDrawMode(m_drawMode2); +} + +void GraphModifier::toggleSurfaceS2(bool enable) +{ + qDebug() << __FUNCTION__ << enable; + if (enable) + m_drawMode2 |= QSurface3DSeries::DrawSurface; + else + m_drawMode2 &= ~QSurface3DSeries::DrawSurface; + + m_multiseries[1]->setDrawMode(m_drawMode2); +} + +void GraphModifier::toggleSeries2Visible(bool enable) +{ + qDebug() << __FUNCTION__ << enable; + m_multiseries[1]->setVisible(enable); +} + +void GraphModifier::toggleSmoothS3(bool enabled) +{ + qDebug() << __FUNCTION__ << enabled; + m_multiseries[2]->setFlatShadingEnabled(enabled); +} + +void GraphModifier::toggleSurfaceGridS3(bool enable) +{ + qDebug() << __FUNCTION__ << enable; + if (enable) + m_drawMode3 |= QSurface3DSeries::DrawWireframe; + else + m_drawMode3 &= ~QSurface3DSeries::DrawWireframe; + + m_multiseries[2]->setDrawMode(m_drawMode3); +} + +void GraphModifier::toggleSurfaceS3(bool enable) +{ + qDebug() << __FUNCTION__ << enable; + if (enable) + m_drawMode3 |= QSurface3DSeries::DrawSurface; + else + m_drawMode3 &= ~QSurface3DSeries::DrawSurface; + + m_multiseries[2]->setDrawMode(m_drawMode3); +} + +void GraphModifier::toggleSeries3Visible(bool enable) +{ + qDebug() << __FUNCTION__ << enable; + m_multiseries[2]->setVisible(enable); +} + +void GraphModifier::toggleSmoothS4(bool enabled) +{ + qDebug() << __FUNCTION__ << enabled; + m_multiseries[3]->setFlatShadingEnabled(enabled); +} + +void GraphModifier::toggleSurfaceGridS4(bool enable) +{ + qDebug() << __FUNCTION__ << enable; + if (enable) + m_drawMode4 |= QSurface3DSeries::DrawWireframe; + else + m_drawMode4 &= ~QSurface3DSeries::DrawWireframe; + + m_multiseries[3]->setDrawMode(m_drawMode4); +} + +void GraphModifier::toggleSurfaceS4(bool enable) +{ + qDebug() << __FUNCTION__ << enable; + if (enable) + m_drawMode4 |= QSurface3DSeries::DrawSurface; + else + m_drawMode4 &= ~QSurface3DSeries::DrawSurface; + + m_multiseries[3]->setDrawMode(m_drawMode4); +} + +void GraphModifier::toggleSeries4Visible(bool enable) +{ + qDebug() << __FUNCTION__ << enable; + m_multiseries[3]->setVisible(enable); } void GraphModifier::toggleSqrtSin(bool enable) @@ -347,9 +569,14 @@ void GraphModifier::gradientPressed() gradient.setColorAt(0.33, Qt::blue); gradient.setColorAt(0.67, Qt::red); gradient.setColorAt(1.0, Qt::yellow); - m_graph->seriesList().at(0)->setBaseGradient(gradient); - m_graph->seriesList().at(0)->setSingleHighlightColor(Qt::red); - m_graph->seriesList().at(0)->setColorStyle(Q3DTheme::ColorStyleRangeGradient); +// m_graph->seriesList().at(0)->setBaseGradient(gradient); +// m_graph->seriesList().at(0)->setSingleHighlightColor(Qt::red); +// m_graph->seriesList().at(0)->setColorStyle(Q3DTheme::ColorStyleRangeGradient); + + QList gradients; + gradients << gradient; + m_graph->activeTheme()->setBaseGradients(gradients); + m_graph->activeTheme()->setColorStyle(Q3DTheme::ColorStyleRangeGradient); } void GraphModifier::changeFont(const QFont &font) @@ -572,7 +799,23 @@ void GraphModifier::addRow() m_theSeries->dataProxy()->addRow(newRow); } else { - qDebug() << "Change row function active only for SqrtSin"; +#ifdef MULTI_SERIES + qDebug() << "Adding a row into series 3"; + int full = m_limitX * m_limitZ; + + QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); + for (int j = 0; j < m_xCount; j++) { + float angle = float((float(m_addRowCounter) - m_limitZ + 0.5f) * (float(j) - m_limitX + 0.5f)) / float(full) * 1.57f; + (*newRow)[j].setPosition(QVector3D(float(j) - m_limitX + 0.5f, + qSin(angle * 1.3f * 1.3f) + 2.2f, + float(m_addRowCounter) - m_limitZ + 0.5f)); + } + m_addRowCounter++; + + m_multiseries[2]->dataProxy()->addRow(newRow); +#else + qDebug() << "Add row function active only for SqrtSin"; +#endif } } @@ -605,7 +848,27 @@ void GraphModifier::addRows() m_theSeries->dataProxy()->addRows(dataArray); } else { - qDebug() << "Change row function active only for SqrtSin"; +#ifdef MULTI_SERIES + qDebug() << "Adding 3 rows into series 3"; + int full = m_limitX * m_limitZ; + + QSurfaceDataArray dataArray; + for (int i = 0; i < 3; i++) { + QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); + for (int j = 0; j < m_xCount; j++) { + float angle = float((float(m_addRowCounter) - m_limitZ + 0.5f) * (float(j) - m_limitX + 0.5f)) / float(full) * 1.57f; + (*newRow)[j].setPosition(QVector3D(float(j) - m_limitX + 0.5f, + qSin(angle * 1.3f * 1.3f) + 2.2f, + float(m_addRowCounter) - m_limitZ + 0.5f)); + } + dataArray.append(newRow); + m_addRowCounter++; + } + + m_multiseries[2]->dataProxy()->addRows(dataArray); +#else + qDebug() << "Add rows function active only for SqrtSin"; +#endif } } @@ -633,7 +896,25 @@ void GraphModifier::insertRow() m_theSeries->dataProxy()->insertRow(m_insertTestIndexPos, newRow); m_insertTestIndexPos += 2; } else { - qDebug() << "Change row function active only for SqrtSin"; +#ifdef MULTI_SERIES + qDebug() << "Inserting a row into series 3"; + int full = m_limitX * m_limitZ; + + QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); + for (int j = 0; j < m_xCount; j++) { + float angle = float((float(m_insertTestZPos) - m_limitZ) * (float(j) - m_limitX)) / float(full) * 1.57f; + (*newRow)[j].setPosition(QVector3D(float(j) - m_limitX + 0.5f, + qSin(angle) + 2.4f, + float(m_insertTestZPos) - m_limitZ + 1.0f)); + } + + m_insertTestZPos++; + + m_multiseries[2]->dataProxy()->insertRow(m_insertTestIndexPos, newRow); + m_insertTestIndexPos += 2; +#else + qDebug() << "Insert row function active only for SqrtSin"; +#endif } } @@ -665,15 +946,47 @@ void GraphModifier::insertRows() m_theSeries->dataProxy()->insertRows(m_insertTestIndexPos, dataArray); m_insertTestIndexPos += 4; } else { - qDebug() << "Change row function active only for SqrtSin"; +#ifdef MULTI_SERIES + qDebug() << "Inserting 3 rows into series 3"; + int full = m_limitX * m_limitZ; + QSurfaceDataArray dataArray; + float zAdd = 0.25f; + for (int i = 0; i < 3; i++) { + QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); + for (int j = 0; j < m_xCount; j++) { + float angle = float((float(m_insertTestZPos) - m_limitZ) * (float(j) - m_limitX)) / float(full) * 1.57f; + (*newRow)[j].setPosition(QVector3D(float(j) - m_limitX + 0.5f, + qSin(angle) + 2.4f, + float(m_insertTestZPos) - m_limitZ + 0.5f + zAdd)); + } + zAdd += 0.25f; + dataArray.append(newRow); + } + + m_insertTestZPos++; + + m_multiseries[2]->dataProxy()->insertRows(m_insertTestIndexPos, dataArray); + m_insertTestIndexPos += 4; +#else + qDebug() << "Insert rows function active only for SqrtSin"; +#endif } } void GraphModifier::removeRow() { qDebug() << "Remove an arbitrary row"; + if (m_zCount < 1) + return; + int row = rand() % m_zCount; + +#ifdef MULTI_SERIES + int series = rand() % 4; + m_multiseries[series]->dataProxy()->removeRows(row, 1); +#else m_theSeries->dataProxy()->removeRows(row, 1); +#endif m_zCount--; } diff --git a/tests/surfacetest/graphmodifier.h b/tests/surfacetest/graphmodifier.h index 8ccff62f..308db1f0 100644 --- a/tests/surfacetest/graphmodifier.h +++ b/tests/surfacetest/graphmodifier.h @@ -25,6 +25,9 @@ #include #include #include +#include + +#define MULTI_SERIES using namespace QtDataVisualization; @@ -41,10 +44,27 @@ public: explicit GraphModifier(Q3DSurface *graph); ~GraphModifier(); + void toggleSeries1(bool enabled); + void toggleSeries2(bool enabled); + void toggleSeries3(bool enabled); + void toggleSeries4(bool enabled); void toggleSmooth(bool enabled); void toggleSurfaceGrid(bool enable); void toggleSurface(bool enable); void toggleSeriesVisible(bool enable); + void toggleSmoothS2(bool enabled); + void toggleSurfaceGridS2(bool enable); + void toggleSurfaceS2(bool enable); + void toggleSeries2Visible(bool enable); + void toggleSmoothS3(bool enabled); + void toggleSurfaceGridS3(bool enable); + void toggleSurfaceS3(bool enable); + void toggleSeries3Visible(bool enable); + void toggleSmoothS4(bool enabled); + void toggleSurfaceGridS4(bool enable); + void toggleSurfaceS4(bool enable); + void toggleSeries4Visible(bool enable); + void toggleSqrtSin(bool enable); void togglePlane(bool enable); void setHeightMapData(bool enable); @@ -55,6 +75,10 @@ public: void setAxisRangeSliderZ(QSlider *slider) { m_axisRangeSliderZ = slider; } void setAxisMinSliderX(QSlider *slider) { m_axisMinSliderX = slider; } void setAxisMinSliderZ(QSlider *slider) { m_axisMinSliderZ = slider; } + void setSeries1CB(QCheckBox *cb) { m_series1CB = cb; } + void setSeries2CB(QCheckBox *cb) { m_series2CB = cb; } + void setSeries3CB(QCheckBox *cb) { m_series3CB = cb; } + void setSeries4CB(QCheckBox *cb) { m_series4CB = cb; } void adjustXCount(int count); void adjustZCount(int count); void adjustXRange(int range); @@ -92,16 +116,26 @@ public slots: void handleAxisZChanged(QValue3DAxis *axis); private: + void fillSeries(); void resetArrayAndSliders(QSurfaceDataArray *array, float minZ, float maxZ, float minX, float maxX); Q3DSurface *m_graph; + QSurface3DSeries *m_multiseries[4]; + QSurface3DSeries *m_series1; + QSurface3DSeries *m_series2; + QSurface3DSeries *m_series3; + QSurface3DSeries *m_series4; QSlider *m_gridSliderX; QSlider *m_gridSliderZ; QSlider *m_axisRangeSliderX; QSlider *m_axisRangeSliderZ; QSlider *m_axisMinSliderX; QSlider *m_axisMinSliderZ; + QCheckBox *m_series1CB; + QCheckBox *m_series2CB; + QCheckBox *m_series3CB; + QCheckBox *m_series4CB; bool m_gridSlidersLocked; int m_xCount; int m_zCount; @@ -119,6 +153,11 @@ private: QLabel *m_selectionInfoLabel; QSurface3DSeries *m_theSeries; QSurface3DSeries::DrawFlags m_drawMode; + QSurface3DSeries::DrawFlags m_drawMode2; + QSurface3DSeries::DrawFlags m_drawMode3; + QSurface3DSeries::DrawFlags m_drawMode4; + float m_limitX; + float m_limitZ; }; #endif diff --git a/tests/surfacetest/main.cpp b/tests/surfacetest/main.cpp index b31586b0..408486f5 100644 --- a/tests/surfacetest/main.cpp +++ b/tests/surfacetest/main.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include using namespace QtDataVisualization; @@ -82,6 +83,72 @@ int main(int argc, char *argv[]) seriesVisibleCB->setText(QStringLiteral("Series Visible")); seriesVisibleCB->setChecked(true); +#ifdef MULTI_SERIES + smoothCB->setText(QStringLiteral("S1 Flat Surface")); + surfaceGridCB->setText(QStringLiteral("S1 Surface Grid")); + surfaceCB->setText(QStringLiteral("S1 Surface Visible")); + seriesVisibleCB->setText(QStringLiteral("Series 1 Visible")); + + QCheckBox *smoothS2CB = new QCheckBox(widget); + smoothS2CB->setText(QStringLiteral("S2 Flat Surface")); + smoothS2CB->setChecked(true); + + QCheckBox *surfaceGridS2CB = new QCheckBox(widget); + surfaceGridS2CB->setText(QStringLiteral("S2 Surface Grid")); + surfaceGridS2CB->setChecked(true); + + QCheckBox *surfaceS2CB = new QCheckBox(widget); + surfaceS2CB->setText(QStringLiteral("S2 Surface Visible")); + surfaceS2CB->setChecked(true); + + QCheckBox *series2VisibleCB = new QCheckBox(widget); + series2VisibleCB->setText(QStringLiteral("Series 2 Visible")); + series2VisibleCB->setChecked(true); + + QCheckBox *smoothS3CB = new QCheckBox(widget); + smoothS3CB->setText(QStringLiteral("S3 Flat Surface")); + smoothS3CB->setChecked(true); + + QCheckBox *surfaceGridS3CB = new QCheckBox(widget); + surfaceGridS3CB->setText(QStringLiteral("S3 Surface Grid")); + surfaceGridS3CB->setChecked(true); + + QCheckBox *surfaceS3CB = new QCheckBox(widget); + surfaceS3CB->setText(QStringLiteral("S3 Surface Visible")); + surfaceS3CB->setChecked(true); + + QCheckBox *series3VisibleCB = new QCheckBox(widget); + series3VisibleCB->setText(QStringLiteral("Series 3 Visible")); + series3VisibleCB->setChecked(true); + + QCheckBox *smoothS4CB = new QCheckBox(widget); + smoothS4CB->setText(QStringLiteral("S4 Flat Surface")); + smoothS4CB->setChecked(true); + + QCheckBox *surfaceGridS4CB = new QCheckBox(widget); + surfaceGridS4CB->setText(QStringLiteral("S4 Surface Grid")); + surfaceGridS4CB->setChecked(true); + + QCheckBox *surfaceS4CB = new QCheckBox(widget); + surfaceS4CB->setText(QStringLiteral("S4 Surface Visible")); + surfaceS4CB->setChecked(true); + + QCheckBox *series4VisibleCB = new QCheckBox(widget); + series4VisibleCB->setText(QStringLiteral("Series 4 Visible")); + series4VisibleCB->setChecked(true); + + QCheckBox *series1CB = new QCheckBox(widget); + series1CB->setText(QStringLiteral("Series 1")); + + QCheckBox *series2CB = new QCheckBox(widget); + series2CB->setText(QStringLiteral("Series 2")); + + QCheckBox *series3CB = new QCheckBox(widget); + series3CB->setText(QStringLiteral("Series 3")); + + QCheckBox *series4CB = new QCheckBox(widget); + series4CB->setText(QStringLiteral("Series 4")); +#else //QCheckBox *sqrtSinCB = new QCheckBox(widget); QRadioButton *sqrtSinCB = new QRadioButton(widget); sqrtSinCB->setText(QStringLiteral("Sqrt & Sin")); @@ -111,6 +178,7 @@ int main(int argc, char *argv[]) gridSliderZ->setValue(30); gridSliderZ->setMaximum(200); gridSliderZ->setEnabled(true); +#endif QSlider *axisRangeSliderX = new QSlider(Qt::Horizontal, widget); axisRangeSliderX->setTickInterval(1); @@ -209,6 +277,7 @@ int main(int argc, char *argv[]) int(QAbstract3DGraph::SelectionSlice | QAbstract3DGraph::SelectionItemAndColumn)); selectionMode->setCurrentIndex(1); +#ifndef MULTI_SERIES QPushButton *selectButton = new QPushButton(widget); selectButton->setText(QStringLiteral("Select random point")); @@ -216,6 +285,7 @@ int main(int argc, char *argv[]) flipViewsButton->setText(QStringLiteral("Flip Views")); QLabel *selectionInfoLabel = new QLabel(widget); +#endif QPushButton *changeRowButton = new QPushButton(widget); changeRowButton->setText(QStringLiteral("Change a row")); @@ -247,11 +317,47 @@ int main(int argc, char *argv[]) QPushButton *removeRowButton = new QPushButton(widget); removeRowButton->setText(QStringLiteral("Remove a row")); + QFrame* line = new QFrame(); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + + QFrame* line2 = new QFrame(); + line2->setFrameShape(QFrame::HLine); + line2->setFrameShadow(QFrame::Sunken); + + QFrame* line3 = new QFrame(); + line3->setFrameShape(QFrame::HLine); + line3->setFrameShadow(QFrame::Sunken); + // Add controls to the layout +#ifdef MULTI_SERIES + vLayout->addWidget(series1CB); +#endif vLayout->addWidget(smoothCB); vLayout->addWidget(surfaceGridCB); vLayout->addWidget(surfaceCB); vLayout->addWidget(seriesVisibleCB); +#ifdef MULTI_SERIES + vLayout->addWidget(line); + vLayout->addWidget(series2CB); + vLayout->addWidget(smoothS2CB); + vLayout->addWidget(surfaceGridS2CB); + vLayout->addWidget(surfaceS2CB); + vLayout->addWidget(series2VisibleCB); + vLayout->addWidget(line2); + vLayout->addWidget(series3CB); + vLayout->addWidget(smoothS3CB); + vLayout->addWidget(surfaceGridS3CB); + vLayout->addWidget(surfaceS3CB); + vLayout->addWidget(series3VisibleCB); + vLayout->addWidget(line3); + vLayout->addWidget(series4CB); + vLayout->addWidget(smoothS4CB); + vLayout->addWidget(surfaceGridS4CB); + vLayout->addWidget(surfaceS4CB); + vLayout->addWidget(series4VisibleCB); +#endif +#ifndef MULTI_SERIES vLayout->addWidget(new QLabel(QStringLiteral("Select surface sample"))); vLayout->addWidget(sqrtSinCB); vLayout->addWidget(planeCB); @@ -260,6 +366,7 @@ int main(int argc, char *argv[]) vLayout->addWidget(gridSlidersLockCB); vLayout->addWidget(gridSliderX); vLayout->addWidget(gridSliderZ); +#endif vLayout->addWidget(new QLabel(QStringLiteral("Adjust axis range"))); vLayout->addWidget(axisRangeSliderX); vLayout->addWidget(axisRangeSliderZ); @@ -277,9 +384,11 @@ int main(int argc, char *argv[]) vLayout->addWidget(shadowQuality); vLayout->addWidget(new QLabel(QStringLiteral("Selection Mode"))); vLayout->addWidget(selectionMode); +#ifndef MULTI_SERIES vLayout->addWidget(selectButton); vLayout->addWidget(selectionInfoLabel); vLayout->addWidget(flipViewsButton); +#endif vLayout2->addWidget(changeRowButton); vLayout2->addWidget(changeRowsButton); @@ -305,6 +414,78 @@ int main(int argc, char *argv[]) modifier, &GraphModifier::toggleSurface); QObject::connect(seriesVisibleCB, &QCheckBox::stateChanged, modifier, &GraphModifier::toggleSeriesVisible); +#ifdef MULTI_SERIES + QObject::connect(smoothS2CB, &QCheckBox::stateChanged, + modifier, &GraphModifier::toggleSmoothS2); + QObject::connect(surfaceGridS2CB, &QCheckBox::stateChanged, + modifier, &GraphModifier::toggleSurfaceGridS2); + QObject::connect(surfaceS2CB, &QCheckBox::stateChanged, + modifier, &GraphModifier::toggleSurfaceS2); + QObject::connect(series2VisibleCB, &QCheckBox::stateChanged, + modifier, &GraphModifier::toggleSeries2Visible); + + QObject::connect(smoothS3CB, &QCheckBox::stateChanged, + modifier, &GraphModifier::toggleSmoothS3); + QObject::connect(surfaceGridS3CB, &QCheckBox::stateChanged, + modifier, &GraphModifier::toggleSurfaceGridS3); + QObject::connect(surfaceS3CB, &QCheckBox::stateChanged, + modifier, &GraphModifier::toggleSurfaceS3); + QObject::connect(series3VisibleCB, &QCheckBox::stateChanged, + modifier, &GraphModifier::toggleSeries3Visible); + + QObject::connect(smoothS4CB, &QCheckBox::stateChanged, + modifier, &GraphModifier::toggleSmoothS4); + QObject::connect(surfaceGridS4CB, &QCheckBox::stateChanged, + modifier, &GraphModifier::toggleSurfaceGridS4); + QObject::connect(surfaceS4CB, &QCheckBox::stateChanged, + modifier, &GraphModifier::toggleSurfaceS4); + QObject::connect(series4VisibleCB, &QCheckBox::stateChanged, + modifier, &GraphModifier::toggleSeries4Visible); + + QObject::connect(series1CB, &QCheckBox::stateChanged, + modifier, &GraphModifier::toggleSeries1); + QObject::connect(series1CB, &QCheckBox::stateChanged, + smoothCB, &QPushButton::setEnabled); + QObject::connect(series1CB, &QCheckBox::stateChanged, + surfaceGridCB, &QPushButton::setEnabled); + QObject::connect(series1CB, &QCheckBox::stateChanged, + surfaceCB, &QPushButton::setEnabled); + QObject::connect(series1CB, &QCheckBox::stateChanged, + seriesVisibleCB, &QPushButton::setEnabled); + + QObject::connect(series2CB, &QCheckBox::stateChanged, + modifier, &GraphModifier::toggleSeries2); + QObject::connect(series2CB, &QCheckBox::stateChanged, + smoothS2CB, &QPushButton::setEnabled); + QObject::connect(series2CB, &QCheckBox::stateChanged, + surfaceGridS2CB, &QPushButton::setEnabled); + QObject::connect(series2CB, &QCheckBox::stateChanged, + surfaceS2CB, &QPushButton::setEnabled); + QObject::connect(series2CB, &QCheckBox::stateChanged, + series2VisibleCB, &QPushButton::setEnabled); + + QObject::connect(series3CB, &QCheckBox::stateChanged, + modifier, &GraphModifier::toggleSeries3); + QObject::connect(series3CB, &QCheckBox::stateChanged, + smoothS3CB, &QPushButton::setEnabled); + QObject::connect(series3CB, &QCheckBox::stateChanged, + surfaceGridS3CB, &QPushButton::setEnabled); + QObject::connect(series3CB, &QCheckBox::stateChanged, + surfaceS3CB, &QPushButton::setEnabled); + QObject::connect(series3CB, &QCheckBox::stateChanged, + series3VisibleCB, &QPushButton::setEnabled); + + QObject::connect(series4CB, &QCheckBox::stateChanged, + modifier, &GraphModifier::toggleSeries4); + QObject::connect(series4CB, &QCheckBox::stateChanged, + smoothS4CB, &QPushButton::setEnabled); + QObject::connect(series4CB, &QCheckBox::stateChanged, + surfaceGridS4CB, &QPushButton::setEnabled); + QObject::connect(series4CB, &QCheckBox::stateChanged, + surfaceS4CB, &QPushButton::setEnabled); + QObject::connect(series4CB, &QCheckBox::stateChanged, + series4VisibleCB, &QPushButton::setEnabled); +#else QObject::connect(sqrtSinCB, &QRadioButton::toggled, modifier, &GraphModifier::toggleSqrtSin); QObject::connect(planeCB, &QCheckBox::toggled, @@ -317,6 +498,7 @@ int main(int argc, char *argv[]) modifier, &GraphModifier::adjustXCount); QObject::connect(gridSliderZ, &QSlider::valueChanged, modifier, &GraphModifier::adjustZCount); +#endif QObject::connect(axisRangeSliderX, &QSlider::valueChanged, modifier, &GraphModifier::adjustXRange); QObject::connect(axisRangeSliderZ, &QSlider::valueChanged, @@ -339,10 +521,12 @@ int main(int argc, char *argv[]) modifier, SLOT(changeShadowQuality(int))); QObject::connect(selectionMode, SIGNAL(currentIndexChanged(int)), modifier, SLOT(changeSelectionMode(int))); +#ifndef MULTI_SERIES QObject::connect(selectButton, &QPushButton::clicked, modifier, &GraphModifier::selectButtonClicked); QObject::connect(flipViewsButton, &QPushButton::clicked, modifier, &GraphModifier::flipViews); +#endif QObject::connect(changeRowButton,&QPushButton::clicked, modifier, &GraphModifier::changeRow); QObject::connect(changeRowsButton,&QPushButton::clicked, @@ -364,15 +548,27 @@ int main(int argc, char *argv[]) QObject::connect(removeRowButton,&QPushButton::clicked, modifier, &GraphModifier::removeRow); - modifier->setGridSliderZ(gridSliderZ); - modifier->setGridSliderX(gridSliderX); +#ifdef MULTI_SERIES + modifier->setSeries1CB(series1CB); + modifier->setSeries2CB(series2CB); + modifier->setSeries3CB(series3CB); + modifier->setSeries4CB(series4CB); + series1CB->setChecked(true); + series2CB->setChecked(true); + series3CB->setChecked(true); + series4CB->setChecked(false); +#endif modifier->setAxisRangeSliderX(axisRangeSliderX); modifier->setAxisRangeSliderZ(axisRangeSliderZ); modifier->setAxisMinSliderX(axisMinSliderX); modifier->setAxisMinSliderZ(axisMinSliderZ); +#ifndef MULTI_SERIES + modifier->setGridSliderZ(gridSliderZ); + modifier->setGridSliderX(gridSliderX); modifier->toggleGridSliderLock(gridSlidersLockCB->checkState()); modifier->setSelectionInfoLabel(selectionInfoLabel); sqrtSinCB->setChecked(true); +#endif shadowQuality->setCurrentIndex(3); return app.exec(); -- cgit v1.2.3