summaryrefslogtreecommitdiffstats
path: root/src/datavisualization/engine/qabstract3dgraph.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/datavisualization/engine/qabstract3dgraph.cpp')
-rw-r--r--src/datavisualization/engine/qabstract3dgraph.cpp355
1 files changed, 351 insertions, 4 deletions
diff --git a/src/datavisualization/engine/qabstract3dgraph.cpp b/src/datavisualization/engine/qabstract3dgraph.cpp
index bde5b585..dabec744 100644
--- a/src/datavisualization/engine/qabstract3dgraph.cpp
+++ b/src/datavisualization/engine/qabstract3dgraph.cpp
@@ -27,6 +27,8 @@
#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLPaintDevice>
#include <QtGui/QPainter>
+#include <QtGui/QOpenGLFramebufferObject>
+#include <QtGui/QOffscreenSurface>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -34,7 +36,7 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
* \class QAbstract3DGraph
* \inmodule QtDataVisualization
* \brief The QAbstract3DGraph class provides a window and render loop for graphs.
- * \since Qt Data Visualization 1.0
+ * \since QtDataVisualization 1.0
*
* This class subclasses a QWindow and provides render loop for graphs inheriting it.
*
@@ -118,6 +120,38 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
*/
/*!
+ \enum QAbstract3DGraph::ElementType
+ \since QtDataVisualization 1.1
+
+ Type of an element in the graph.
+
+ \value ElementNone
+ No defined element.
+ \value ElementSeries
+ A series (i.e. an item in a series).
+ \value ElementAxisXLabel
+ X axis label.
+ \value ElementAxisYLabel
+ Y axis label.
+ \value ElementAxisZLabel
+ Z axis label.
+ \value ElementCustomItem
+ Custom item.
+*/
+
+/*!
+ \enum QAbstract3DGraph::OptimizationHint
+ \since Qt Data Visualization 1.1
+
+ The optimization hint for rendering.
+
+ \value OptimizationDefault
+ Provides the full feature set at a reasonable performance.
+ \value OptimizationStatic
+ Beta level feature. Optimizes the rendering of static data sets at the expense of some features.
+*/
+
+/*!
* \internal
*/
QAbstract3DGraph::QAbstract3DGraph(QAbstract3DGraphPrivate *d, const QSurfaceFormat *format,
@@ -126,6 +160,7 @@ QAbstract3DGraph::QAbstract3DGraph(QAbstract3DGraphPrivate *d, const QSurfaceFor
d_ptr(d)
{
qRegisterMetaType<QAbstract3DGraph::ShadowQuality>("QAbstract3DGraph::ShadowQuality");
+ qRegisterMetaType<QAbstract3DGraph::ElementType>("QAbstract3DGraph::ElementType");
// Default to frameless window, as typically graphs are not toplevel
setFlags(flags() | Qt::FramelessWindowHint);
@@ -164,7 +199,8 @@ QAbstract3DGraph::QAbstract3DGraph(QAbstract3DGraphPrivate *d, const QSurfaceFor
#if !defined(QT_OPENGL_ES_2)
// If we have real OpenGL, GLSL version must be 1.2 or over. Quit if not.
- QStringList splitversionstr = QString::fromLatin1((const char *)shaderVersion).split(QChar::fromLatin1(' '));
+ QStringList splitversionstr =
+ QString::fromLatin1((const char *)shaderVersion).split(QChar::fromLatin1(' '));
if (splitversionstr[0].toFloat() < 1.2)
qFatal("GLSL version must be 1.20 or higher. Try installing latest display drivers.");
#else
@@ -342,7 +378,8 @@ bool QAbstract3DGraph::shadowsSupported() const
/*!
* \property QAbstract3DGraph::scene
*
- * This property contains the read only Q3DScene that can be used to access, for example, a camera object.
+ * This property contains the read only Q3DScene that can be used to access, for example, a camera
+ * object.
*/
Q3DScene *QAbstract3DGraph::scene() const
{
@@ -358,6 +395,257 @@ void QAbstract3DGraph::clearSelection()
}
/*!
+ * Adds a QCustom3DItem \a item to the graph. Graph takes ownership of the added item.
+ *
+ * \return index to the added item if add was successful, -1 if trying to add a null item, and
+ * index of the item if trying to add an already added item.
+ *
+ * \sa removeCustomItems(), removeCustomItem(), removeCustomItemAt()
+ *
+ * \since QtDataVisualization 1.1
+ */
+int QAbstract3DGraph::addCustomItem(QCustom3DItem *item)
+{
+ return d_ptr->m_visualController->addCustomItem(item);
+}
+
+/*!
+ * Removes all custom items. Deletes the resources allocated to them.
+ *
+ * \since QtDataVisualization 1.1
+ */
+void QAbstract3DGraph::removeCustomItems()
+{
+ d_ptr->m_visualController->deleteCustomItems();
+}
+
+/*!
+ * Removes the custom \a {item}. Deletes the resources allocated to it.
+ *
+ * \since QtDataVisualization 1.1
+ */
+void QAbstract3DGraph::removeCustomItem(QCustom3DItem *item)
+{
+ d_ptr->m_visualController->deleteCustomItem(item);
+}
+
+/*!
+ * Removes all custom items at \a {position}. Deletes the resources allocated to them.
+ *
+ * \since QtDataVisualization 1.1
+ */
+void QAbstract3DGraph::removeCustomItemAt(const QVector3D &position)
+{
+ d_ptr->m_visualController->deleteCustomItem(position);
+}
+
+/*!
+ * Gets ownership of given \a item back and removes the \a item from the graph.
+ *
+ * \since QtDataVisualization 1.1
+ *
+ * \note If the same item is added back to the graph, the texture or the texture file needs to be
+ * re-set.
+ *
+ * \sa QCustom3DItem::setTextureImage(), QCustom3DItem::setTextureFile()
+ */
+void QAbstract3DGraph::releaseCustomItem(QCustom3DItem *item)
+{
+ return d_ptr->m_visualController->releaseCustomItem(item);
+}
+
+/*!
+ * Can be used to query the index of the selected label after receiving \c selectedElementChanged
+ * signal with any label type. Selection is valid until the next \c selectedElementChanged signal.
+ *
+ * \return index of the selected label, or -1.
+ *
+ * \since QtDataVisualization 1.1
+ *
+ * \sa selectedElement
+ */
+int QAbstract3DGraph::selectedLabelIndex() const
+{
+ return d_ptr->m_visualController->selectedLabelIndex();
+}
+
+/*!
+ * Can be used to get the selected axis after receiving \c selectedElementChanged signal with any label
+ * type. Selection is valid until the next \c selectedElementChanged signal.
+ *
+ * \return pointer to the selected axis, or null.
+ *
+ * \since QtDataVisualization 1.1
+ *
+ * \sa selectedElement
+ */
+QAbstract3DAxis *QAbstract3DGraph::selectedAxis() const
+{
+ return d_ptr->m_visualController->selectedAxis();
+}
+
+/*!
+ * Can be used to query the index of the selected custom item after receiving \c selectedElementChanged
+ * signal with QAbstract3DGraph::ElementCustomItem type. Selection is valid until the next
+ * \c selectedElementChanged signal.
+ *
+ * \return index of the selected custom item, or -1.
+ *
+ * \since QtDataVisualization 1.1
+ *
+ * \sa selectedElement
+ */
+int QAbstract3DGraph::selectedCustomItemIndex() const
+{
+ return d_ptr->m_visualController->selectedCustomItemIndex();
+}
+
+/*!
+ * Can be used to get the selected custom item after receiving \c selectedElementChanged signal with
+ * QAbstract3DGraph::ElementCustomItem type. Ownership of the item remains with the graph.
+ * Selection is valid until the next \c selectedElementChanged signal.
+ *
+ * \return pointer to the selected custom item, or null.
+ *
+ * \since QtDataVisualization 1.1
+ *
+ * \sa selectedElement
+ */
+QCustom3DItem *QAbstract3DGraph::selectedCustomItem() const
+{
+ return d_ptr->m_visualController->selectedCustomItem();
+}
+
+/*!
+ * \property QAbstract3DGraph::selectedElement
+ *
+ * Can be used to query the selected element type.
+ * Type is valid until the next \c selectedElementChanged signal.
+ *
+ * \c selectedElementChanged signal is emitted when a selection is made in the graph.
+ *
+ * Signal can be used for example for implementing custom input handlers, as demonstrated in this
+ * \l {Axis Range Dragging With Labels Example}{example}.
+ *
+ * \sa selectedLabelIndex(), selectedAxis(), selectedCustomItemIndex(), selectedCustomItem(),
+ * Q3DBars::selectedSeries(), Q3DScatter::selectedSeries(), Q3DSurface::selectedSeries(),
+ * Q3DScene::setSelectionQueryPosition()
+ *
+ * \since QtDataVisualization 1.1
+ */
+QAbstract3DGraph::ElementType QAbstract3DGraph::selectedElement() const
+{
+ return d_ptr->m_visualController->selectedElement();
+}
+
+/*!
+ * Renders current frame to an image of \a imageSize. Default size is the window size. Image is
+ * rendered with antialiasing level given in \a msaaSamples. Default level is \c{0}.
+ *
+ * \since QtDataVisualization 1.1
+ *
+ * \return rendered image.
+ */
+QImage QAbstract3DGraph::renderToImage(int msaaSamples, const QSize &imageSize)
+{
+ QSize renderSize = imageSize;
+ if (renderSize.isEmpty())
+ renderSize = size();
+ return d_ptr->renderToImage(msaaSamples, renderSize);
+}
+
+/*!
+ * \property QAbstract3DGraph::measureFps
+ * \since QtDataVisualization 1.1
+ *
+ * If \c {true}, the rendering is done continuously instead of on demand, and currentFps property
+ * is updated. Defaults to \c{false}.
+ *
+ * \sa currentFps
+ */
+void QAbstract3DGraph::setMeasureFps(bool enable)
+{
+ d_ptr->m_visualController->setMeasureFps(enable);
+}
+
+bool QAbstract3DGraph::measureFps() const
+{
+ return d_ptr->m_visualController->measureFps();
+}
+
+/*!
+ * \property QAbstract3DGraph::currentFps
+ * \since QtDataVisualization 1.1
+ *
+ * When fps measuring is enabled, the results for the last second are stored in this read-only
+ * property. It takes at least a second before this value updates after measurement is activated.
+ *
+ * \sa measureFps
+ */
+qreal QAbstract3DGraph::currentFps() const
+{
+ return d_ptr->m_visualController->currentFps();
+}
+
+/*!
+ * \property QAbstract3DGraph::orthoProjection
+ * \since QtDataVisualization 1.1
+ *
+ * If \c {true}, orthographic projection will be used for displaying the graph. Defaults to \c{false}.
+ * \note Shadows will be disabled when set to \c{true}.
+ */
+void QAbstract3DGraph::setOrthoProjection(bool enable)
+{
+ d_ptr->m_visualController->setOrthoProjection(enable);
+}
+
+bool QAbstract3DGraph::isOrthoProjection() const
+{
+ return d_ptr->m_visualController->isOrthoProjection();
+}
+
+/*!
+ * \property QAbstract3DGraph::aspectRatio
+ * \since QtDataVisualization 1.1
+ *
+ * Aspect ratio of the graph data. This is the ratio of data scaling between horizontal and
+ * vertical axes. Defaults to \c{2.0}.
+ *
+ * \note Has no effect on Q3DBars.
+ */
+void QAbstract3DGraph::setAspectRatio(qreal ratio)
+{
+ d_ptr->m_visualController->setAspectRatio(float(ratio));
+}
+
+qreal QAbstract3DGraph::aspectRatio() const
+{
+ return d_ptr->m_visualController->aspectRatio();
+}
+
+/*!
+ * \property QAbstract3DGraph::optimizationHints
+ *
+ * Defines if the rendering optimization is default or static. Default mode provides the full feature set at
+ * reasonable performance. Static is a beta level feature and currently supports only a subset of the
+ * features on the Scatter graph. Missing features are object gradient for mesh objects, both gradients
+ * for points, and diffuse and specular color on rotations. At this point static is intended just for
+ * introducing a new feature. It optimizes graph rendering and is ideal for large non-changing data
+ * sets. It is slower with dynamic data changes and item rotations. Selection is not optimized, so using it
+ * with massive data sets is not advisable.
+ * Defaults to \c{OptimizationDefault}.
+ */
+void QAbstract3DGraph::setOptimizationHints(OptimizationHints hints)
+{
+ d_ptr->m_visualController->setOptimizationHints(hints);
+}
+
+QAbstract3DGraph::OptimizationHints QAbstract3DGraph::optimizationHints() const
+{
+ return d_ptr->m_visualController->optimizationHints();
+}
+
+/*!
* \internal
*/
bool QAbstract3DGraph::event(QEvent *event)
@@ -453,12 +741,17 @@ QAbstract3DGraphPrivate::QAbstract3DGraphPrivate(QAbstract3DGraph *q)
q_ptr(q),
m_updatePending(false),
m_visualController(0),
- m_devicePixelRatio(1.f)
+ m_devicePixelRatio(1.f),
+ m_offscreenSurface(0)
{
}
QAbstract3DGraphPrivate::~QAbstract3DGraphPrivate()
{
+ if (m_offscreenSurface) {
+ m_offscreenSurface->destroy();
+ delete m_offscreenSurface;
+ }
if (m_context)
m_context->makeCurrent(q_ptr);
@@ -477,6 +770,11 @@ void QAbstract3DGraphPrivate::setVisualController(Abstract3DController *controll
&QAbstract3DGraph::selectionModeChanged);
QObject::connect(m_visualController, &Abstract3DController::shadowQualityChanged, q_ptr,
&QAbstract3DGraph::shadowQualityChanged);
+ QObject::connect(m_visualController, &Abstract3DController::optimizationHintsChanged, q_ptr,
+ &QAbstract3DGraph::optimizationHintsChanged);
+ QObject::connect(m_visualController, &Abstract3DController::elementSelected, q_ptr,
+ &QAbstract3DGraph::selectedElementChanged);
+
QObject::connect(m_visualController, &Abstract3DController::needRender, this,
&QAbstract3DGraphPrivate::renderLater);
@@ -486,6 +784,17 @@ void QAbstract3DGraphPrivate::setVisualController(Abstract3DController *controll
&QAbstract3DGraphPrivate::handleAxisYChanged);
QObject::connect(m_visualController, &Abstract3DController::axisZChanged, this,
&QAbstract3DGraphPrivate::handleAxisZChanged);
+
+ QObject::connect(m_visualController, &Abstract3DController::measureFpsChanged, q_ptr,
+ &QAbstract3DGraph::measureFpsChanged);
+ QObject::connect(m_visualController, &Abstract3DController::currentFpsChanged, q_ptr,
+ &QAbstract3DGraph::currentFpsChanged);
+
+ QObject::connect(m_visualController, &Abstract3DController::orthoProjectionChanged, q_ptr,
+ &QAbstract3DGraph::orthoProjectionChanged);
+
+ QObject::connect(m_visualController, &Abstract3DController::aspectRatioChanged, q_ptr,
+ &QAbstract3DGraph::aspectRatioChanged);
}
void QAbstract3DGraphPrivate::handleDevicePixelRatioChange()
@@ -526,4 +835,42 @@ void QAbstract3DGraphPrivate::renderNow()
m_context->swapBuffers(q_ptr);
}
+QImage QAbstract3DGraphPrivate::renderToImage(int msaaSamples, const QSize &imageSize)
+{
+ QImage image;
+ QOpenGLFramebufferObject *fbo;
+ QOpenGLFramebufferObjectFormat fboFormat;
+ if (!m_offscreenSurface) {
+ // Create an offscreen surface for rendering to images without rendering on screen
+ m_offscreenSurface = new QOffscreenSurface(q_ptr->screen());
+ m_offscreenSurface->setFormat(q_ptr->requestedFormat());
+ m_offscreenSurface->create();
+ }
+ // Render the wanted frame offscreen
+ m_context->makeCurrent(m_offscreenSurface);
+ fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ fboFormat.setInternalTextureFormat(GL_RGB);
+ fboFormat.setSamples(msaaSamples);
+ fbo = new QOpenGLFramebufferObject(imageSize, fboFormat);
+ if (fbo->isValid()) {
+ QRect originalViewport = m_visualController->m_scene->viewport();
+ m_visualController->m_scene->d_ptr->setWindowSize(imageSize);
+ m_visualController->m_scene->d_ptr->setViewport(QRect(0, 0,
+ imageSize.width(),
+ imageSize.height()));
+ m_visualController->synchDataToRenderer();
+ fbo->bind();
+ m_context->swapBuffers(m_offscreenSurface);
+ m_visualController->requestRender(fbo);
+ image = fbo->toImage();
+ fbo->release();
+ m_visualController->m_scene->d_ptr->setWindowSize(originalViewport.size());
+ m_visualController->m_scene->d_ptr->setViewport(originalViewport);
+ }
+ delete fbo;
+ m_context->makeCurrent(q_ptr);
+
+ return image;
+}
+
QT_END_NAMESPACE_DATAVISUALIZATION