summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMika Salmela <mika.salmela@digia.com>2013-09-26 10:46:01 +0300
committerMika Salmela <mika.salmela@digia.com>2013-09-26 12:22:27 +0300
commit037d0960a2bde8ad310a9917055c7c0c3488152a (patch)
tree79996eeaa3396d0e2670a070559fd7674f9db462 /src
parent88695159e16bdfb8424de99d482adf332a93740d (diff)
Slice view implemented
Implemented slice view and fixed selection mechanism. Task-number: QTRD-2321 Task-number: QTRD-2307 Change-Id: I492bd96678bb1bdb8020448e122931a0deccdc0d Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com> Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/datavisualization/engine/q3dsurface.cpp17
-rw-r--r--src/datavisualization/engine/q3dsurface.h3
-rw-r--r--src/datavisualization/engine/selectionpointer.cpp79
-rw-r--r--src/datavisualization/engine/selectionpointer_p.h3
-rw-r--r--src/datavisualization/engine/surface3dcontroller.cpp21
-rw-r--r--src/datavisualization/engine/surface3dcontroller_p.h3
-rw-r--r--src/datavisualization/engine/surface3drenderer.cpp524
-rw-r--r--src/datavisualization/engine/surface3drenderer_p.h14
8 files changed, 563 insertions, 101 deletions
diff --git a/src/datavisualization/engine/q3dsurface.cpp b/src/datavisualization/engine/q3dsurface.cpp
index c8249399..bc6e4bca 100644
--- a/src/datavisualization/engine/q3dsurface.cpp
+++ b/src/datavisualization/engine/q3dsurface.cpp
@@ -259,6 +259,23 @@ bool Q3DSurface::isSmoothSurfaceEnabled() const
}
/*!
+ * \property Q3DSurface::selectionMode
+ *
+ * Sets point selection \a mode to one of \c QDataVis::SelectionMode. Surface supports ModeItem,
+ * ModeSliceRow and ModeSliceColumn. It is preset to \c QDataVis::ModeItem by default.
+ */
+void Q3DSurface::setSelectionMode(QDataVis::SelectionMode mode)
+{
+ d_ptr->m_shared->setSelectionMode(mode);
+}
+
+QDataVis::SelectionMode Q3DSurface::selectionMode() const
+{
+ return d_ptr->m_shared->selectionMode();
+}
+
+
+/*!
* \property Q3DSurface::surfaceGridEnabled
*
* Sets surface grid to \a enabled. It is preset to \c true by default.
diff --git a/src/datavisualization/engine/q3dsurface.h b/src/datavisualization/engine/q3dsurface.h
index 167af32d..c0edd6d7 100644
--- a/src/datavisualization/engine/q3dsurface.h
+++ b/src/datavisualization/engine/q3dsurface.h
@@ -33,6 +33,7 @@ class QSurfaceDataProxy;
class QT_DATAVISUALIZATION_EXPORT Q3DSurface : public Q3DWindow
{
Q_OBJECT
+ Q_PROPERTY(QtDataVisualization::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode)
Q_PROPERTY(QtDataVisualization::QDataVis::LabelTransparency labelTransparency READ labelTransparency WRITE setLabelTransparency)
Q_PROPERTY(QtDataVisualization::QDataVis::ColorTheme theme READ theme WRITE setTheme)
Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality)
@@ -63,6 +64,8 @@ public:
void setSmoothSurfaceEnabled(bool enabled);
bool isSmoothSurfaceEnabled() const;
+ void setSelectionMode(QDataVis::SelectionMode mode);
+ QDataVis::SelectionMode selectionMode() const;
void setSurfaceGridEnabled(bool enabled);
bool isSurfaceGridEnabled() const;
diff --git a/src/datavisualization/engine/selectionpointer.cpp b/src/datavisualization/engine/selectionpointer.cpp
index 2476740d..3178863d 100644
--- a/src/datavisualization/engine/selectionpointer.cpp
+++ b/src/datavisualization/engine/selectionpointer.cpp
@@ -92,13 +92,24 @@ void SelectionPointer::render(GLuint defaultFboHandle)
{
Q_UNUSED(defaultFboHandle)
+ glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
+ m_mainViewPort.width(), m_mainViewPort.height());
+
Q3DCamera *camera = m_cachedScene->activeCamera();
QSize textureSize = m_labelItem.size();
QMatrix4x4 itModelMatrix;
// Get view matrix
- QMatrix4x4 viewMatrix = camera->viewMatrix();
+ QMatrix4x4 viewMatrix;
+ if (m_cachedIsSlicingActivated) {
+ GLfloat camZPosSliced = 5.0f / m_autoScaleAdjustment + zComp;
+ viewMatrix.lookAt(QVector3D(0.0f, 0.0f, camZPosSliced),
+ QVector3D(0.0f, 0.0f, zComp),
+ QVector3D(0.0f, 1.0f, 0.0f));
+ } else {
+ viewMatrix = camera->viewMatrix();
+ }
itModelMatrix.scale(m_scale);
@@ -148,50 +159,50 @@ void SelectionPointer::render(GLuint defaultFboHandle)
//
// Draw the label
//
- if (m_labelItem.textureId()) {
- QMatrix4x4 modelMatrixLabel;
+ QMatrix4x4 modelMatrixLabel;
- // Position label
- QVector3D labelAlign(0.0f, 1.0f * scaledFontSize + 0.05f, 0.0f);
- modelMatrixLabel.translate(m_position * m_scale + labelAlign + QVector3D(0.0f, 0.0f, zComp));
+ // Position label
+ QVector3D labelAlign(0.0f, 1.0f * scaledFontSize + 0.05f, 0.0f);
+ modelMatrixLabel.translate(m_position * m_scale + labelAlign + QVector3D(0.0f, 0.0f, zComp));
- // Position the label towards the camera
- QPointF camRotations = camera->rotations();
+ // Position the label towards the camera
+ QPointF camRotations = camera->rotations();
+ if (!m_cachedIsSlicingActivated) {
modelMatrixLabel.rotate(-camRotations.x(), 0.0f, 1.0f, 0.0f);
modelMatrixLabel.rotate(-camRotations.y(), 1.0f, 0.0f, 0.0f);
+ }
- // Scale label based on text size
- modelMatrixLabel.scale(QVector3D((GLfloat)textureSize.width() * scaleFactor,
- scaledFontSize,
- 0.0f));
+ // Scale label based on text size
+ modelMatrixLabel.scale(QVector3D((GLfloat)textureSize.width() * scaleFactor,
+ scaledFontSize,
+ 0.0f));
- // Make label to be always on top
- glDisable(GL_DEPTH_TEST);
+ // Make label to be always on top
+ glDisable(GL_DEPTH_TEST);
- // Make label transparent
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ // Make label transparent
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- m_labelShader->bind();
+ m_labelShader->bind();
- // Set shader bindings
- MVPMatrix = projectionMatrix * viewMatrix * modelMatrixLabel;
- m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix);
+ // Set shader bindings
+ MVPMatrix = projectionMatrix * viewMatrix * modelMatrixLabel;
+ m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix);
- // Draw the object
- m_drawer->drawObject(m_labelShader, m_labelObj, m_labelItem.textureId());
+ // Draw the object
+ m_drawer->drawObject(m_labelShader, m_labelObj, m_labelItem.textureId());
- m_labelShader->release();
+ m_labelShader->release();
- // Disable textures
- glDisable(GL_TEXTURE_2D);
+ // Disable textures
+ glDisable(GL_TEXTURE_2D);
- // Disable transparency
- glDisable(GL_BLEND);
+ // Disable transparency
+ glDisable(GL_BLEND);
- // Depth test back to normal
- glEnable(GL_DEPTH_TEST);
- }
+ // Depth test back to normal
+ glEnable(GL_DEPTH_TEST);
}
void SelectionPointer::setPosition(QVector3D position)
@@ -204,6 +215,12 @@ void SelectionPointer::setScaling(QVector3D scaling)
m_scale = scaling;
}
+void SelectionPointer::updateSliceData(bool sliceActivated, GLfloat autoScaleAdjustment)
+{
+ m_cachedIsSlicingActivated = sliceActivated;
+ m_autoScaleAdjustment = autoScaleAdjustment;
+}
+
void SelectionPointer::setLabel(QString label)
{
m_label = label;
diff --git a/src/datavisualization/engine/selectionpointer_p.h b/src/datavisualization/engine/selectionpointer_p.h
index d13dffaa..c6d2514b 100644
--- a/src/datavisualization/engine/selectionpointer_p.h
+++ b/src/datavisualization/engine/selectionpointer_p.h
@@ -68,6 +68,7 @@ public:
void updateTheme(Theme theme);
void updateBoundingRect(QRect rect);
void updateScene(Q3DScene *scene);
+ void updateSliceData(bool sliceActivated, GLfloat autoScaleAdjustment);
private:
void initShaders();
@@ -91,6 +92,8 @@ private:
QVector3D m_scale;
Q3DScene *m_cachedScene;
QString m_label;
+ bool m_cachedIsSlicingActivated;
+ GLfloat m_autoScaleAdjustment;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/surface3dcontroller.cpp b/src/datavisualization/engine/surface3dcontroller.cpp
index e4903a6f..b4caf5de 100644
--- a/src/datavisualization/engine/surface3dcontroller.cpp
+++ b/src/datavisualization/engine/surface3dcontroller.cpp
@@ -45,8 +45,6 @@ Surface3DController::Surface3DController(QRect rect)
setAxisX(0);
setAxisY(0);
setAxisZ(0);
- QObject::connect(m_activeInputHandler, &QAbstract3DInputHandler::selectionAtPoint,
- this, &Surface3DController::handleSelectionAtPoint);
// Set the default from the theme
m_userDefinedGradient = theme().m_surfaceGradient;
@@ -150,6 +148,19 @@ void Surface3DController::setGradientColorAt(qreal pos, const QColor &color)
emitNeedRender();
}
+void Surface3DController::setSelectionMode(QDataVis::SelectionMode mode)
+{
+ if (!(mode == QDataVis::ModeNone || mode == QDataVis::ModeItem || mode == QDataVis::ModeSliceRow
+ || mode == QDataVis::ModeSliceColumn)) {
+ qWarning("Unsupported selection mode.");
+ return;
+ }
+ // Disable zoom if selection mode changes
+ setSlicingActive(false);
+ Abstract3DController::setSelectionMode(mode);
+}
+
+
void Surface3DController::setActiveDataProxy(QAbstractDataProxy *proxy)
{
// Setting null proxy indicates default proxy
@@ -177,12 +188,6 @@ void Surface3DController::handleArrayReset()
emitNeedRender();
}
-
-void Surface3DController::handleSelectionAtPoint(const QPoint &point)
-{
- emit leftMousePressed(point);
-}
-
void Surface3DController::adjustValueAxisRange()
{
if (m_data) {
diff --git a/src/datavisualization/engine/surface3dcontroller_p.h b/src/datavisualization/engine/surface3dcontroller_p.h
index bf7167a6..947034ec 100644
--- a/src/datavisualization/engine/surface3dcontroller_p.h
+++ b/src/datavisualization/engine/surface3dcontroller_p.h
@@ -82,6 +82,8 @@ public:
void setGradientColorAt(qreal pos, const QColor &color);
+ void setSelectionMode(QDataVis::SelectionMode mode);
+
virtual void setActiveDataProxy(QAbstractDataProxy *proxy);
virtual void handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust);
@@ -94,7 +96,6 @@ signals:
void smoothStatusChanged(bool enable);
void surfaceGridChanged(bool enable);
void segmentCountChanged(GLint segmentCount, GLfloat step, GLfloat minimum);
- void leftMousePressed(const QPoint &point); // My temp solution
private:
void adjustValueAxisRange();
diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp
index 5d779789..9a95805f 100644
--- a/src/datavisualization/engine/surface3drenderer.cpp
+++ b/src/datavisualization/engine/surface3drenderer.cpp
@@ -53,7 +53,9 @@ const GLfloat backgroundMargin = 1.1f; // Margin for background (1.1f = make it
const GLfloat labelMargin = 0.05f;
const GLfloat backgroundBottom = 1.0f;
const GLfloat gridLineWidth = 0.005f;
+const GLfloat sliceZScale = 0.1f;
const GLfloat surfaceGridYOffsetValue = 0.001f;
+const int subViewDivider = 5;
// The second offset to opposite direction is double because same matrix is translated twice
const GLfloat surfaceGridYOffset[2] = {-surfaceGridYOffsetValue, 2.0f * surfaceGridYOffsetValue};
@@ -63,8 +65,6 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_labelTransparency(QDataVis::TransparencyFromTheme),
m_font(QFont(QStringLiteral("Arial"))),
m_isGridEnabled(true),
- m_segmentYCount(0),
- m_segmentYStep(0.0f),
m_shader(0),
m_depthShader(0),
m_backgroundShader(0),
@@ -92,6 +92,7 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_gridLineObj(0),
m_labelObj(0),
m_surfaceObj(0),
+ m_sliceSurfaceObj(0),
m_depthTexture(0),
m_depthFrameBuffer(0),
m_selectionFrameBuffer(0),
@@ -100,7 +101,6 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_selectionTexture(0),
m_selectionResultTexture(0),
m_shadowQualityToShader(33.3f),
- m_querySelection(false),
m_flatSupported(true),
m_selectionPointer(0),
m_selectionActive(false),
@@ -111,10 +111,6 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_shadowQualityMultiplier(3),
m_hasHeightAdjustmentChanged(true)
{
- // Listen to changes in the controller
- QObject::connect(m_controller, &Surface3DController::leftMousePressed, this,
- &Surface3DRenderer::requestSelectionAtPoint); // TODO: Possible temp
-
#if !defined(QT_OPENGL_ES_2)
// Check if flat feature is supported
ShaderHelper tester(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
@@ -156,6 +152,7 @@ Surface3DRenderer::~Surface3DRenderer()
delete m_backgroundObj;
delete m_surfaceObj;
+ delete m_sliceSurfaceObj;
delete m_gridLineObj;
delete m_labelObj;
@@ -165,6 +162,9 @@ Surface3DRenderer::~Surface3DRenderer()
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 Surface3DRenderer::initializeOpenGL()
@@ -193,10 +193,6 @@ void Surface3DRenderer::initializeOpenGL()
// Load label mesh
loadLabelMesh();
- // Set view port
- glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
- m_mainViewPort.width(), m_mainViewPort.height());
-
// Resize in case we've missed resize events
// Resize calls initSelectionBuffer and initDepthBuffer, so they don't need to be called here
handleResize();
@@ -257,6 +253,45 @@ void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy)
Abstract3DRenderer::updateDataModel(dataProxy);
}
+void Surface3DRenderer::updateSliceDataModel(int selectionId)
+{
+ int column = (selectionId - 1) % m_sampleSpace.width();
+ int row = (selectionId - 1) / m_sampleSpace.width();
+
+ for (int i = 0; i < m_sliceDataArray.size(); i++)
+ delete m_sliceDataArray.at(i);
+ m_sliceDataArray.clear();
+
+ m_sliceDataArray.reserve(2);
+ QSurfaceDataRow *sliceRow;
+
+ if (m_cachedSelectionMode == QDataVis::ModeSliceRow) {
+ sliceRow = new QSurfaceDataRow(*m_dataArray.at(row));
+ } else if (m_cachedSelectionMode == QDataVis::ModeSliceColumn) {
+ sliceRow = new QSurfaceDataRow();
+ sliceRow->resize(m_sampleSpace.height());
+ for (int i = 0; i < m_sampleSpace.height(); i++)
+ (*sliceRow)[i] = m_dataArray.at(i)->at(column);
+ }
+ m_sliceDataArray << sliceRow;
+
+ // Make a duplicate, so that we get a little bit depth
+ QSurfaceDataRow *duplicateRow = new QSurfaceDataRow(*sliceRow);
+ m_sliceDataArray << duplicateRow;
+
+ QRect sliceRect(0, 0, sliceRow->size(), 2);
+
+ if (sliceRow->size() > 0) {
+ if (!m_sliceSurfaceObj)
+ loadSliceSurfaceObj();
+
+ if (m_cachedSmoothSurface)
+ m_sliceSurfaceObj->setUpSmoothData(m_sliceDataArray, sliceRect, m_heightNormalizer, true);
+ else
+ m_sliceSurfaceObj->setUpData(m_sliceDataArray, sliceRect, m_heightNormalizer, true);
+ }
+}
+
QRect Surface3DRenderer::calculateSampleRect(QSurfaceDataProxy *dataProxy)
{
QRect sampleSpace;
@@ -308,7 +343,7 @@ QRect Surface3DRenderer::calculateSampleRect(QSurfaceDataProxy *dataProxy)
GLfloat data2XCenterX = (m_minVisibleColumnValue + m_maxVisibleColumnValue);
GLfloat data2XCenterZ = (m_minVisibleRowValue + m_maxVisibleRowValue);
m_surfaceOffsetX = m_scaleX * (data2XCenterX - axis2XCenterX) / m_areaSize.width();
- m_surfaceOffsetZ = -m_scaleZ * (data2XCenterZ - axis2XCenterZ) / m_areaSize.height() + zComp;
+ m_surfaceOffsetZ = -m_scaleZ * (data2XCenterZ - axis2XCenterZ) / m_areaSize.height();
return sampleSpace;
}
@@ -316,6 +351,7 @@ QRect Surface3DRenderer::calculateSampleRect(QSurfaceDataProxy *dataProxy)
void Surface3DRenderer::updateScene(Q3DScene *scene)
{
// TODO: Move these to more suitable place e.g. controller should be controlling the viewports.
+ scene->setSecondarySubViewport(m_sliceViewPort);
scene->setPrimarySubViewport(m_mainViewPort);
scene->setUnderSideCameraEnabled(false);
@@ -340,10 +376,16 @@ void Surface3DRenderer::updateScene(Q3DScene *scene)
void Surface3DRenderer::render(GLuint defaultFboHandle)
{
- m_cachedScene->setUnderSideCameraEnabled(false);
+ bool slicingActivated = m_cachedScene->isSlicingActive();
+ updateSlicingActive(slicingActivated);
+
// Handle GL state setup for FBO buffers and clearing of the render surface
Abstract3DRenderer::render(defaultFboHandle);
+ // If slice selection is on, draw the sliced scene
+ if (m_cachedIsSlicingActivated)
+ drawSlicedScene();
+
// Draw the surface scene
drawScene(defaultFboHandle);
@@ -352,9 +394,324 @@ void Surface3DRenderer::render(GLuint defaultFboHandle)
m_selectionPointer->render(defaultFboHandle);
}
+void Surface3DRenderer::drawSlicedScene()
+{
+ QVector3D lightPos;
+
+ // Specify viewport
+ glViewport(m_sliceViewPort.x(), m_sliceViewPort.y(),
+ m_sliceViewPort.width(), m_sliceViewPort.height());
+
+ // Set up projection matrix
+ QMatrix4x4 projectionMatrix;
+ projectionMatrix.perspective(45.0f, (GLfloat)m_sliceViewPort.width()
+ / (GLfloat)m_sliceViewPort.height(), 0.1f, 100.0f);
+
+ // Set view matrix
+ QMatrix4x4 viewMatrix;
+
+ // Adjust scaling (zoom rate based on aspect ratio)
+ GLfloat camZPosSliced = 5.0f / m_autoScaleAdjustment + zComp;
+
+ viewMatrix.lookAt(QVector3D(0.0f, 0.0f, camZPosSliced),
+ QVector3D(0.0f, 0.0f, zComp),
+ QVector3D(0.0f, 1.0f, 0.0f));
+
+ // Set light position
+ lightPos = m_cachedScene->activeLight()->position();
+
+ QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix;
+
+ GLfloat scaleX;
+ GLfloat scaleXBackground;
+ GLfloat offset;
+ if (m_cachedSelectionMode == QDataVis::ModeSliceRow) {
+ scaleX = m_surfaceScaleX;
+ scaleXBackground = m_scaleXWithBackground;
+ offset = m_surfaceOffsetX;
+ } else if (m_cachedSelectionMode == QDataVis::ModeSliceColumn) {
+ scaleX = m_surfaceScaleZ;
+ scaleXBackground = m_scaleZWithBackground;
+ offset = -m_surfaceOffsetZ;
+ }
+
+ if (m_surfaceObj) {
+ ShaderHelper *surfaceShader = m_shader;
+ surfaceShader->bind();
+
+ // For surface we can see climpses from underneath
+ glDisable(GL_CULL_FACE);
+
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+ QMatrix4x4 itModelMatrix;
+
+ modelMatrix.translate(offset, 0.0f, zComp);
+ QVector3D scaling(scaleX, 1.0f, sliceZScale);
+ modelMatrix.scale(scaling);
+ itModelMatrix.scale(scaling);
+
+ MVPMatrix = projectionViewMatrix * modelMatrix;
+
+ QVector3D color;
+ if (m_cachedSelectionMode == QDataVis::ModeSliceRow)
+ color = Utils::vectorFromColor(m_cachedTheme.m_highlightRowColor);
+ else
+ color = Utils::vectorFromColor(m_cachedTheme.m_highlightColumnColor);
+
+ // 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->color(), color);
+ surfaceShader->setUniformValue(surfaceShader->ambientS(), m_cachedTheme.m_ambientStrength);
+ surfaceShader->setUniformValue(surfaceShader->lightS(),
+ m_cachedTheme.m_lightStrength * 2.0f);
+
+ m_drawer->drawObject(surfaceShader, m_sliceSurfaceObj);
+
+ surfaceShader->release();
+
+ glEnable(GL_CULL_FACE);
+
+ // Draw surface grid
+ if (m_cachedSurfaceGridOn) {
+ m_surfaceGridShader->bind();
+
+ m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(),
+ Utils::vectorFromColor(m_cachedTheme.m_gridLine));
+ // Draw the grid twice, with slight offset on Y axis to each direction
+ for (int i = 0; i < 2; i++) {
+ MVPMatrix.translate(0.0f, surfaceGridYOffset[i], 0.0f);
+
+ m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), MVPMatrix);
+ m_drawer->drawSurfaceGrid(m_surfaceGridShader, m_sliceSurfaceObj);
+ }
+ m_surfaceGridShader->release();
+ }
+ }
+
+ // Disable textures
+ glDisable(GL_TEXTURE_2D);
+
+ ShaderHelper *lineShader = m_backgroundShader;
+ // Bind line shader
+ lineShader->bind();
+
+ // lines to the back
+ if (m_axisCacheY.segmentCount() > 0) {
+ QVector3D gridLineScaleX(scaleXBackground, gridLineWidth, gridLineWidth);
+
+ // Set unchanging shader bindings
+ QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme.m_gridLine);
+ lineShader->setUniformValue(lineShader->lightP(), lightPos);
+ lineShader->setUniformValue(lineShader->view(), viewMatrix);
+ lineShader->setUniformValue(lineShader->color(), lineColor);
+ lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme.m_ambientStrength);
+
+ // Back wall
+ GLfloat lineStep = 2.0f * m_axisCacheY.subSegmentStep() / m_heightNormalizer;
+ GLfloat linePos = -1.0f;
+ int lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount();
+
+ for (int segment = 0; segment <= lastSegment; segment++) {
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+ QMatrix4x4 itModelMatrix;
+
+ modelMatrix.translate(0.0f, linePos, zComp - sliceZScale);
+
+ modelMatrix.scale(gridLineScaleX);
+ itModelMatrix.scale(gridLineScaleX);
+
+ MVPMatrix = projectionViewMatrix * modelMatrix;
+
+ // Set the rest of the shader bindings
+ lineShader->setUniformValue(lineShader->model(), modelMatrix);
+ lineShader->setUniformValue(lineShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ lineShader->setUniformValue(lineShader->MVP(), MVPMatrix);
+
+ // Set shadowless shader bindings, no shadows on slice view
+ lineShader->setUniformValue(lineShader->lightS(),
+ m_cachedTheme.m_lightStrength);
+
+ // Draw the object
+ m_drawer->drawObject(lineShader, m_gridLineObj);
+
+ linePos += lineStep;
+ }
+ }
+
+ // Floor lines
+ QVector3D gridLineScaleZ(gridLineWidth, gridLineWidth, sliceZScale);
+ QVector3D gridLineScaleY(gridLineWidth, backgroundMargin, gridLineWidth);
+
+ int lastSegment;
+ GLfloat lineStep;
+ GLfloat linePos;
+ if (m_cachedSelectionMode == QDataVis::ModeSliceRow) {
+ lineStep = -2.0f * aspectRatio * m_axisCacheX.subSegmentStep() / m_scaleFactor;
+ lastSegment = m_axisCacheX.subSegmentCount() * m_axisCacheX.segmentCount();
+ linePos = m_scaleX;
+ } else {
+ lineStep = -2.0f * aspectRatio * m_axisCacheZ.subSegmentStep() / m_scaleFactor;
+ lastSegment = m_axisCacheZ.subSegmentCount() * m_axisCacheZ.segmentCount();
+ linePos = m_scaleZ;
+ }
+
+ for (int segment = 0; segment <= lastSegment; segment++) {
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+ QMatrix4x4 itModelMatrix;
+
+ modelMatrix.translate(linePos, -backgroundMargin, zComp);
+
+ modelMatrix.scale(gridLineScaleZ);
+ itModelMatrix.scale(gridLineScaleZ);
+
+ MVPMatrix = projectionViewMatrix * modelMatrix;
+
+ // Set the rest of the shader bindings
+ lineShader->setUniformValue(lineShader->model(), modelMatrix);
+ lineShader->setUniformValue(lineShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ lineShader->setUniformValue(lineShader->MVP(), MVPMatrix);
+
+ // Set shadowless shader bindings
+ lineShader->setUniformValue(lineShader->lightS(),
+ m_cachedTheme.m_lightStrength);
+
+ // Draw the object
+ m_drawer->drawObject(lineShader, m_gridLineObj);
+
+ linePos += lineStep;
+ }
+
+ if (m_cachedSelectionMode == QDataVis::ModeSliceRow)
+ linePos = m_scaleX;
+ else
+ linePos = m_scaleZ;
+
+ for (int segment = 0; segment <= lastSegment; segment++) {
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+ QMatrix4x4 itModelMatrix;
+
+ modelMatrix.translate(linePos, 0.0f, zComp - sliceZScale);
+ modelMatrix.scale(gridLineScaleY);
+ itModelMatrix.scale(gridLineScaleY);
+
+ MVPMatrix = projectionViewMatrix * modelMatrix;
+
+ // Set the rest of the shader bindings
+ lineShader->setUniformValue(lineShader->model(), modelMatrix);
+ lineShader->setUniformValue(lineShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ lineShader->setUniformValue(lineShader->MVP(), MVPMatrix);
+
+ // Set shadowless shader bindings
+ lineShader->setUniformValue(lineShader->lightS(),
+ m_cachedTheme.m_lightStrength);
+
+ // Draw the object
+ m_drawer->drawObject(lineShader, m_gridLineObj);
+
+ linePos += lineStep;
+ }
+
+ // Release line shader
+ lineShader->release();
+
+ // Draw axis labels
+ m_labelShader->bind();
+ glEnable(GL_TEXTURE_2D);
+ glDisable(GL_DEPTH_TEST);
+ glCullFace(GL_BACK);
+ if (m_cachedLabelTransparency > QDataVis::TransparencyNone) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ // Y Labels to back wall
+ GLfloat posStep = 2.0f * m_axisCacheY.segmentStep() / m_heightNormalizer;
+ GLfloat labelPos = -1.0f;
+ int labelNbr = 0;
+
+ QVector3D positionComp(0.0f, 0.0f, zComp);
+ QVector3D rotation(0.0f, 0.0f, 0.0f);
+ QVector3D labelTrans = QVector3D(scaleXBackground + labelMargin, labelPos, zComp);
+ for (int segment = 0; segment <= m_axisCacheY.segmentCount(); segment++) {
+ if (m_axisCacheY.labelItems().size() > labelNbr) {
+ labelTrans.setY(labelPos);
+ const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr);
+
+ // Draw the label here
+ m_dummyRenderItem.setTranslation(labelTrans);
+ m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
+ positionComp, rotation, 0, m_cachedSelectionMode, m_labelShader,
+ m_labelObj, m_cachedScene->activeCamera(),
+ true, true, Drawer::LabelMid, Qt::AlignRight);
+ }
+ labelNbr++;
+ labelPos += posStep;
+ }
+
+ // X Labels to ground
+ int countLabelItems;
+ if (m_cachedSelectionMode == QDataVis::ModeSliceRow) {
+ posStep = 2.0f * aspectRatio * m_axisCacheX.segmentStep() / m_scaleFactor;
+ labelPos = -m_scaleX;
+ lastSegment = m_axisCacheX.segmentCount();
+ countLabelItems = m_axisCacheX.labelItems().size();
+ } else {
+ posStep = 2.0f * aspectRatio * m_axisCacheZ.segmentStep() / m_scaleFactor;
+ labelPos = -m_scaleZ;
+ lastSegment = m_axisCacheZ.segmentCount();
+ countLabelItems = m_axisCacheZ.labelItems().size();
+ }
+
+ labelNbr = 0;
+ positionComp.setY(backgroundMargin);
+ rotation.setZ(-45.0f);
+ labelTrans.setY(-backgroundMargin);
+ for (int segment = 0; segment <= lastSegment; segment++) {
+ if (countLabelItems > labelNbr) {
+ // Draw the label here
+ labelTrans.setX(labelPos);
+
+ m_dummyRenderItem.setTranslation(labelTrans);
+
+ LabelItem *axisLabelItem;
+ if (m_cachedSelectionMode == QDataVis::ModeSliceRow)
+ axisLabelItem = m_axisCacheX.labelItems().at(labelNbr);
+ else
+ axisLabelItem = m_axisCacheZ.labelItems().at(labelNbr);
+
+ m_drawer->drawLabel(m_dummyRenderItem, *axisLabelItem, viewMatrix, projectionMatrix,
+ positionComp, rotation, 0, QDataVis::ModeSliceRow, m_labelShader,
+ m_labelObj, m_cachedScene->activeCamera(), false, false,
+ Drawer::LabelBelow, Qt::AlignTop);
+ }
+ labelNbr++;
+ labelPos += posStep;
+ }
+
+ glDisable(GL_TEXTURE_2D);
+ glEnable(GL_DEPTH_TEST);
+ if (m_cachedLabelTransparency > QDataVis::TransparencyNone)
+ glDisable(GL_BLEND);
+
+ // Release label shader
+ m_labelShader->release();
+}
+
void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
{
GLfloat backgroundRotation = 0;
+ uint selectionId = 0;
// Specify viewport
glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
@@ -398,12 +755,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
GLfloat adjustedLightStrength = m_cachedTheme.m_lightStrength / 10.0f;
- //
- // Do the surface drawing
- //
-
QVector3D surfaceScaler(m_surfaceScaleX, 1.0f, m_surfaceScaleZ);
- QVector3D surfaceOffset(m_surfaceOffsetX, 0.0f, m_surfaceOffsetZ);
+ QVector3D surfaceOffset(m_surfaceOffsetX, 0.0f, m_surfaceOffsetZ + zComp);
// Draw depth buffer
#if !defined(QT_OPENGL_ES_2)
@@ -513,7 +866,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glEnable(GL_TEXTURE_2D);
// Draw selection buffer
- if (m_querySelection && m_surfaceObj && m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) {
+ if (!m_cachedIsSlicingActivated && m_controller->inputState() == QDataVis::InputOnScene && m_surfaceObj
+ && m_cachedSelectionMode > QDataVis::ModeNone) {
m_selectionShader->bind();
glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer);
glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used
@@ -537,8 +891,6 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glEnable(GL_DITHER);
- m_querySelection = false;
-
QPoint point = m_controller->inputPosition();
GLubyte pixel[4] = {0};
glReadPixels(point.x(), m_cachedBoundingRect.height() - point.y(), 1, 1,
@@ -550,19 +902,12 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_selectionShader->release();
// Put the RGBA value back to uint
- uint id = pixel[0] + pixel[1] * 256 + pixel[2] * 65536 + pixel[3] * 16777216;
- if (id) {
- surfacePointSelected(id);
- } else {
- //surfacePointCleared();
- m_selectionActive = false;
- }
- glEnable(GL_CULL_FACE);
+ selectionId = pixel[0] + pixel[1] * 256 + pixel[2] * 65536 + pixel[3] * 16777216;
}
+ // Draw the surface
if (m_surfaceObj && m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) {
m_surfaceShader->bind();
- // m_selectionShader->bind(); // IFDEF print selection
// For surface we can see climpses from underneath
glDisable(GL_CULL_FACE);
@@ -615,6 +960,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_surfaceShader->release();
+ glEnable(GL_CULL_FACE);
+
// Draw surface grid
if (m_cachedSurfaceGridOn) {
m_surfaceGridShader->bind();
@@ -630,7 +977,6 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
}
m_surfaceGridShader->release();
}
- glEnable(GL_CULL_FACE);
}
// Bind background shader
@@ -1169,6 +1515,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
if (m_axisCacheY.labelItems().size() > labelNbr) {
const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr);
+ // Side wall
QVector3D labelTrans = QVector3D(labelXTrans, labelPos,
labelZTrans + labelMarginZTrans + zComp);
if (m_xFlipped)
@@ -1187,7 +1534,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_labelShader, m_labelObj, m_cachedScene->activeCamera(),
true, true, Drawer::LabelMid, alignment);
- // Side wall
+ // Back wall
if (m_xFlipped)
alignment = Qt::AlignLeft;
else
@@ -1218,6 +1565,30 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Release label shader
m_labelShader->release();
+
+ // Selection handling
+ if (m_controller->inputState() == QDataVis::InputOnScene) {
+ if (m_cachedSelectionMode == QDataVis::ModeItem) {
+ if (selectionId)
+ surfacePointSelected(selectionId);
+ else
+ m_selectionActive = false;
+ }
+ if (m_cachedSelectionMode == QDataVis::ModeSliceRow || m_cachedSelectionMode == QDataVis::ModeSliceColumn) {
+ if (selectionId) {
+ updateSliceDataModel(selectionId);
+ m_cachedScene->setSlicingActive(true);
+
+ surfacePointSelected(selectionId);
+ }
+ }
+ }
+ if (m_controller->inputState() == QDataVis::InputOnOverview) {
+ if (m_cachedIsSlicingActivated) {
+ m_cachedScene->setSlicingActive(false);
+ m_selectionActive = false;
+ }
+ }
}
void Surface3DRenderer::updateSurfaceGradient(const QLinearGradient &gradient)
@@ -1236,18 +1607,6 @@ void Surface3DRenderer::updateSurfaceGradient(const QLinearGradient &gradient)
m_gradientTexture = m_textureHelper->create2DTexture(image, false, true);
}
-void Surface3DRenderer::requestSelectionAtPoint(const QPoint &point)
-{
- Q_UNUSED(point)
-
- // QMutexLocker locker(&m_mutex);
- // m_selectionPointRequest.setX(point.x());
- // m_selectionPointRequest.setY(point.y());
- // m_isSelectionPointRequestActive = true;
-
- m_querySelection = true;
-}
-
// This one needs to be called when the data size changes
void Surface3DRenderer::updateSelectionTexture()
{
@@ -1281,10 +1640,6 @@ void Surface3DRenderer::updateSelectionTexture()
id++;
}
- // Use this to save the ID image to file
- //QImage image(bits, idImageWidth, idImageHeight, QImage::Format_ARGB32);
- //image.save("C:\\Users\\misalmel\\Work\\gerrit\\qtdatavisualization_2\\selection.png");
-
// If old texture exists, delete it
if (m_selectionTexture) {
m_textureHelper->deleteTexture(&m_selectionTexture);
@@ -1411,6 +1766,13 @@ void Surface3DRenderer::loadSurfaceObj()
m_surfaceObj = new SurfaceObject();
}
+void Surface3DRenderer::loadSliceSurfaceObj()
+{
+ if (m_sliceSurfaceObj)
+ delete m_sliceSurfaceObj;
+ m_sliceSurfaceObj = new SurfaceObject();
+}
+
void Surface3DRenderer::loadGridLineMesh()
{
if (m_gridLineObj)
@@ -1424,10 +1786,23 @@ void Surface3DRenderer::handleResize()
if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0)
return;
- m_mainViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height());
+ // Set view port
+ if (m_cachedIsSlicingActivated) {
+ m_mainViewPort = QRect(0,
+ m_cachedBoundingRect.height() - m_cachedBoundingRect.height() / subViewDivider,
+ m_cachedBoundingRect.width() / subViewDivider,
+ m_cachedBoundingRect.height() / subViewDivider);
+ } else {
+ m_mainViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height());
+ }
+ m_sliceViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height());
- if (m_selectionPointer)
- m_selectionPointer->updateBoundingRect(m_mainViewPort);
+ if (m_selectionPointer) {
+ if (m_cachedIsSlicingActivated)
+ m_selectionPointer->updateBoundingRect(m_sliceViewPort);
+ else
+ m_selectionPointer->updateBoundingRect(m_mainViewPort);
+ }
Abstract3DRenderer::handleResize();
}
@@ -1441,13 +1816,29 @@ void Surface3DRenderer::surfacePointSelected(int id)
if (!m_selectionPointer)
m_selectionPointer = new SelectionPointer(m_controller, m_drawer);
- QVector3D pos(normalize(float(column), value, float(row)));
- pos += QVector3D(m_surfaceOffsetX, 0.0f, m_surfaceOffsetZ - zComp);
+ QVector3D pos;
+ if (m_cachedSelectionMode == QDataVis::ModeSliceRow) {
+ pos = normalize(float(column), value, 0.0f);
+ pos += QVector3D(m_surfaceOffsetX, 0.0f, -1.0f);
+ m_selectionPointer->setScaling(QVector3D(m_surfaceScaleX, 1.0f, sliceZScale));
+ m_selectionPointer->updateBoundingRect(m_sliceViewPort);
+ m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment);
+ } else if (m_cachedSelectionMode == QDataVis::ModeSliceColumn) {
+ pos = normalize(float(row), value, 0.0f);
+ pos += QVector3D(m_surfaceOffsetZ, 0.0f, -1.0f);
+ m_selectionPointer->setScaling(QVector3D(m_surfaceScaleZ, 1.0f, sliceZScale));
+ m_selectionPointer->updateBoundingRect(m_sliceViewPort);
+ m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment);
+ } else {
+ pos = normalize(float(column), value, float(row));
+ pos += QVector3D(m_surfaceOffsetX, 0.0f, m_surfaceOffsetZ);
+ m_selectionPointer->setScaling(QVector3D(m_surfaceScaleX, 1.0f, m_surfaceScaleZ));
+ m_selectionPointer->updateBoundingRect(m_mainViewPort);
+ m_selectionPointer->updateSliceData(false, m_autoScaleAdjustment);
+ }
m_selectionPointer->setPosition(pos);
- m_selectionPointer->setScaling(QVector3D(m_surfaceScaleX, 1.0f, m_surfaceScaleZ));
m_selectionPointer->setLabel(createSelectionLabel(value, column, row));
- m_selectionPointer->updateBoundingRect(m_mainViewPort);
m_selectionPointer->updateScene(m_cachedScene);
//Put the selection pointer flag active
@@ -1559,6 +1950,29 @@ void Surface3DRenderer::updateShadowQuality(QDataVis::ShadowQuality quality)
#endif
}
+void Surface3DRenderer::updateSlicingActive(bool isSlicing)
+{
+ if (isSlicing == m_cachedIsSlicingActivated)
+ return;
+
+ m_cachedIsSlicingActivated = isSlicing;
+ if (isSlicing) {
+ m_mainViewPort = QRect(0, m_cachedBoundingRect.height() - m_cachedBoundingRect.height() / subViewDivider,
+ m_cachedBoundingRect.width() / subViewDivider, m_cachedBoundingRect.height() / subViewDivider);
+ if (m_depthTexture) {
+ m_textureHelper->deleteTexture(&m_depthTexture);
+ m_depthTexture = 0;
+ }
+ } else {
+ m_mainViewPort = QRect(0, 0, this->m_cachedBoundingRect.width(),
+ this->m_cachedBoundingRect.height());
+ initSelectionBuffer(); // We need to re-init selection buffer in case there has been a resize
+#if !defined(QT_OPENGL_ES_2)
+ updateDepthBuffer(); // Re-init depth buffer as well
+#endif
+ }
+}
+
void Surface3DRenderer::loadLabelMesh()
{
if (m_labelObj)
diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h
index 6b6f61c6..4edd80f9 100644
--- a/src/datavisualization/engine/surface3drenderer_p.h
+++ b/src/datavisualization/engine/surface3drenderer_p.h
@@ -69,13 +69,11 @@ public:
bool m_isGridEnabled;
private:
- // Data parameters
- QList<qreal> m_series; // TODO: TEMP
- GLint m_segmentYCount;
- GLfloat m_segmentYStep;
+ bool m_cachedIsSlicingActivated;
// Internal attributes purely related to how the scene is drawn with GL.
QRect m_mainViewPort;
+ QRect m_sliceViewPort;
ShaderHelper *m_shader;
ShaderHelper *m_depthShader;
ShaderHelper *m_backgroundShader;
@@ -103,6 +101,7 @@ private:
ObjectHelper *m_gridLineObj;
ObjectHelper *m_labelObj;
SurfaceObject *m_surfaceObj;
+ SurfaceObject *m_sliceSurfaceObj;
GLuint m_depthTexture;
GLuint m_depthFrameBuffer;
GLuint m_selectionFrameBuffer;
@@ -111,7 +110,6 @@ private:
GLuint m_selectionTexture;
GLuint m_selectionResultTexture;
GLfloat m_shadowQualityToShader;
- bool m_querySelection;
bool m_cachedSmoothSurface;
bool m_flatSupported;
bool m_cachedSurfaceGridOn;
@@ -122,6 +120,7 @@ private:
bool m_yFlipped;
AbstractRenderItem m_dummyRenderItem;
QSurfaceDataArray m_dataArray;
+ QSurfaceDataArray m_sliceDataArray;
QRect m_sampleSpace;
GLint m_shadowQualityMultiplier;
QSizeF m_areaSize;
@@ -134,6 +133,7 @@ public:
void updateDataModel(QSurfaceDataProxy *dataProxy);
void updateScene(Q3DScene *scene);
+ void drawSlicedScene();
void render(GLuint defaultFboHandle = 0);
protected:
@@ -144,9 +144,10 @@ public slots:
bool updateSmoothStatus(bool enable);
void updateSurfaceGridStatus(bool enable);
void updateSurfaceGradient(const QLinearGradient &gradient);
- virtual void requestSelectionAtPoint(const QPoint &point);
+ void updateSlicingActive(bool isSlicing);
private:
+ void updateSliceDataModel(int selectionId);
virtual void updateShadowQuality(QDataVis::ShadowQuality quality);
virtual void updateTextures();
virtual void initShaders(const QString &vertexShader, const QString &fragmentShader);
@@ -155,6 +156,7 @@ private:
void loadGridLineMesh();
void loadLabelMesh();
void loadSurfaceObj();
+ void loadSliceSurfaceObj();
void drawScene(GLuint defaultFboHandle);
void handleResize();
void calculateSceneScalingFactors();