From e0034b33b9e88aae416d6af0751f5826b9b03924 Mon Sep 17 00:00:00 2001 From: Mika Salmela Date: Wed, 19 Feb 2014 11:22:24 +0200 Subject: Scaling and offset support for multiseries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTRD-2868 Change-Id: I47cb0c6e26e2445ca39426e6a52963b80ebb3816 Reviewed-by: Tomi Korpipää Reviewed-by: Miikka Heikkinen --- src/datavisualization/engine/surface3drenderer.cpp | 289 +++++++++++++++------ src/datavisualization/engine/surface3drenderer_p.h | 9 +- .../engine/surfaceseriesrendercache.cpp | 2 + .../engine/surfaceseriesrendercache_p.h | 14 +- tests/surfacetest/graphmodifier.cpp | 121 +++++---- tests/surfacetest/graphmodifier.h | 5 +- tests/surfacetest/main.cpp | 4 +- 7 files changed, 295 insertions(+), 149 deletions(-) diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp index fdb3c170..f4b35803 100644 --- a/src/datavisualization/engine/surface3drenderer.cpp +++ b/src/datavisualization/engine/surface3drenderer.cpp @@ -63,10 +63,6 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller) m_scaleZ(0.0f), m_scaleXWithBackground(0.0f), m_scaleZWithBackground(0.0f), - m_surfaceScaleX(0.0f), - m_surfaceScaleZ(0.0f), - m_surfaceOffsetX(0.0f), - m_surfaceOffsetZ(0.0f), m_minVisibleColumnValue(0.0f), m_maxVisibleColumnValue(0.0f), m_minVisibleRowValue(0.0f), @@ -195,7 +191,7 @@ void Surface3DRenderer::updateData() // Need minimum of 2x2 array to draw a surface if (array.size() >= 2 && array.at(0)->size() >= 2) { - QRect sampleSpace = calculateSampleRect(array); + QRect sampleSpace = calculateSampleRect(cache, array); QSurfaceDataArray &dataArray = cache->dataArray(); bool dimensionChanged = false; @@ -311,7 +307,7 @@ void Surface3DRenderer::updateRows(const QVector foreach (Surface3DController::ChangeRow item, rows) { SurfaceSeriesRenderCache *cache = m_renderCacheList.value(item.series); QSurfaceDataArray &dstArray = cache->dataArray(); - QRect sampleSpace = cache->sampleSpace(); + const QRect &sampleSpace = cache->sampleSpace(); const QSurfaceDataArray *srcArray = 0; QSurfaceDataProxy *dataProxy = item.series->dataProxy(); @@ -353,7 +349,7 @@ void Surface3DRenderer::updateItem(const QVectordataArray(); - QRect sampleSpace = cache->sampleSpace(); + const QRect &sampleSpace = cache->sampleSpace(); const QSurfaceDataArray *srcArray = 0; QSurfaceDataProxy *dataProxy = item.series->dataProxy(); @@ -397,8 +393,21 @@ void Surface3DRenderer::updateSliceDataModel(const QPoint &point) cache->sliceSurfaceObject()->clear(); if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionMultiSeries)) { - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) - updateSliceObject(cache, point); + // Find axis coordinates for the selected point + SurfaceSeriesRenderCache *selectedCache = + m_renderCacheList.value(const_cast(m_selectedSeries)); + QSurfaceDataArray &dataArray = selectedCache->dataArray(); + QSurfaceDataItem item = dataArray.at(point.x())->at(point.y()); + QPointF coords(item.x(), item.z()); + + foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + if (cache->series() != m_selectedSeries) { + QPoint mappedPoint = mapCoordsToSampleSpace(cache, coords); + updateSliceObject(cache, mappedPoint); + } else { + updateSliceObject(cache, point); + } + } } else { if (m_selectedSeries) { SurfaceSeriesRenderCache *cache = @@ -409,11 +418,109 @@ void Surface3DRenderer::updateSliceDataModel(const QPoint &point) } } +QPoint Surface3DRenderer::mapCoordsToSampleSpace(SurfaceSeriesRenderCache *cache, + const QPointF &coords) +{ + QPoint point(-1, -1); + + QSurfaceDataArray &dataArray = cache->dataArray(); + int top = dataArray.size() - 1; + int right = dataArray.at(top)->size() - 1; + QSurfaceDataItem itemBottomLeft = dataArray.at(0)->at(0); + QSurfaceDataItem itemTopRight = dataArray.at(top)->at(right); + + if (itemBottomLeft.x() <= coords.x() && itemTopRight.x() >= coords.x()) { + float modelX = coords.x() - itemBottomLeft.x(); + float spanX = itemTopRight.x() - itemBottomLeft.x(); + float stepX = spanX / float(right); + int sampleX = int((modelX + (stepX / 2.0f)) / stepX); + + QSurfaceDataItem item = dataArray.at(0)->at(sampleX); + if (!::qFuzzyCompare(float(coords.x()), item.x())) { + int direction = 1; + if (item.x() > coords.x()) + direction = -1; + + findMatchingColumn(coords.x(), sampleX, direction, dataArray); + } + + if (sampleX >= 0 && sampleX <= right) + point.setY(sampleX); + } + + if (itemBottomLeft.z() <= coords.y() && itemTopRight.z() >= coords.y()) { + float modelY = coords.y() - itemBottomLeft.z(); + float spanY = itemTopRight.z() - itemBottomLeft.z(); + float stepY = spanY / float(top); + int sampleY = int((modelY + (stepY / 2.0f)) / stepY); + + QSurfaceDataItem item = dataArray.at(sampleY)->at(0); + if (!::qFuzzyCompare(float(coords.y()), item.z())) { + int direction = 1; + if (item.z() > coords.y()) + direction = -1; + + findMatchingRow(coords.y(), sampleY, direction, dataArray); + } + + if (sampleY >= 0 && sampleY <= top) + point.setX(sampleY); + } + + return point; +} + +void Surface3DRenderer::findMatchingRow(float y, int &sample, int direction, + QSurfaceDataArray &dataArray) +{ + int maxY = dataArray.size() - 1; + QSurfaceDataItem item = dataArray.at(sample)->at(0); + float distance = qAbs(y - item.z()); + int newSample = sample + direction; + while (newSample >= 0 && newSample <= maxY) { + item = dataArray.at(newSample)->at(0); + float newDist = qAbs(y - item.z()); + if (newDist < distance) { + sample = newSample; + distance = newDist; + } else { + break; + } + newSample = sample + direction; + } +} + +void Surface3DRenderer::findMatchingColumn(float x, int &sample, int direction, + QSurfaceDataArray &dataArray) +{ + int maxX = dataArray.at(0)->size() - 1; + QSurfaceDataItem item = dataArray.at(0)->at(sample); + float distance = qAbs(x - item.x()); + int newSample = sample + direction; + while (newSample >= 0 && newSample <= maxX) { + item = dataArray.at(0)->at(newSample); + float newDist = qAbs(x - item.x()); + if (newDist < distance) { + sample = newSample; + distance = newDist; + } else { + break; + } + newSample = sample + direction; + } +} + void Surface3DRenderer::updateSliceObject(SurfaceSeriesRenderCache *cache, const QPoint &point) { int column = point.y(); int row = point.x(); + if ((m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow) && row == -1) || + (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionColumn) && column == -1)) { + cache->sliceSurfaceObject()->clear(); + return; + } + QSurfaceDataArray &sliceDataArray = cache->sliceDataArray(); for (int i = 0; i < sliceDataArray.size(); i++) delete sliceDataArray.at(i); @@ -430,7 +537,7 @@ void Surface3DRenderer::updateSliceObject(SurfaceSeriesRenderCache *cache, const 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(); + const 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(), @@ -463,7 +570,7 @@ void Surface3DRenderer::updateSliceObject(SurfaceSeriesRenderCache *cache, const } } -QRect Surface3DRenderer::calculateSampleRect(const QSurfaceDataArray &array) +QRect Surface3DRenderer::calculateSampleRect(SurfaceSeriesRenderCache *cache, const QSurfaceDataArray &array) { QRect sampleSpace; @@ -539,14 +646,17 @@ QRect Surface3DRenderer::calculateSampleRect(const QSurfaceDataArray &array) m_visibleColumnRange = m_maxVisibleColumnValue - m_minVisibleColumnValue; m_visibleRowRange = m_maxVisibleRowValue - m_minVisibleRowValue; - m_surfaceScaleX = m_scaleX * m_visibleColumnRange / m_areaSize.width(); - m_surfaceScaleZ = m_scaleZ * m_visibleRowRange / m_areaSize.height(); + GLfloat surfaceScaleX = m_scaleX * m_visibleColumnRange / m_areaSize.width(); + GLfloat surfaceScaleZ = m_scaleZ * m_visibleRowRange / m_areaSize.height(); GLfloat axis2XCenterX = axisMinX + axisMaxX; GLfloat axis2XCenterZ = axisMinZ + axisMaxZ; GLfloat data2XCenterX = GLfloat(m_minVisibleColumnValue + m_maxVisibleColumnValue); GLfloat data2XCenterZ = GLfloat(m_minVisibleRowValue + m_maxVisibleRowValue); - m_surfaceOffsetX = m_scaleX * (data2XCenterX - axis2XCenterX) / m_areaSize.width(); - m_surfaceOffsetZ = -m_scaleZ * (data2XCenterZ - axis2XCenterZ) / m_areaSize.height(); + GLfloat surfaceOffsetX = m_scaleX * (data2XCenterX - axis2XCenterX) / m_areaSize.width(); + GLfloat surfaceOffsetZ = -m_scaleZ * (data2XCenterZ - axis2XCenterZ) / m_areaSize.height(); + + cache->setScale(QVector3D(surfaceScaleX, 1.0f, surfaceScaleZ)); + cache->setOffset(QVector3D(surfaceOffsetX, 0.0f, surfaceOffsetZ)); return sampleSpace; } @@ -623,31 +733,9 @@ void Surface3DRenderer::drawSlicedScene() bool rowMode = m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow); - GLfloat scaleX = 0.0f; GLfloat scaleXBackground = 0.0f; - GLfloat offset = 0.0f; - if (rowMode) { - scaleX = m_surfaceScaleX; - scaleXBackground = m_scaleXWithBackground; - offset = m_surfaceOffsetX; - } else { - scaleX = m_surfaceScaleZ; - scaleXBackground = m_scaleZWithBackground; - offset = -m_surfaceOffsetZ; - } if (m_renderCacheList.size()) { - QMatrix4x4 MVPMatrix; - QMatrix4x4 modelMatrix; - QMatrix4x4 itModelMatrix; - - modelMatrix.translate(offset, 0.0f, 0.0f); - QVector3D scaling(scaleX, 1.0f, sliceZScale); - modelMatrix.scale(scaling); - itModelMatrix.scale(scaling); - - MVPMatrix = projectionViewMatrix * modelMatrix; - bool drawGrid = false; foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { @@ -659,6 +747,30 @@ void Surface3DRenderer::drawSlicedScene() drawGrid = true; } + GLfloat scaleX = 0.0f; + GLfloat offset = 0.0f; + if (rowMode) { + scaleX = cache->scale().x(); + scaleXBackground = m_scaleXWithBackground; + offset = cache->offset().x(); + } else { + scaleX = cache->scale().z(); + scaleXBackground = m_scaleZWithBackground; + offset = -cache->offset().z(); + } + + QMatrix4x4 MVPMatrix; + QMatrix4x4 modelMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(offset, 0.0f, 0.0f); + QVector3D scaling(scaleX, 1.0f, sliceZScale); + modelMatrix.scale(scaling); + itModelMatrix.scale(scaling); + + MVPMatrix = projectionViewMatrix * modelMatrix; + cache->setMVPMatrix(MVPMatrix); + if (cache->surfaceVisible()) { ShaderHelper *surfaceShader = m_surfaceFlatShader; surfaceShader->bind(); @@ -689,10 +801,12 @@ void Surface3DRenderer::drawSlicedScene() m_surfaceGridShader->bind(); m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(), Utils::vectorFromColor(m_cachedTheme->gridLineColor())); - m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), MVPMatrix); foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { - if (cache->sliceSurfaceObject()->indexCount() && cache->surfaceGridVisible()) + if (cache->sliceSurfaceObject()->indexCount() && cache->isSeriesVisible() && + cache->surfaceGridVisible()) { + m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), cache->MVPMatrix()); m_drawer->drawSurfaceGrid(m_surfaceGridShader, cache->sliceSurfaceObject()); + } } glDisable(GL_POLYGON_OFFSET_FILL); @@ -944,9 +1058,6 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) QMatrix4x4 depthProjectionMatrix; QMatrix4x4 depthProjectionViewMatrix; - QVector3D surfaceScaler(m_surfaceScaleX, 1.0f, m_surfaceScaleZ); - QVector3D surfaceOffset(m_surfaceOffsetX, 0.0f, m_surfaceOffsetZ); - // Draw depth buffer #if !defined(QT_OPENGL_ES_2) GLfloat adjustedLightStrength = m_cachedTheme->lightStrength() / 10.0f; @@ -989,20 +1100,19 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) glDisable(GL_CULL_FACE); - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - - modelMatrix.translate(surfaceOffset); - modelMatrix.scale(surfaceScaler); - - MVPMatrix = depthProjectionViewMatrix * modelMatrix; - - m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix); - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { SurfaceObject *object = cache->surfaceObject(); if (object->indexCount() && cache->surfaceVisible() && cache->isSeriesVisible() && cache->sampleSpace().width() >= 2 && cache->sampleSpace().height() >= 2) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + + modelMatrix.translate(cache->offset()); + modelMatrix.scale(cache->scale()); + MVPMatrix = depthProjectionViewMatrix * modelMatrix; + cache->setMVPMatrix(MVPMatrix); + m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix); + // 1st attribute buffer : vertices glEnableVertexAttribArray(m_depthShader->posAtt()); glBindBuffer(GL_ARRAY_BUFFER, object->vertexBuf()); @@ -1029,6 +1139,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) SurfaceObject *object = cache->surfaceObject(); if (object->indexCount() && cache->surfaceVisible() && cache->isSeriesVisible() && cache->sampleSpace().width() >= 2 && cache->sampleSpace().height() >= 2) { + m_depthShader->setUniformValue(m_depthShader->MVP(), cache->MVPMatrix()); + // 1st attribute buffer : vertices glEnableVertexAttribArray(m_depthShader->posAtt()); glBindBuffer(GL_ARRAY_BUFFER, object->vertexBuf()); @@ -1084,19 +1196,18 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) glDisable(GL_CULL_FACE); - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - - modelMatrix.translate(surfaceOffset); - modelMatrix.scale(surfaceScaler); - - MVPMatrix = projectionViewMatrix * modelMatrix; - - m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix); - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { if (cache->surfaceObject()->indexCount() && cache->isSeriesVisible() && (cache->surfaceVisible() || cache->surfaceGridVisible())) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + + modelMatrix.translate(cache->offset()); + modelMatrix.scale(cache->scale()); + + MVPMatrix = projectionViewMatrix * modelMatrix; + m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix); + m_drawer->drawObject(m_selectionShader, cache->surfaceObject(), cache->selectionTexture()); } @@ -1133,23 +1244,25 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) // For surface we can see climpses from underneath glDisable(GL_CULL_FACE); - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 itModelMatrix; + bool drawGrid = false; - modelMatrix.translate(surfaceOffset); - modelMatrix.scale(surfaceScaler); - itModelMatrix.scale(surfaceScaler); + foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(cache->offset()); + modelMatrix.scale(cache->scale()); + itModelMatrix.scale(cache->scale()); #ifdef SHOW_DEPTH_TEXTURE_SCENE - MVPMatrix = depthProjectionViewMatrix * modelMatrix; + MVPMatrix = depthProjectionViewMatrix * modelMatrix; #else - MVPMatrix = projectionViewMatrix * modelMatrix; + MVPMatrix = projectionViewMatrix * modelMatrix; #endif - bool drawGrid = false; + cache->setMVPMatrix(MVPMatrix); - foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { - QRect sampleSpace = cache->sampleSpace(); + const QRect &sampleSpace = cache->sampleSpace(); if (cache->surfaceObject()->indexCount() && cache->isSeriesVisible() && sampleSpace.width() >= 2 && sampleSpace.height() >= 2) { noShadows = false; @@ -1213,12 +1326,14 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) m_surfaceGridShader->bind(); m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(), Utils::vectorFromColor(m_cachedTheme->gridLineColor())); - m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), MVPMatrix); foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) { - QRect sampleSpace = cache->sampleSpace(); + m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), cache->MVPMatrix()); + + const QRect &sampleSpace = cache->sampleSpace(); if (cache->surfaceObject()->indexCount() && cache->surfaceGridVisible() && - cache->isSeriesVisible() && sampleSpace.width() >= 2 && sampleSpace.height() >= 2) + cache->isSeriesVisible() && sampleSpace.width() >= 2 && sampleSpace.height() >= 2) { m_drawer->drawSurfaceGrid(m_surfaceGridShader, cache->surfaceObject()); + } } glDisable(GL_POLYGON_OFFSET_FILL); @@ -1805,7 +1920,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle) SurfaceSeriesRenderCache *cache = m_renderCacheList.value(const_cast(m_selectedSeries)); if (cache && m_selectedPoint != Surface3DController::invalidSelectionPosition()) { - QRect sampleSpace = cache->sampleSpace(); + const 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() @@ -1855,7 +1970,7 @@ void Surface3DRenderer::createSelectionTexture(SurfaceSeriesRenderCache *cache, { // 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 - QRect sampleSpace = cache->sampleSpace(); + const 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) @@ -1962,7 +2077,7 @@ void Surface3DRenderer::checkFlatSupport(SurfaceSeriesRenderCache *cache) void Surface3DRenderer::updateObjects(SurfaceSeriesRenderCache *cache, bool dimensionChanged) { QSurfaceDataArray &dataArray = cache->dataArray(); - const QRect sampleSpace = cache->sampleSpace(); + const QRect &sampleSpace = cache->sampleSpace(); if (cache->isFlatShadingEnabled()) { cache->surfaceObject()->setUpData(dataArray, sampleSpace, m_heightNormalizer, @@ -2016,24 +2131,26 @@ void Surface3DRenderer::surfacePointSelected(const QPoint &point) m_selectionPointer = new SelectionPointer(m_drawer); QVector3D pos; + const QVector3D &scale = cache->scale(); + const QVector3D &offset = cache->offset(); if (m_cachedIsSlicingActivated) { if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow)) { pos = cache->sliceSurfaceObject()->vertexAt(column, 0); - pos *= QVector3D(m_surfaceScaleX, 1.0f, 0.0f); - pos += QVector3D(m_surfaceOffsetX, 0.0f, 0.0f); + pos *= QVector3D(scale.x(), 1.0f, 0.0f); + pos += QVector3D(offset.x(), 0.0f, 0.0f); m_selectionPointer->updateBoundingRect(m_secondarySubViewport); m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment); } else if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionColumn)) { pos = cache->sliceSurfaceObject()->vertexAt(row, 0); - pos *= QVector3D(m_surfaceScaleZ, 1.0f, 0.0f); - pos += QVector3D(-m_surfaceOffsetZ, 0.0f, 0.0f); + pos *= QVector3D(scale.z(), 1.0f, 0.0f); + pos += QVector3D(-offset.z(), 0.0f, 0.0f); m_selectionPointer->updateBoundingRect(m_secondarySubViewport); m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment); } } else { pos = cache->surfaceObject()->vertexAt(column, row); - pos *= QVector3D(m_surfaceScaleX, 1.0f, m_surfaceScaleZ);; - pos += QVector3D(m_surfaceOffsetX, 0.0f, m_surfaceOffsetZ); + pos *= scale; + pos += offset; m_selectionPointer->updateBoundingRect(m_primarySubViewport); m_selectionPointer->updateSliceData(false, m_autoScaleAdjustment); } @@ -2062,7 +2179,7 @@ QPoint Surface3DRenderer::selectionIdToSurfacePoint(uint id) } uint idInSeries = id - selectedCache->selectionIdStart() + 1; - QRect sampleSpace = selectedCache->sampleSpace(); + const QRect &sampleSpace = selectedCache->sampleSpace(); int column = ((idInSeries - 1) % sampleSpace.width()) + sampleSpace.x(); int row = ((idInSeries - 1) / sampleSpace.width()) + sampleSpace.y(); diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h index 4649fd72..1d57e85d 100644 --- a/src/datavisualization/engine/surface3drenderer_p.h +++ b/src/datavisualization/engine/surface3drenderer_p.h @@ -65,10 +65,6 @@ private: GLfloat m_scaleZ; GLfloat m_scaleXWithBackground; GLfloat m_scaleZWithBackground; - GLfloat m_surfaceScaleX; - GLfloat m_surfaceScaleZ; - GLfloat m_surfaceOffsetX; - GLfloat m_surfaceOffsetZ; GLfloat m_minVisibleColumnValue; GLfloat m_maxVisibleColumnValue; GLfloat m_minVisibleRowValue; @@ -131,11 +127,14 @@ private: void checkFlatSupport(SurfaceSeriesRenderCache *cache); void updateObjects(SurfaceSeriesRenderCache *cache, bool dimensionChanged); void updateSliceDataModel(const QPoint &point); + QPoint mapCoordsToSampleSpace(SurfaceSeriesRenderCache *cache, const QPointF &coords); + void findMatchingRow(float y, int &sample, int direction, QSurfaceDataArray &dataArray); + void findMatchingColumn(float x, int &sample, int direction, QSurfaceDataArray &dataArray); void updateSliceObject(SurfaceSeriesRenderCache *cache, const QPoint &point); void updateShadowQuality(QAbstract3DGraph::ShadowQuality quality); void updateTextures(); void initShaders(const QString &vertexShader, const QString &fragmentShader); - QRect calculateSampleRect(const QSurfaceDataArray &array); + QRect calculateSampleRect(SurfaceSeriesRenderCache *cache, const QSurfaceDataArray &array); void loadBackgroundMesh(); void loadGridLineMesh(); void loadLabelMesh(); diff --git a/src/datavisualization/engine/surfaceseriesrendercache.cpp b/src/datavisualization/engine/surfaceseriesrendercache.cpp index e6243472..59b50358 100644 --- a/src/datavisualization/engine/surfaceseriesrendercache.cpp +++ b/src/datavisualization/engine/surfaceseriesrendercache.cpp @@ -37,6 +37,8 @@ SurfaceSeriesRenderCache::SurfaceSeriesRenderCache() m_selectionIdEnd(0), m_flatChangeAllowed(true), m_flatStatusDirty(false), + m_scale(QVector3D(1.0f, 1.0f, 1.0f)), + m_offset(QVector3D(0.0f, 0.0f, 0.0f)), m_valid(false), m_objectDirty(true) { diff --git a/src/datavisualization/engine/surfaceseriesrendercache_p.h b/src/datavisualization/engine/surfaceseriesrendercache_p.h index a0d23e45..c0a3cec3 100644 --- a/src/datavisualization/engine/surfaceseriesrendercache_p.h +++ b/src/datavisualization/engine/surfaceseriesrendercache_p.h @@ -35,6 +35,8 @@ #include "qsurface3dseries_p.h" #include "surfaceobject_p.h" +#include + QT_BEGIN_NAMESPACE_DATAVISUALIZATION class Abstract3DRenderer; @@ -59,7 +61,7 @@ public: 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 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; } @@ -76,6 +78,13 @@ public: selection <= m_selectionIdEnd; } inline bool isFlatStatusDirty() const { return m_flatStatusDirty; } inline void setFlatStatusDirty(bool status) { m_flatStatusDirty = status; } + inline void setScale(const QVector3D &scale) { m_scale = scale; } + inline const QVector3D &scale() const { return m_scale; } + inline void setOffset(const QVector3D &offset) { m_offset = offset; } + inline const QVector3D &offset() const { return m_offset; } + // m_MVPMatrix is volatile, used only for optimizing rendering a bit + inline void setMVPMatrix(const QMatrix4x4 &matrix) { m_MVPMatrix = matrix; } + inline const QMatrix4x4 &MVPMatrix() { return m_MVPMatrix; } protected: bool m_surfaceVisible; @@ -91,6 +100,9 @@ protected: uint m_selectionIdEnd; bool m_flatChangeAllowed; bool m_flatStatusDirty; + QVector3D m_scale; + QVector3D m_offset; + QMatrix4x4 m_MVPMatrix; bool m_valid; bool m_objectDirty; diff --git a/tests/surfacetest/graphmodifier.cpp b/tests/surfacetest/graphmodifier.cpp index 849a3070..7f2a3ef2 100644 --- a/tests/surfacetest/graphmodifier.cpp +++ b/tests/surfacetest/graphmodifier.cpp @@ -60,17 +60,34 @@ GraphModifier::GraphModifier(Q3DSurface *graph) m_drawMode(QSurface3DSeries::DrawSurfaceAndWireframe), m_drawMode2(QSurface3DSeries::DrawSurfaceAndWireframe), m_drawMode3(QSurface3DSeries::DrawSurfaceAndWireframe), - m_drawMode4(QSurface3DSeries::DrawSurfaceAndWireframe) + m_drawMode4(QSurface3DSeries::DrawSurfaceAndWireframe), + m_offset(4.0f) { m_graph->setAxisX(new QValue3DAxis); + m_graph->axisX()->setTitle("X-Axis"); m_graph->setAxisY(new QValue3DAxis); + m_graph->axisY()->setTitle("Value Axis"); m_graph->setAxisZ(new QValue3DAxis); + m_graph->axisZ()->setTitle("Z-Axis"); #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); + // Series 1 + m_multiSampleOffsetX[0] = -m_offset; + m_multiSampleOffsetZ[0] = -m_offset; + // Series 2 + m_multiSampleOffsetX[1] = -m_offset; + m_multiSampleOffsetZ[1] = m_offset; + // Series 3 + m_multiSampleOffsetX[2] = m_offset; + m_multiSampleOffsetZ[2] = -m_offset; + // Series 4 + m_multiSampleOffsetX[3] = m_offset; + m_multiSampleOffsetZ[3] = m_offset; + + m_graph->axisX()->setRange(-m_limitX - m_offset, m_limitX + m_offset); m_graph->axisY()->setRange(-1.0f, 4.5f); - m_graph->axisZ()->setRange(-m_limitZ, m_limitZ); + m_graph->axisZ()->setRange(-m_limitZ - m_offset, m_limitZ + m_offset); #else m_graph->axisX()->setRange(m_minX, m_minX + m_rangeX); m_graph->axisZ()->setRange(m_minZ, m_minZ + m_rangeZ); @@ -79,6 +96,7 @@ GraphModifier::GraphModifier(Q3DSurface *graph) for (int i = 0; i < 4; i++) { m_multiseries[i] = new QSurface3DSeries; + m_multiseries[i]->setName(QStringLiteral("Series %1").arg(i+1)); m_multiseries[i]->setItemLabelFormat(QStringLiteral("@seriesName: (@xLabel, @zLabel): @yLabel")); } @@ -105,7 +123,7 @@ GraphModifier::~GraphModifier() void GraphModifier::fillSeries() { - int full = m_limitX * m_limitZ; + float full = m_limitX * m_limitZ; QSurfaceDataArray *dataArray1 = new QSurfaceDataArray; dataArray1->reserve(m_zCount); @@ -117,27 +135,21 @@ void GraphModifier::fillSeries() 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); - - float z = float(i) - m_limitZ + 0.5f; - for (int j = 0; j < m_xCount; j++) { - float x = float(j) - m_limitX + 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)); + QSurfaceDataRow *newRow[4]; + for (int s = 0; s < 4; s++) { + newRow[s] = new QSurfaceDataRow(m_xCount); + float z = float(i) - m_limitZ + 0.5f + m_multiSampleOffsetZ[s]; + for (int j = 0; j < m_xCount; j++) { + float x = float(j) - m_limitX + 0.5f + m_multiSampleOffsetX[s]; + float angle = (z * x) / full * 1.57f; + float y = qSin(angle * float(qPow(1.3f, s))) + 1.1f * s; + (*newRow[s])[j].setPosition(QVector3D(x, y, z)); + } } - *dataArray1 << newRow1; - *dataArray2 << newRow2; - *dataArray3 << newRow3; - *dataArray4 << newRow4; + *dataArray1 << newRow[0]; + *dataArray2 << newRow[1]; + *dataArray3 << newRow[2]; + *dataArray4 << newRow[3]; } m_multiseries[0]->dataProxy()->resetArray(dataArray1); @@ -706,7 +718,7 @@ void GraphModifier::changeRow() qDebug() << "Generating new values to a row at random pos for series " << changeRowSeries; int row = rand() % m_zCount; - QSurfaceDataRow *newRow = createMultiRow(row, changeRowSeries); + QSurfaceDataRow *newRow = createMultiRow(row, changeRowSeries, true); m_multiseries[changeRowSeries]->dataProxy()->setRow(row, newRow); changeRowSeries++; @@ -718,16 +730,16 @@ void GraphModifier::changeRow() } } -QSurfaceDataRow *GraphModifier::createMultiRow(int row, int series) +QSurfaceDataRow *GraphModifier::createMultiRow(int row, int series, bool change) { int full = m_limitX * m_limitZ; float i = float(row); QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); - float z = float(i) - m_limitZ + 0.5f; + float z = float(i) - m_limitZ + 0.5f + m_multiSampleOffsetZ[series]; for (int j = 0; j < m_xCount; j++) { - float x = float(j) - m_limitX + 0.5f; + float x = float(j) - m_limitX + 0.5f + m_multiSampleOffsetX[series]; float angle = (z * x) / float(full) * 1.57f; - float y = qSin(angle * float(qPow(1.3f, series))) + 0.2f + 1.1f *series; + float y = qSin(angle * float(qPow(1.3f, series))) + 0.2f * float(change) + 1.1f *series; (*newRow)[j].setPosition(QVector3D(x, y, z)); } @@ -770,7 +782,7 @@ void GraphModifier::changeRows() int row = rand() % (m_zCount - 3); QSurfaceDataArray dataArray; for (int i = 0; i < 3; i++) { - QSurfaceDataRow *newRow = createMultiRow(row + i, changeRowSeries); + QSurfaceDataRow *newRow = createMultiRow(row + i, changeRowSeries, true); dataArray.append(newRow); } m_multiseries[changeRowSeries]->dataProxy()->setRows(row, dataArray); @@ -810,8 +822,8 @@ void GraphModifier::changeItem() int full = m_limitX * m_limitZ; float i = float(rand() % m_zCount); float j = float(rand() % m_xCount); - float x = float(j) - m_limitX + 0.5f; - float z = float(i) - m_limitZ + 0.5f; + float x = float(j) - m_limitX + 0.5f + m_multiSampleOffsetX[changeItemSeries]; + float z = float(i) - m_limitZ + 0.5f + m_multiSampleOffsetZ[changeItemSeries]; float angle = (z * x) / float(full) * 1.57f; float y = qSin(angle * float(qPow(1.3f, changeItemSeries))) + 0.2f + 1.1f *changeItemSeries; QSurfaceDataItem newItem(QVector3D(x, y, z)); @@ -864,17 +876,18 @@ void GraphModifier::addRow() #ifdef MULTI_SERIES qDebug() << "Adding a row into series 3"; int full = m_limitX * m_limitZ; + int series = 2; QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); + float z = float(m_addRowCounter) - m_limitZ + 0.5f + m_multiSampleOffsetZ[series]; 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)); + float x = float(j) - m_limitX + 0.5f + m_multiSampleOffsetX[series]; + float angle = float(z * x) / float(full) * 1.57f; + (*newRow)[j].setPosition(QVector3D(x, qSin(angle *float(qPow(1.3f, series))) + 1.1f * series, z)); } m_addRowCounter++; - m_multiseries[2]->dataProxy()->addRow(newRow); + m_multiseries[series]->dataProxy()->addRow(newRow); #else qDebug() << "Add row function active only for SqrtSin"; #endif @@ -912,22 +925,16 @@ void GraphModifier::addRows() } else { #ifdef MULTI_SERIES qDebug() << "Adding 3 rows into series 3"; - int full = m_limitX * m_limitZ; + int changedSeries = 2; 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)); - } + QSurfaceDataRow *newRow = createMultiRow(m_addRowCounter, changedSeries, false); dataArray.append(newRow); m_addRowCounter++; } - m_multiseries[2]->dataProxy()->addRows(dataArray); + m_multiseries[changedSeries]->dataProxy()->addRows(dataArray); #else qDebug() << "Add rows function active only for SqrtSin"; #endif @@ -961,13 +968,16 @@ void GraphModifier::insertRow() #ifdef MULTI_SERIES qDebug() << "Inserting a row into series 3"; int full = m_limitX * m_limitZ; + int changedSeries = 2; QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); + float z = float(m_insertTestZPos) - m_limitZ + m_multiSampleOffsetZ[changedSeries]; 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)); + float x = float(j) - m_limitX + m_multiSampleOffsetX[changedSeries]; + float angle = (z * x) / float(full) * 1.57f; + (*newRow)[j].setPosition(QVector3D(x + 0.5f, + qSin(angle * float(qPow(1.3f, changedSeries))) + 1.2f * changedSeries, + z + 1.0f)); } m_insertTestZPos++; @@ -1011,15 +1021,18 @@ void GraphModifier::insertRows() #ifdef MULTI_SERIES qDebug() << "Inserting 3 rows into series 3"; int full = m_limitX * m_limitZ; + int changedSeries = 2; + QSurfaceDataArray dataArray; float zAdd = 0.25f; for (int i = 0; i < 3; i++) { QSurfaceDataRow *newRow = new QSurfaceDataRow(m_xCount); + float z = float(m_insertTestZPos) - m_limitZ + 0.5f + zAdd + m_multiSampleOffsetZ[changedSeries]; 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)); + float x = float(j) - m_limitX + 0.5f + m_multiSampleOffsetX[changedSeries]; + float angle = (z * x) / float(full) * 1.57f; + float y = qSin(angle * float(qPow(1.3f, changedSeries))) + + 1.2f * changedSeries; + (*newRow)[j].setPosition(QVector3D(x, y, z)); } zAdd += 0.25f; dataArray.append(newRow); diff --git a/tests/surfacetest/graphmodifier.h b/tests/surfacetest/graphmodifier.h index 699bb9bf..7d7d425e 100644 --- a/tests/surfacetest/graphmodifier.h +++ b/tests/surfacetest/graphmodifier.h @@ -119,7 +119,7 @@ private: void fillSeries(); void resetArrayAndSliders(QSurfaceDataArray *array, float minZ, float maxZ, float minX, float maxX); - QSurfaceDataRow *createMultiRow(int row, int series); + QSurfaceDataRow *createMultiRow(int row, int series, bool change); Q3DSurface *m_graph; QSurface3DSeries *m_multiseries[4]; @@ -159,6 +159,9 @@ private: QSurface3DSeries::DrawFlags m_drawMode4; float m_limitX; float m_limitZ; + float m_offset; + float m_multiSampleOffsetX[4]; + float m_multiSampleOffsetZ[4]; }; #endif diff --git a/tests/surfacetest/main.cpp b/tests/surfacetest/main.cpp index de69b48f..f2b187e6 100644 --- a/tests/surfacetest/main.cpp +++ b/tests/surfacetest/main.cpp @@ -283,7 +283,6 @@ int main(int argc, char *argv[]) selectionMode->addItem(QStringLiteral("Multi: Slice, Column & Item"), int(QAbstract3DGraph::SelectionSlice | QAbstract3DGraph::SelectionItemAndColumn | QAbstract3DGraph::SelectionMultiSeries)); - selectionMode->setCurrentIndex(1); #ifndef MULTI_SERIES QPushButton *selectButton = new QPushButton(widget); @@ -564,12 +563,13 @@ int main(int argc, char *argv[]) series1CB->setChecked(true); series2CB->setChecked(true); series3CB->setChecked(true); - series4CB->setChecked(false); + series4CB->setChecked(true); #endif modifier->setAxisRangeSliderX(axisRangeSliderX); modifier->setAxisRangeSliderZ(axisRangeSliderZ); modifier->setAxisMinSliderX(axisMinSliderX); modifier->setAxisMinSliderZ(axisMinSliderZ); + selectionMode->setCurrentIndex(1); #ifndef MULTI_SERIES modifier->setGridSliderZ(gridSliderZ); modifier->setGridSliderX(gridSliderX); -- cgit v1.2.3