summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMika Salmela <mika.salmela@digia.com>2014-02-19 11:22:24 +0200
committerMika Salmela <mika.salmela@digia.com>2014-02-20 09:28:00 +0200
commite0034b33b9e88aae416d6af0751f5826b9b03924 (patch)
tree4dc98d6540f0d778d47959763f3f382be97ae996
parentc81ffed936c4f87bdcb5966ac3561b77c3f5b4c2 (diff)
Scaling and offset support for multiseries
Task-number: QTRD-2868 Change-Id: I47cb0c6e26e2445ca39426e6a52963b80ebb3816 Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com> Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
-rw-r--r--src/datavisualization/engine/surface3drenderer.cpp289
-rw-r--r--src/datavisualization/engine/surface3drenderer_p.h9
-rw-r--r--src/datavisualization/engine/surfaceseriesrendercache.cpp2
-rw-r--r--src/datavisualization/engine/surfaceseriesrendercache_p.h14
-rw-r--r--tests/surfacetest/graphmodifier.cpp121
-rw-r--r--tests/surfacetest/graphmodifier.h5
-rw-r--r--tests/surfacetest/main.cpp4
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<Surface3DController::ChangeRow>
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 QVector<Surface3DController::ChangeItem
foreach (Surface3DController::ChangeItem item, points) {
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();
@@ -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<QSurface3DSeries *>(m_selectedSeries));
+ QSurfaceDataArray &dataArray = selectedCache->dataArray();
+ QSurfaceDataItem item = dataArray.at(point.x())->at(point.y());
+ QPointF coords(item.x(), item.z());
+
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ 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<QSurface3DSeries *>(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 <QtGui/QMatrix4x4>
+
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<QSurface3DSeries *>(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);