summaryrefslogtreecommitdiffstats
path: root/src/datavisualization/engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/datavisualization/engine')
-rw-r--r--src/datavisualization/engine/abstract3dcontroller.cpp33
-rw-r--r--src/datavisualization/engine/abstract3dcontroller_p.h7
-rw-r--r--src/datavisualization/engine/abstract3drenderer.cpp124
-rw-r--r--src/datavisualization/engine/abstract3drenderer_p.h19
-rw-r--r--src/datavisualization/engine/bars3drenderer.cpp20
-rw-r--r--src/datavisualization/engine/engine.qrc3
-rw-r--r--src/datavisualization/engine/q3dscene.cpp62
-rw-r--r--src/datavisualization/engine/q3dscene.h5
-rw-r--r--src/datavisualization/engine/q3dscene_p.h3
-rw-r--r--src/datavisualization/engine/qabstract3dgraph.cpp27
-rw-r--r--src/datavisualization/engine/qabstract3dgraph.h4
-rw-r--r--src/datavisualization/engine/scatter3drenderer.cpp10
-rw-r--r--src/datavisualization/engine/shaders/position.vert (renamed from src/datavisualization/engine/shaders/colorandposition.vert)0
-rw-r--r--src/datavisualization/engine/shaders/positionmap.frag11
-rw-r--r--src/datavisualization/engine/surface3drenderer.cpp17
15 files changed, 310 insertions, 35 deletions
diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp
index e2f8c1ad..c1d27bab 100644
--- a/src/datavisualization/engine/abstract3dcontroller.cpp
+++ b/src/datavisualization/engine/abstract3dcontroller.cpp
@@ -62,6 +62,7 @@ Abstract3DController::Abstract3DController(QRect initialViewport, Q3DScene *scen
{
if (!m_scene)
m_scene = new Q3DScene;
+ m_scene->setParent(this);
// Set initial theme
Q3DTheme *defaultTheme = new Q3DTheme(Q3DTheme::ThemeQt);
@@ -165,7 +166,12 @@ void Abstract3DController::synchDataToRenderer()
{
// Subclass implementations check for renderer validity already, so no need to check here.
- // If there is a pending click from renderer, handle that first.
+ // If there are pending queries, handle those first
+ if (m_renderer->isGraphPositionQueryPending()) {
+ handlePendingGraphPositionQuery();
+ m_renderer->clearGraphPositionQueryPending();
+ }
+
if (m_renderer->isClickPending()) {
handlePendingClick();
m_renderer->clearClickPending();
@@ -804,14 +810,15 @@ void Abstract3DController::setActiveInputHandler(QAbstract3DInputHandler *inputH
addInputHandler(inputHandler);
m_activeInputHandler = inputHandler;
- if (m_activeInputHandler)
+ if (m_activeInputHandler) {
m_activeInputHandler->setScene(m_scene);
- // Connect the input handler
- QObject::connect(m_activeInputHandler, &QAbstract3DInputHandler::inputViewChanged, this,
- &Abstract3DController::handleInputViewChanged);
- QObject::connect(m_activeInputHandler, &QAbstract3DInputHandler::positionChanged, this,
- &Abstract3DController::handleInputPositionChanged);
+ // Connect the input handler
+ QObject::connect(m_activeInputHandler, &QAbstract3DInputHandler::inputViewChanged, this,
+ &Abstract3DController::handleInputViewChanged);
+ QObject::connect(m_activeInputHandler, &QAbstract3DInputHandler::positionChanged, this,
+ &Abstract3DController::handleInputPositionChanged);
+ }
// Notify change of input handler
emit activeInputHandlerChanged(m_activeInputHandler);
@@ -1468,6 +1475,12 @@ void Abstract3DController::handlePendingClick()
emit elementSelected(type);
}
+void Abstract3DController::handlePendingGraphPositionQuery()
+{
+ m_queriedGraphPosition = m_renderer->queriedGraphPosition();
+ emit queriedGraphPositionChanged(m_queriedGraphPosition);
+}
+
int Abstract3DController::selectedLabelIndex() const
{
int index = m_renderer->m_selectedLabelIndex;
@@ -1659,4 +1672,10 @@ QLocale Abstract3DController::locale() const
return m_locale;
}
+QVector3D Abstract3DController::queriedGraphPosition() const
+{
+ return m_queriedGraphPosition;
+}
+
+
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/abstract3dcontroller_p.h b/src/datavisualization/engine/abstract3dcontroller_p.h
index 03061a13..125e9885 100644
--- a/src/datavisualization/engine/abstract3dcontroller_p.h
+++ b/src/datavisualization/engine/abstract3dcontroller_p.h
@@ -173,6 +173,7 @@ private:
bool m_reflectionEnabled;
qreal m_reflectivity;
QLocale m_locale;
+ QVector3D m_queriedGraphPosition;
protected:
Q3DScene *m_scene;
@@ -302,6 +303,8 @@ public:
void setLocale(const QLocale &locale);
QLocale locale() const;
+ QVector3D queriedGraphPosition() const;
+
void emitNeedRender();
virtual void clearSelection() = 0;
@@ -327,7 +330,8 @@ public:
virtual void handleAxisTitleVisibilityChangedBySender(QObject *sender);
virtual void handleAxisTitleFixedChangedBySender(QObject *sender);
virtual void handleSeriesVisibilityChangedBySender(QObject *sender);
- virtual void handlePendingClick() = 0;
+ virtual void handlePendingClick();
+ virtual void handlePendingGraphPositionQuery();
virtual void adjustAxisRanges() = 0;
void markSeriesItemLabelsDirty();
@@ -384,6 +388,7 @@ signals:
void reflectionChanged(bool enabled);
void reflectivityChanged(qreal reflectivity);
void localeChanged(const QLocale &locale);
+ void queriedGraphPositionChanged(const QVector3D &data);
protected:
virtual QAbstract3DAxis *createDefaultAxis(QAbstract3DAxis::AxisOrientation orientation);
diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp
index d0f3c04b..a5e1bc9b 100644
--- a/src/datavisualization/engine/abstract3drenderer.cpp
+++ b/src/datavisualization/engine/abstract3drenderer.cpp
@@ -54,8 +54,11 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller)
m_devicePixelRatio(1.0f),
m_selectionLabelDirty(true),
m_clickPending(false),
+ m_graphPositionQueryPending(false),
m_clickedSeries(0),
m_clickedType(QAbstract3DGraph::ElementNone),
+ m_selectedLabelIndex(-1),
+ m_selectedCustomItemIndex(-1),
m_selectionLabelItem(0),
m_visibleSeriesCount(0),
m_customItemShader(0),
@@ -64,6 +67,9 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller)
m_volumeTextureSliceShader(0),
m_volumeSliceFrameShader(0),
m_labelShader(0),
+ m_cursorPositionShader(0),
+ m_cursorPositionFrameBuffer(0),
+ m_cursorPositionTexture(0),
m_useOrthoProjection(false),
m_xFlipped(false),
m_yFlipped(false),
@@ -72,6 +78,7 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller)
m_backgroundObj(0),
m_gridLineObj(0),
m_labelObj(0),
+ m_positionMapperObj(0),
m_graphAspectRatio(2.0f),
m_graphHorizontalAspectRatio(0.0f),
m_polarGraph(false),
@@ -110,6 +117,7 @@ Abstract3DRenderer::~Abstract3DRenderer()
delete m_volumeSliceFrameShader;
delete m_volumeTextureSliceShader;
delete m_labelShader;
+ delete m_cursorPositionShader;
foreach (SeriesRenderCache *cache, m_renderCacheList) {
cache->cleanup(m_textureHelper);
@@ -127,9 +135,15 @@ Abstract3DRenderer::~Abstract3DRenderer()
ObjectHelper::releaseObjectHelper(this, m_backgroundObj);
ObjectHelper::releaseObjectHelper(this, m_gridLineObj);
ObjectHelper::releaseObjectHelper(this, m_labelObj);
+ ObjectHelper::releaseObjectHelper(this, m_positionMapperObj);
if (m_textureHelper) {
m_textureHelper->deleteTexture(&m_depthTexture);
+ m_textureHelper->deleteTexture(&m_cursorPositionTexture);
+
+ if (QOpenGLContext::currentContext())
+ m_textureHelper->glDeleteFramebuffers(1, &m_cursorPositionFrameBuffer);
+
delete m_textureHelper;
}
}
@@ -157,6 +171,12 @@ void Abstract3DRenderer::initializeOpenGL()
initLabelShaders(QStringLiteral(":/shaders/vertexLabel"),
QStringLiteral(":/shaders/fragmentLabel"));
+
+ initCursorPositionShaders(QStringLiteral(":/shaders/vertexPosition"),
+ QStringLiteral(":/shaders/fragmentPositionMap"));
+
+ loadLabelMesh();
+ loadPositionMapperMesh();
}
void Abstract3DRenderer::render(const GLuint defaultFboHandle)
@@ -191,11 +211,6 @@ void Abstract3DRenderer::updateSelectionState(SelectionState state)
m_selectionState = state;
}
-void Abstract3DRenderer::updateInputPosition(const QPoint &position)
-{
- m_inputPosition = position;
-}
-
void Abstract3DRenderer::initGradientShaders(const QString &vertexShader,
const QString &fragmentShader)
{
@@ -244,6 +259,27 @@ void Abstract3DRenderer::initLabelShaders(const QString &vertexShader, const QSt
m_labelShader->initialize();
}
+void Abstract3DRenderer::initCursorPositionShaders(const QString &vertexShader,
+ const QString &fragmentShader)
+{
+ // Init the shader
+ delete m_cursorPositionShader;
+ m_cursorPositionShader = new ShaderHelper(this, vertexShader, fragmentShader);
+ m_cursorPositionShader->initialize();
+}
+
+void Abstract3DRenderer::initCursorPositionBuffer()
+{
+ m_textureHelper->deleteTexture(&m_cursorPositionTexture);
+
+ if (m_primarySubViewport.size().isEmpty())
+ return;
+
+ m_cursorPositionTexture =
+ m_textureHelper->createCursorPositionTexture(m_primarySubViewport.size(),
+ m_cursorPositionFrameBuffer);
+}
+
void Abstract3DRenderer::updateTheme(Q3DTheme *theme)
{
// Synchronize the controller theme with renderer
@@ -270,8 +306,12 @@ void Abstract3DRenderer::updateScene(Q3DScene *scene)
}
QPoint logicalPixelPosition = scene->selectionQueryPosition();
- updateInputPosition(QPoint(logicalPixelPosition.x() * m_devicePixelRatio,
- logicalPixelPosition.y() * m_devicePixelRatio));
+ m_inputPosition = QPoint(logicalPixelPosition.x() * m_devicePixelRatio,
+ logicalPixelPosition.y() * m_devicePixelRatio);
+
+ QPoint logicalGraphPosition = scene->graphPositionQuery();
+ m_graphPositionQuery = QPoint(logicalGraphPosition.x() * m_devicePixelRatio,
+ logicalGraphPosition.y() * m_devicePixelRatio);
// Synchronize the renderer scene to controller scene
scene->d_ptr->sync(*m_cachedScene->d_ptr);
@@ -296,6 +336,11 @@ void Abstract3DRenderer::updateScene(Q3DScene *scene)
updateSelectionState(SelectOnScene);
}
}
+
+ if (Q3DScene::invalidSelectionPoint() != logicalGraphPosition) {
+ m_graphPositionQueryPending = true;
+ scene->setGraphPositionQuery(Q3DScene::invalidSelectionPoint());
+ }
}
void Abstract3DRenderer::updateTextures()
@@ -347,7 +392,7 @@ void Abstract3DRenderer::reInitShaders()
QStringLiteral(":/shaders/fragmentTexture3D"),
QStringLiteral(":/shaders/fragmentTexture3DLowDef"),
QStringLiteral(":/shaders/fragmentTexture3DSlice"),
- QStringLiteral(":/shaders/colorAndPosition"),
+ QStringLiteral(":/shaders/vertexPosition"),
QStringLiteral(":/shaders/fragment3DSliceFrames"));
#else
if (m_cachedOptimizationHint.testFlag(QAbstract3DGraph::OptimizationStatic)
@@ -434,6 +479,8 @@ void Abstract3DRenderer::handleResize()
// Re-init depth buffer
updateDepthBuffer();
#endif
+
+ initCursorPositionBuffer();
}
void Abstract3DRenderer::calculateZoomLevel()
@@ -929,6 +976,12 @@ void Abstract3DRenderer::loadLabelMesh()
QStringLiteral(":/defaultMeshes/plane"));
}
+void Abstract3DRenderer::loadPositionMapperMesh()
+{
+ ObjectHelper::resetObjectHelper(this, m_positionMapperObj,
+ QStringLiteral(":/defaultMeshes/barFull"));
+}
+
void Abstract3DRenderer::generateBaseColorTexture(const QColor &color, GLuint *texture)
{
m_textureHelper->deleteTexture(texture);
@@ -1305,7 +1358,7 @@ void Abstract3DRenderer::drawCustomItems(RenderingState state,
// Check that the render item is visible, and skip drawing if not
// Also check if reflected item is on the "wrong" side, and skip drawing if it is
if (!item->isVisible() || ((m_reflectionEnabled && reflection < 0.0f)
- && (m_yFlipped == item->translation().y() >= 0.0))) {
+ && (m_yFlipped == (item->translation().y() >= 0.0)))) {
continue;
}
if (loopCount == 0) {
@@ -1627,6 +1680,59 @@ void Abstract3DRenderer::drawVolumeSliceFrame(const CustomRenderItem *item, Qt::
}
+void Abstract3DRenderer::queriedGraphPosition(const QMatrix4x4 &projectionViewMatrix,
+ const QVector3D &scaling,
+ GLuint defaultFboHandle)
+{
+ m_cursorPositionShader->bind();
+
+ // Set up mapper framebuffer
+ glBindFramebuffer(GL_FRAMEBUFFER, m_cursorPositionFrameBuffer);
+ glViewport(0, 0,
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
+ glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glDisable(GL_DITHER); // Dither may affect colors if enabled
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_FRONT);
+
+ // Draw a cube scaled to the graph dimensions
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+
+ modelMatrix.scale(scaling);
+
+ MVPMatrix = projectionViewMatrix * modelMatrix;
+ m_cursorPositionShader->setUniformValue(m_cursorPositionShader->MVP(), MVPMatrix);
+ m_drawer->drawObject(m_cursorPositionShader, m_positionMapperObj);
+
+ QVector4D dataColor = Utils::getSelection(m_graphPositionQuery,
+ m_primarySubViewport.height());
+ if (dataColor.w() > 0.0f) {
+ // If position is outside the graph, set the position well outside the graph boundaries
+ dataColor = QVector4D(-10000.0f, -10000.0f, -10000.0f, 0.0f);
+ } else {
+ // Normalize to range [0.0, 1.0]
+ dataColor /= 255.0f;
+ }
+
+ // Restore state
+ glEnable(GL_DITHER);
+ glCullFace(GL_BACK);
+ glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle);
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
+
+ QVector3D normalizedValues = dataColor.toVector3D() * 2.0f;
+ normalizedValues -= oneVector;
+ m_queriedGraphPosition = QVector3D(normalizedValues.x(),
+ normalizedValues.y(),
+ normalizedValues.z());
+}
+
void Abstract3DRenderer::calculatePolarXZ(const QVector3D &dataPos, float &x, float &z) const
{
// x is angular, z is radial
diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h
index a46e6176..6d134ee3 100644
--- a/src/datavisualization/engine/abstract3drenderer_p.h
+++ b/src/datavisualization/engine/abstract3drenderer_p.h
@@ -80,7 +80,6 @@ public:
virtual void updateTextures();
virtual void initSelectionBuffer() = 0;
virtual void updateSelectionState(SelectionState state);
- virtual void updateInputPosition(const QPoint &position);
#if !defined(QT_OPENGL_ES_2)
virtual void updateDepthBuffer() = 0;
@@ -99,6 +98,9 @@ public:
const QString &sliceFrameVertexShader,
const QString &sliceFrameShader);
virtual void initLabelShaders(const QString &vertexShader, const QString &fragmentShader);
+ virtual void initCursorPositionShaders(const QString &vertexShader,
+ const QString &fragmentShader);
+ virtual void initCursorPositionBuffer();
virtual void updateAxisType(QAbstract3DAxis::AxisOrientation orientation,
QAbstract3DAxis::AxisType type);
@@ -120,7 +122,7 @@ public:
virtual void updateAxisLabelAutoRotation(QAbstract3DAxis::AxisOrientation orientation,
float angle);
virtual void updateAxisTitleVisibility(QAbstract3DAxis::AxisOrientation orientation,
- bool visible);
+ bool visible);
virtual void updateAxisTitleFixed(QAbstract3DAxis::AxisOrientation orientation,
bool fixed);
virtual void modifiedSeriesList(const QVector<QAbstract3DSeries *> &seriesList);
@@ -145,6 +147,9 @@ public:
inline void clearClickPending() { m_clickPending = false; }
inline QAbstract3DSeries *clickedSeries() const { return m_clickedSeries; }
inline QAbstract3DGraph::ElementType clickedType() { return m_clickedType; }
+ inline bool isGraphPositionQueryPending() { return m_graphPositionQueryPending; }
+ inline void clearGraphPositionQueryPending() { m_graphPositionQueryPending = false; }
+ inline QVector3D queriedGraphPosition() const { return m_queriedGraphPosition; }
LabelItem &selectionLabelItem();
void setSelectionLabel(const QString &label);
@@ -199,6 +204,7 @@ protected:
void loadGridLineMesh();
void loadLabelMesh();
+ void loadPositionMapperMesh();
void drawRadialGrid(ShaderHelper *shader, float yFloorLinePos,
const QMatrix4x4 &projectionViewMatrix, const QMatrix4x4 &depthMatrix);
@@ -213,6 +219,8 @@ protected:
virtual void getVisibleItemBounds(QVector3D &minBounds, QVector3D &maxBounds) = 0;
void drawVolumeSliceFrame(const CustomRenderItem *item, Qt::Axis axis,
const QMatrix4x4 &projectionViewMatrix);
+ void queriedGraphPosition(const QMatrix4x4 &projectionViewMatrix, const QVector3D &scaling,
+ GLuint defaultFboHandle);
bool m_hasNegativeValues;
Q3DTheme *m_cachedTheme;
@@ -241,10 +249,13 @@ protected:
float m_devicePixelRatio;
bool m_selectionLabelDirty;
bool m_clickPending;
+ bool m_graphPositionQueryPending;
QAbstract3DSeries *m_clickedSeries;
QAbstract3DGraph::ElementType m_clickedType;
int m_selectedLabelIndex;
int m_selectedCustomItemIndex;
+ QVector3D m_queriedGraphPosition;
+ QPoint m_graphPositionQuery;
QString m_selectionLabel;
LabelItem *m_selectionLabelItem;
@@ -256,6 +267,9 @@ protected:
ShaderHelper *m_volumeTextureSliceShader;
ShaderHelper *m_volumeSliceFrameShader;
ShaderHelper *m_labelShader;
+ ShaderHelper *m_cursorPositionShader;
+ GLuint m_cursorPositionFrameBuffer;
+ GLuint m_cursorPositionTexture;
bool m_useOrthoProjection;
bool m_xFlipped;
@@ -266,6 +280,7 @@ protected:
ObjectHelper *m_backgroundObj; // Shared reference
ObjectHelper *m_gridLineObj; // Shared reference
ObjectHelper *m_labelObj; // Shared reference
+ ObjectHelper *m_positionMapperObj; // Shared reference
float m_graphAspectRatio;
float m_graphHorizontalAspectRatio;
diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp
index 9f3c2e2a..2d394d57 100644
--- a/src/datavisualization/engine/bars3drenderer.cpp
+++ b/src/datavisualization/engine/bars3drenderer.cpp
@@ -122,9 +122,6 @@ void Bars3DRenderer::initializeOpenGL()
// Load grid line mesh
loadGridLineMesh();
- // Load label mesh
- loadLabelMesh();
-
// Load background mesh (we need to be initialized first)
loadBackgroundMesh();
}
@@ -1161,6 +1158,16 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
}
#endif
+ // Do position mapping when necessary
+ if (m_graphPositionQueryPending) {
+ QVector3D graphDimensions(m_xScaleFactor, 0.0f, m_zScaleFactor);
+ queriedGraphPosition(projectionViewMatrix, graphDimensions, defaultFboHandle);
+
+ // Y is always at floor level
+ m_queriedGraphPosition.setY(0.0f);
+ emit needRender();
+ }
+
// Skip selection mode drawing if we're slicing or have no selection mode
if (!m_cachedIsSlicingActivated && m_cachedSelectionMode > QAbstract3DGraph::SelectionNone
&& m_selectionState == SelectOnScene
@@ -2732,8 +2739,11 @@ void Bars3DRenderer::updateSlicingActive(bool isSlicing)
m_cachedIsSlicingActivated = isSlicing;
- if (!m_cachedIsSlicingActivated)
- initSelectionBuffer(); // We need to re-init selection buffer in case there has been a resize
+ if (!m_cachedIsSlicingActivated) {
+ // We need to re-init selection buffer in case there has been a resize
+ initSelectionBuffer();
+ initCursorPositionBuffer();
+ }
#if !defined(QT_OPENGL_ES_2)
updateDepthBuffer(); // Re-init depth buffer as well
diff --git a/src/datavisualization/engine/engine.qrc b/src/datavisualization/engine/engine.qrc
index af759ba3..8c234a3b 100644
--- a/src/datavisualization/engine/engine.qrc
+++ b/src/datavisualization/engine/engine.qrc
@@ -67,6 +67,7 @@
<file alias="fragmentTexture3DLowDef">shaders/texture3dlowdef.frag</file>
<file alias="vertexPointES2_UV">shaders/point_ES2_UV.vert</file>
<file alias="fragment3DSliceFrames">shaders/3dsliceframes.frag</file>
- <file alias="colorAndPosition">shaders/colorandposition.vert</file>
+ <file alias="vertexPosition">shaders/position.vert</file>
+ <file alias="fragmentPositionMap">shaders/positionmap.frag</file>
</qresource>
</RCC>
diff --git a/src/datavisualization/engine/q3dscene.cpp b/src/datavisualization/engine/q3dscene.cpp
index 08721b97..87826a8b 100644
--- a/src/datavisualization/engine/q3dscene.cpp
+++ b/src/datavisualization/engine/q3dscene.cpp
@@ -96,6 +96,26 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
*/
/*!
+ * \qmlproperty point Scene3D::graphPositionQuery
+ *
+ * This property contains the coordinates for the user input that should be processed
+ * by the scene as a graph position query. If this is set to value other than
+ * invalidSelectionPoint, the graph tries to match a graph position to the given \a point
+ * within the primary viewport.
+ * After the rendering pass this property is returned to its default state of
+ * invalidSelectionPoint. The queried graph position can be read from
+ * AbstractGraph3D::queriedGraphPosition property after the next render pass.
+ *
+ * There isn't a single correct 3D coordinate to match to each specific screen position, so to be
+ * consistent, the queries are always done against the inner sides of an invisible box surrounding
+ * the graph.
+ *
+ * \note Bar graphs allow graph position queries only at the graph floor level.
+ *
+ * \sa AbstractGraph3D::queriedGraphPosition
+ */
+
+/*!
* \qmlproperty bool Scene3D::slicingActive
*
* This property contains whether 2D slicing view is currently active or not. If setting it, you
@@ -258,7 +278,7 @@ void Q3DScene::setSecondarySubViewport(const QRect &secondarySubViewport)
* \property Q3DScene::selectionQueryPosition
*
* This property contains the coordinates for the user input that should be processed
- * by the scene as selection. If this is set to value other than invalidSelectionPoint() the
+ * by the scene as a selection. If this is set to value other than invalidSelectionPoint(), the
* graph tries to select a data item, axis label, or a custom item at the given \a point within
* the primary viewport.
* After the rendering pass the property is returned to its default state of
@@ -293,6 +313,42 @@ QPoint Q3DScene::invalidSelectionPoint()
}
/*!
+ * \property Q3DScene::graphPositionQuery
+ *
+ * This property contains the coordinates for the user input that should be processed
+ * by the scene as a graph position query. If this is set to value other than
+ * invalidSelectionPoint(), the graph tries to match a graph position to the given \a point
+ * within the primary viewport.
+ * After the rendering pass this property is returned to its default state of
+ * invalidSelectionPoint(). The queried graph position can be read from
+ * QAbstract3DGraph::queriedGraphPosition property after the next render pass.
+ *
+ * There isn't a single correct 3D coordinate to match to each specific screen position, so to be
+ * consistent, the queries are always done against the inner sides of an invisible box surrounding
+ * the graph.
+ *
+ * \note Bar graphs allow graph position queries only at the graph floor level.
+ *
+ * \sa QAbstract3DGraph::queriedGraphPosition
+ */
+void Q3DScene::setGraphPositionQuery(const QPoint &point)
+{
+ if (point != d_ptr->m_graphPositionQueryPosition) {
+ d_ptr->m_graphPositionQueryPosition = point;
+ d_ptr->m_changeTracker.graphPositionQueryPositionChanged = true;
+ d_ptr->m_sceneDirty = true;
+
+ emit graphPositionQueryChanged(point);
+ emit d_ptr->needRender();
+ }
+}
+
+QPoint Q3DScene::graphPositionQuery() const
+{
+ return d_ptr->m_graphPositionQueryPosition;
+}
+
+/*!
* \property Q3DScene::slicingActive
*
* This property contains whether 2D slicing view is currently active or not. If setting it, you
@@ -453,7 +509,9 @@ Q3DScenePrivate::Q3DScenePrivate(Q3DScene *q) :
m_light(),
m_isUnderSideCameraEnabled(false),
m_isSlicingActive(false),
- m_selectionQueryPosition(Q3DScene::invalidSelectionPoint())
+ m_selectionQueryPosition(Q3DScene::invalidSelectionPoint()),
+ m_graphPositionQueryPosition(Q3DScene::invalidSelectionPoint()),
+ m_sceneDirty(true)
{
}
diff --git a/src/datavisualization/engine/q3dscene.h b/src/datavisualization/engine/q3dscene.h
index 1699b125..a46b4d7b 100644
--- a/src/datavisualization/engine/q3dscene.h
+++ b/src/datavisualization/engine/q3dscene.h
@@ -41,6 +41,7 @@ class QT_DATAVISUALIZATION_EXPORT Q3DScene : public QObject
Q_PROPERTY(Q3DCamera* activeCamera READ activeCamera WRITE setActiveCamera NOTIFY activeCameraChanged)
Q_PROPERTY(Q3DLight* activeLight READ activeLight WRITE setActiveLight NOTIFY activeLightChanged)
Q_PROPERTY(float devicePixelRatio READ devicePixelRatio WRITE setDevicePixelRatio NOTIFY devicePixelRatioChanged)
+ Q_PROPERTY(QPoint graphPositionQuery READ graphPositionQuery WRITE setGraphPositionQuery NOTIFY graphPositionQueryChanged REVISION 1)
public:
Q3DScene(QObject *parent = 0);
@@ -60,6 +61,9 @@ public:
QPoint selectionQueryPosition() const;
static QPoint invalidSelectionPoint();
+ void setGraphPositionQuery(const QPoint &point);
+ QPoint graphPositionQuery() const;
+
void setSlicingActive(bool isSlicing);
bool isSlicingActive() const;
@@ -85,6 +89,7 @@ signals:
void activeLightChanged(Q3DLight *light);
void devicePixelRatioChanged(float pixelRatio);
void selectionQueryPositionChanged(const QPoint &position);
+ Q_REVISION(1) void graphPositionQueryChanged(const QPoint &position);
private:
QScopedPointer<Q3DScenePrivate> d_ptr;
diff --git a/src/datavisualization/engine/q3dscene_p.h b/src/datavisualization/engine/q3dscene_p.h
index c86a0ec1..b7321c25 100644
--- a/src/datavisualization/engine/q3dscene_p.h
+++ b/src/datavisualization/engine/q3dscene_p.h
@@ -47,6 +47,7 @@ struct Q3DSceneChangeBitField {
bool slicingActivatedChanged : 1;
bool devicePixelRatioChanged : 1;
bool selectionQueryPositionChanged : 1;
+ bool graphPositionQueryPositionChanged : 1;
bool windowSizeChanged : 1;
Q3DSceneChangeBitField()
@@ -59,6 +60,7 @@ struct Q3DSceneChangeBitField {
slicingActivatedChanged(true),
devicePixelRatioChanged(true),
selectionQueryPositionChanged(false),
+ graphPositionQueryPositionChanged(false),
windowSizeChanged(true)
{
}
@@ -108,6 +110,7 @@ public:
bool m_isUnderSideCameraEnabled;
bool m_isSlicingActive;
QPoint m_selectionQueryPosition;
+ QPoint m_graphPositionQueryPosition;
QSize m_windowSize;
QRect m_glViewport;
QRect m_glPrimarySubViewport;
diff --git a/src/datavisualization/engine/qabstract3dgraph.cpp b/src/datavisualization/engine/qabstract3dgraph.cpp
index 8ced09fe..0249478f 100644
--- a/src/datavisualization/engine/qabstract3dgraph.cpp
+++ b/src/datavisualization/engine/qabstract3dgraph.cpp
@@ -786,6 +786,31 @@ QLocale QAbstract3DGraph::locale() const
}
/*!
+ * \property QAbstract3DGraph::queriedGraphPosition
+ * \since QtDataVisualization 1.2
+ *
+ * This read-only property contains the latest graph position values along each axis queried using
+ * Q3DScene::graphPositionQuery. The values are normalized to range \c{[-1, 1]}.
+ * If the queried position was outside the graph bounds, the values
+ * will not reflect the real position, but will instead be some undefined position outside
+ * the range \c{[-1, 1]}. The value will be undefined before any queries are made.
+ *
+ * There isn't a single correct 3D coordinate to match to each specific screen position, so to be
+ * consistent, the queries are always done against the inner sides of an invisible box surrounding
+ * the graph.
+ *
+ * \note Bar graphs only allow querying graph position at the graph floor level,
+ * so the Y-value is always zero for bar graphs and the valid queries can be only made at
+ * screen positions that contain the floor of the graph.
+ *
+ * \sa Q3DScene::graphPositionQuery
+ */
+QVector3D QAbstract3DGraph::queriedGraphPosition() const
+{
+ return d_ptr->m_visualController->queriedGraphPosition();
+}
+
+/*!
* \internal
*/
bool QAbstract3DGraph::event(QEvent *event)
@@ -948,6 +973,8 @@ void QAbstract3DGraphPrivate::setVisualController(Abstract3DController *controll
&QAbstract3DGraph::reflectivityChanged);
QObject::connect(m_visualController, &Abstract3DController::localeChanged, q_ptr,
&QAbstract3DGraph::localeChanged);
+ QObject::connect(m_visualController, &Abstract3DController::queriedGraphPositionChanged, q_ptr,
+ &QAbstract3DGraph::queriedGraphPositionChanged);
}
void QAbstract3DGraphPrivate::handleDevicePixelRatioChange()
diff --git a/src/datavisualization/engine/qabstract3dgraph.h b/src/datavisualization/engine/qabstract3dgraph.h
index 2d76f780..4a6de4f2 100644
--- a/src/datavisualization/engine/qabstract3dgraph.h
+++ b/src/datavisualization/engine/qabstract3dgraph.h
@@ -57,6 +57,7 @@ class QT_DATAVISUALIZATION_EXPORT QAbstract3DGraph : public QWindow, protected Q
Q_PROPERTY(bool reflection READ isReflection WRITE setReflection NOTIFY reflectionChanged)
Q_PROPERTY(qreal reflectivity READ reflectivity WRITE setReflectivity NOTIFY reflectivityChanged)
Q_PROPERTY(QLocale locale READ locale WRITE setLocale NOTIFY localeChanged)
+ Q_PROPERTY(QVector3D queriedGraphPosition READ queriedGraphPosition NOTIFY queriedGraphPositionChanged)
protected:
explicit QAbstract3DGraph(QAbstract3DGraphPrivate *d, const QSurfaceFormat *format,
@@ -175,6 +176,8 @@ public:
void setLocale(const QLocale &locale);
QLocale locale() const;
+ QVector3D queriedGraphPosition() const;
+
protected:
bool event(QEvent *event);
void resizeEvent(QResizeEvent *event);
@@ -204,6 +207,7 @@ signals:
void reflectionChanged(bool enabled);
void reflectivityChanged(qreal reflectivity);
void localeChanged(const QLocale &locale);
+ void queriedGraphPositionChanged(const QVector3D &data);
private:
Q_DISABLE_COPY(QAbstract3DGraph)
diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp
index e9e395be..d1dca8c6 100644
--- a/src/datavisualization/engine/scatter3drenderer.cpp
+++ b/src/datavisualization/engine/scatter3drenderer.cpp
@@ -117,9 +117,6 @@ void Scatter3DRenderer::initializeOpenGL()
loadGridLineMesh();
#endif
- // Load label mesh
- loadLabelMesh();
-
// Set view port
glViewport(m_primarySubViewport.x(),
m_primarySubViewport.y(),
@@ -651,6 +648,13 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
#endif
ShaderHelper *selectionShader = m_selectionShader;
+ // Do position mapping when necessary
+ if (m_graphPositionQueryPending) {
+ QVector3D graphDimensions(m_scaleX, m_scaleY, m_scaleZ);
+ queriedGraphPosition(projectionViewMatrix, graphDimensions, defaultFboHandle);
+ emit needRender();
+ }
+
// Skip selection mode drawing if we have no selection mode
if (m_cachedSelectionMode > QAbstract3DGraph::SelectionNone
&& SelectOnScene == m_selectionState
diff --git a/src/datavisualization/engine/shaders/colorandposition.vert b/src/datavisualization/engine/shaders/position.vert
index 34849eae..34849eae 100644
--- a/src/datavisualization/engine/shaders/colorandposition.vert
+++ b/src/datavisualization/engine/shaders/position.vert
diff --git a/src/datavisualization/engine/shaders/positionmap.frag b/src/datavisualization/engine/shaders/positionmap.frag
new file mode 100644
index 00000000..9a277ab8
--- /dev/null
+++ b/src/datavisualization/engine/shaders/positionmap.frag
@@ -0,0 +1,11 @@
+varying highp vec3 pos;
+
+void main() {
+ // This shader encodes the axis position into the vertex color, assuming the object
+ // is a cube filling the entire data area of the graph
+ gl_FragColor = vec4((pos.x + 1.0) / 2.0,
+ (pos.y + 1.0) / 2.0,
+ (-pos.z + 1.0) / 2.0,
+ 0.0);
+}
+
diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp
index 9121e37c..3d39a71d 100644
--- a/src/datavisualization/engine/surface3drenderer.cpp
+++ b/src/datavisualization/engine/surface3drenderer.cpp
@@ -131,9 +131,6 @@ void Surface3DRenderer::initializeOpenGL()
loadGridLineMesh();
#endif
- // Load label mesh
- loadLabelMesh();
-
// Resize in case we've missed resize events
// Resize calls initSelectionBuffer and initDepthBuffer, so they don't need to be called here
handleResize();
@@ -1297,6 +1294,13 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
}
#endif
+ // Do position mapping when necessary
+ if (m_graphPositionQueryPending) {
+ QVector3D graphDimensions(m_scaleX, m_scaleY, m_scaleZ);
+ queriedGraphPosition(projectionViewMatrix, graphDimensions, defaultFboHandle);
+ emit needRender();
+ }
+
// Draw selection buffer
if (!m_cachedIsSlicingActivated && (!m_renderCacheList.isEmpty()
|| !m_customRenderCache.isEmpty())
@@ -2830,8 +2834,11 @@ void Surface3DRenderer::updateSlicingActive(bool isSlicing)
m_cachedIsSlicingActivated = isSlicing;
- if (!m_cachedIsSlicingActivated)
- initSelectionBuffer(); // We need to re-init selection buffer in case there has been a resize
+ if (!m_cachedIsSlicingActivated) {
+ // We need to re-init selection buffer in case there has been a resize
+ initSelectionBuffer();
+ initCursorPositionBuffer();
+ }
#if !defined(QT_OPENGL_ES_2)
updateDepthBuffer(); // Re-init depth buffer as well