summaryrefslogtreecommitdiffstats
path: root/src/datavisualization/engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/datavisualization/engine')
-rw-r--r--src/datavisualization/engine/abstract3dcontroller.cpp539
-rw-r--r--src/datavisualization/engine/abstract3dcontroller_p.h212
-rw-r--r--src/datavisualization/engine/abstract3drenderer.cpp296
-rw-r--r--src/datavisualization/engine/abstract3drenderer_p.h101
-rw-r--r--src/datavisualization/engine/axisrendercache.cpp12
-rw-r--r--src/datavisualization/engine/axisrendercache_p.h12
-rw-r--r--src/datavisualization/engine/bars3dcontroller.cpp446
-rw-r--r--src/datavisualization/engine/bars3dcontroller_p.h38
-rw-r--r--src/datavisualization/engine/bars3drenderer.cpp1842
-rw-r--r--src/datavisualization/engine/bars3drenderer_p.h51
-rw-r--r--src/datavisualization/engine/drawer.cpp99
-rw-r--r--src/datavisualization/engine/drawer_p.h23
-rw-r--r--src/datavisualization/engine/engine.pri4
-rw-r--r--src/datavisualization/engine/engine.qrc28
-rw-r--r--src/datavisualization/engine/meshes/backgroudNegatives.obj33
-rw-r--r--src/datavisualization/engine/meshes/backgroudSmooth.obj36
-rw-r--r--src/datavisualization/engine/meshes/background.obj (renamed from src/datavisualization/engine/meshes/backgroudFlat.obj)0
-rw-r--r--src/datavisualization/engine/meshes/backgroundNegatives.obj22
-rw-r--r--src/datavisualization/engine/meshes/minimalFlat.obj27
-rw-r--r--src/datavisualization/engine/meshes/minimalSmooth.obj27
-rw-r--r--src/datavisualization/engine/meshes/scatterdot.obj28
-rw-r--r--src/datavisualization/engine/meshes/scatterdotFlat.obj28
-rw-r--r--src/datavisualization/engine/q3dbars.cpp396
-rw-r--r--src/datavisualization/engine/q3dbars.h83
-rw-r--r--src/datavisualization/engine/q3dbars_p.h13
-rw-r--r--src/datavisualization/engine/q3dcamera.cpp550
-rw-r--r--src/datavisualization/engine/q3dcamera.h113
-rw-r--r--src/datavisualization/engine/q3dcamera_p.h16
-rw-r--r--src/datavisualization/engine/q3dlight.cpp33
-rw-r--r--src/datavisualization/engine/q3dlight.h2
-rw-r--r--src/datavisualization/engine/q3dobject.h5
-rw-r--r--src/datavisualization/engine/q3dscatter.cpp349
-rw-r--r--src/datavisualization/engine/q3dscatter.h72
-rw-r--r--src/datavisualization/engine/q3dscatter_p.h13
-rw-r--r--src/datavisualization/engine/q3dscene.cpp389
-rw-r--r--src/datavisualization/engine/q3dscene.h36
-rw-r--r--src/datavisualization/engine/q3dscene_p.h35
-rw-r--r--src/datavisualization/engine/q3dsurface.cpp329
-rw-r--r--src/datavisualization/engine/q3dsurface.h70
-rw-r--r--src/datavisualization/engine/q3dsurface_p.h9
-rw-r--r--src/datavisualization/engine/q3dwindow.cpp149
-rw-r--r--src/datavisualization/engine/q3dwindow.h16
-rw-r--r--src/datavisualization/engine/q3dwindow_p.h20
-rw-r--r--src/datavisualization/engine/scatter3dcontroller.cpp297
-rw-r--r--src/datavisualization/engine/scatter3dcontroller_p.h35
-rw-r--r--src/datavisualization/engine/scatter3drenderer.cpp1032
-rw-r--r--src/datavisualization/engine/scatter3drenderer_p.h47
-rw-r--r--src/datavisualization/engine/selectionpointer.cpp53
-rw-r--r--src/datavisualization/engine/selectionpointer_p.h17
-rw-r--r--src/datavisualization/engine/seriesrendercache.cpp174
-rw-r--r--src/datavisualization/engine/seriesrendercache_p.h83
-rw-r--r--src/datavisualization/engine/shaders/ambient.frag32
-rw-r--r--src/datavisualization/engine/shaders/colorOnY.frag8
-rw-r--r--src/datavisualization/engine/shaders/colorOnY_ES2.frag8
-rw-r--r--src/datavisualization/engine/shaders/default.vert2
-rw-r--r--src/datavisualization/engine/shaders/default_ES2.vert26
-rw-r--r--src/datavisualization/engine/shaders/plainColor.frag (renamed from src/datavisualization/engine/shaders/selection.frag)0
-rw-r--r--src/datavisualization/engine/shaders/plainColor.vert (renamed from src/datavisualization/engine/shaders/selection.vert)0
-rw-r--r--src/datavisualization/engine/shaders/point_ES2.vert (renamed from src/datavisualization/engine/shaders/surfaceGrid.vert)4
-rw-r--r--src/datavisualization/engine/shaders/shadowNoTexColorOnY.frag8
-rw-r--r--src/datavisualization/engine/shaders/surface.frag4
-rw-r--r--src/datavisualization/engine/shaders/surfaceFlat.frag2
-rw-r--r--src/datavisualization/engine/shaders/surfaceGrid.frag6
-rw-r--r--src/datavisualization/engine/shaders/surfaceShadowFlat.frag70
-rw-r--r--src/datavisualization/engine/shaders/surfaceShadowFlat.vert (renamed from src/datavisualization/engine/shaders/surface.vert)14
-rw-r--r--src/datavisualization/engine/shaders/surfaceShadowNoTex.frag68
-rw-r--r--src/datavisualization/engine/shaders/surface_ES2.frag4
-rw-r--r--src/datavisualization/engine/shaders/texture.frag35
-rw-r--r--src/datavisualization/engine/shaders/texture.vert26
-rw-r--r--src/datavisualization/engine/shaders/texture_ES2.frag37
-rw-r--r--src/datavisualization/engine/surface3dcontroller.cpp452
-rw-r--r--src/datavisualization/engine/surface3dcontroller_p.h60
-rw-r--r--src/datavisualization/engine/surface3drenderer.cpp936
-rw-r--r--src/datavisualization/engine/surface3drenderer_p.h56
-rw-r--r--src/datavisualization/engine/theme.cpp250
-rw-r--r--src/datavisualization/engine/theme_p.h82
76 files changed, 5704 insertions, 4826 deletions
diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp
index bfdc375e..9835dbe4 100644
--- a/src/datavisualization/engine/abstract3dcontroller.cpp
+++ b/src/datavisualization/engine/abstract3dcontroller.cpp
@@ -27,21 +27,19 @@
#include "qabstractdataproxy_p.h"
#include "qabstract3dinputhandler_p.h"
#include "qtouch3dinputhandler.h"
+#include "qabstract3dseries_p.h"
+#include "thememanager_p.h"
+#include "q3dscene_p.h"
#include <QThread>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-Abstract3DController::Abstract3DController(QRect boundRect, QObject *parent) :
+Abstract3DController::Abstract3DController(QRect initialViewport, QObject *parent) :
QObject(parent),
- m_boundingRect(boundRect.x(), boundRect.y(), boundRect.width(), boundRect.height()),
- m_theme(),
- m_font(QFont(QStringLiteral("Arial"))),
- m_selectionMode(QDataVis::SelectionModeItem),
+ m_themeManager(new ThemeManager(this)),
+ m_selectionMode(QDataVis::SelectionItem),
m_shadowQuality(QDataVis::ShadowQualityMedium),
- m_labelStyle(QDataVis::LabelStyleTransparent),
- m_isBackgroundEnabled(true),
- m_isGridEnabled(true),
m_scene(new Q3DScene()),
m_activeInputHandler(0),
m_axisX(0),
@@ -49,10 +47,14 @@ Abstract3DController::Abstract3DController(QRect boundRect, QObject *parent) :
m_axisZ(0),
m_renderer(0),
m_isDataDirty(true),
- m_data(0),
+ m_isSeriesVisibilityDirty(true),
+ m_isSeriesVisualsDirty(true),
m_renderPending(false)
{
- m_theme.useTheme(QDataVis::ThemeQt);
+ // Set initial theme
+ setTheme(new Q3DTheme(Q3DTheme::ThemeQt));
+
+ m_scene->d_ptr->setViewport(initialViewport);
// Populate the scene
m_scene->activeLight()->setPosition(defaultLightPos);
@@ -63,8 +65,10 @@ Abstract3DController::Abstract3DController(QRect boundRect, QObject *parent) :
inputHandler->d_ptr->m_isDefaultHandler = true;
setActiveInputHandler(inputHandler);
connect(inputHandler, &QAbstract3DInputHandler::inputStateChanged, this,
- &Abstract3DController::emitNeedRender);
- connect(m_scene, &Q3DScene::needRender, this,
+ &Abstract3DController::handleInputStateChanged);
+ connect(inputHandler, &QAbstract3DInputHandler::positionChanged, this,
+ &Abstract3DController::handleInputPositionChanged);
+ connect(m_scene->d_ptr.data(), &Q3DScenePrivate::needRender, this,
&Abstract3DController::emitNeedRender);
}
@@ -76,46 +80,62 @@ Abstract3DController::~Abstract3DController()
else
delete m_renderer;
delete m_scene;
+ delete m_themeManager;
}
+/**
+ * @brief setRenderer Sets the renderer to be used. isInitialized returns true from this point onwards.
+ * @param renderer Renderer to be used.
+ */
void Abstract3DController::setRenderer(Abstract3DRenderer *renderer)
{
m_renderer = renderer;
}
-void Abstract3DController::synchDataToRenderer()
+void Abstract3DController::addSeries(QAbstract3DSeries *series)
{
- // If we don't have a renderer, don't do anything
- if (!m_renderer)
- return;
-
- if (m_changeTracker.boundingRectChanged || m_changeTracker.sizeChanged) {
- m_renderer->updateBoundingRect(m_boundingRect);
- m_changeTracker.boundingRectChanged = false;
- m_changeTracker.sizeChanged = false;
+ if (series && !m_seriesList.contains(series)) {
+ int oldSize = m_seriesList.size();
+ m_seriesList.append(series);
+ series->d_ptr->setController(this);
+ QObject::connect(series, &QAbstract3DSeries::visibilityChanged,
+ this, &Abstract3DController::handleSeriesVisibilityChanged);
+ if (series->isVisible())
+ handleSeriesVisibilityChangedBySender(series);
+ series->d_ptr->resetToTheme(*m_themeManager->theme(), oldSize, false);
}
+}
- if (m_changeTracker.positionChanged) {
- m_renderer->updatePosition(m_boundingRect);
- m_changeTracker.positionChanged = false;
+void Abstract3DController::removeSeries(QAbstract3DSeries *series)
+{
+ if (series && series->d_ptr->m_controller == this) {
+ m_seriesList.removeAll(series);
+ QObject::disconnect(series, &QAbstract3DSeries::visibilityChanged,
+ this, &Abstract3DController::handleSeriesVisibilityChanged);
+ series->d_ptr->setController(0);
+ m_isDataDirty = true;
+ m_isSeriesVisibilityDirty = true;
+ emitNeedRender();
}
+}
- m_renderer->updateScene(m_scene);
+QList<QAbstract3DSeries *> Abstract3DController::seriesList()
+{
+ return m_seriesList;
+}
- if (m_changeTracker.themeChanged) {
- m_renderer->updateTheme(m_theme);
- m_changeTracker.themeChanged = false;
- }
+/**
+ * @brief synchDataToRenderer Called on the render thread while main GUI thread is blocked before rendering.
+ */
+void Abstract3DController::synchDataToRenderer()
+{
+ // If we don't have a renderer, don't do anything
+ if (!m_renderer)
+ return;
- if (m_changeTracker.fontChanged) {
- m_renderer->updateFont(m_font);
- m_changeTracker.fontChanged = false;
- }
+ m_renderer->updateScene(m_scene);
- if (m_changeTracker.labelStyleChanged) {
- m_renderer->updateLabelStyle(m_labelStyle);
- m_changeTracker.labelStyleChanged = false;
- }
+ m_renderer->updateTheme(m_themeManager->theme());
if (m_changeTracker.shadowQualityChanged) {
m_renderer->updateShadowQuality(m_shadowQuality);
@@ -127,21 +147,6 @@ void Abstract3DController::synchDataToRenderer()
m_changeTracker.selectionModeChanged = false;
}
- if (m_changeTracker.objFileChanged) {
- m_renderer->updateMeshFileName(m_objFile);
- m_changeTracker.objFileChanged = false;
- }
-
- if (m_changeTracker.gridEnabledChanged) {
- m_renderer->updateGridEnabled(m_isGridEnabled);
- m_changeTracker.gridEnabledChanged = false;
- }
-
- if (m_changeTracker.backgroundEnabledChanged) {
- m_renderer->updateBackgroundEnabled(m_isBackgroundEnabled);
- m_changeTracker.backgroundEnabledChanged = false;
- }
-
if (m_changeTracker.axisXTypeChanged) {
m_renderer->updateAxisType(Q3DAbstractAxis::AxisOrientationX, m_axisX->type());
m_changeTracker.axisXTypeChanged = false;
@@ -284,6 +289,19 @@ void Abstract3DController::synchDataToRenderer()
valueAxisZ->labelFormat());
}
}
+
+ if (m_isSeriesVisibilityDirty || m_isSeriesVisualsDirty) {
+ m_renderer->updateSeries(m_seriesList, m_isSeriesVisibilityDirty);
+ m_isSeriesVisibilityDirty = false;
+ m_isSeriesVisualsDirty = false;
+ }
+
+ if (m_isDataDirty) {
+ // Series list supplied above in updateSeries() is used to access the data,
+ // so no data needs to be passed in updateData()
+ m_renderer->updateData();
+ m_isDataDirty = false;
+ }
}
void Abstract3DController::render(const GLuint defaultFboHandle)
@@ -306,156 +324,126 @@ void Abstract3DController::mouseDoubleClickEvent(QMouseEvent *event)
{
if (m_activeInputHandler)
m_activeInputHandler->mouseDoubleClickEvent(event);
-
- emitNeedRender();
}
void Abstract3DController::touchEvent(QTouchEvent *event)
{
if (m_activeInputHandler)
m_activeInputHandler->touchEvent(event);
-
- emitNeedRender();
}
void Abstract3DController::mousePressEvent(QMouseEvent *event, const QPoint &mousePos)
{
if (m_activeInputHandler)
m_activeInputHandler->mousePressEvent(event, mousePos);
-
- emitNeedRender();
}
void Abstract3DController::mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos)
{
if (m_activeInputHandler)
m_activeInputHandler->mouseReleaseEvent(event, mousePos);
-
- emitNeedRender();
}
void Abstract3DController::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos)
{
if (m_activeInputHandler)
m_activeInputHandler->mouseMoveEvent(event, mousePos);
-
- emitNeedRender();
}
void Abstract3DController::wheelEvent(QWheelEvent *event)
{
if (m_activeInputHandler)
m_activeInputHandler->wheelEvent(event);
-
- emitNeedRender();
}
-void Abstract3DController::setSize(const int width, const int height)
+void Abstract3DController::handleThemeColorStyleChanged(Q3DTheme::ColorStyle style)
{
- m_boundingRect.setWidth(width);
- m_boundingRect.setHeight(height);
- m_scene->setViewportSize(width, height);
-
- m_changeTracker.boundingRectChanged = true;
- emitNeedRender();
-}
-
-const QSize Abstract3DController::size()
-{
- return m_boundingRect.size();
-}
-
-const QRect Abstract3DController::boundingRect()
-{
- return m_boundingRect;
-}
-
-void Abstract3DController::setBoundingRect(const QRect boundingRect)
-{
- m_boundingRect = boundingRect;
- m_scene->setViewport(boundingRect);
-
- m_changeTracker.boundingRectChanged = true;
- emitNeedRender();
-}
-
-void Abstract3DController::setWidth(const int width)
-{
- m_boundingRect.setWidth(width);
- m_scene->setViewportSize(width, m_scene->viewport().height());
-
- m_changeTracker.sizeChanged = true;
- emitNeedRender();
-}
-
-int Abstract3DController::width()
-{
- return m_boundingRect.width();
-}
-
-void Abstract3DController::setHeight(const int height)
-{
- m_boundingRect.setHeight(height);
- m_scene->setViewportSize(m_scene->viewport().width(), height);
-
- m_changeTracker.sizeChanged = true;
- emitNeedRender();
-}
-
-int Abstract3DController::height()
-{
- return m_boundingRect.height();
-}
-
-void Abstract3DController::setX(const int x)
-{
- m_boundingRect.setX(x);
-
- m_changeTracker.positionChanged = true;
- emitNeedRender();
-}
-
-int Abstract3DController::x()
-{
- return m_boundingRect.x();
-}
-
-void Abstract3DController::setY(const int y)
-{
- m_boundingRect.setY(y);
-
- m_changeTracker.positionChanged = true;
- emitNeedRender();
+ // Set value for series that have not explicitly set this value
+ foreach (QAbstract3DSeries *series, m_seriesList) {
+ if (!series->d_ptr->m_themeTracker.colorStyleOverride) {
+ series->setColorStyle(style);
+ series->d_ptr->m_themeTracker.colorStyleOverride = false;
+ }
+ }
+ markSeriesVisualsDirty();
}
-int Abstract3DController::y()
+void Abstract3DController::handleThemeBaseColorsChanged(const QList<QColor> &colors)
{
- return m_boundingRect.y();
+ int colorIdx = 0;
+ // Set value for series that have not explicitly set this value
+ foreach (QAbstract3DSeries *series, m_seriesList) {
+ if (!series->d_ptr->m_themeTracker.baseColorOverride) {
+ series->setBaseColor(colors.at(colorIdx));
+ series->d_ptr->m_themeTracker.baseColorOverride = false;
+ }
+ if (++colorIdx >= colors.size())
+ colorIdx = 0;
+ }
+ markSeriesVisualsDirty();
}
-QRect Abstract3DController::primarySubViewport() const
+void Abstract3DController::handleThemeBaseGradientsChanged(const QList<QLinearGradient> &gradients)
{
- return m_scene->primarySubViewport();
+ int gradientIdx = 0;
+ // Set value for series that have not explicitly set this value
+ foreach (QAbstract3DSeries *series, m_seriesList) {
+ if (!series->d_ptr->m_themeTracker.baseGradientOverride) {
+ series->setBaseGradient(gradients.at(gradientIdx));
+ series->d_ptr->m_themeTracker.baseGradientOverride = false;
+ }
+ if (++gradientIdx >= gradients.size())
+ gradientIdx = 0;
+ }
+ markSeriesVisualsDirty();
}
-void Abstract3DController::setPrimarySubViewport(const QRect &primarySubViewport)
+void Abstract3DController::handleThemeSingleHighlightColorChanged(const QColor &color)
{
- m_scene->setPrimarySubViewport(primarySubViewport);
+ // Set value for series that have not explicitly set this value
+ foreach (QAbstract3DSeries *series, m_seriesList) {
+ if (!series->d_ptr->m_themeTracker.singleHighlightColorOverride) {
+ series->setSingleHighlightColor(color);
+ series->d_ptr->m_themeTracker.singleHighlightColorOverride = false;
+ }
+ }
+ markSeriesVisualsDirty();
}
-QRect Abstract3DController::secondarySubViewport() const
+void Abstract3DController::handleThemeSingleHighlightGradientChanged(const QLinearGradient &gradient)
{
- return m_scene->secondarySubViewport();
+ // Set value for series that have not explicitly set this value
+ foreach (QAbstract3DSeries *series, m_seriesList) {
+ if (!series->d_ptr->m_themeTracker.singleHighlightGradientOverride) {
+ series->setSingleHighlightGradient(gradient);
+ series->d_ptr->m_themeTracker.singleHighlightGradientOverride = false;
+ }
+ }
+ markSeriesVisualsDirty();
}
-void Abstract3DController::setSecondarySubViewport(const QRect &secondarySubViewport)
+void Abstract3DController::handleThemeMultiHighlightColorChanged(const QColor &color)
{
- m_scene->setSecondarySubViewport(secondarySubViewport);
+ // Set value for series that have not explicitly set this value
+ foreach (QAbstract3DSeries *series, m_seriesList) {
+ if (!series->d_ptr->m_themeTracker.multiHighlightColorOverride) {
+ series->setMultiHighlightColor(color);
+ series->d_ptr->m_themeTracker.multiHighlightColorOverride = false;
+ }
+ }
+ markSeriesVisualsDirty();
}
-void Abstract3DController::updateDevicePixelRatio(qreal ratio)
+void Abstract3DController::handleThemeMultiHighlightGradientChanged(const QLinearGradient &gradient)
{
- m_scene->setDevicePixelRatio(ratio);
+ // Set value for series that have not explicitly set this value
+ foreach (QAbstract3DSeries *series, m_seriesList) {
+ if (!series->d_ptr->m_themeTracker.multiHighlightGradientOverride) {
+ series->setMultiHighlightGradient(gradient);
+ series->d_ptr->m_themeTracker.multiHighlightGradientOverride = false;
+ }
+ }
+ markSeriesVisualsDirty();
}
void Abstract3DController::setAxisX(Q3DAbstractAxis *axis)
@@ -532,64 +520,6 @@ QList<Q3DAbstractAxis *> Abstract3DController::axes() const
return m_axes;
}
-QAbstractDataProxy *Abstract3DController::activeDataProxy() const
-{
- return m_data;
-}
-
-void Abstract3DController::addDataProxy(QAbstractDataProxy *proxy)
-{
- Q_ASSERT(proxy);
- Abstract3DController *owner = qobject_cast<Abstract3DController *>(proxy->parent());
- if (owner != this) {
- Q_ASSERT_X(!owner, "addDataProxy", "Proxy already attached to a graph.");
- proxy->setParent(this);
- }
- if (!m_dataProxies.contains(proxy))
- m_dataProxies.append(proxy);
-}
-
-void Abstract3DController::releaseDataProxy(QAbstractDataProxy *proxy)
-{
- if (proxy && m_dataProxies.contains(proxy)) {
- // Clear the default status from released default proxies
- if (proxy->d_ptr->isDefaultProxy())
- proxy->d_ptr->setDefaultProxy(false);
-
- // If the proxy is in use, replace it with a temporary one
- if (m_data == proxy)
- setActiveDataProxy(0);
-
- m_dataProxies.removeAll(proxy);
- proxy->setParent(0);
- }
-}
-
-QList<QAbstractDataProxy *> Abstract3DController::dataProxies() const
-{
- return m_dataProxies;
-}
-
-void Abstract3DController::setActiveDataProxy(QAbstractDataProxy *proxy)
-{
- // If existing proxy is the default proxy, delete it
- if (m_data) {
- if (m_data->d_ptr->isDefaultProxy()) {
- m_dataProxies.removeAll(m_data);
- delete m_data;
- } else {
- // Disconnect the old proxy from use
- QObject::disconnect(m_data, 0, this, 0);
- }
- }
-
- // Assume ownership and activate
- addDataProxy(proxy);
- m_data = proxy;
- m_isDataDirty = true;
- emitNeedRender();
-}
-
void Abstract3DController::addInputHandler(QAbstract3DInputHandler *inputHandler)
{
Q_ASSERT(inputHandler);
@@ -665,110 +595,55 @@ void Abstract3DController::setZoomLevel(int zoomLevel)
emitNeedRender();
}
-void Abstract3DController::setObjectColor(const QColor &baseColor, bool uniform)
+void Abstract3DController::setTheme(Q3DTheme *theme)
{
- m_theme.m_baseColor = baseColor;
- m_theme.m_uniformColor = uniform;
-
- m_changeTracker.themeChanged = true;
- emitNeedRender();
-}
-
-QColor Abstract3DController::objectColor() const
-{
- return m_theme.m_baseColor;
-}
-
-void Abstract3DController::setTheme(QDataVis::Theme theme)
-{
- m_theme.useTheme(theme);
-
- m_changeTracker.themeChanged = true;
- emitNeedRender();
-}
-
-Theme Abstract3DController::theme()
-{
- return m_theme;
-}
-
-void Abstract3DController::setFont(const QFont &font)
-{
- m_font = font;
-
- m_changeTracker.fontChanged = true;
- emitNeedRender();
+ if (theme != m_themeManager->theme()) {
+ m_themeManager->setTheme(theme);
+ m_changeTracker.themeChanged = true;
+ // Reset all attached series to the new theme
+ for (int i = 0; i < m_seriesList.size(); i++)
+ m_seriesList.at(i)->d_ptr->resetToTheme(*theme, i, true);
+ markSeriesVisualsDirty();
+ emit themeChanged(theme);
+ }
}
-QFont Abstract3DController::font()
+Q3DTheme *Abstract3DController::theme() const
{
- return m_font;
+ return m_themeManager->theme();
}
-void Abstract3DController::setSelectionMode(QDataVis::SelectionMode mode)
+void Abstract3DController::setSelectionMode(QDataVis::SelectionFlags mode)
{
- m_selectionMode = mode;
- m_changeTracker.selectionModeChanged = true;
- emitNeedRender();
+ if (mode != m_selectionMode) {
+ m_selectionMode = mode;
+ m_changeTracker.selectionModeChanged = true;
+ emit selectionModeChanged(mode);
+ emitNeedRender();
+ }
}
-QDataVis::SelectionMode Abstract3DController::selectionMode()
+QDataVis::SelectionFlags Abstract3DController::selectionMode() const
{
return m_selectionMode;
}
void Abstract3DController::setShadowQuality(QDataVis::ShadowQuality quality)
{
- m_shadowQuality = quality;
-
- m_changeTracker.shadowQualityChanged = true;
- emit shadowQualityChanged(m_shadowQuality);
- emitNeedRender();
+ if (quality != m_shadowQuality) {
+ m_shadowQuality = quality;
+ m_changeTracker.shadowQualityChanged = true;
+ emit shadowQualityChanged(m_shadowQuality);
+ emitNeedRender();
+ }
}
-QDataVis::ShadowQuality Abstract3DController::shadowQuality()
+QDataVis::ShadowQuality Abstract3DController::shadowQuality() const
{
return m_shadowQuality;
}
-void Abstract3DController::setLabelStyle(QDataVis::LabelStyle style)
-{
- m_labelStyle = style;
-
- m_changeTracker.labelStyleChanged = true;
- emitNeedRender();
-}
-
-QDataVis::LabelStyle Abstract3DController::labelStyle()
-{
- return m_labelStyle;
-}
-
-void Abstract3DController::setBackgroundEnabled(bool enable)
-{
- m_isBackgroundEnabled = enable;
- m_changeTracker.backgroundEnabledChanged = true;
- emitNeedRender();
-}
-
-bool Abstract3DController::backgroundEnabled()
-{
- return m_isBackgroundEnabled;
-}
-
-void Abstract3DController::setGridEnabled(bool enable)
-{
- m_isGridEnabled = enable;
- m_changeTracker.gridEnabledChanged = true;
- emitNeedRender();
-}
-
-bool Abstract3DController::gridEnabled()
-{
- return m_isGridEnabled;
-}
-
-bool Abstract3DController::isSlicingActive()
+bool Abstract3DController::isSlicingActive() const
{
return m_scene->isSlicingActive();
}
@@ -779,37 +654,21 @@ void Abstract3DController::setSlicingActive(bool isSlicing)
emitNeedRender();
}
-QDataVis::InputState Abstract3DController::inputState()
-{
- if (m_activeInputHandler)
- return m_activeInputHandler->inputState();
- else
- return QDataVis::InputStateNone;
-}
-
-QPoint Abstract3DController::inputPosition()
+Q3DScene *Abstract3DController::scene()
{
- if (m_activeInputHandler)
- return m_activeInputHandler->inputPosition();
- else
- return QPoint(0,0);
+ return m_scene;
}
-void Abstract3DController::setMeshFileName(const QString &fileName)
+void Abstract3DController::markDataDirty()
{
- m_objFile = fileName;
- m_changeTracker.objFileChanged = true;
+ m_isDataDirty = true;
emitNeedRender();
}
-QString Abstract3DController::meshFileName()
-{
- return m_objFile;
-}
-
-Q3DScene *Abstract3DController::scene()
+void Abstract3DController::markSeriesVisualsDirty()
{
- return m_scene;
+ m_isSeriesVisualsDirty = true;
+ emitNeedRender();
}
void Abstract3DController::handleAxisTitleChanged(const QString &title)
@@ -849,7 +708,7 @@ void Abstract3DController::handleAxisLabelsChangedBySender(QObject *sender)
emitNeedRender();
}
-void Abstract3DController::handleAxisRangeChanged(qreal min, qreal max)
+void Abstract3DController::handleAxisRangeChanged(float min, float max)
{
Q_UNUSED(min)
Q_UNUSED(max)
@@ -927,6 +786,38 @@ void Abstract3DController::handleAxisLabelFormatChanged(const QString &format)
handleAxisLabelFormatChangedBySender(sender());
}
+void Abstract3DController::handleInputStateChanged(QAbstract3DInputHandler::InputState state)
+{
+ // When in automatic slicing mode, input state change to overview disables slice mode
+ if (m_selectionMode.testFlag(QDataVis::SelectionSlice)
+ && state == QAbstract3DInputHandler::InputStateOnPrimaryView) {
+ setSlicingActive(false);
+ }
+
+ m_changeTracker.inputStateChanged = true;
+ emitNeedRender();
+}
+
+void Abstract3DController::handleInputPositionChanged(const QPoint &position)
+{
+ Q_UNUSED(position)
+
+ m_changeTracker.inputPositionChanged = true;
+ emitNeedRender();
+}
+
+void Abstract3DController::handleSeriesVisibilityChanged(bool visible)
+{
+ Q_UNUSED(visible)
+
+ handleSeriesVisibilityChangedBySender(sender());
+}
+
+void Abstract3DController::handleRequestShadowQuality(QDataVis::ShadowQuality quality)
+{
+ setShadowQuality(quality);
+}
+
void Abstract3DController::handleAxisLabelFormatChangedBySender(QObject *sender)
{
// Label format changing needs to dirty the data so that labels are reset.
@@ -945,6 +836,15 @@ void Abstract3DController::handleAxisLabelFormatChangedBySender(QObject *sender)
emitNeedRender();
}
+void Abstract3DController::handleSeriesVisibilityChangedBySender(QObject *sender)
+{
+ Q_UNUSED(sender)
+
+ m_isDataDirty = true;
+ m_isSeriesVisibilityDirty = true;
+ emitNeedRender();
+}
+
void Abstract3DController::setAxisHelper(Q3DAbstractAxis::AxisOrientation orientation,
Q3DAbstractAxis *axis, Q3DAbstractAxis **axisPtr)
{
@@ -1024,12 +924,7 @@ Q3DAbstractAxis *Abstract3DController::createDefaultAxis(Q3DAbstractAxis::AxisOr
Q3DValueAxis *Abstract3DController::createDefaultValueAxis()
{
// Default value axis has single segment, empty label format, and auto scaling
- // TODO: Grid should be also hidden, but that is not currently controlled by axis
Q3DValueAxis *defaultAxis = new Q3DValueAxis;
- defaultAxis->setSegmentCount(1);
- defaultAxis->setSubSegmentCount(1);
- defaultAxis->setAutoAdjustRange(true);
- defaultAxis->setLabelFormat(QString());
defaultAxis->d_ptr->setDefaultAxis(true);
return defaultAxis;
@@ -1038,9 +933,7 @@ Q3DValueAxis *Abstract3DController::createDefaultValueAxis()
Q3DCategoryAxis *Abstract3DController::createDefaultCategoryAxis()
{
// Default category axis has no labels
- // TODO: Grid should be also hidden, but that is not currently controlled by axis.
Q3DCategoryAxis *defaultAxis = new Q3DCategoryAxis;
- defaultAxis->setAutoAdjustRange(true);
defaultAxis->d_ptr->setDefaultAxis(true);
return defaultAxis;
}
diff --git a/src/datavisualization/engine/abstract3dcontroller_p.h b/src/datavisualization/engine/abstract3dcontroller_p.h
index f17c6c4d..c56b8a72 100644
--- a/src/datavisualization/engine/abstract3dcontroller_p.h
+++ b/src/datavisualization/engine/abstract3dcontroller_p.h
@@ -26,19 +26,19 @@
//
// We mean it.
-#ifndef CONTROLLER3DBASE_H
-#define CONTROLLER3DBASE_H
+#ifndef ABSTRACT3DCONTROLLER_P_H
+#define ABSTRACT3DCONTROLLER_P_H
#include "datavisualizationglobal_p.h"
-#include "theme_p.h"
#include "q3dabstractaxis.h"
#include "drawer_p.h"
#include "qabstract3dinputhandler.h"
#include "qabstractdataproxy.h"
-#include "q3dscene.h"
+#include "q3dscene_p.h"
#include "q3dbox.h"
#include <QObject>
+#include <QLinearGradient>
class QFont;
@@ -46,55 +46,45 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class CameraHelper;
class Abstract3DRenderer;
+class QAbstract3DSeries;
+class ThemeManager;
struct Abstract3DChangeBitField {
- bool positionChanged : 1;
- bool zoomLevelChanged : 1;
- bool themeChanged : 1;
- bool fontChanged : 1;
- bool labelStyleChanged : 1;
- bool boundingRectChanged : 1;
- bool sizeChanged : 1;
- bool shadowQualityChanged : 1;
- bool selectionModeChanged : 1;
- bool objFileChanged : 1;
- bool gridEnabledChanged : 1;
- bool backgroundEnabledChanged : 1;
- bool axisXTypeChanged : 1;
- bool axisYTypeChanged : 1;
- bool axisZTypeChanged : 1;
- bool axisXTitleChanged : 1;
- bool axisYTitleChanged : 1;
- bool axisZTitleChanged : 1;
- bool axisXLabelsChanged : 1;
- bool axisYLabelsChanged : 1;
- bool axisZLabelsChanged : 1;
- bool axisXRangeChanged : 1;
- bool axisYRangeChanged : 1;
- bool axisZRangeChanged : 1;
- bool axisXSegmentCountChanged : 1;
- bool axisYSegmentCountChanged : 1;
- bool axisZSegmentCountChanged : 1;
- bool axisXSubSegmentCountChanged : 1;
- bool axisYSubSegmentCountChanged : 1;
- bool axisZSubSegmentCountChanged : 1;
- bool axisXLabelFormatChanged : 1;
- bool axisYLabelFormatChanged : 1;
- bool axisZLabelFormatChanged : 1;
+ bool zoomLevelChanged : 1;
+ bool themeChanged : 1;
+ bool shadowQualityChanged : 1;
+ bool selectionModeChanged : 1;
+ bool objFileChanged : 1;
+ bool axisXTypeChanged : 1;
+ bool axisYTypeChanged : 1;
+ bool axisZTypeChanged : 1;
+ bool axisXTitleChanged : 1;
+ bool axisYTitleChanged : 1;
+ bool axisZTitleChanged : 1;
+ bool axisXLabelsChanged : 1;
+ bool axisYLabelsChanged : 1;
+ bool axisZLabelsChanged : 1;
+ bool axisXRangeChanged : 1;
+ bool axisYRangeChanged : 1;
+ bool axisZRangeChanged : 1;
+ bool axisXSegmentCountChanged : 1;
+ bool axisYSegmentCountChanged : 1;
+ bool axisZSegmentCountChanged : 1;
+ bool axisXSubSegmentCountChanged : 1;
+ bool axisYSubSegmentCountChanged : 1;
+ bool axisZSubSegmentCountChanged : 1;
+ bool axisXLabelFormatChanged : 1;
+ bool axisYLabelFormatChanged : 1;
+ bool axisZLabelFormatChanged : 1;
+ bool inputStateChanged : 1;
+ bool inputPositionChanged : 1;
Abstract3DChangeBitField() :
- positionChanged(true),
zoomLevelChanged(true),
themeChanged(true),
- fontChanged(true),
- labelStyleChanged(true),
- boundingRectChanged(true),
- sizeChanged(true),
shadowQualityChanged(true),
selectionModeChanged(true),
objFileChanged(true),
- gridEnabledChanged(true),
- backgroundEnabledChanged(true),
axisXTypeChanged(true),
axisYTypeChanged(true),
axisZTypeChanged(true),
@@ -143,18 +133,11 @@ public:
private:
Abstract3DChangeBitField m_changeTracker;
- QRect m_boundingRect;
GLfloat m_horizontalRotation;
GLfloat m_verticalRotation;
- Theme m_theme;
- QFont m_font;
- QDataVis::SelectionMode m_selectionMode;
+ ThemeManager *m_themeManager;
+ QDataVis::SelectionFlags m_selectionMode;
QDataVis::ShadowQuality m_shadowQuality;
- QDataVis::LabelStyle m_labelStyle;
- bool m_isBackgroundEnabled;
- bool m_isGridEnabled;
- QString m_objFile;
-
Q3DScene *m_scene;
protected:
@@ -169,51 +152,26 @@ protected:
QList<Q3DAbstractAxis *> m_axes; // List of all added axes
Abstract3DRenderer *m_renderer;
bool m_isDataDirty;
-
- QAbstractDataProxy *m_data;
- QList<QAbstractDataProxy *> m_dataProxies;
-
+ bool m_isSeriesVisibilityDirty;
+ bool m_isSeriesVisualsDirty;
bool m_renderPending;
- explicit Abstract3DController(QRect boundRect, QObject *parent = 0);
+ QList<QAbstract3DSeries *> m_seriesList;
+
+ explicit Abstract3DController(QRect initialViewport, QObject *parent = 0);
virtual ~Abstract3DController();
public:
inline bool isInitialized() { return (m_renderer != 0); }
-
- /**
- * @brief synchDataToRenderer Called on the render thread while main GUI thread is blocked before rendering.
- */
virtual void synchDataToRenderer();
-
virtual void render(const GLuint defaultFboHandle = 0);
-
- /**
- * @brief setRenderer Sets the renderer to be used. isInitialized returns true from this point onwards.
- * @param renderer Renderer to be used.
- */
+ virtual void initializeOpenGL() = 0;
void setRenderer(Abstract3DRenderer *renderer);
- // Size
- virtual void setSize(const int width, const int height);
- virtual const QSize size();
- virtual const QRect boundingRect();
- virtual void setBoundingRect(const QRect boundingRect);
- virtual void setWidth(const int width);
- virtual int width();
- virtual void setHeight(const int height);
- virtual int height();
- virtual void setX(const int x);
- virtual int x();
- virtual void setY(const int y);
- virtual int y();
-
- virtual QRect primarySubViewport() const;
- virtual void setPrimarySubViewport(const QRect &primarySubViewport);
-
- virtual QRect secondarySubViewport() const;
- virtual void setSecondarySubViewport(const QRect &secondarySubViewport);
+ virtual void addSeries(QAbstract3DSeries *series);
+ virtual void removeSeries(QAbstract3DSeries *series);
+ QList<QAbstract3DSeries *> seriesList();
virtual void setAxisX(Q3DAbstractAxis *axis);
virtual Q3DAbstractAxis *axisX();
@@ -230,63 +188,27 @@ public:
virtual void setActiveInputHandler(QAbstract3DInputHandler *inputHandler);
virtual QAbstract3DInputHandler *activeInputHandler();
- virtual QAbstractDataProxy *activeDataProxy() const;
- virtual void addDataProxy(QAbstractDataProxy *proxy);
- virtual void releaseDataProxy(QAbstractDataProxy *proxy);
- virtual QList<QAbstractDataProxy *> dataProxies() const;
- virtual void setActiveDataProxy(QAbstractDataProxy *proxy);
- virtual void updateDevicePixelRatio(qreal ratio);
-
virtual int zoomLevel();
virtual void setZoomLevel(int zoomLevel);
- // Set color if you don't want to use themes.
- virtual void setObjectColor(const QColor &baseColor, bool uniform = true);
- virtual QColor objectColor() const;
-
- // Set theme (bar colors, shaders, window color, background colors, light intensity and text
- // colors are affected)
- virtual void setTheme(QDataVis::Theme theme);
- virtual Theme theme();
+ virtual void setTheme(Q3DTheme *theme);
+ virtual Q3DTheme *theme() const;
- // Set font
- virtual void setFont(const QFont &font);
- virtual QFont font();
+ virtual void setSelectionMode(QDataVis::SelectionFlags mode);
+ virtual QDataVis::SelectionFlags selectionMode() const;
- // Selection mode
- virtual void setSelectionMode(QDataVis::SelectionMode mode);
- virtual QDataVis::SelectionMode selectionMode();
-
- // Adjust shadow quality
virtual void setShadowQuality(QDataVis::ShadowQuality quality);
- virtual QDataVis::ShadowQuality shadowQuality();
-
- // Label style adjustment
- virtual void setLabelStyle(QDataVis::LabelStyle style);
- virtual QDataVis::LabelStyle labelStyle();
+ virtual QDataVis::ShadowQuality shadowQuality() const;
- // Enable or disable background mesh
- virtual void setBackgroundEnabled(bool enable);
- virtual bool backgroundEnabled();
-
- // Enable or disable background grid
- virtual void setGridEnabled(bool enable);
- virtual bool gridEnabled();
-
- // Query input state and position
- QDataVis::InputState inputState();
- QPoint inputPosition();
-
- // Enable or disable slicing mode
- bool isSlicingActive();
+ bool isSlicingActive() const;
void setSlicingActive(bool isSlicing);
+ Q3DScene *scene();
- // override bar type with own mesh
- virtual void setMeshFileName(const QString &fileName);
- virtual QString meshFileName();
+ void markDataDirty();
+ void markSeriesVisualsDirty();
- Q3DScene *scene();
+ void emitNeedRender();
virtual void mouseDoubleClickEvent(QMouseEvent *event);
virtual void touchEvent(QTouchEvent *event);
@@ -303,32 +225,50 @@ public:
virtual void handleAxisAutoAdjustRangeChangedInOrientation(
Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust) = 0;
virtual void handleAxisLabelFormatChangedBySender(QObject *sender);
+ virtual void handleSeriesVisibilityChangedBySender(QObject *sender);
public slots:
void handleAxisTitleChanged(const QString &title);
void handleAxisLabelsChanged();
- void handleAxisRangeChanged(qreal min, qreal max);
+ void handleAxisRangeChanged(float min, float max);
void handleAxisSegmentCountChanged(int count);
void handleAxisSubSegmentCountChanged(int count);
void handleAxisAutoAdjustRangeChanged(bool autoAdjust);
void handleAxisLabelFormatChanged(const QString &format);
+ void handleInputStateChanged(QAbstract3DInputHandler::InputState state);
+ void handleInputPositionChanged(const QPoint &position);
+ void handleSeriesVisibilityChanged(bool visible);
+
+ void handleThemeColorStyleChanged(Q3DTheme::ColorStyle style);
+ void handleThemeBaseColorsChanged(const QList<QColor> &color);
+ void handleThemeBaseGradientsChanged(const QList<QLinearGradient> &gradient);
+ void handleThemeSingleHighlightColorChanged(const QColor &color);
+ void handleThemeSingleHighlightGradientChanged(const QLinearGradient &gradient);
+ void handleThemeMultiHighlightColorChanged(const QColor &color);
+ void handleThemeMultiHighlightGradientChanged(const QLinearGradient &gradient);
+
+ // Renderer callback handlers
+ void handleRequestShadowQuality(QDataVis::ShadowQuality quality);
signals:
void shadowQualityChanged(QDataVis::ShadowQuality quality);
void activeInputHandlerChanged(QAbstract3DInputHandler *inputHandler);
+ void themeChanged(Q3DTheme *theme);
+ void selectionModeChanged(QDataVis::SelectionFlags mode);
void needRender();
protected:
virtual Q3DAbstractAxis *createDefaultAxis(Q3DAbstractAxis::AxisOrientation orientation);
Q3DValueAxis *createDefaultValueAxis();
Q3DCategoryAxis *createDefaultCategoryAxis();
- void emitNeedRender();
private:
void setAxisHelper(Q3DAbstractAxis::AxisOrientation orientation, Q3DAbstractAxis *axis,
Q3DAbstractAxis **axisPtr);
+
+ friend class Bars3DController;
};
QT_DATAVISUALIZATION_END_NAMESPACE
-#endif // CONTROLLER3DBASE_H
+#endif
diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp
index eef810df..74088b7c 100644
--- a/src/datavisualization/engine/abstract3drenderer.cpp
+++ b/src/datavisualization/engine/abstract3drenderer.cpp
@@ -23,24 +23,27 @@
#include "q3dscene_p.h"
#include "q3dcamera_p.h"
#include "q3dlight_p.h"
+#include "qabstract3dseries_p.h"
+#include "q3dtheme_p.h"
+#include "objecthelper_p.h"
+
+Q_DECLARE_METATYPE(QtDataVisualization::QDataVis::ShadowQuality)
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller)
: QObject(0),
- m_controller(controller),
m_hasNegativeValues(false),
- m_cachedTheme(),
- m_cachedFont(QFont(QStringLiteral("Arial"))),
- m_cachedLabelStyle(QDataVis::LabelStyleFromTheme),
- m_drawer(new Drawer(m_cachedTheme, m_cachedFont, m_cachedLabelStyle)),
- m_cachedBoundingRect(QRect(0,0,0,0)),
+ m_cachedTheme(new Q3DTheme()),
+ m_drawer(new Drawer(m_cachedTheme)),
m_cachedShadowQuality(QDataVis::ShadowQualityMedium),
m_autoScaleAdjustment(1.0f),
- m_cachedSelectionMode(QDataVis::SelectionModeNone),
- m_cachedIsGridEnabled(false),
- m_cachedIsBackgroundEnabled(false),
- m_cachedScene(new Q3DScene())
+ m_cachedSelectionMode(QDataVis::SelectionNone),
+ m_textureHelper(0),
+ m_cachedScene(new Q3DScene()),
+ m_selectionDirty(true),
+ m_selectionState(SelectNone),
+ m_devicePixelRatio(1.0f)
#ifdef DISPLAY_RENDER_SPEED
, m_isFirstFrame(true),
m_numFrames(0)
@@ -48,15 +51,21 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller)
{
QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Abstract3DRenderer::updateTextures);
- QObject::connect(this, &Abstract3DRenderer::needRender, m_controller,
+ QObject::connect(this, &Abstract3DRenderer::needRender, controller,
&Abstract3DController::needRender, Qt::QueuedConnection);
+ QObject::connect(this, &Abstract3DRenderer::requestShadowQuality, controller,
+ &Abstract3DController::handleRequestShadowQuality, Qt::QueuedConnection);
}
Abstract3DRenderer::~Abstract3DRenderer()
{
+ for (int i = 0; i < m_visibleSeriesList.size(); i++)
+ m_visibleSeriesList[i].cleanup(m_textureHelper);
+
delete m_drawer;
delete m_textureHelper;
delete m_cachedScene;
+ delete m_cachedTheme;
}
void Abstract3DRenderer::initializeOpenGL()
@@ -93,7 +102,7 @@ void Abstract3DRenderer::render(const GLuint defaultFboHandle)
// Measure speed (as milliseconds per frame)
m_numFrames++;
if (m_lastFrameTime.elapsed() >= 1000) { // print only if last measurement was more than 1s ago
- qDebug() << qreal(m_lastFrameTime.elapsed()) / qreal(m_numFrames) << "ms/frame (=" << qreal(m_numFrames) << "fps)";
+ qDebug() << float(m_lastFrameTime.elapsed()) / float(m_numFrames) << "ms/frame (=" << float(m_numFrames) << "fps)";
m_numFrames = 0;
m_lastFrameTime.restart();
}
@@ -108,17 +117,17 @@ void Abstract3DRenderer::render(const GLuint defaultFboHandle)
glDisable(GL_BLEND); // For QtQuick2 blending is enabled by default, but we don't want it to be
}
- glViewport(m_cachedScene->viewport().x(),
- m_cachedScene->viewport().y(),
- m_cachedScene->viewport().width(),
- m_cachedScene->viewport().height());
-
- QVector3D clearColor = Utils::vectorFromColor(m_cachedTheme.m_windowColor);
+ // Clear the graph background to the theme color
+ glViewport(m_viewport.x(),
+ m_viewport.y(),
+ m_viewport.width(),
+ m_viewport.height());
+ QVector3D clearColor = Utils::vectorFromColor(m_cachedTheme->windowColor());
glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
-QString Abstract3DRenderer::generateValueLabel(const QString &format, qreal value)
+QString Abstract3DRenderer::generateValueLabel(const QString &format, float value)
{
QString valueLabelFormat = format;
Utils::ParamType valueParamType = Utils::findFormatParamType(valueLabelFormat);
@@ -126,126 +135,140 @@ QString Abstract3DRenderer::generateValueLabel(const QString &format, qreal valu
return Utils::formatLabel(valueFormatArray, valueParamType, value);
}
-void Abstract3DRenderer::updateDataModel(QAbstractDataProxy *dataProxy)
+void Abstract3DRenderer::updateSelectionState(SelectionState state)
{
- m_cachedItemLabelFormat = dataProxy->itemLabelFormat();
+ m_selectionState = state;
}
-QString Abstract3DRenderer::itemLabelFormat() const
+void Abstract3DRenderer::updateInputPosition(const QPoint &position)
{
- return m_cachedItemLabelFormat;
+ m_inputPosition = position;
}
-void Abstract3DRenderer::updateBoundingRect(const QRect &boundingRect)
+void Abstract3DRenderer::initGradientShaders(const QString &vertexShader, const QString &fragmentShader)
{
- m_cachedBoundingRect = boundingRect;
- handleResize();
+ // Do nothing by default
+ Q_UNUSED(vertexShader)
+ Q_UNUSED(fragmentShader)
}
-void Abstract3DRenderer::updatePosition(const QRect &boundingRect)
+void Abstract3DRenderer::updateTheme(Q3DTheme *theme)
{
- m_cachedBoundingRect = boundingRect;
+ // Synchronize the controller theme with renderer
+ bool changed = theme->d_ptr->sync(*m_cachedTheme->d_ptr);
+
+ if (changed) {
+ // Update drawer if sync changed something
+ m_drawer->setTheme(m_cachedTheme);
+ // Re-initialize shaders
+ reInitShaders();
+ }
}
-void Abstract3DRenderer::updateTheme(Theme theme)
+void Abstract3DRenderer::updateScene(Q3DScene *scene)
{
- m_cachedTheme.setFromTheme(theme);
+ m_viewport = scene->d_ptr->glViewport();
+ m_secondarySubViewport = scene->d_ptr->glSecondarySubViewport();
- m_drawer->setTheme(m_cachedTheme);
- // Re-initialize shaders
- handleShadowQualityChange();
-}
+ if (m_primarySubViewport != scene->d_ptr->glPrimarySubViewport()) {
+ // Resize of primary subviewport means resizing shadow and selection buffers
+ m_primarySubViewport = scene->d_ptr->glPrimarySubViewport();
+ handleResize();
+ }
-void Abstract3DRenderer::updateScene(Q3DScene *scene)
-{
- // Synchronize the controller scene to that of the renderer, and vice versa.
- // Controller scene had priority if both have changed same values.
+ if (m_devicePixelRatio != scene->devicePixelRatio()) {
+ m_devicePixelRatio = scene->devicePixelRatio();
+ handleResize();
+ }
+
+ scene->activeCamera()->d_ptr->updateViewMatrix(m_autoScaleAdjustment);
+ // Set light position (rotate light with activeCamera, a bit above it (as set in defaultLightPos))
+ scene->setLightPositionRelativeToCamera(defaultLightPos);
+
+ QPoint logicalPixelPosition = scene->selectionQueryPosition();
+ updateInputPosition(QPoint(logicalPixelPosition.x() * m_devicePixelRatio,
+ logicalPixelPosition.y() * m_devicePixelRatio));
+
+ if (Q3DScene::invalidSelectionPoint() == logicalPixelPosition) {
+ updateSelectionState(SelectNone);
+ } else {
+ // Selections are one-shot, reset selection active to false before processing
+ scene->setSelectionQueryPosition(Q3DScene::invalidSelectionPoint());
+
+ if (scene->isSlicingActive()) {
+ if (scene->isPointInPrimarySubView(logicalPixelPosition))
+ updateSelectionState(SelectOnOverview);
+ else if (scene->isPointInSecondarySubView(logicalPixelPosition))
+ updateSelectionState(SelectOnSlice);
+ else
+ updateSelectionState(SelectNone);
+ } else {
+ updateSelectionState(SelectOnScene);
+ }
+ }
+
+ // Synchronize the controller scene with renderer
scene->d_ptr->sync(*m_cachedScene->d_ptr);
- m_cachedScene->d_ptr->sync(*scene->d_ptr);
}
-void Abstract3DRenderer::handleShadowQualityChange()
+void Abstract3DRenderer::reInitShaders()
{
#if !defined(QT_OPENGL_ES_2)
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
- if (!m_cachedTheme.m_uniformColor) {
- initShaders(QStringLiteral(":/shaders/vertexShadow"),
- QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY"));
- } else {
- initShaders(QStringLiteral(":/shaders/vertexShadow"),
- QStringLiteral(":/shaders/fragmentShadowNoTex"));
- }
+ initGradientShaders(QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY"));
+ initShaders(QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentShadowNoTex"));
initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"),
QStringLiteral(":/shaders/fragmentShadowNoTex"));
} else {
- if (!m_cachedTheme.m_uniformColor) {
- initShaders(QStringLiteral(":/shaders/vertex"),
- QStringLiteral(":/shaders/fragmentColorOnY"));
- } else {
- initShaders(QStringLiteral(":/shaders/vertex"),
- QStringLiteral(":/shaders/fragment"));
- }
+ initGradientShaders(QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragmentColorOnY"));
+ initShaders(QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragment"));
initBackgroundShaders(QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragment"));
}
#else
- if (!m_cachedTheme.m_uniformColor) {
- initShaders(QStringLiteral(":/shaders/vertexES2"),
- QStringLiteral(":/shaders/fragmentColorOnYES2"));
- } else {
- initShaders(QStringLiteral(":/shaders/vertexES2"),
- QStringLiteral(":/shaders/fragmentES2"));
- }
- initBackgroundShaders(QStringLiteral(":/shaders/vertexES2"),
+ initGradientShaders(QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragmentColorOnYES2"));
+ initShaders(QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragmentES2"));
+ initBackgroundShaders(QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragmentES2"));
#endif
}
-void Abstract3DRenderer::updateFont(const QFont &font)
-{
- m_cachedFont = font;
- m_drawer->setFont(font);
-}
-
-void Abstract3DRenderer::updateLabelStyle(QDataVis::LabelStyle style)
+void Abstract3DRenderer::handleShadowQualityChange()
{
- m_cachedLabelStyle = style;
- m_drawer->setStyle(style);
-}
+ reInitShaders();
-void Abstract3DRenderer::updateMeshFileName(const QString &objFileName)
-{
- if (objFileName != m_cachedObjFile) {
- m_cachedObjFile = objFileName;
- loadMeshFile();
+#if defined(QT_OPENGL_ES_2)
+ if (m_cachedShadowQuality != QDataVis::ShadowQualityNone) {
+ emit requestShadowQuality(QDataVis::ShadowQualityNone);
+ qWarning("Shadows are not yet supported for OpenGL ES2");
+ m_cachedShadowQuality = QDataVis::ShadowQualityNone;
}
+#endif
}
-void Abstract3DRenderer::updateSelectionMode(QDataVis::SelectionMode mode)
+void Abstract3DRenderer::updateSelectionMode(QDataVis::SelectionFlags mode)
{
m_cachedSelectionMode = mode;
-}
-
-void Abstract3DRenderer::updateGridEnabled(bool enable)
-{
- m_cachedIsGridEnabled = enable;
-}
-
-void Abstract3DRenderer::updateBackgroundEnabled(bool enable)
-{
- m_cachedIsBackgroundEnabled = enable;
+ m_selectionDirty = true;
}
void Abstract3DRenderer::handleResize()
{
- if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0)
+ if (m_primarySubViewport.width() == 0 || m_primarySubViewport.height() == 0)
return;
+
// Calculate zoom level based on aspect ratio
GLfloat div;
GLfloat zoomAdjustment;
- div = qMin(m_cachedBoundingRect.width(), m_cachedBoundingRect.height());
- zoomAdjustment = defaultRatio * ((m_cachedBoundingRect.width() / div)
- / (m_cachedBoundingRect.height() / div));
+ div = qMin(m_primarySubViewport.width(), m_primarySubViewport.height());
+ zoomAdjustment = defaultRatio * ((m_primarySubViewport.width() / div)
+ / (m_primarySubViewport.height() / div));
m_autoScaleAdjustment = qMin(zoomAdjustment, 1.0f); // clamp to 1.0f
// Re-init selection buffer
@@ -272,7 +295,7 @@ void Abstract3DRenderer::updateAxisLabels(Q3DAbstractAxis::AxisOrientation orien
axisCacheForOrientation(orientation).setLabels(labels);
}
-void Abstract3DRenderer::updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, qreal min, qreal max)
+void Abstract3DRenderer::updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, float min, float max)
{
AxisRenderCache &cache = axisCacheForOrientation(orientation);
cache.setMin(min);
@@ -294,6 +317,42 @@ void Abstract3DRenderer::updateAxisLabelFormat(Q3DAbstractAxis::AxisOrientation
axisCacheForOrientation(orientation).setLabelFormat(format);
}
+void Abstract3DRenderer::fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh)
+{
+ // Default implementation does nothing.
+ Q_UNUSED(fileName)
+ Q_UNUSED(mesh)
+}
+
+void Abstract3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList,
+ bool updateVisibility)
+{
+ int visibleCount = 0;
+ if (updateVisibility) {
+ int oldSize = m_visibleSeriesList.size();
+ foreach (QAbstract3DSeries *current, seriesList) {
+ if (current->isVisible())
+ visibleCount++;
+ }
+
+ // Clean up series caches that are about to be permanently deleted.
+ // Can't just use cache destructor, as resize will call that to all items.
+ if (visibleCount < oldSize) {
+ for (int i = visibleCount; i < oldSize; i++)
+ m_visibleSeriesList[i].cleanup(m_textureHelper);
+ }
+
+ if (visibleCount != oldSize)
+ m_visibleSeriesList.resize(visibleCount);
+
+ visibleCount = 0;
+ }
+ foreach (QAbstract3DSeries *current, seriesList) {
+ if (current->isVisible())
+ m_visibleSeriesList[visibleCount++].populate(current, this);
+ }
+}
+
AxisRenderCache &Abstract3DRenderer::axisCacheForOrientation(Q3DAbstractAxis::AxisOrientation orientation)
{
switch (orientation) {
@@ -309,5 +368,56 @@ AxisRenderCache &Abstract3DRenderer::axisCacheForOrientation(Q3DAbstractAxis::Ax
}
}
+void Abstract3DRenderer::lowerShadowQuality()
+{
+ QDataVis::ShadowQuality newQuality = QDataVis::ShadowQualityNone;
+
+ switch (m_cachedShadowQuality) {
+ case QDataVis::ShadowQualityHigh:
+ qWarning("Creating high quality shadows failed. Changing to medium quality.");
+ newQuality = QDataVis::ShadowQualityMedium;
+ break;
+ case QDataVis::ShadowQualityMedium:
+ qWarning("Creating medium quality shadows failed. Changing to low quality.");
+ newQuality = QDataVis::ShadowQualityLow;
+ break;
+ case QDataVis::ShadowQualityLow:
+ qWarning("Creating low quality shadows failed. Switching shadows off.");
+ newQuality = QDataVis::ShadowQualityNone;
+ break;
+ case QDataVis::ShadowQualitySoftHigh:
+ qWarning("Creating soft high quality shadows failed. Changing to soft medium quality.");
+ newQuality = QDataVis::ShadowQualitySoftMedium;
+ break;
+ case QDataVis::ShadowQualitySoftMedium:
+ qWarning("Creating soft medium quality shadows failed. Changing to soft low quality.");
+ newQuality = QDataVis::ShadowQualitySoftLow;
+ break;
+ case QDataVis::ShadowQualitySoftLow:
+ qWarning("Creating soft low quality shadows failed. Switching shadows off.");
+ newQuality = QDataVis::ShadowQualityNone;
+ break;
+ default:
+ // You'll never get here
+ break;
+ }
+
+ emit requestShadowQuality(newQuality);
+ updateShadowQuality(newQuality);
+}
+
+void Abstract3DRenderer::fixGradientAndGenerateTexture(QLinearGradient *gradient, GLuint *gradientTexture)
+{
+ // Readjust start/stop to match gradient texture size
+ gradient->setStart(qreal(gradientTextureWidth), qreal(gradientTextureHeight));
+ gradient->setFinalStop(0.0, 0.0);
+
+ if (*gradientTexture) {
+ m_textureHelper->deleteTexture(gradientTexture);
+ *gradientTexture = 0;
+ }
+
+ *gradientTexture = m_textureHelper->createGradientTexture(*gradient);
+}
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h
index 1c61ac07..17a55ac9 100644
--- a/src/datavisualization/engine/abstract3drenderer_p.h
+++ b/src/datavisualization/engine/abstract3drenderer_p.h
@@ -37,6 +37,7 @@
#include "abstract3dcontroller_p.h"
#include "axisrendercache_p.h"
#include "qabstractdataproxy.h"
+#include "seriesrendercache_p.h"
//#define DISPLAY_RENDER_SPEED
@@ -50,90 +51,98 @@ class Abstract3DRenderer : public QObject, protected QOpenGLFunctions
{
Q_OBJECT
-private:
- Abstract3DController *m_controller;
-
protected:
- bool m_hasNegativeValues;
- Theme m_cachedTheme;
- QFont m_cachedFont;
- QDataVis::LabelStyle m_cachedLabelStyle;
- Drawer *m_drawer;
- QRect m_cachedBoundingRect;
- QDataVis::ShadowQuality m_cachedShadowQuality;
- GLfloat m_autoScaleAdjustment;
-
- QString m_cachedItemLabelFormat;
- QString m_cachedObjFile;
- QDataVis::SelectionMode m_cachedSelectionMode;
- bool m_cachedIsGridEnabled;
- bool m_cachedIsBackgroundEnabled;
-
- AxisRenderCache m_axisCacheX;
- AxisRenderCache m_axisCacheY;
- AxisRenderCache m_axisCacheZ;
- TextureHelper *m_textureHelper;
- Q3DBox m_boundingBox;
+ enum SelectionState {
+ SelectNone = 0,
+ SelectOnScene,
+ SelectOnOverview,
+ SelectOnSlice
+ };
- Q3DScene *m_cachedScene;
-
-#ifdef DISPLAY_RENDER_SPEED
- bool m_isFirstFrame;
- QTime m_lastFrameTime;
- GLint m_numFrames;
-#endif
-
- QString generateValueLabel(const QString &format, qreal value);
+ QString generateValueLabel(const QString &format, float value);
public:
virtual ~Abstract3DRenderer();
- void updateDataModel(QAbstractDataProxy *dataProxy);
+ virtual void updateData() = 0;
+ virtual void updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility);
virtual void render(GLuint defaultFboHandle);
- virtual void updateBoundingRect(const QRect &boundingRect);
- virtual void updatePosition(const QRect &boundingRect);
-
- virtual void updateTheme(Theme theme);
- virtual void updateFont(const QFont &font);
- virtual void updateLabelStyle(QDataVis::LabelStyle style);
- virtual void updateSelectionMode(QDataVis::SelectionMode newMode);
- virtual void updateGridEnabled(bool enable);
- virtual void updateBackgroundEnabled(bool enable);
- virtual void updateMeshFileName(const QString &objFileName);
+ virtual void updateTheme(Q3DTheme *theme);
+ virtual void updateSelectionMode(QDataVis::SelectionFlags newMode);
virtual void updateScene(Q3DScene *scene);
- virtual QString itemLabelFormat() const;
virtual void updateTextures() = 0;
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;
#endif
virtual void updateShadowQuality(QDataVis::ShadowQuality quality) = 0;
virtual void initShaders(const QString &vertexShader, const QString &fragmentShader) = 0;
+ virtual void initGradientShaders(const QString &vertexShader, const QString &fragmentShader);
virtual void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader) = 0;
virtual void updateAxisType(Q3DAbstractAxis::AxisOrientation orientation, Q3DAbstractAxis::AxisType type);
virtual void updateAxisTitle(Q3DAbstractAxis::AxisOrientation orientation, const QString &title);
virtual void updateAxisLabels(Q3DAbstractAxis::AxisOrientation orientation, const QStringList &labels);
- virtual void updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, qreal min, qreal max);
+ virtual void updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, float min, float max);
virtual void updateAxisSegmentCount(Q3DAbstractAxis::AxisOrientation orientation, int count);
virtual void updateAxisSubSegmentCount(Q3DAbstractAxis::AxisOrientation orientation, int count);
virtual void updateAxisLabelFormat(Q3DAbstractAxis::AxisOrientation orientation, const QString &format);
+ virtual void fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh);
+ void fixGradientAndGenerateTexture(QLinearGradient *gradient, GLuint *gradientTexture);
+
signals:
void needRender(); // Emit this if something in renderer causes need for another render pass.
+ void requestShadowQuality(QDataVis::ShadowQuality quality); // For automatic quality adjustments
protected:
Abstract3DRenderer(Abstract3DController *controller);
virtual void initializeOpenGL();
+ void reInitShaders();
virtual void handleShadowQualityChange();
virtual void handleResize();
- virtual void loadMeshFile() = 0;
AxisRenderCache &axisCacheForOrientation(Q3DAbstractAxis::AxisOrientation orientation);
+
+ virtual void lowerShadowQuality();
+
+ void fixGradient(QLinearGradient *gradient, GLuint *gradientTexture);
+
+ bool m_hasNegativeValues;
+ Q3DTheme *m_cachedTheme;
+ Drawer *m_drawer;
+ QRect m_viewport;
+ QDataVis::ShadowQuality m_cachedShadowQuality;
+ GLfloat m_autoScaleAdjustment;
+
+ QDataVis::SelectionFlags m_cachedSelectionMode;
+
+ AxisRenderCache m_axisCacheX;
+ AxisRenderCache m_axisCacheY;
+ AxisRenderCache m_axisCacheZ;
+ TextureHelper *m_textureHelper;
+ Q3DBox m_boundingBox;
+
+ Q3DScene *m_cachedScene;
+ bool m_selectionDirty;
+ SelectionState m_selectionState;
+ QPoint m_inputPosition;
+ QVector<SeriesRenderCache> m_visibleSeriesList;
+ QRect m_primarySubViewport;
+ QRect m_secondarySubViewport;
+ float m_devicePixelRatio;
+
+#ifdef DISPLAY_RENDER_SPEED
+ bool m_isFirstFrame;
+ QTime m_lastFrameTime;
+ GLint m_numFrames;
+#endif
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/axisrendercache.cpp b/src/datavisualization/engine/axisrendercache.cpp
index 55ac0765..f7960b2b 100644
--- a/src/datavisualization/engine/axisrendercache.cpp
+++ b/src/datavisualization/engine/axisrendercache.cpp
@@ -24,8 +24,8 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
AxisRenderCache::AxisRenderCache()
: m_type(Q3DAbstractAxis::AxisTypeNone),
- m_min(0.0),
- m_max(10.0),
+ m_min(0.0f),
+ m_max(10.0f),
m_segmentCount(5),
m_subSegmentCount(1),
m_font(QFont(QStringLiteral("Arial"))),
@@ -58,8 +58,8 @@ void AxisRenderCache::setType(Q3DAbstractAxis::AxisType type)
// If type is set, it means completely new axis instance, so clear all old data
m_labels.clear();
m_title.clear();
- m_min = 0.0;
- m_max = 10.0;
+ m_min = 0.0f;
+ m_max = 10.0f;
m_segmentCount = 5;
m_subSegmentCount = 1;
m_labelFormat.clear();
@@ -109,13 +109,13 @@ void AxisRenderCache::setLabels(const QStringList &labels)
}
}
-void AxisRenderCache::setMin(qreal min)
+void AxisRenderCache::setMin(float min)
{
m_min = min;
updateSegmentStep();
}
-void AxisRenderCache::setMax(qreal max)
+void AxisRenderCache::setMax(float max)
{
m_max = max;
updateSegmentStep();
diff --git a/src/datavisualization/engine/axisrendercache_p.h b/src/datavisualization/engine/axisrendercache_p.h
index 0bb1cf92..cddc7839 100644
--- a/src/datavisualization/engine/axisrendercache_p.h
+++ b/src/datavisualization/engine/axisrendercache_p.h
@@ -51,10 +51,10 @@ public:
inline const QString &title() { return m_title; }
void setLabels(const QStringList &labels);
inline const QStringList &labels() { return m_labels; }
- void setMin(qreal min);
- inline qreal min() { return m_min; }
- void setMax(qreal max);
- inline qreal max() { return m_max; }
+ void setMin(float min);
+ inline float min() { return m_min; }
+ void setMax(float max);
+ inline float max() { return m_max; }
void setSegmentCount(int count);
inline int segmentCount() const { return m_segmentCount; }
void setSubSegmentCount(int count);
@@ -79,8 +79,8 @@ private:
Q3DAbstractAxis::AxisType m_type;
QString m_title;
QStringList m_labels;
- qreal m_min;
- qreal m_max;
+ float m_min;
+ float m_max;
int m_segmentCount;
int m_subSegmentCount;
QString m_labelFormat;
diff --git a/src/datavisualization/engine/bars3dcontroller.cpp b/src/datavisualization/engine/bars3dcontroller.cpp
index 2eea6c74..5232a566 100644
--- a/src/datavisualization/engine/bars3dcontroller.cpp
+++ b/src/datavisualization/engine/bars3dcontroller.cpp
@@ -23,6 +23,9 @@
#include "q3dvalueaxis_p.h"
#include "q3dcategoryaxis_p.h"
#include "qbardataproxy_p.h"
+#include "qbar3dseries_p.h"
+#include "thememanager_p.h"
+#include "q3dtheme_p.h"
#include <QMatrix4x4>
#include <qmath.h>
@@ -31,17 +34,13 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
Bars3DController::Bars3DController(QRect boundRect)
: Abstract3DController(boundRect),
- m_selectedBarPos(noSelectionPoint()),
+ m_selectedBar(invalidSelectionPosition()),
+ m_selectedBarSeries(0),
m_isBarSpecRelative(true),
m_barThicknessRatio(1.0f),
m_barSpacing(QSizeF(1.0, 1.0)),
m_renderer(0)
{
- // Default bar type; specific to bars
- setBarType(QDataVis::MeshStyleBevelBars, false);
-
- setActiveDataProxy(0);
-
// Setting a null axis creates a new default axis according to orientation and graph type.
// Note: these cannot be set in the Abstract3DController constructor, as they will call virtual
// functions implemented by subclasses.
@@ -65,13 +64,20 @@ void Bars3DController::initializeOpenGL()
setRenderer(m_renderer);
synchDataToRenderer();
- QObject::connect(m_renderer, &Bars3DRenderer::selectedBarPosChanged, this,
- &Bars3DController::handleSelectedBarPosChanged, Qt::QueuedConnection);
+ QObject::connect(m_renderer, &Bars3DRenderer::barClicked, this,
+ &Bars3DController::handleBarClicked, Qt::QueuedConnection);
emitNeedRender();
}
void Bars3DController::synchDataToRenderer()
{
+ // Background change requires reloading the meshes in bar graphs, so dirty the series visuals
+ if (m_themeManager->theme()->d_ptr->m_dirtyBits.backgroundEnabledDirty) {
+ m_isSeriesVisualsDirty = true;
+ foreach (QAbstract3DSeries *series, m_seriesList)
+ series->d_ptr->m_changeTracker.meshChanged = true;
+ }
+
Abstract3DController::synchDataToRenderer();
if (!isInitialized())
@@ -83,67 +89,19 @@ void Bars3DController::synchDataToRenderer()
m_changeTracker.barSpecsChanged = false;
}
- if (m_changeTracker.selectedBarPosChanged) {
- m_renderer->updateSelectedBarPos(m_selectedBarPos);
- m_changeTracker.selectedBarPosChanged = false;
- }
-
- if (m_isDataDirty) {
- m_renderer->updateDataModel(static_cast<QBarDataProxy *>(m_data));
- m_isDataDirty = false;
+ // Needs to be done after data is set, as it needs to know the visual array.
+ if (m_changeTracker.selectedBarChanged) {
+ m_renderer->updateSelectedBar(m_selectedBar, m_selectedBarSeries);
+ m_changeTracker.selectedBarChanged = false;
}
}
-void Bars3DController::setActiveDataProxy(QAbstractDataProxy *proxy)
-{
- // Setting null proxy indicates default proxy
- if (!proxy) {
- proxy = new QBarDataProxy;
- proxy->d_ptr->setDefaultProxy(true);
- }
-
- Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeBar);
-
- Abstract3DController::setActiveDataProxy(proxy);
-
- QBarDataProxy *barDataProxy = static_cast<QBarDataProxy *>(m_data);
-
- QObject::connect(barDataProxy, &QBarDataProxy::arrayReset, this,
- &Bars3DController::handleArrayReset);
- QObject::connect(barDataProxy, &QBarDataProxy::rowsAdded, this,
- &Bars3DController::handleRowsAdded);
- QObject::connect(barDataProxy, &QBarDataProxy::rowsChanged, this,
- &Bars3DController::handleRowsChanged);
- QObject::connect(barDataProxy, &QBarDataProxy::rowsRemoved, this,
- &Bars3DController::handleRowsRemoved);
- QObject::connect(barDataProxy, &QBarDataProxy::rowsInserted, this,
- &Bars3DController::handleRowsInserted);
- QObject::connect(barDataProxy, &QBarDataProxy::itemChanged, this,
- &Bars3DController::handleItemChanged);
- QObject::connect(barDataProxy, &QBarDataProxy::rowLabelsChanged, this,
- &Bars3DController::handleDataRowLabelsChanged);
- QObject::connect(barDataProxy, &QBarDataProxy::columnLabelsChanged, this,
- &Bars3DController::handleDataColumnLabelsChanged);
-
- scene()->setSlicingActive(false);
- adjustAxisRanges();
-
- // Always clear selection on proxy change
- setSelectedBarPos(noSelectionPoint());
-
- handleDataRowLabelsChanged();
- handleDataColumnLabelsChanged();
- m_isDataDirty = true;
- emitNeedRender();
-}
-
void Bars3DController::handleArrayReset()
{
- scene()->setSlicingActive(false);
adjustAxisRanges();
m_isDataDirty = true;
// Clear selection unless still valid
- setSelectedBarPos(m_selectedBarPos);
+ setSelectedBar(m_selectedBar, m_selectedBarSeries);
emitNeedRender();
}
@@ -151,8 +109,6 @@ void Bars3DController::handleRowsAdded(int startIndex, int count)
{
Q_UNUSED(startIndex)
Q_UNUSED(count)
- // TODO should update slice instead of deactivating?
- scene()->setSlicingActive(false);
adjustAxisRanges();
m_isDataDirty = true;
emitNeedRender();
@@ -162,8 +118,6 @@ void Bars3DController::handleRowsChanged(int startIndex, int count)
{
Q_UNUSED(startIndex)
Q_UNUSED(count)
- // TODO should update slice instead of deactivating?
- scene()->setSlicingActive(false);
adjustAxisRanges();
m_isDataDirty = true;
emitNeedRender();
@@ -173,13 +127,11 @@ void Bars3DController::handleRowsRemoved(int startIndex, int count)
{
Q_UNUSED(startIndex)
Q_UNUSED(count)
- // TODO should update slice instead of deactivating?
- scene()->setSlicingActive(false);
adjustAxisRanges();
m_isDataDirty = true;
// Clear selection unless still valid
- setSelectedBarPos(m_selectedBarPos);
+ setSelectedBar(m_selectedBar, m_selectedBarSeries);
emitNeedRender();
}
@@ -188,8 +140,6 @@ void Bars3DController::handleRowsInserted(int startIndex, int count)
{
Q_UNUSED(startIndex)
Q_UNUSED(count)
- // TODO should update slice instead of deactivating?
- scene()->setSlicingActive(false);
adjustAxisRanges();
m_isDataDirty = true;
emitNeedRender();
@@ -199,8 +149,6 @@ void Bars3DController::handleItemChanged(int rowIndex, int columnIndex)
{
Q_UNUSED(rowIndex)
Q_UNUSED(columnIndex)
- // TODO should update slice instead of deactivating?
- scene()->setSlicingActive(false);
adjustAxisRanges();
m_isDataDirty = true;
emitNeedRender();
@@ -208,36 +156,39 @@ void Bars3DController::handleItemChanged(int rowIndex, int columnIndex)
void Bars3DController::handleDataRowLabelsChanged()
{
- if (m_axisX && m_data) {
+ QBar3DSeries *firstSeries = 0;
+ if (m_seriesList.size())
+ firstSeries = static_cast<QBar3DSeries *>(m_seriesList.at(0));
+ if (m_axisZ && firstSeries && firstSeries->dataProxy()) {
// Grab a sublist equal to data window (no need to have more labels in axis)
- int min = int(m_axisX->min());
- int count = int(m_axisX->max()) - min + 1;
- QStringList subList = static_cast<QBarDataProxy *>(m_data)->rowLabels().mid(min, count);
- static_cast<Q3DCategoryAxis *>(m_axisX)->dptr()->setDataLabels(subList);
+ int min = int(m_axisZ->min());
+ int count = int(m_axisZ->max()) - min + 1;
+ QStringList subList = firstSeries->dataProxy()->rowLabels().mid(min, count);
+ static_cast<Q3DCategoryAxis *>(m_axisZ)->dptr()->setDataLabels(subList);
}
}
void Bars3DController::handleDataColumnLabelsChanged()
{
- if (m_axisZ && m_data) {
+ QBar3DSeries *firstSeries = 0;
+ if (m_seriesList.size())
+ firstSeries = static_cast<QBar3DSeries *>(m_seriesList.at(0));
+ if (m_axisX && firstSeries && firstSeries->dataProxy()) {
// Grab a sublist equal to data window (no need to have more labels in axis)
- int min = int(m_axisZ->min());
- int count = int(m_axisZ->max()) - min + 1;
- QStringList subList = static_cast<QBarDataProxy *>(m_data)->columnLabels().mid(min, count);
- static_cast<Q3DCategoryAxis *>(m_axisZ)->dptr()->setDataLabels(subList);
+ int min = int(m_axisX->min());
+ int count = int(m_axisX->max()) - min + 1;
+ QStringList subList = static_cast<QBarDataProxy *>(firstSeries->dataProxy())
+ ->columnLabels().mid(min, count);
+ static_cast<Q3DCategoryAxis *>(m_axisX)->dptr()->setDataLabels(subList);
}
}
-void Bars3DController::handleSelectedBarPosChanged(const QPoint &position)
+void Bars3DController::handleBarClicked(const QPoint &position, QBar3DSeries *series)
{
- QPoint pos = position;
- if (pos == QPoint(255, 255))
- pos = noSelectionPoint();
- if (pos != m_selectedBarPos) {
- m_selectedBarPos = pos;
- emit selectedBarPosChanged(pos);
- emitNeedRender();
- }
+ setSelectedBar(position, series);
+
+ // TODO: pass clicked to parent. (QTRD-2517)
+ // TODO: Also hover needed? (QTRD-2131)
}
void Bars3DController::handleAxisAutoAdjustRangeChangedInOrientation(
@@ -248,41 +199,97 @@ void Bars3DController::handleAxisAutoAdjustRangeChangedInOrientation(
adjustAxisRanges();
}
-QPoint Bars3DController::noSelectionPoint()
+void Bars3DController::handleSeriesVisibilityChangedBySender(QObject *sender)
+{
+ Abstract3DController::handleSeriesVisibilityChangedBySender(sender);
+
+ // Visibility changes may require disabling/enabling slicing,
+ // so just reset selection to ensure everything is still valid.
+ setSelectedBar(m_selectedBar, m_selectedBarSeries);
+}
+
+QPoint Bars3DController::invalidSelectionPosition()
{
- static QPoint noSelectionPos(-1, -1);
- return noSelectionPos;
+ static QPoint invalidSelectionPos(-1, -1);
+ return invalidSelectionPos;
}
void Bars3DController::setAxisX(Q3DAbstractAxis *axis)
{
Abstract3DController::setAxisX(axis);
- handleDataRowLabelsChanged();
+ handleDataColumnLabelsChanged();
}
void Bars3DController::setAxisZ(Q3DAbstractAxis *axis)
{
Abstract3DController::setAxisZ(axis);
- handleDataColumnLabelsChanged();
+ handleDataRowLabelsChanged();
+}
+
+void Bars3DController::addSeries(QAbstract3DSeries *series)
+{
+ Q_ASSERT(series && series->type() == QAbstract3DSeries::SeriesTypeBar);
+
+ bool firstAdded = !m_seriesList.size();
+
+ Abstract3DController::addSeries(series);
+
+ if (firstAdded) {
+ adjustAxisRanges();
+
+ handleDataRowLabelsChanged();
+ handleDataColumnLabelsChanged();
+ }
+
+ QBar3DSeries *barSeries = static_cast<QBar3DSeries *>(series);
+ if (barSeries->selectedBar() != invalidSelectionPosition())
+ setSelectedBar(barSeries->selectedBar(), barSeries);
+}
+
+void Bars3DController::removeSeries(QAbstract3DSeries *series)
+{
+ bool firstRemoved = (m_seriesList.size() && m_seriesList.at(0) == series);
+
+ Abstract3DController::removeSeries(series);
+
+ if (m_selectedBarSeries == series)
+ setSelectedBar(invalidSelectionPosition(), 0);
+
+ if (firstRemoved) {
+ adjustAxisRanges();
+
+ handleDataRowLabelsChanged();
+ handleDataColumnLabelsChanged();
+ }
+}
+
+QList<QBar3DSeries *> Bars3DController::barSeriesList()
+{
+ QList<QAbstract3DSeries *> abstractSeriesList = seriesList();
+ QList<QBar3DSeries *> barSeriesList;
+ foreach (QAbstract3DSeries *abstractSeries, abstractSeriesList) {
+ QBar3DSeries *barSeries = qobject_cast<QBar3DSeries *>(abstractSeries);
+ if (barSeries)
+ barSeriesList.append(barSeries);
+ }
+
+ return barSeriesList;
}
void Bars3DController::handleAxisRangeChangedBySender(QObject *sender)
{
// Data window changed
if (sender == m_axisX || sender == m_axisZ) {
- // Disable zoom mode if we're in it (causes crash if not, as zoom selection is deleted)
- scene()->setSlicingActive(false);
-
- // Clear selection unless still valid
- setSelectedBarPos(m_selectedBarPos);
-
if (sender == m_axisX)
- handleDataRowLabelsChanged();
- if (sender == m_axisZ)
handleDataColumnLabelsChanged();
+ if (sender == m_axisZ)
+ handleDataRowLabelsChanged();
}
Abstract3DController::handleAxisRangeChangedBySender(sender);
+
+ // Update selected bar - may be moved offscreen
+ setSelectedBar(m_selectedBar, m_selectedBarSeries);
}
void Bars3DController::setBarSpecs(GLfloat thicknessRatio, const QSizeF &spacing, bool relative)
@@ -310,109 +317,182 @@ bool Bars3DController::isBarSpecRelative()
return m_isBarSpecRelative;
}
-void Bars3DController::setBarType(QDataVis::MeshStyle style, bool smooth)
-{
- QString objFile;
- if (style == QDataVis::MeshStyleBars)
- objFile = QStringLiteral(":/defaultMeshes/bar");
- else if (style == QDataVis::MeshStylePyramids)
- objFile = QStringLiteral(":/defaultMeshes/pyramid");
- else if (style == QDataVis::MeshStyleCones)
- objFile = QStringLiteral(":/defaultMeshes/cone");
- else if (style == QDataVis::MeshStyleCylinders)
- objFile = QStringLiteral(":/defaultMeshes/cylinder");
- else if (style == QDataVis::MeshStyleBevelBars)
- objFile = QStringLiteral(":/defaultMeshes/bevelbar");
-
- if (smooth)
- objFile += QStringLiteral("Smooth");
-
- Abstract3DController::setMeshFileName(objFile);
-}
-
-void Bars3DController::setSelectionMode(QDataVis::SelectionMode mode)
+void Bars3DController::setSelectionMode(QDataVis::SelectionFlags mode)
{
- // Disable zoom if selection mode changes
- scene()->setSlicingActive(false);
- Abstract3DController::setSelectionMode(mode);
+ if (mode.testFlag(QDataVis::SelectionSlice)
+ && (mode.testFlag(QDataVis::SelectionRow) == mode.testFlag(QDataVis::SelectionColumn))) {
+ qWarning("Must specify one of either row or column selection mode in conjunction with slicing mode.");
+ } else {
+ QDataVis::SelectionFlags oldMode = selectionMode();
+
+ Abstract3DController::setSelectionMode(mode);
+
+ if (mode != oldMode) {
+ // Refresh selection upon mode change to ensure slicing is correctly updated
+ // according to series the visibility.
+ setSelectedBar(m_selectedBar, m_selectedBarSeries);
+
+ // Special case: Always deactivate slicing when changing away from slice
+ // automanagement, as this can't be handled in setSelectedBar.
+ if (!mode.testFlag(QDataVis::SelectionSlice)
+ && oldMode.testFlag(QDataVis::SelectionSlice)) {
+ scene()->setSlicingActive(false);
+ }
+ }
+ }
}
-void Bars3DController::setSelectedBarPos(const QPoint &position)
+void Bars3DController::setSelectedBar(const QPoint &position, QBar3DSeries *series)
{
- // If the selection is outside data window or targets non-existent
- // bar, clear selection instead.
+ // If the selection targets non-existent bar, clear selection instead.
QPoint pos = position;
- if (pos != noSelectionPoint()) {
- int minRow = int(m_axisX->min());
- int maxRow = int(m_axisX->max());
- int minCol = int(m_axisZ->min());
- int maxCol = int(m_axisZ->max());
+ // Series may already have been removed, so check it before setting the selection.
+ if (!m_seriesList.contains(series))
+ series = 0;
+
+ adjustSelectionPosition(pos, series);
- if (pos.x() < minRow || pos.x() > maxRow || pos.y() < minCol || pos.y() > maxCol
- || pos.x() + minRow >= static_cast<QBarDataProxy *>(m_data)->rowCount()
- || pos.y() + minCol >= static_cast<QBarDataProxy *>(m_data)->rowAt(pos.x())->size()) {
- pos = noSelectionPoint();
+ if (selectionMode().testFlag(QDataVis::SelectionSlice)) {
+ // If the selected bar is outside data window, or there is no visible selected bar, disable slicing
+ if (pos.x() < m_axisZ->min() || pos.x() > m_axisZ->max()
+ || pos.y() < m_axisX->min() || pos.y() > m_axisX->max()
+ || !series->isVisible()) {
+ scene()->setSlicingActive(false);
+ } else {
+ scene()->setSlicingActive(true);
}
+ emitNeedRender();
}
- if (pos != m_selectedBarPos) {
- m_selectedBarPos = pos;
- m_changeTracker.selectedBarPosChanged = true;
- emit selectedBarPosChanged(pos);
+ if (pos != m_selectedBar || series != m_selectedBarSeries) {
+ m_selectedBar = pos;
+ m_selectedBarSeries = series;
+ m_changeTracker.selectedBarChanged = true;
+
+ // Clear selection from other series and finally set new selection to the specified series
+ foreach (QAbstract3DSeries *otherSeries, m_seriesList) {
+ QBar3DSeries *barSeries = static_cast<QBar3DSeries *>(otherSeries);
+ if (barSeries != m_selectedBarSeries)
+ barSeries->dptr()->setSelectedBar(invalidSelectionPosition());
+ }
+ if (m_selectedBarSeries)
+ m_selectedBarSeries->dptr()->setSelectedBar(m_selectedBar);
+
emitNeedRender();
}
}
-QPoint Bars3DController::selectedBarPos() const
-{
- return m_selectedBarPos;
-}
-
void Bars3DController::adjustAxisRanges()
{
- const QBarDataProxy *proxy = static_cast<QBarDataProxy *>(m_data);
- const QBarDataArray *array = proxy->array();
-
+ Q3DCategoryAxis *categoryAxisZ = static_cast<Q3DCategoryAxis *>(m_axisZ);
Q3DCategoryAxis *categoryAxisX = static_cast<Q3DCategoryAxis *>(m_axisX);
- if (categoryAxisX && categoryAxisX->isAutoAdjustRange() && proxy) {
- int rowCount = proxy->rowCount();
- if (rowCount)
- rowCount--;
- categoryAxisX->dptr()->setRange(0.0, qreal(rowCount));
- }
+ Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(m_axisY);
- Q3DCategoryAxis *categoryAxisZ = static_cast<Q3DCategoryAxis *>(m_axisZ);
- if (categoryAxisZ && categoryAxisZ->isAutoAdjustRange() && proxy) {
- int columnCount = 0;
- for (int i = 0; i < array->size(); i++) {
- if (columnCount < array->at(i)->size())
- columnCount = array->at(i)->size();
+ bool adjustZ = (categoryAxisZ && categoryAxisZ->isAutoAdjustRange());
+ bool adjustX = (categoryAxisX && categoryAxisX->isAutoAdjustRange());
+ bool adjustY = (valueAxis && categoryAxisX && categoryAxisZ && valueAxis->isAutoAdjustRange());
+
+ if (adjustZ || adjustX || adjustY) {
+ int maxRowCount = 1;
+ int maxColumnCount = 1;
+ float minValue = 0.0f;
+ float maxValue = 0.0f;
+
+ // First figure out row and column counts
+ int seriesCount = m_seriesList.size();
+ if (adjustZ || adjustX) {
+ for (int series = 0; series < seriesCount; series++) {
+ const QBar3DSeries *barSeries = static_cast<QBar3DSeries *>(m_seriesList.at(series));
+ if (barSeries->isVisible()) {
+ const QBarDataProxy *proxy = barSeries->dataProxy();
+
+ if (adjustZ && proxy) {
+ int rowCount = proxy->rowCount();
+ if (rowCount)
+ rowCount--;
+
+ maxRowCount = qMax(maxRowCount, rowCount);
+ }
+
+ if (adjustX && proxy) {
+ const QBarDataArray *array = proxy->array();
+ int columnCount = 0;
+ for (int i = 0; i < array->size(); i++) {
+ if (columnCount < array->at(i)->size())
+ columnCount = array->at(i)->size();
+ }
+ if (columnCount)
+ columnCount--;
+
+ maxColumnCount = qMax(maxColumnCount, columnCount);
+ }
+ }
+ }
+ // Call private implementations of setRange to avoid unsetting auto adjust flag
+ if (adjustZ)
+ categoryAxisZ->dptr()->setRange(0.0f, float(maxRowCount));
+ if (adjustX)
+ categoryAxisX->dptr()->setRange(0.0f, float(maxColumnCount));
}
- if (columnCount)
- columnCount--;
- categoryAxisZ->dptr()->setRange(0.0, qreal(columnCount));
- }
- Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(m_axisY);
- if (valueAxis && categoryAxisX && categoryAxisZ && valueAxis->isAutoAdjustRange() && proxy) {
- QPair<GLfloat, GLfloat> limits = proxy->dptrc()->limitValues(categoryAxisX->min(),
- categoryAxisX->max(),
- categoryAxisZ->min(),
- categoryAxisZ->max());
- if (limits.first < 0) {
- // TODO: Currently we only support symmetric y-axis for bar graph if there are negative values
- qreal maxAbs = qMax(qFabs(limits.first), qFabs(limits.second));
- // Call private implementation to avoid unsetting auto adjust flag
- valueAxis->dptr()->setRange(-maxAbs, maxAbs);
- } else if (limits.second == 0.0) {
- valueAxis->dptr()->setRange(0.0, 1.0); // Only zero value values in data set, set range to something.
- } else {
- valueAxis->dptr()->setRange(0.0, limits.second);
+ // Now that we know the row and column ranges, figure out the value axis range
+ if (adjustY) {
+ for (int series = 0; series < seriesCount; series++) {
+ const QBar3DSeries *barSeries = static_cast<QBar3DSeries *>(m_seriesList.at(series));
+ if (barSeries->isVisible()) {
+ const QBarDataProxy *proxy = barSeries->dataProxy();
+ if (adjustY && proxy) {
+ QPair<GLfloat, GLfloat> limits = proxy->dptrc()->limitValues(categoryAxisZ->min(),
+ categoryAxisZ->max(),
+ categoryAxisX->min(),
+ categoryAxisX->max());
+ if (!series) {
+ // First series initializes the values
+ minValue = limits.first;
+ maxValue = limits.second;
+ } else {
+ minValue = qMin(minValue, limits.first);
+ maxValue = qMax(maxValue, limits.second);
+ }
+ }
+ }
+ }
+
+ if (maxValue < 0.0f)
+ maxValue = 0.0f;
+ if (minValue > 0.0f)
+ minValue = 0.0f;
+ if (minValue == 0.0f && maxValue == 0.0f) {
+ // Only zero value values in data set, set range to something.
+ minValue = 0.0f;
+ maxValue = 1.0f;
+ }
+ valueAxis->dptr()->setRange(minValue, maxValue);
}
}
}
+// Invalidate selection position if outside data for the series
+void Bars3DController::adjustSelectionPosition(QPoint &pos, const QBar3DSeries *series)
+{
+ const QBarDataProxy *proxy = 0;
+ if (series)
+ proxy = series->dataProxy();
+
+ if (!proxy)
+ pos = invalidSelectionPosition();
+
+ if (pos != invalidSelectionPosition()) {
+ int maxRow = proxy->rowCount() - 1;
+ int maxCol = (pos.x() <= maxRow && pos.x() >= 0 && proxy->rowAt(pos.x()))
+ ? proxy->rowAt(pos.x())->size() - 1 : -1;
+
+ if (pos.x() < 0 || pos.x() > maxRow || pos.y() < 0 || pos.y() > maxCol)
+ pos = invalidSelectionPosition();
+ }
+}
+
Q3DAbstractAxis *Bars3DController::createDefaultAxis(Q3DAbstractAxis::AxisOrientation orientation)
{
Q3DAbstractAxis *defaultAxis = 0;
diff --git a/src/datavisualization/engine/bars3dcontroller_p.h b/src/datavisualization/engine/bars3dcontroller_p.h
index 8398dd81..54385571 100644
--- a/src/datavisualization/engine/bars3dcontroller_p.h
+++ b/src/datavisualization/engine/bars3dcontroller_p.h
@@ -37,17 +37,17 @@
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class Bars3DRenderer;
-class QBarDataProxy;
+class QBar3DSeries;
struct Bars3DChangeBitField {
bool slicingActiveChanged : 1;
bool barSpecsChanged : 1;
- bool selectedBarPosChanged : 1;
+ bool selectedBarChanged : 1;
Bars3DChangeBitField() :
slicingActiveChanged(true),
barSpecsChanged(true),
- selectedBarPosChanged(true)
+ selectedBarChanged(true)
{
}
};
@@ -60,7 +60,9 @@ private:
Bars3DChangeBitField m_changeTracker;
// Interaction
- QPoint m_selectedBarPos; // Points to row & column in data window.
+ QPoint m_selectedBar; // Points to row & column in data window.
+ QBar3DSeries *m_selectedBarSeries; // Points to the series for which the bar is selected in
+ // single series selection cases.
// Look'n'feel
bool m_isBarSpecRelative;
@@ -74,7 +76,7 @@ public:
explicit Bars3DController(QRect rect);
~Bars3DController();
- void initializeOpenGL();
+ virtual void initializeOpenGL();
virtual void synchDataToRenderer();
// bar thickness, spacing between bars, and is spacing relative to thickness or absolute
@@ -87,24 +89,21 @@ public:
QSizeF barSpacing();
bool isBarSpecRelative();
- // bar type; bars (=cubes), pyramids, cones, cylinders, etc.
- void setBarType(QDataVis::MeshStyle style, bool smooth = false);
-
- // Change selection mode; single bar, bar and row, bar and column, or all
- void setSelectionMode(QDataVis::SelectionMode mode);
-
- void setSelectedBarPos(const QPoint &position);
- QPoint selectedBarPos() const;
-
- virtual void setActiveDataProxy(QAbstractDataProxy *proxy);
+ void setSelectionMode(QDataVis::SelectionFlags mode);
+ void setSelectedBar(const QPoint &position, QBar3DSeries *series);
virtual void handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust);
+ virtual void handleSeriesVisibilityChangedBySender(QObject *sender);
- static QPoint noSelectionPoint();
+ static QPoint invalidSelectionPosition();
virtual void setAxisX(Q3DAbstractAxis *axis);
virtual void setAxisZ(Q3DAbstractAxis *axis);
+ virtual void addSeries(QAbstract3DSeries *series);
+ virtual void removeSeries(QAbstract3DSeries *series);
+ virtual QList<QBar3DSeries *> barSeriesList();
+
virtual void handleAxisRangeChangedBySender(QObject *sender);
public slots:
@@ -117,16 +116,15 @@ public slots:
void handleDataRowLabelsChanged();
void handleDataColumnLabelsChanged();
- void handleSelectedBarPosChanged(const QPoint &position);
-
-signals:
- void selectedBarPosChanged(QPoint position);
+ // Renderer callback handlers
+ void handleBarClicked(const QPoint &position, QBar3DSeries *series);
protected:
virtual Q3DAbstractAxis *createDefaultAxis(Q3DAbstractAxis::AxisOrientation orientation);
private:
void adjustAxisRanges();
+ void adjustSelectionPosition(QPoint &pos, const QBar3DSeries *series);
Q_DISABLE_COPY(Bars3DController)
diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp
index c7c2f64c..ecdac21f 100644
--- a/src/datavisualization/engine/bars3drenderer.cpp
+++ b/src/datavisualization/engine/bars3drenderer.cpp
@@ -22,11 +22,11 @@
#include "shaderhelper_p.h"
#include "objecthelper_p.h"
#include "texturehelper_p.h"
-#include "theme_p.h"
#include "utils_p.h"
#include "drawer_p.h"
#include "qbardataitem.h"
#include "q3dlight.h"
+#include "qbar3dseries_p.h"
#include <QMatrix4x4>
#include <QMouseEvent>
@@ -42,17 +42,15 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
const GLfloat labelMargin = 0.05f;
const GLfloat gridLineWidth = 0.005f;
-static QVector3D selectionSkipColor = QVector3D(255, 255, 255); // Selection texture's background color
-const int smallerVPSize = 5;
+
+const bool sliceGridLabels = true; // TODO: Make this user controllable (QTRD-2546)
Bars3DRenderer::Bars3DRenderer(Bars3DController *controller)
: Abstract3DRenderer(controller),
- m_controller(controller),
m_cachedIsSlicingActivated(false),
m_cachedRowCount(0),
m_cachedColumnCount(0),
m_selectedBar(0),
- m_sliceSelection(0),
m_sliceCache(0),
m_sliceTitleItem(0),
m_xFlipped(false),
@@ -60,11 +58,11 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller)
m_yFlipped(false),
m_updateLabels(false),
m_barShader(0),
+ m_barGradientShader(0),
m_depthShader(0),
m_selectionShader(0),
m_backgroundShader(0),
m_labelShader(0),
- m_barObj(0),
m_backgroundObj(0),
m_gridLineObj(0),
m_labelObj(0),
@@ -77,7 +75,7 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller)
m_shadowQualityToShader(100.0f),
m_shadowQualityMultiplier(3),
m_heightNormalizer(1.0f),
- m_yAdjustment(0.0f),
+ m_negativeBackgroundAdjustment(0.0f),
m_rowWidth(0),
m_columnDepth(0),
m_maxDimension(0),
@@ -85,9 +83,15 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller)
m_scaleZ(0),
m_scaleFactor(0),
m_maxSceneSize(40.0f),
- m_selection(selectionSkipColor),
- m_previousSelection(selectionSkipColor),
- m_hasHeightAdjustmentChanged(true)
+ m_visualSelectedBarPos(Bars3DController::invalidSelectionPosition()),
+ m_visualSelectedBarSeriesIndex(-1),
+ m_hasHeightAdjustmentChanged(true),
+ m_selectedBarPos(Bars3DController::invalidSelectionPosition()),
+ m_selectedBarSeries(0),
+ m_noZeroInRange(false),
+ m_seriesScale(0.0f),
+ m_seriesStep(0.0f),
+ m_seriesStart(0.0f)
{
initializeOpenGLFunctions();
initializeOpenGL();
@@ -100,15 +104,12 @@ Bars3DRenderer::~Bars3DRenderer()
m_textureHelper->deleteTexture(&m_selectionTexture);
m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer);
m_textureHelper->deleteTexture(&m_bgrTexture);
- if (m_sliceSelection) {
- m_sliceSelection->clear(); // Slice doesn't own its items
- delete m_sliceSelection;
- }
+
delete m_barShader;
+ delete m_barGradientShader;
delete m_depthShader;
delete m_selectionShader;
delete m_backgroundShader;
- delete m_barObj;
delete m_backgroundObj;
delete m_gridLineObj;
delete m_labelObj;
@@ -120,8 +121,6 @@ void Bars3DRenderer::initializeOpenGL()
Abstract3DRenderer::initializeOpenGL();
// Initialize shaders
- handleShadowQualityChange();
-
initLabelShaders(QStringLiteral(":/shaders/vertexLabel"),
QStringLiteral(":/shaders/fragmentLabel"));
@@ -139,34 +138,35 @@ void Bars3DRenderer::initializeOpenGL()
// Load label mesh
loadLabelMesh();
- // Set view port
- glViewport(m_sliceViewPort.x(), m_sliceViewPort.y(),
- m_sliceViewPort.width(), m_sliceViewPort.height());
-
// Load background mesh (we need to be initialized first)
loadBackgroundMesh();
}
-void Bars3DRenderer::updateDataModel(QBarDataProxy *dataProxy)
+void Bars3DRenderer::updateData()
{
- int minRow = m_axisCacheX.min();
- int maxRow = m_axisCacheX.max();
- int minCol = m_axisCacheZ.min();
- int maxCol = m_axisCacheZ.max();
+ int seriesCount = m_visibleSeriesList.size();
+ int minRow = m_axisCacheZ.min();
+ int maxRow = m_axisCacheZ.max();
+ int minCol = m_axisCacheX.min();
+ int maxCol = m_axisCacheX.max();
int newRows = maxRow - minRow + 1;
int newColumns = maxCol - minCol + 1;
- if (newRows != m_renderItemArray.size() || newColumns != m_renderItemArray.at(0).size()) {
- // Destroy old render items and reallocate new array
- m_renderItemArray.clear();
- m_renderItemArray.resize(newRows);
- for (int i = 0; i < newRows; i++)
- m_renderItemArray[i].resize(newColumns);
+ int updateSize = 0;
+ int dataRowCount = 0;
+ int maxDataRowCount = 0;
+
+ if (m_renderingArrays.size() != seriesCount) {
+ m_renderingArrays.resize(seriesCount);
+ m_seriesScale = 1.0f / float(seriesCount);
+ m_seriesStep = 1.0f / float(seriesCount);
+ m_seriesStart = -((float(seriesCount) - 1.0f) / 2.0f) * m_seriesStep;
+ }
+ if (m_cachedRowCount != newRows || m_cachedColumnCount != newColumns) {
// Force update for selection related items
m_sliceCache = 0;
m_sliceTitleItem = 0;
- if (m_sliceSelection)
- m_sliceSelection->clear();
+ m_sliceSelection.clear();
m_cachedColumnCount = newColumns;
m_cachedRowCount = newRows;
@@ -178,62 +178,81 @@ void Bars3DRenderer::updateDataModel(QBarDataProxy *dataProxy)
calculateSceneScalingFactors();
}
- // Update cached data window
- int dataRowCount = dataProxy->rowCount();
- int dataRowIndex = minRow;
- int updateSize = 0;
- for (int i = 0; i < newRows; i++) {
- int j = 0;
- if (dataRowIndex < dataRowCount) {
- const QBarDataRow *dataRow = dataProxy->rowAt(dataRowIndex);
- updateSize = qMin((dataRow->size() - minCol), m_renderItemArray[i].size());
- if (dataRow) {
- int dataColIndex = minCol;
- for (; j < updateSize ; j++) {
- qreal value = dataRow->at(dataColIndex).value();
- m_renderItemArray[i][j].setValue(value);
- m_renderItemArray[i][j].setHeight(GLfloat(value) / m_heightNormalizer);
- dataColIndex++;
+ for (int series = 0; series < seriesCount; series++) {
+ if (newRows != m_renderingArrays.at(series).size()
+ || newColumns != m_renderingArrays.at(series).at(0).size()) {
+ // Destroy old render items and reallocate new array
+ m_renderingArrays[series].resize(newRows);
+ for (int i = 0; i < newRows; i++)
+ m_renderingArrays[series][i].resize(newColumns);
+ }
+
+ // Update cached data window
+ QBarDataProxy *dataProxy =
+ static_cast<QBar3DSeries *>(m_visibleSeriesList.at(series).series())->dataProxy();
+ dataRowCount = dataProxy->rowCount();
+ if (maxDataRowCount < dataRowCount)
+ maxDataRowCount = qMin(dataRowCount, newRows);
+ int dataRowIndex = minRow;
+ GLfloat heightValue = 0.0f;
+ for (int i = 0; i < newRows; i++) {
+ int j = 0;
+ if (dataRowIndex < dataRowCount) {
+ const QBarDataRow *dataRow = dataProxy->rowAt(dataRowIndex);
+ updateSize = qMin((dataRow->size() - minCol),
+ m_renderingArrays.at(series).at(i).size());
+ if (dataRow) {
+ int dataColIndex = minCol;
+ for (; j < updateSize ; j++) {
+ float value = dataRow->at(dataColIndex).value();
+ if (!m_noZeroInRange) {
+ heightValue = GLfloat(value);
+ } else {
+ // Adjust height to range
+ if (!m_hasNegativeValues) {
+ heightValue = value - m_axisCacheY.min();
+ if (heightValue < 0.0f)
+ heightValue = 0.0f;
+ } else if (m_axisCacheY.max() < 0.0f) {
+ heightValue = value - m_axisCacheY.max();
+ if (heightValue > 0.0f)
+ heightValue = 0.0f;
+ }
+ }
+ m_renderingArrays[series][i][j].setValue(value);
+ m_renderingArrays[series][i][j].setHeight(heightValue / m_heightNormalizer);
+ dataColIndex++;
+ }
}
}
+ for (; j < m_renderingArrays.at(series).at(i).size(); j++) {
+ m_renderingArrays[series][i][j].setValue(0.0f);
+ m_renderingArrays[series][i][j].setHeight(0.0f);
+ }
+ dataRowIndex++;
}
- for (; j < m_renderItemArray[i].size(); j++) {
- m_renderItemArray[i][j].setValue(0.0);
- m_renderItemArray[i][j].setHeight(0.0f);
- }
- dataRowIndex++;
}
- m_renderColumns = updateSize;
- m_renderRows = qMin((dataRowCount - minRow), m_renderItemArray.size());
-
- Abstract3DRenderer::updateDataModel(dataProxy);
+ // Reset selected bar to update selection
+ updateSelectedBar(m_selectedBarPos, m_selectedBarSeries);
}
void Bars3DRenderer::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);
-
// TODO: See QTRD-2374
if (m_hasNegativeValues)
scene->activeCamera()->setMinYRotation(-90.0);
else
- scene->activeCamera()->setMinYRotation(0.0);
+ scene->activeCamera()->setMinYRotation(0.0f);
if (m_hasHeightAdjustmentChanged) {
// Set initial camera position. Also update if height adjustment has changed.
scene->activeCamera()->setBaseOrientation(cameraDistanceVector,
- QVector3D(0.0f, -m_yAdjustment, 0.0f),
+ zeroVector,
upVector);
m_hasHeightAdjustmentChanged = false;
}
- scene->activeCamera()->d_ptr->updateViewMatrix(m_autoScaleAdjustment);
- // Set light position (rotate light with camera, a bit above it (as set in defaultLightPos))
- scene->setLightPositionRelativeToCamera(defaultLightPos);
-
Abstract3DRenderer::updateScene(scene);
updateSlicingActive(scene->isSlicingActive());
@@ -241,48 +260,29 @@ void Bars3DRenderer::updateScene(Q3DScene *scene)
void Bars3DRenderer::render(GLuint defaultFboHandle)
{
- bool slicingChanged = m_cachedIsSlicingActivated != m_cachedScene->isSlicingActive();
-
// Handle GL state setup for FBO buffers and clearing of the render surface
Abstract3DRenderer::render(defaultFboHandle);
- // Draw bars scene
drawScene(defaultFboHandle);
-
- // If slice selection is on, draw the sliced scene
if (m_cachedIsSlicingActivated)
- drawSlicedScene(m_axisCacheX.titleItem(), m_axisCacheY.titleItem(), m_axisCacheZ.titleItem());
-
- // If slicing has been activated by this render pass, we need another render
- // Also trigger another render always when slicing changes in general to ensure
- // final draw is correct.
- if (m_cachedIsSlicingActivated != m_cachedScene->isSlicingActive() || slicingChanged)
- emit needRender();
+ drawSlicedScene();
}
-void Bars3DRenderer::drawSlicedScene(const LabelItem &xLabel,
- const LabelItem &yLabel,
- const LabelItem &zLabel)
+void Bars3DRenderer::drawSlicedScene()
{
GLfloat barPosX = 0;
- GLint startBar = 0;
- GLint stopBar = m_sliceSelection->size();
- GLint stepBar = 1;
QVector3D lightPos;
- GLfloat negativesComp = 1.0f;
-
- // Compensate bar scaling a bit to avoid drawing on axis titles when we have negative values
- if (m_hasNegativeValues)
- negativesComp = 0.67f;
// Specify viewport
- glViewport(m_sliceViewPort.x(), m_sliceViewPort.y(),
- m_sliceViewPort.width(), m_sliceViewPort.height());
+ glViewport(m_secondarySubViewport.x(),
+ m_secondarySubViewport.y(),
+ m_secondarySubViewport.width(),
+ m_secondarySubViewport.height());
// Set up projection matrix
QMatrix4x4 projectionMatrix;
- projectionMatrix.perspective(40.0f, (GLfloat)m_sliceViewPort.width()
- / (GLfloat)m_sliceViewPort.height(), 0.1f, 10.0f);
+ projectionMatrix.perspective(40.0f, (GLfloat)m_secondarySubViewport.width()
+ / (GLfloat)m_secondarySubViewport.height(), 0.1f, 100.0f);
// Set view matrix
QMatrix4x4 viewMatrix;
@@ -293,89 +293,276 @@ void Bars3DRenderer::drawSlicedScene(const LabelItem &xLabel,
viewMatrix.lookAt(QVector3D(0.0f, 0.0f, camZPosSliced), zeroVector, upVector);
// Set light position
- lightPos = QVector3D(0.0f, -m_yAdjustment, camZPosSliced * 2.0f);
+ lightPos = QVector3D(0.0f, 0.0f, camZPosSliced * 2.0f);
- // Bind bar shader
- m_barShader->bind();
+ const Q3DCamera *activeCamera = m_cachedScene->activeCamera();
+
+ // Draw the selected row / column
+ GLfloat barPosYAdjustment = -0.8f; // Positives only -> translate to -1.0 + 0.2 for row/column labels
+ if (m_hasNegativeValues) {
+ if (m_noZeroInRange)
+ barPosYAdjustment = 1.2f; // Negatives only -> translate to 1.0 + 0.2 for row/column labels
+ else
+ barPosYAdjustment = 0.2f; // Both -> translate to 0.0 + 0.2 for row/column labels
+ }
+ QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix;
+ bool rowMode = m_cachedSelectionMode.testFlag(QDataVis::SelectionRow);
+ bool itemMode = m_cachedSelectionMode.testFlag(QDataVis::SelectionItem);
+
+ // Draw grid lines
+ if (m_cachedTheme->isGridEnabled()) {
+ glDisable(GL_DEPTH_TEST);
+ ShaderHelper *lineShader = m_backgroundShader;
+ // Bind line shader
+ lineShader->bind();
+
+ // Set unchanging shader bindings
+ QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
+ lineShader->setUniformValue(lineShader->lightP(), lightPos);
+ lineShader->setUniformValue(lineShader->view(), viewMatrix);
+ lineShader->setUniformValue(lineShader->color(), lineColor);
+ lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme->ambientLightStrength() * 2.0f);
+ lineShader->setUniformValue(lineShader->lightS(), 0.25f);
+
+ GLfloat scaleFactor = 0.0f;
+ if (rowMode)
+ scaleFactor = (1.1f * m_rowWidth) / m_scaleFactor;
+ else
+ scaleFactor = (1.1f * m_columnDepth) / m_scaleFactor;
+
+ GLfloat startLine = 0.0f;
+ if (m_noZeroInRange)
+ startLine = 2.0f * (m_axisCacheY.min() - m_axisCacheY.max()) / m_heightNormalizer;
+ else
+ startLine = 2.0f * m_axisCacheY.min() / m_heightNormalizer;
+
+ GLfloat gridStep = (2.0f * m_axisCacheY.subSegmentStep()) / m_heightNormalizer;
+ GLfloat gridPos = startLine + barPosYAdjustment;
+ int lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount();
+
+ // Horizontal lines
+ if (m_axisCacheY.segmentCount() > 0) {
+ QVector3D gridLineScale(scaleFactor, gridLineWidth, gridLineWidth);
+ bool noZero = true;
+ QMatrix4x4 MVPMatrix;
+ QMatrix4x4 itModelMatrix;
+
+ for (int segment = 0; segment <= lastSegment; segment++) {
+ QMatrix4x4 modelMatrix;
+ modelMatrix.translate(0.0f, gridPos, 0.0f);
+ modelMatrix.scale(gridLineScale);
+ itModelMatrix = modelMatrix;
+ 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);
+
+ // Draw the object
+ m_drawer->drawObject(lineShader, m_gridLineObj);
+
+ if (gridPos == barPosYAdjustment)
+ noZero = false;
+
+ gridPos += gridStep;
+ }
+ // Draw a line at zero, if none exists
+ if (!m_noZeroInRange && noZero) {
+ QMatrix4x4 modelMatrix;
+ modelMatrix.translate(0.0f, barPosYAdjustment, 0.0f);
+ modelMatrix.scale(gridLineScale);
+ itModelMatrix = modelMatrix;
+ 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);
+ lineShader->setUniformValue(lineShader->color(),
+ Utils::vectorFromColor(m_cachedTheme->backgroundColor()));
+
+ // Draw the object
+ m_drawer->drawObject(lineShader, m_gridLineObj);
+ }
+ }
+
+ // TODO: Make user controllable (QTRD-2546)
+ if (sliceGridLabels) {
+ // Bind label shader
+ m_labelShader->bind();
+ glEnable(GL_TEXTURE_2D);
+ glCullFace(GL_BACK);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ // Draw grid labels
+ int labelNbr = 0;
+ int labelCount = m_axisCacheY.labels().size();
+ gridStep = (2.0f * m_axisCacheY.segmentStep()) / m_heightNormalizer;
+ gridPos = startLine + barPosYAdjustment;
+ QVector3D backLabelRotation(0.0f, 0.0f, 0.0f);
+ QVector3D labelTrans = QVector3D(scaleFactor + labelMargin, 0.0f, 0.0f);
+
+ for (int i = 0; i < labelCount; i++) {
+ if (m_axisCacheY.labelItems().size() > labelNbr) {
+ const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr);
+ labelTrans.setY(gridPos);
+ m_dummyBarRenderItem.setTranslation(labelTrans);
+ m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix,
+ projectionMatrix, zeroVector, backLabelRotation, 0,
+ m_cachedSelectionMode, m_labelShader, m_labelObj,
+ activeCamera, true, true, Drawer::LabelMid, Qt::AlignRight);
+ }
+ labelNbr++;
+ gridPos += gridStep;
+ }
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+ glEnable(GL_DEPTH_TEST);
+ }
+ }
+
+ // Draw bars
+ QVector3D modelMatrixScaler(m_scaleX, 0.0f, m_scaleZ);
+ if (rowMode)
+ modelMatrixScaler.setX(m_scaleX * m_seriesScale);
+ else
+ modelMatrixScaler.setZ(m_scaleZ * m_seriesScale);
// Set common bar shader bindings
+ m_barShader->bind();
m_barShader->setUniformValue(m_barShader->lightP(), lightPos);
m_barShader->setUniformValue(m_barShader->view(), viewMatrix);
m_barShader->setUniformValue(m_barShader->lightS(), 0.5f);
m_barShader->setUniformValue(m_barShader->ambientS(),
- m_cachedTheme.m_ambientStrength * 2.0f);
-
- // Draw the selected row / column
- // We need some room for labels underneath; add +0.2f
- GLfloat barPosYAdjustment = m_yAdjustment / 2.0f - 0.2f;
- QVector3D modelMatrixScaler(m_scaleX, 0.0f, m_scaleZ);
- QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix;
- QVector3D barHighlightColor(Utils::vectorFromColor(m_cachedTheme.m_highlightBarColor));
- QVector3D rowHighlightColor(Utils::vectorFromColor(m_cachedTheme.m_highlightRowColor));
- QVector3D columnHighlightColor(Utils::vectorFromColor(m_cachedTheme.m_highlightColumnColor));
- for (int bar = startBar; bar != stopBar; bar += stepBar) {
- BarRenderItem *item = m_sliceSelection->at(bar);
+ m_cachedTheme->ambientLightStrength() * 2.0f);
+ m_barGradientShader->bind();
+ m_barGradientShader->setUniformValue(m_barGradientShader->lightP(), lightPos);
+ m_barGradientShader->setUniformValue(m_barGradientShader->view(), viewMatrix);
+ m_barGradientShader->setUniformValue(m_barGradientShader->lightS(), 0.5f);
+ m_barGradientShader->setUniformValue(m_barGradientShader->ambientS(),
+ m_cachedTheme->ambientLightStrength() * 2.0f);
+ m_barGradientShader->setUniformValue(m_barGradientShader->gradientMin(), 0.0f);
+
+ // Default to uniform shader
+ ShaderHelper *barShader = m_barShader;
+ barShader->bind();
+
+ int currentSeriesIndex = -1;
+ Q3DTheme::ColorStyle previousColorStyle = Q3DTheme::ColorStyleUniform;
+ Q3DTheme::ColorStyle colorStyle = Q3DTheme::ColorStyleUniform;
+ ObjectHelper *barObj = 0;
+ QVector3D barHighlightColor;
+ QVector3D rowHighlightColor;
+ GLuint barGradientTexture = 0;
+ GLuint rowGradientTexture = 0;
+ const SeriesRenderCache *currentSeries = 0;
+ bool colorStyleIsUniform = true;
+
+ int sliceItemCount = m_sliceSelection.size();
+ for (int bar = 0; bar < sliceItemCount; bar++) {
+ BarRenderItem *item = m_sliceSelection.at(bar);
if (!item)
continue;
+ if (item->seriesIndex() != currentSeriesIndex) {
+ currentSeriesIndex = item->seriesIndex();
+ currentSeries = &(m_visibleSeriesList.at(currentSeriesIndex));
+ barObj = currentSeries->object();
+ colorStyle = currentSeries->colorStyle();
+ colorStyleIsUniform = (colorStyle == Q3DTheme::ColorStyleUniform);
+ if (colorStyleIsUniform) {
+ barHighlightColor = currentSeries->singleHighlightColor();
+ rowHighlightColor = currentSeries->multiHighlightColor();
+ } else {
+ barGradientTexture = currentSeries->singleHighlightGradientTexture();
+ rowGradientTexture = currentSeries->multiHighlightGradientTexture();
+ }
+
+ // Rebind shader if it has changed
+ if (colorStyleIsUniform != (previousColorStyle == Q3DTheme::ColorStyleUniform)) {
+ if (colorStyleIsUniform)
+ barShader = m_barShader;
+ else
+ barShader = m_barGradientShader;
+ barShader->bind();
+
+ }
+
+ if (!colorStyleIsUniform && (previousColorStyle != colorStyle)
+ && (colorStyle == Q3DTheme::ColorStyleObjectGradient)) {
+ m_barGradientShader->setUniformValue(m_barGradientShader->gradientHeight(), 0.5f);
+ }
+
+ previousColorStyle = colorStyle;
+ }
+
if (item->height() < 0)
glCullFace(GL_FRONT);
else
glCullFace(GL_BACK);
- QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
+ QMatrix4x4 modelMatrix;
QMatrix4x4 itModelMatrix;
+ GLfloat barRotation = 0.0f;
+ GLfloat barPosY = item->translation().y() + barPosYAdjustment;
- GLfloat barPosY = negativesComp * item->translation().y() - barPosYAdjustment;
- if (QDataVis::SelectionModeSliceRow == m_cachedSelectionMode)
+ if (rowMode) {
barPosX = item->translation().x();
- else
+ } else {
barPosX = -(item->translation().z()); // flip z; frontmost bar to the left
+ barRotation = 90.0f;
+ }
+
modelMatrix.translate(barPosX, barPosY, 0.0f);
- modelMatrixScaler.setY(negativesComp * item->height());
+ modelMatrixScaler.setY(item->height());
+ modelMatrix.rotate(barRotation, 0.0f, 1.0f, 0.0f);
+ itModelMatrix.rotate(barRotation, 0.0f, 1.0f, 0.0f);
modelMatrix.scale(modelMatrixScaler);
itModelMatrix.scale(modelMatrixScaler);
MVPMatrix = projectionViewMatrix * modelMatrix;
-#if 0
- QVector3D baseColor;
- if (m_selection.x() == item->position().x() && m_selection.y() == item->position().y())
- baseColor = barHighlightColor;
- else if (QDataVis::SelectionModeSliceRow == m_cachedSelectionMode)
- baseColor = rowHighlightColor;
- else
- baseColor = columnHighlightColor;
-
- QVector3D heightColor = Utils::vectorFromColor(m_cachedTheme.m_heightColor) * item->height();
- QVector3D barColor = baseColor + heightColor;
-#else
QVector3D barColor;
- if (m_selection.x() == item->position().x() && m_selection.y() == item->position().y())
- barColor = barHighlightColor;
- else if (QDataVis::SelectionModeSliceRow == m_cachedSelectionMode)
- barColor = rowHighlightColor;
- else
- barColor = columnHighlightColor;
-#endif
+ GLuint gradientTexture = 0;
+
+ if (itemMode && m_visualSelectedBarPos.x() == item->position().x()
+ && m_visualSelectedBarPos.y() == item->position().y()) {
+ if (colorStyleIsUniform)
+ barColor = barHighlightColor;
+ else
+ gradientTexture = barGradientTexture;
+ } else {
+ if (colorStyleIsUniform)
+ barColor = rowHighlightColor;
+ else
+ gradientTexture = rowGradientTexture;
+ }
if (item->height() != 0) {
// Set shader bindings
- m_barShader->setUniformValue(m_barShader->model(), modelMatrix);
- m_barShader->setUniformValue(m_barShader->nModel(),
- itModelMatrix.inverted().transposed());
- m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix);
- m_barShader->setUniformValue(m_barShader->color(), barColor);
+ barShader->setUniformValue(barShader->model(), modelMatrix);
+ barShader->setUniformValue(barShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ barShader->setUniformValue(barShader->MVP(), MVPMatrix);
+ if (colorStyleIsUniform) {
+ barShader->setUniformValue(barShader->color(), barColor);
+ } else if (colorStyle == Q3DTheme::ColorStyleRangeGradient) {
+ barShader->setUniformValue(barShader->gradientHeight(),
+ (qAbs(item->height()) / m_gradientFraction));
+ }
// Draw the object
- m_drawer->drawObject(m_barShader, m_barObj);
+ m_drawer->drawObject(barShader,
+ barObj,
+ gradientTexture);
}
}
- // Release bar shader
- m_barShader->release();
-
// Draw labels
m_labelShader->bind();
glDisable(GL_DEPTH_TEST);
@@ -384,69 +571,106 @@ void Bars3DRenderer::drawSlicedScene(const LabelItem &xLabel,
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- // Draw labels for axes
BarRenderItem *dummyItem(0);
const LabelItem &sliceSelectionLabel = *m_sliceTitleItem;
QVector3D positionComp(0.0f, m_autoScaleAdjustment, 0.0f);
- const Q3DCamera *activeCamera = m_cachedScene->activeCamera();
- if (QDataVis::SelectionModeSliceRow == m_cachedSelectionMode) {
+
+ // Draw labels for bars
+ QVector3D valuePositionComp = zeroVector;
+ if (!m_hasNegativeValues)
+ valuePositionComp.setY(2.0f);
+ else if (m_noZeroInRange)
+ valuePositionComp.setY(-2.0f);
+ QVector3D sliceValueRotation(0.0f, 0.0f, 90.0f);
+ QVector3D sliceLabelRotation(0.0f, 0.0f, -45.0f);
+
+ for (int col = 0; col < sliceItemCount; col++) {
+ BarRenderItem *item = m_sliceSelection.at(col);
+
+ // TODO: Make user controllable (QTRD-2546)
+ if (!sliceGridLabels) {
+ // Draw values
+ if (item->height() != 0.0f || (!m_noZeroInRange && item->value() == 0.0f)) {
+ // Create label texture if we need it
+ if (item->sliceLabel().isNull()) {
+ item->setSliceLabel(generateValueLabel(m_axisCacheY.labelFormat(), item->value()));
+ m_drawer->generateLabelItem(item->sliceLabelItem(), item->sliceLabel());
+ }
+ m_drawer->drawLabel(*item, item->sliceLabelItem(), viewMatrix, projectionMatrix,
+ valuePositionComp, sliceValueRotation, item->height(),
+ m_cachedSelectionMode, m_labelShader, m_labelObj, activeCamera,
+ false, false, Drawer::LabelOver, Qt::AlignTop, true);
+ }
+ } else {
+ // Only draw value for selected item when grid labels are on
+ // TODO: Maybe use selection label instead of value? Should it be user controllable
+ // as well? (QTRD-2546)
+ if (itemMode && m_visualSelectedBarPos.x() == item->position().x()
+ && m_visualSelectedBarPos.y() == item->position().y()
+ && item->seriesIndex() == m_visualSelectedBarSeriesIndex) {
+ // Create label texture if we need it
+ if (item->sliceLabel().isNull()) {
+ item->setSliceLabel(generateValueLabel(m_axisCacheY.labelFormat(), item->value()));
+ m_drawer->generateLabelItem(item->sliceLabelItem(), item->sliceLabel());
+ }
+ m_drawer->drawLabel(*item, item->sliceLabelItem(), viewMatrix, projectionMatrix,
+ valuePositionComp, sliceValueRotation, item->height(),
+ m_cachedSelectionMode, m_labelShader, m_labelObj, activeCamera,
+ false, false, Drawer::LabelOver, Qt::AlignTop, true);
+ }
+ }
+ }
+
+ int lastLabel = m_sliceCache->labelItems().size() - 1;
+
+ for (int labelNo = 0; labelNo <= lastLabel; labelNo++) {
+ // Get labels from first series only
+ BarRenderItem *item = m_sliceSelection.at(labelNo);
+ // TODO: Make user controllable (QTRD-2546)
+ // Draw labels
+ m_drawer->drawLabel(*item, *m_sliceCache->labelItems().at(labelNo), viewMatrix,
+ projectionMatrix, positionComp, sliceLabelRotation,
+ item->height(), m_cachedSelectionMode, m_labelShader,
+ m_labelObj, activeCamera, false, false, Drawer::LabelBelow,
+ Qt::AlignCenter, true);
+ }
+
+ // TODO: Make user controllable (QTRD-2546)
+ // Draw labels for axes
+ if (rowMode) {
if (m_sliceTitleItem) {
m_drawer->drawLabel(*dummyItem, sliceSelectionLabel, viewMatrix, projectionMatrix,
positionComp, zeroVector, 0, m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera, false, false, Drawer::LabelTop);
+ m_labelObj, activeCamera, false, false, Drawer::LabelTop,
+ Qt::AlignCenter, true);
}
- m_drawer->drawLabel(*dummyItem, zLabel, viewMatrix, projectionMatrix,
+ m_drawer->drawLabel(*dummyItem, m_axisCacheX.titleItem(), viewMatrix, projectionMatrix,
positionComp, zeroVector, 0, m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera, false, false, Drawer::LabelBottom);
+ m_labelObj, activeCamera, false, false, Drawer::LabelBottom,
+ Qt::AlignCenter, true);
} else {
- m_drawer->drawLabel(*dummyItem, xLabel, viewMatrix, projectionMatrix,
+ m_drawer->drawLabel(*dummyItem, m_axisCacheZ.titleItem(), viewMatrix, projectionMatrix,
positionComp, zeroVector, 0, m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera, false, false, Drawer::LabelBottom);
+ m_labelObj, activeCamera, false, false, Drawer::LabelBottom,
+ Qt::AlignCenter, true);
if (m_sliceTitleItem) {
m_drawer->drawLabel(*dummyItem, sliceSelectionLabel, viewMatrix, projectionMatrix,
positionComp, zeroVector, 0, m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera, false, false, Drawer::LabelTop);
+ m_labelObj, activeCamera, false, false, Drawer::LabelTop,
+ Qt::AlignCenter, true);
}
}
- m_drawer->drawLabel(*dummyItem, yLabel, viewMatrix, projectionMatrix,
+ m_drawer->drawLabel(*dummyItem, m_axisCacheY.titleItem(), viewMatrix, projectionMatrix,
positionComp, QVector3D(0.0f, 0.0f, 90.0f), 0,
m_cachedSelectionMode, m_labelShader, m_labelObj, activeCamera,
- false, false, Drawer::LabelLeft);
-
- // Draw labels for bars
- QVector3D valuePositionComp(0.0f, m_yAdjustment, 0.0f);
- QVector3D negativesRotation(0.0f, 0.0f, 90.0f);
- QVector3D sliceLabelRotation(0.0f, 0.0f, -45.0f);
- GLfloat negativesCompPow2 = negativesComp * negativesComp;
- for (int col = 0; col < stopBar; col++) {
- BarRenderItem *item = m_sliceSelection->at(col);
- // Draw values
- if (!m_hasNegativeValues) {
- m_drawer->drawLabel(*item, item->sliceLabelItem(), viewMatrix, projectionMatrix,
- valuePositionComp, negativesRotation, item->height(),
- m_cachedSelectionMode, m_labelShader, m_labelObj, activeCamera,
- false, false, Drawer::LabelOver, Qt::AlignTop);
- } else {
- m_drawer->drawLabel(*item, item->sliceLabelItem(), viewMatrix, projectionMatrix,
- valuePositionComp, zeroVector, negativesCompPow2 * item->height(),
- m_cachedSelectionMode, m_labelShader, m_labelObj, activeCamera);
- }
-
- // Draw labels
- if (m_sliceCache->labelItems().size() > col) {
- m_drawer->drawLabel(*item, *m_sliceCache->labelItems().at(col), viewMatrix,
- projectionMatrix, positionComp, sliceLabelRotation,
- item->height(), m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera, false, false, Drawer::LabelBelow);
- }
- }
+ false, false, Drawer::LabelLeft, Qt::AlignCenter, true);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
- // Release label shader
- m_labelShader->release();
+ // Release shader
+ glUseProgram(0);
}
void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
@@ -464,15 +688,18 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
GLfloat colPos = 0;
GLfloat rowPos = 0;
+ int seriesCount = m_visibleSeriesList.size();
+
const Q3DCamera *activeCamera = m_cachedScene->activeCamera();
- // Specify viewport
- glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
- m_mainViewPort.width(), m_mainViewPort.height());
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
// Set up projection matrix
QMatrix4x4 projectionMatrix;
- GLfloat viewPortRatio = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height();
+ GLfloat viewPortRatio = (GLfloat)m_primarySubViewport.width() / (GLfloat)m_primarySubViewport.height();
projectionMatrix.perspective(45.0f, viewPortRatio, 0.1f, 100.0f);
// Get the view matrix
@@ -531,6 +758,8 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix;
+ bool rowMode = m_cachedSelectionMode.testFlag(QDataVis::SelectionRow);
+
#if !defined(QT_OPENGL_ES_2)
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
// Render scene into a depth texture for using with shadow mapping
@@ -544,15 +773,14 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
// Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows.
// Depth viewport must always start from 0, 0, as it is rendered into a texture, not screen
glViewport(0, 0,
- m_mainViewPort.width() * m_shadowQualityMultiplier,
- m_mainViewPort.height() * m_shadowQualityMultiplier);
+ m_primarySubViewport.width() * m_shadowQualityMultiplier,
+ m_primarySubViewport.height() * m_shadowQualityMultiplier);
// Get the depth view matrix
// It may be possible to hack lightPos here if we want to make some tweaks to shadow
QVector3D depthLightPos = activeCamera->calculatePositionRelativeToCamera(
zeroVector, 0.0f, 3.5f / m_autoScaleAdjustment);
- depthViewMatrix.lookAt(depthLightPos, QVector3D(0.0f, -m_yAdjustment, 0.0f),
- upVector);
+ depthViewMatrix.lookAt(depthLightPos, zeroVector, upVector);
// TODO: Why does depthViewMatrix.column(3).y() goes to zero when we're directly above?
// That causes the scene to be not drawn from above -> must be fixed
@@ -563,73 +791,73 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
depthProjectionViewMatrix = depthProjectionMatrix * depthViewMatrix;
// Draw bars to depth buffer
- QVector3D shadowScaler(m_scaleX * 0.9f, 0.0f, m_scaleZ * 0.9f);
- for (int row = startRow; row != stopRow; row += stepRow) {
- for (int bar = startBar; bar != stopBar; bar += stepBar) {
- const BarRenderItem &item = m_renderItemArray.at(row).at(bar);
- if (!item.value())
- continue;
-
- GLfloat shadowOffset = 0.0f;
-
- // Set front face culling for negative valued bars and back face culling for
- // positive valued bars to remove peter-panning issues
- if (item.height() > 0) {
- glCullFace(GL_BACK);
- if (m_yFlipped)
- shadowOffset = 0.015f;
- } else {
- glCullFace(GL_FRONT);
- if (!m_yFlipped)
- shadowOffset = -0.015f;
- }
+ QVector3D shadowScaler(m_scaleX * m_seriesScale * 0.9f, 0.0f, m_scaleZ * 0.9f);
+ float seriesPos = m_seriesStart;
+ for (int series = 0; series < seriesCount; series++) {
+ ObjectHelper *barObj = m_visibleSeriesList.at(series).object();
+ for (int row = startRow; row != stopRow; row += stepRow) {
+ for (int bar = startBar; bar != stopBar; bar += stepBar) {
+ GLfloat shadowOffset = 0.0f;
+ const BarRenderItem &item = m_renderingArrays.at(series).at(row).at(bar);
+ if (!item.value())
+ continue;
+ // Set front face culling for negative valued bars and back face culling for
+ // positive valued bars to remove peter-panning issues
+ if (item.height() > 0) {
+ glCullFace(GL_BACK);
+ if (m_yFlipped)
+ shadowOffset = 0.015f;
+ } else {
+ glCullFace(GL_FRONT);
+ if (!m_yFlipped)
+ shadowOffset = -0.015f;
+ }
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
- colPos = (bar + 0.5f) * (m_cachedBarSpacing.width());
- rowPos = (row + 0.5f) * (m_cachedBarSpacing.height());
+ colPos = (bar + 0.5f + seriesPos) * (m_cachedBarSpacing.width());
+ rowPos = (row + 0.5f) * (m_cachedBarSpacing.height());
- // Draw shadows for bars "on the other side" a bit off ground to avoid seeing
- // shadows through the ground
- modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor,
- item.height() - m_yAdjustment + shadowOffset,
- (m_columnDepth - rowPos) / m_scaleFactor);
- // Scale the bars down in X and Z to reduce self-shadowing issues
- shadowScaler.setY(item.height());
- modelMatrix.scale(shadowScaler);
+ // Draw shadows for bars "on the other side" a bit off ground to avoid seeing
+ // shadows through the ground
+ modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor,
+ item.height() + shadowOffset,
+ (m_columnDepth - rowPos) / m_scaleFactor);
+ // Scale the bars down in X and Z to reduce self-shadowing issues
+ shadowScaler.setY(item.height());
+ modelMatrix.scale(shadowScaler);
- MVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ MVPMatrix = depthProjectionViewMatrix * modelMatrix;
- m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix);
+ m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix);
- // 1st attribute buffer : vertices
- glEnableVertexAttribArray(m_depthShader->posAtt());
- glBindBuffer(GL_ARRAY_BUFFER, m_barObj->vertexBuf());
- glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0,
- (void *)0);
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(m_depthShader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, barObj->vertexBuf());
+ glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0,
+ (void *)0);
- // Index buffer
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_barObj->elementBuf());
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, barObj->elementBuf());
- // Draw the triangles
- glDrawElements(GL_TRIANGLES, m_barObj->indexCount(), GL_UNSIGNED_SHORT,
- (void *)0);
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, barObj->indexCount(), GL_UNSIGNED_SHORT,
+ (void *)0);
- // Free buffers
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
+ // Free buffers
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
- glDisableVertexAttribArray(m_depthShader->posAtt());
+ glDisableVertexAttribArray(m_depthShader->posAtt());
+ }
}
+ seriesPos += m_seriesStep;
}
// Disable drawing to depth framebuffer (= enable drawing to screen)
glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle);
- // Release depth shader
- m_depthShader->release();
-
#if 0 // Use this if you want to see what is being drawn to the framebuffer
// You'll also have to comment out GL_COMPARE_R_TO_TEXTURE -line in texturehelper (if using it)
m_labelShader->bind();
@@ -642,329 +870,419 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix);
m_drawer->drawObject(m_labelShader, m_labelObj, m_depthTexture);
glDisable(GL_TEXTURE_2D);
- m_labelShader->release();
#endif
// Reset culling to normal
glCullFace(GL_BACK);
// Revert to original viewport
- glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
- m_mainViewPort.width(), m_mainViewPort.height());
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
}
#endif
+ // TODO: Selection must be enabled currently to support clicked signal. (QTRD-2517)
// Skip selection mode drawing if we're slicing or have no selection mode
- if (!m_cachedIsSlicingActivated && m_cachedSelectionMode > QDataVis::SelectionModeNone) {
+ if (!m_cachedIsSlicingActivated && m_cachedSelectionMode > QDataVis::SelectionNone
+ && m_selectionState == SelectOnScene && seriesCount > 0) {
// Bind selection shader
m_selectionShader->bind();
// Draw bars to selection buffer
glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer);
+ glViewport(0, 0,
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
+
glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used
glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Set clear color to white (= selectionSkipColor)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer
glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled
- for (int row = startRow; row != stopRow; row += stepRow) {
- for (int bar = startBar; bar != stopBar; bar += stepBar) {
- const BarRenderItem &item = m_renderItemArray.at(row).at(bar);
- if (!item.value())
- continue;
-
- if (item.height() < 0)
- glCullFace(GL_FRONT);
- else
- glCullFace(GL_BACK);
-
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
-
- colPos = (bar + 0.5f) * (m_cachedBarSpacing.width());
- rowPos = (row + 0.5f) * (m_cachedBarSpacing.height());
-
- modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor,
- item.height() - m_yAdjustment,
- (m_columnDepth - rowPos) / m_scaleFactor);
- modelMatrix.scale(QVector3D(m_scaleX, item.height(), m_scaleZ));
-
- MVPMatrix = projectionViewMatrix * modelMatrix;
-
- //#if !defined(QT_OPENGL_ES_2)
- // QVector3D barColor = QVector3D((GLdouble)row / 32767.0,
- // (GLdouble)bar / 32767.0,
- // 0.0);
- //#else
- QVector3D barColor = QVector3D((GLdouble)row / 255.0,
- (GLdouble)bar / 255.0,
- 0.0);
- //#endif
-
- m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix);
- m_selectionShader->setUniformValue(m_selectionShader->color(), barColor);
-
- // 1st attribute buffer : vertices
- glEnableVertexAttribArray(m_selectionShader->posAtt());
- glBindBuffer(GL_ARRAY_BUFFER, m_barObj->vertexBuf());
- glVertexAttribPointer(m_selectionShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0,
- (void *)0);
-
- // Index buffer
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_barObj->elementBuf());
-
- // Draw the triangles
- glDrawElements(GL_TRIANGLES, m_barObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0);
-
- // Free buffers
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
- glDisableVertexAttribArray(m_selectionShader->posAtt());
+ float seriesPos = m_seriesStart;
+ for (int series = 0; series < seriesCount; series++) {
+ ObjectHelper *barObj = m_visibleSeriesList.at(series).object();
+ for (int row = startRow; row != stopRow; row += stepRow) {
+ for (int bar = startBar; bar != stopBar; bar += stepBar) {
+ const BarRenderItem &item = m_renderingArrays.at(series).at(row).at(bar);
+ if (!item.value())
+ continue;
+
+ if (item.height() < 0)
+ glCullFace(GL_FRONT);
+ else
+ glCullFace(GL_BACK);
+
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+
+ colPos = (bar + 0.5f + seriesPos) * (m_cachedBarSpacing.width());
+ rowPos = (row + 0.5f) * (m_cachedBarSpacing.height());
+
+ modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor,
+ item.height(),
+ (m_columnDepth - rowPos) / m_scaleFactor);
+ modelMatrix.scale(QVector3D(m_scaleX * m_seriesScale,
+ item.height(),
+ m_scaleZ));
+
+ MVPMatrix = projectionViewMatrix * modelMatrix;
+
+ //#if !defined(QT_OPENGL_ES_2)
+ // QVector3D barColor = QVector3D(GLfloat(row) / 32767.0f,
+ // GLfloat(bar) / 32767.0f,
+ // 0.0f);
+ //#else
+ QVector3D barColor = QVector3D(GLfloat(row) / 255.0f,
+ GLfloat(bar) / 255.0f,
+ GLfloat(series) / 255.0f);
+ //#endif
+
+ m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix);
+ m_selectionShader->setUniformValue(m_selectionShader->color(), barColor);
+
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(m_selectionShader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, barObj->vertexBuf());
+ glVertexAttribPointer(m_selectionShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0,
+ (void *)0);
+
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, barObj->elementBuf());
+
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, barObj->indexCount(), GL_UNSIGNED_SHORT,
+ (void *)0);
+
+ // Free buffers
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDisableVertexAttribArray(m_selectionShader->posAtt());
+ }
}
+ seriesPos += m_seriesStep;
}
glEnable(GL_DITHER);
// Read color under cursor
- if (QDataVis::InputStateOnScene == m_controller->inputState()) {
- m_selection = Utils::getSelection(m_controller->inputPosition(),
- m_cachedBoundingRect.height());
- }
+ QVector3D clickedColor = Utils::getSelection(m_inputPosition,
+ m_viewport.height());
+ emit barClicked(selectionColorToArrayPosition(clickedColor), selectionColorToSeries(clickedColor));
+ // Revert to original render target and viewport
glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle);
-
- // Release selection shader
- m_selectionShader->release();
-
-#if 0 // Use this if you want to see what is being drawn to the framebuffer
- glCullFace(GL_BACK);
- m_labelShader->bind();
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_TEXTURE_2D);
- QMatrix4x4 modelMatrix;
- QMatrix4x4 viewmatrix;
- viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.0f), zeroVector, upVector);
- QMatrix4x4 MVPMatrix = projectionViewMatrix * modelMatrix;
- m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix);
- m_drawer->drawObject(m_labelShader, m_labelObj, m_selectionTexture);
- glDisable(GL_TEXTURE_2D);
- m_labelShader->release();
-#endif
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
}
// Enable texturing
glEnable(GL_TEXTURE_2D);
- // Bind bar shader
- m_barShader->bind();
+ ShaderHelper *barShader = 0;
+ GLuint gradientTexture = 0;
+ Q3DTheme::ColorStyle previousColorStyle = Q3DTheme::ColorStyleUniform;
+ bool haveUniformColorSeries = false;
+ bool haveGradientSeries = false;
- // Set common bar shader bindings
- m_barShader->setUniformValue(m_barShader->lightP(), lightPos);
- m_barShader->setUniformValue(m_barShader->view(), viewMatrix);
- m_barShader->setUniformValue(m_barShader->ambientS(),
- m_cachedTheme.m_ambientStrength);
-
- bool selectionDirty = (m_selection != m_previousSelection
- || (m_selection != selectionSkipColor
- && QDataVis::InputStateOnScene == m_controller->inputState()
- && !m_cachedIsSlicingActivated));
- if (selectionDirty) {
- m_previousSelection = m_selection;
- if (m_sliceSelection) {
- if (!m_cachedIsSlicingActivated) {
- m_sliceCache = 0;
- m_sliceTitleItem = 0;
- }
- if (m_sliceSelection->size()) {
- // Slice doesn't own its items, no need to delete them - just clear
- m_sliceSelection->clear();
- }
- }
+ for (int i = 0; i < seriesCount; i++) {
+ if (m_visibleSeriesList.at(i).colorStyle() == Q3DTheme::ColorStyleUniform)
+ haveUniformColorSeries = true;
+ else
+ haveGradientSeries = true;
+ }
+
+ // Set unchanging shader bindings
+ if (haveGradientSeries) {
+ m_barGradientShader->bind();
+ m_barGradientShader->setUniformValue(m_barGradientShader->lightP(), lightPos);
+ m_barGradientShader->setUniformValue(m_barGradientShader->view(), viewMatrix);
+ m_barGradientShader->setUniformValue(m_barGradientShader->ambientS(),
+ m_cachedTheme->ambientLightStrength());
+ m_barGradientShader->setUniformValue(m_barGradientShader->gradientMin(), 0.0f);
+ }
+
+ if (haveUniformColorSeries) {
+ m_barShader->bind();
+ m_barShader->setUniformValue(m_barShader->lightP(), lightPos);
+ m_barShader->setUniformValue(m_barShader->view(), viewMatrix);
+ m_barShader->setUniformValue(m_barShader->ambientS(),
+ m_cachedTheme->ambientLightStrength());
+ barShader = m_barShader;
+ } else {
+ barShader = m_barGradientShader;
+ previousColorStyle = Q3DTheme::ColorStyleRangeGradient;
+ }
+
+ if (m_selectionDirty && m_cachedIsSlicingActivated) {
+ // Slice doesn't own its items, no need to delete them - just clear
+ m_sliceSelection.clear();
+ int reserveAmount;
+ if (rowMode)
+ reserveAmount = m_cachedColumnCount;
+ else
+ reserveAmount = m_cachedRowCount;
+ if (m_cachedSelectionMode.testFlag(QDataVis::SelectionMultiSeries))
+ reserveAmount *= m_visibleSeriesList.size();
+ m_sliceSelection.resize(reserveAmount);
+
+ // Set slice cache, i.e. axis cache from where slice labels are taken
+ if (rowMode)
+ m_sliceCache = &m_axisCacheX;
+ else
+ m_sliceCache = &m_axisCacheZ;
+ m_sliceTitleItem = 0;
}
// Draw bars
- QVector3D barHighlightColor(Utils::vectorFromColor(m_cachedTheme.m_highlightBarColor));
- QVector3D rowHighlightColor(Utils::vectorFromColor(m_cachedTheme.m_highlightRowColor));
- QVector3D columnHighlightColor(Utils::vectorFromColor(m_cachedTheme.m_highlightColumnColor));
- QVector3D baseColor(Utils::vectorFromColor(m_cachedTheme.m_baseColor));
- GLfloat adjustedLightStrength = m_cachedTheme.m_lightStrength / 10.0f;
- GLfloat adjustedHighlightStrength = m_cachedTheme.m_highlightLightStrength / 10.0f;
+ GLfloat adjustedLightStrength = m_cachedTheme->lightStrength() / 10.0f;
+ GLfloat adjustedHighlightStrength = m_cachedTheme->highlightLightStrength() / 10.0f;
bool barSelectionFound = false;
BarRenderItem *selectedBar(0);
- QVector3D modelScaler(m_scaleX, 0.0f, m_scaleZ);
- for (int row = startRow; row != stopRow; row += stepRow) {
- for (int bar = startBar; bar != stopBar; bar += stepBar) {
- BarRenderItem &item = m_renderItemArray[row][bar];
- if (item.height() < 0)
- glCullFace(GL_FRONT);
+ QVector3D baseColor;
+ QVector3D barColor;
+ QVector3D modelScaler(m_scaleX * m_seriesScale, 0.0f, m_scaleZ);
+ bool somethingSelected = (m_visualSelectedBarPos != Bars3DController::invalidSelectionPosition());
+ float seriesPos = m_seriesStart;
+ for (int series = 0; series < seriesCount; series++) {
+ const SeriesRenderCache &currentSeries = m_visibleSeriesList.at(series);
+ ObjectHelper *barObj = currentSeries.object();
+ Q3DTheme::ColorStyle colorStyle = currentSeries.colorStyle();
+ bool colorStyleIsUniform = (colorStyle == Q3DTheme::ColorStyleUniform);
+
+ // Rebind shader if it has changed
+ if (colorStyleIsUniform != (previousColorStyle == Q3DTheme::ColorStyleUniform)) {
+ if (colorStyleIsUniform)
+ barShader = m_barShader;
else
- glCullFace(GL_BACK);
+ barShader = m_barGradientShader;
+ barShader->bind();
+ }
- QMatrix4x4 modelMatrix;
- QMatrix4x4 itModelMatrix;
- QMatrix4x4 MVPMatrix;
+ if (colorStyleIsUniform) {
+ baseColor = currentSeries.baseColor();
+ } else if ((previousColorStyle != colorStyle)
+ && (colorStyle == Q3DTheme::ColorStyleObjectGradient)) {
+ m_barGradientShader->setUniformValue(m_barGradientShader->gradientHeight(), 0.5f);
+ }
- colPos = (bar + 0.5f) * (m_cachedBarSpacing.width());
- rowPos = (row + 0.5f) * (m_cachedBarSpacing.height());
+ // Always use base color when no selection mode
+ if (m_cachedSelectionMode == QDataVis::SelectionNone) {
+ if (colorStyleIsUniform)
+ barColor = baseColor;
+ else
+ gradientTexture = currentSeries.baseGradientTexture();
+ }
- modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor,
- item.height() - m_yAdjustment,
- (m_columnDepth - rowPos) / m_scaleFactor);
- modelScaler.setY(item.height());
- modelMatrix.scale(modelScaler);
- itModelMatrix.scale(modelScaler);
-#ifdef SHOW_DEPTH_TEXTURE_SCENE
- MVPMatrix = depthProjectionViewMatrix * modelMatrix;
-#else
- MVPMatrix = projectionViewMatrix * modelMatrix;
-#endif
+ previousColorStyle = colorStyle;
+ int sliceSeriesAdjust = 0;
+ if (m_selectionDirty && m_cachedIsSlicingActivated) {
+ int seriesMultiplier = 0;
+ if (m_cachedSelectionMode.testFlag(QDataVis::SelectionMultiSeries))
+ seriesMultiplier = series;
+ if (rowMode)
+ sliceSeriesAdjust = seriesMultiplier * m_cachedColumnCount;
+ else
+ sliceSeriesAdjust = seriesMultiplier * m_cachedRowCount;
+ }
+
+ for (int row = startRow; row != stopRow; row += stepRow) {
+ for (int bar = startBar; bar != stopBar; bar += stepBar) {
+ BarRenderItem &item = m_renderingArrays[series][row][bar];
+
+ if (item.height() < 0)
+ glCullFace(GL_FRONT);
+ else
+ glCullFace(GL_BACK);
-#if 0
- QVector3D heightColor = Utils::vectorFromColor(m_cachedTheme.m_heightColor)
- * item.height();
- QVector3D depthColor = Utils::vectorFromColor(m_cachedTheme.m_depthColor)
- * (float(row) / GLfloat(m_cachedRowCount));
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 itModelMatrix;
+ QMatrix4x4 MVPMatrix;
+
+ colPos = (bar + 0.5f + seriesPos) * (m_cachedBarSpacing.width());
+ rowPos = (row + 0.5f) * (m_cachedBarSpacing.height());
- QVector3D barColor = baseColor + heightColor + depthColor;
+ modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor,
+ item.height(),
+ (m_columnDepth - rowPos) / m_scaleFactor);
+ modelScaler.setY(item.height());
+ modelMatrix.scale(modelScaler);
+ itModelMatrix.scale(modelScaler);
+#ifdef SHOW_DEPTH_TEXTURE_SCENE
+ MVPMatrix = depthProjectionViewMatrix * modelMatrix;
#else
- QVector3D barColor = baseColor;
+ MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
-
- GLfloat lightStrength = m_cachedTheme.m_lightStrength;
- GLfloat shadowLightStrength = adjustedLightStrength;
-
- if (m_cachedSelectionMode > QDataVis::SelectionModeNone) {
- Bars3DController::SelectionType selectionType = isSelected(row, bar);
-
- switch (selectionType) {
- case Bars3DController::SelectionItem: {
- barColor = barHighlightColor;
- lightStrength = m_cachedTheme.m_highlightLightStrength;
- shadowLightStrength = adjustedHighlightStrength;
- // Insert position data into render item. We have no ownership, don't delete the previous one
- if (!m_cachedIsSlicingActivated) {
- selectedBar = &item;
- selectedBar->setPosition(QPoint(row, bar));
- item.setTranslation(modelMatrix.column(3).toVector3D());
- barSelectionFound = true;
+ GLfloat lightStrength = m_cachedTheme->lightStrength();
+ GLfloat shadowLightStrength = adjustedLightStrength;
+
+ if (m_cachedSelectionMode > QDataVis::SelectionNone) {
+ Bars3DController::SelectionType selectionType = Bars3DController::SelectionNone;
+ if (somethingSelected)
+ selectionType = isSelected(row, bar, series);
+
+ switch (selectionType) {
+ case Bars3DController::SelectionItem: {
+ if (colorStyleIsUniform)
+ barColor = currentSeries.singleHighlightColor();
+ else
+ gradientTexture = currentSeries.singleHighlightGradientTexture();
+
+ lightStrength = m_cachedTheme->highlightLightStrength();
+ shadowLightStrength = adjustedHighlightStrength;
+ // Insert position data into render item. We have no ownership, don't delete the previous one
+ if (!m_cachedIsSlicingActivated && m_visualSelectedBarSeriesIndex == series) {
+ selectedBar = &item;
+ selectedBar->setPosition(QPoint(row, bar));
+ item.setTranslation(modelMatrix.column(3).toVector3D());
+ barSelectionFound = true;
+ }
+ if (m_selectionDirty && m_cachedIsSlicingActivated) {
+ QVector3D translation = modelMatrix.column(3).toVector3D();
+ if (m_cachedSelectionMode & QDataVis::SelectionColumn
+ && seriesCount > 1) {
+ translation.setZ((m_columnDepth - ((row + 0.5f + seriesPos)
+ * (m_cachedBarSpacing.height())))
+ / m_scaleFactor);
+ }
+ item.setTranslation(translation);
+ item.setPosition(QPoint(row, bar));
+ item.setSeriesIndex(series);
+ if (rowMode)
+ m_sliceSelection[sliceSeriesAdjust + bar] = &item;
+ else
+ m_sliceSelection[sliceSeriesAdjust + row] = &item;
+ }
+ break;
}
- if (selectionDirty && m_cachedSelectionMode >= QDataVis::SelectionModeSliceRow) {
- item.setTranslation(modelMatrix.column(3).toVector3D());
- item.setPosition(QPoint(row, bar));
- m_sliceSelection->append(&item);
- barSelectionFound = true;
- if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) {
- if (m_axisCacheX.labelItems().size() > row)
- m_sliceTitleItem = m_axisCacheX.labelItems().at(row);
- if (!m_sliceCache) {
- // m_sliceCache is the axis for labels, while title comes from different axis.
- m_sliceCache = &m_axisCacheZ;
+ case Bars3DController::SelectionRow: {
+ // Current bar is on the same row as the selected bar
+ if (colorStyleIsUniform)
+ barColor = currentSeries.multiHighlightColor();
+ else
+ gradientTexture = currentSeries.multiHighlightGradientTexture();
+
+ lightStrength = m_cachedTheme->highlightLightStrength();
+ shadowLightStrength = adjustedHighlightStrength;
+ if (m_cachedIsSlicingActivated) {
+ item.setTranslation(modelMatrix.column(3).toVector3D());
+ item.setPosition(QPoint(row, bar));
+ if (m_selectionDirty) {
+ item.setSeriesIndex(series);
+ if (!m_sliceTitleItem && m_axisCacheZ.labelItems().size() > row)
+ m_sliceTitleItem = m_axisCacheZ.labelItems().at(row);
+ m_sliceSelection[sliceSeriesAdjust + bar] = &item;
}
- } else if (m_cachedSelectionMode == QDataVis::SelectionModeSliceColumn) {
- if (m_axisCacheZ.labelItems().size() > bar)
- m_sliceTitleItem = m_axisCacheZ.labelItems().at(bar);
- if (!m_sliceCache) {
- // m_sliceCache is the axis for labels, while title comes from different axis.
- m_sliceCache = &m_axisCacheX;
+ }
+ break;
+ }
+ case Bars3DController::SelectionColumn: {
+ // Current bar is on the same column as the selected bar
+ if (colorStyleIsUniform)
+ barColor = currentSeries.multiHighlightColor();
+ else
+ gradientTexture = currentSeries.multiHighlightGradientTexture();
+
+ lightStrength = m_cachedTheme->highlightLightStrength();
+ shadowLightStrength = adjustedHighlightStrength;
+ if (m_cachedIsSlicingActivated) {
+ QVector3D translation = modelMatrix.column(3).toVector3D();
+ if (seriesCount > 1) {
+ translation.setZ((m_columnDepth - ((row + 0.5f + seriesPos)
+ * (m_cachedBarSpacing.height())))
+ / m_scaleFactor);
+ }
+ item.setTranslation(translation);
+ item.setPosition(QPoint(row, bar));
+ if (m_selectionDirty) {
+ item.setSeriesIndex(series);
+ if (!m_sliceTitleItem && m_axisCacheX.labelItems().size() > bar)
+ m_sliceTitleItem = m_axisCacheX.labelItems().at(bar);
+ m_sliceSelection[sliceSeriesAdjust + row] = &item;
}
}
+ break;
}
- break;
- }
- case Bars3DController::SelectionRow: {
- // Current bar is on the same row as the selected bar
- barColor = rowHighlightColor;
- lightStrength = m_cachedTheme.m_highlightLightStrength;
- shadowLightStrength = adjustedHighlightStrength;
- if (QDataVis::SelectionModeSliceRow == m_cachedSelectionMode) {
- item.setTranslation(modelMatrix.column(3).toVector3D());
- item.setPosition(QPoint(row, bar));
- if (selectionDirty && bar < m_renderColumns)
- m_sliceSelection->append(&item);
+ case Bars3DController::SelectionNone: {
+ // Current bar is not selected, nor on a row or column
+ if (colorStyleIsUniform)
+ barColor = baseColor;
+ else
+ gradientTexture = currentSeries.baseGradientTexture();
+ break;
}
- break;
- }
- case Bars3DController::SelectionColumn: {
- // Current bar is on the same column as the selected bar
- barColor = columnHighlightColor;
- lightStrength = m_cachedTheme.m_highlightLightStrength;
- shadowLightStrength = adjustedHighlightStrength;
- if (QDataVis::SelectionModeSliceColumn == m_cachedSelectionMode) {
- item.setTranslation(modelMatrix.column(3).toVector3D());
- item.setPosition(QPoint(row, bar));
- if (selectionDirty && row < m_renderRows)
- m_sliceSelection->append(&item);
}
- break;
- }
- case Bars3DController::SelectionNone: {
- // Current bar is not selected, nor on a row or column
- // do nothing
- break;
- }
}
- }
- // Skip drawing of 0 -height bars
- if (item.height() != 0) {
- // Set shader bindings
- m_barShader->setUniformValue(m_barShader->model(), modelMatrix);
- m_barShader->setUniformValue(m_barShader->nModel(),
- itModelMatrix.transposed().inverted());
- m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix);
- m_barShader->setUniformValue(m_barShader->color(), barColor);
+ // Skip drawing of 0-height bars
+ if (item.height() != 0) {
+ // Set shader bindings
+ barShader->setUniformValue(barShader->model(), modelMatrix);
+ barShader->setUniformValue(barShader->nModel(),
+ itModelMatrix.transposed().inverted());
+ barShader->setUniformValue(barShader->MVP(), MVPMatrix);
+ if (colorStyleIsUniform) {
+ barShader->setUniformValue(barShader->color(), barColor);
+ } else if (colorStyle == Q3DTheme::ColorStyleRangeGradient) {
+ barShader->setUniformValue(barShader->gradientHeight(),
+ qAbs(item.height()) / m_gradientFraction);
+ }
#if !defined(QT_OPENGL_ES_2)
- if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
- // Set shadow shader bindings
- QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix;
- m_barShader->setUniformValue(m_barShader->shadowQ(), m_shadowQualityToShader);
- m_barShader->setUniformValue(m_barShader->depth(), depthMVPMatrix);
- m_barShader->setUniformValue(m_barShader->lightS(), shadowLightStrength);
-
- // Draw the object
- m_drawer->drawObject(m_barShader, m_barObj, 0, m_depthTexture);
- } else
+ if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
+ // Set shadow shader bindings
+ QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ barShader->setUniformValue(barShader->shadowQ(), m_shadowQualityToShader);
+ barShader->setUniformValue(barShader->depth(), depthMVPMatrix);
+ barShader->setUniformValue(barShader->lightS(), shadowLightStrength);
+
+ // Draw the object
+ m_drawer->drawObject(barShader, barObj, gradientTexture, m_depthTexture);
+ } else
#endif
- {
- // Set shadowless shader bindings
- m_barShader->setUniformValue(m_barShader->lightS(), lightStrength);
+ {
+ // Set shadowless shader bindings
+ barShader->setUniformValue(barShader->lightS(), lightStrength);
- // Draw the object
- m_drawer->drawObject(m_barShader, m_barObj);
+ // Draw the object
+ m_drawer->drawObject(barShader, barObj, gradientTexture);
+ }
}
}
}
+ seriesPos += m_seriesStep;
}
- if (selectionDirty)
- emit selectedBarPosChanged(QPoint(int(m_selection.x()), int(m_selection.y())));
-
- // Release bar shader
- m_barShader->release();
-
// Bind background shader
m_backgroundShader->bind();
- if (m_hasNegativeValues)
- glDisable(GL_CULL_FACE);
- else
- glCullFace(GL_BACK);
+ // Reset culling
+ glCullFace(GL_BACK);
// Draw background
GLfloat rowScaleFactor = m_rowWidth / m_scaleFactor;
GLfloat columnScaleFactor = m_columnDepth / m_scaleFactor;
- if (m_cachedIsBackgroundEnabled && m_backgroundObj) {
+ if (m_cachedTheme->isBackgroundEnabled() && m_backgroundObj) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
QVector3D backgroundScaler(rowScaleFactor, 1.0f, columnScaleFactor);
- modelMatrix.translate(0.0f, 1.0f - m_yAdjustment, 0.0f);
+ if (m_hasNegativeValues) {
+ backgroundScaler.setY(0.5f);
+ modelMatrix.translate(0.0f, m_negativeBackgroundAdjustment, 0.0f);
+ } else {
+ modelMatrix.translate(0.0f, 1.0f, 0.0f);
+ }
modelMatrix.scale(backgroundScaler);
- modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f);
itModelMatrix.scale(backgroundScaler);
+ modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f);
itModelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f);
#ifdef SHOW_DEPTH_TEXTURE_SCENE
@@ -972,7 +1290,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
#else
MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
- QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme.m_backgroundColor);
+ QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme->backgroundColor());
// Set shader bindings
m_backgroundShader->setUniformValue(m_backgroundShader->lightP(), lightPos);
@@ -983,7 +1301,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
m_backgroundShader->setUniformValue(m_backgroundShader->MVP(), MVPMatrix);
m_backgroundShader->setUniformValue(m_backgroundShader->color(), backgroundColor);
m_backgroundShader->setUniformValue(m_backgroundShader->ambientS(),
- m_cachedTheme.m_ambientStrength * 2.0f);
+ m_cachedTheme->ambientLightStrength() * 2.0f);
#if !defined(QT_OPENGL_ES_2)
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
@@ -1002,53 +1320,96 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
{
// Set shadowless shader bindings
m_backgroundShader->setUniformValue(m_backgroundShader->lightS(),
- m_cachedTheme.m_lightStrength);
+ m_cachedTheme->lightStrength());
// Draw the object
m_drawer->drawObject(m_backgroundShader, m_backgroundObj);
}
- }
- // Release background shader
- m_backgroundShader->release();
+ // Draw floor for graph with negatives
+ if (m_hasNegativeValues) {
+ modelMatrix = QMatrix4x4();
+ itModelMatrix = QMatrix4x4();
- // Disable textures
- glDisable(GL_TEXTURE_2D);
+ modelMatrix.scale(backgroundScaler);
- // Reset culling
- if (m_hasNegativeValues) {
- glEnable(GL_CULL_FACE);
- glCullFace(GL_BACK);
+ if (m_yFlipped)
+ modelMatrix.rotate(90.0f, 1.0f, 0.0f, 0.0f);
+ else
+ modelMatrix.rotate(-90.0f, 1.0f, 0.0f, 0.0f);
+
+ itModelMatrix = modelMatrix;
+
+#ifdef SHOW_DEPTH_TEXTURE_SCENE
+ MVPMatrix = depthProjectionViewMatrix * modelMatrix;
+#else
+ MVPMatrix = projectionViewMatrix * modelMatrix;
+#endif
+ // Set changed shader bindings
+ m_backgroundShader->setUniformValue(m_backgroundShader->model(), modelMatrix);
+ m_backgroundShader->setUniformValue(m_backgroundShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ m_backgroundShader->setUniformValue(m_backgroundShader->MVP(), MVPMatrix);
+
+#if !defined(QT_OPENGL_ES_2)
+ if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
+ // Set shadow shader bindings
+ QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ m_backgroundShader->setUniformValue(m_backgroundShader->depth(), depthMVPMatrix);
+ // Draw the object
+ m_drawer->drawObject(m_backgroundShader, m_gridLineObj, 0, m_depthTexture);
+ } else
+#endif
+ {
+ // Draw the object
+ m_drawer->drawObject(m_backgroundShader, m_gridLineObj);
+ }
+ }
}
+ // Disable textures
+ glDisable(GL_TEXTURE_2D);
+
// Draw grid lines
- if (m_cachedIsGridEnabled && m_heightNormalizer) {
+ if (m_cachedTheme->isGridEnabled() && m_heightNormalizer) {
ShaderHelper *lineShader = m_backgroundShader;
+ QQuaternion lineRotation = QQuaternion();
// Bind bar shader
lineShader->bind();
// Set unchanging shader bindings
- QVector3D barColor = Utils::vectorFromColor(m_cachedTheme.m_gridLine);
+ QVector3D barColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
lineShader->setUniformValue(lineShader->lightP(), lightPos);
lineShader->setUniformValue(lineShader->view(), viewMatrix);
lineShader->setUniformValue(lineShader->color(), barColor);
- lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme.m_ambientStrength);
+ lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme->ambientLightStrength());
#if !defined(QT_OPENGL_ES_2)
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
// Set shadowed shader bindings
lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader);
lineShader->setUniformValue(lineShader->lightS(),
- m_cachedTheme.m_lightStrength / 20.0f);
+ m_cachedTheme->lightStrength() / 20.0f);
} else
#endif
{
// Set shadowless shader bindings
- lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme.m_lightStrength / 2.5f);
+ lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme->lightStrength() / 2.5f);
}
+ GLfloat yFloorLinePosition = 0.0f;
+ if (m_yFlipped)
+ yFloorLinePosition -= gridLineOffset;
+ else
+ yFloorLinePosition += gridLineOffset;
+
QVector3D gridLineScaler(rowScaleFactor, gridLineWidth, gridLineWidth);
+ if (m_yFlipped)
+ lineRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 90.0f);
+ else
+ lineRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, -90.0f);
+
// Floor lines: rows
for (GLfloat row = 0.0f; row <= m_cachedRowCount; row++) {
QMatrix4x4 modelMatrix;
@@ -1056,15 +1417,12 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
QMatrix4x4 itModelMatrix;
rowPos = row * m_cachedBarSpacing.height();
- modelMatrix.translate(0.0f, -m_yAdjustment,
+ modelMatrix.translate(0.0f, yFloorLinePosition,
(m_columnDepth - rowPos) / m_scaleFactor);
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
- // If we're viewing from below, grid line object must be flipped
- if (m_yFlipped) {
- modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- itModelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- }
+ modelMatrix.rotate(lineRotation);
+ itModelMatrix.rotate(lineRotation);
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -1098,15 +1456,11 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
colPos = bar * m_cachedBarSpacing.width();
modelMatrix.translate((m_rowWidth - colPos) / m_scaleFactor,
- -m_yAdjustment, 0.0f);
+ yFloorLinePosition, 0.0f);
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
-
- // If we're viewing from below, grid line object must be flipped
- if (m_yFlipped) {
- modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- itModelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- }
+ modelMatrix.rotate(lineRotation);
+ itModelMatrix.rotate(lineRotation);
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -1135,28 +1489,35 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
// Wall lines: back wall
GLfloat heightStep = m_axisCacheY.subSegmentStep();
GLfloat startLine = 0.0f;
+ int segmentCount = m_axisCacheY.segmentCount() * m_axisCacheY.subSegmentCount();
- if (m_hasNegativeValues)
- startLine = -m_heightNormalizer;
+ GLfloat zWallLinePosition = -columnScaleFactor + gridLineOffset;
+ if (m_zFlipped)
+ zWallLinePosition = -zWallLinePosition;
+ if (m_hasNegativeValues) {
+ if (m_noZeroInRange)
+ startLine = m_axisCacheY.min() - m_axisCacheY.max();
+ else
+ startLine = m_axisCacheY.min();
+ }
+
+ GLfloat lineHeight = startLine;
gridLineScaler = QVector3D(rowScaleFactor, gridLineWidth, gridLineWidth);
- for (GLfloat lineHeight = startLine; lineHeight <= m_heightNormalizer;
- lineHeight += heightStep) {
+ for (int segment = 0; segment <= segmentCount; segment++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- if (m_zFlipped) {
- modelMatrix.translate(0.0f,
- 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment,
- columnScaleFactor);
- } else {
- modelMatrix.translate(0.0f,
- 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment,
- -columnScaleFactor);
- }
+ modelMatrix.translate(0.0f,
+ 2.0f * lineHeight / m_heightNormalizer,
+ zWallLinePosition);
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
+ if (m_zFlipped) {
+ modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ itModelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ }
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -1179,27 +1540,33 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
+ lineHeight += heightStep;
}
// Wall lines: side wall
+ GLfloat xWallLinePosition = -rowScaleFactor + gridLineOffset;
+ if (m_xFlipped)
+ xWallLinePosition = -xWallLinePosition;
+
+ if (m_xFlipped)
+ lineRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, -90.0f);
+ else
+ lineRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f);
+
+ lineHeight = startLine;
gridLineScaler = QVector3D(gridLineWidth, gridLineWidth, columnScaleFactor);
- for (GLfloat lineHeight = startLine; lineHeight <= m_heightNormalizer;
- lineHeight += heightStep) {
+ for (int segment = 0; segment <= segmentCount; segment++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- if (m_xFlipped) {
- modelMatrix.translate(rowScaleFactor,
- 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment,
- 0.0f);
- } else {
- modelMatrix.translate(-rowScaleFactor,
- 2.0f * lineHeight / m_heightNormalizer - m_yAdjustment,
- 0.0f);
- }
+ modelMatrix.translate(xWallLinePosition,
+ 2.0f * lineHeight / m_heightNormalizer,
+ 0.0f);
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
+ modelMatrix.rotate(lineRotation);
+ itModelMatrix.rotate(lineRotation);
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -1222,27 +1589,25 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
+ lineHeight += heightStep;
}
}
- // Release bar shader
- lineShader->release();
}
- // TODO: Calculations done temporarily here. When optimizing, move to after data set addition? Keep drawing of the labels here.
// Bind label shader
m_labelShader->bind();
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_POLYGON_OFFSET_FILL);
// Calculate the positions for row and column labels and store them
- GLfloat labelYAdjustment = -m_yAdjustment + 0.005f;
+ GLfloat labelYAdjustment = 0.005f;
GLfloat scaledRowWidth = rowScaleFactor;
GLfloat scaledColumnDepth = columnScaleFactor;
GLfloat colPosValue = scaledRowWidth + labelMargin;
GLfloat rowPosValue = scaledColumnDepth + labelMargin;
- QVector3D positionComp(0.0f, m_yAdjustment, 0.0f);
QVector3D labelRotation(-90.0f, 0.0f, 0.0f);
if (m_zFlipped)
labelRotation.setY(180.0f);
@@ -1253,9 +1618,10 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
labelRotation.setY(180.0f);
labelRotation.setZ(180.0f);
}
+
Qt::AlignmentFlag alignment = m_xFlipped ? Qt::AlignLeft : Qt::AlignRight;
for (int row = 0; row != m_cachedRowCount; row++) {
- if (m_axisCacheX.labelItems().size() > row) {
+ if (m_axisCacheZ.labelItems().size() > row) {
// Go through all rows and get position of max+1 or min-1 column, depending on x flip
// We need only positions for them, labels have already been generated at QDataSetPrivate. Just add LabelItems
rowPos = (row + 0.5f) * m_cachedBarSpacing.height();
@@ -1264,18 +1630,19 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
else
colPos = colPosValue;
+ glPolygonOffset(GLfloat(row) / -10.0f, 1.0f);
+
QVector3D labelPos = QVector3D(colPos,
labelYAdjustment, // raise a bit over background to avoid depth "glimmering"
(m_columnDepth - rowPos) / m_scaleFactor);
m_dummyBarRenderItem.setTranslation(labelPos);
- const LabelItem &axisLabelItem = *m_axisCacheX.labelItems().at(row);
- //qDebug() << "labelPos, row" << row + 1 << ":" << labelPos << m_axisCacheX.labels().at(row);
+ const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(row);
m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- positionComp, labelRotation, 0, m_cachedSelectionMode,
+ zeroVector, labelRotation, 0, m_cachedSelectionMode,
m_labelShader, m_labelObj, activeCamera,
- true, true, Drawer::LabelMid, alignment);
+ true, true, Drawer::LabelMid, alignment, m_cachedIsSlicingActivated);
}
}
labelRotation = QVector3D(-90.0f, 90.0f, 0.0f);
@@ -1290,8 +1657,8 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
}
alignment = m_zFlipped ? Qt::AlignRight : Qt::AlignLeft;
- for (int column = 0; column != m_cachedColumnCount; column += 1) {
- if (m_axisCacheZ.labelItems().size() > column) {
+ for (int column = 0; column != m_cachedColumnCount; column++) {
+ if (m_axisCacheX.labelItems().size() > column) {
// Go through all columns and get position of max+1 or min-1 row, depending on z flip
// We need only positions for them, labels have already been generated at QDataSetPrivate. Just add LabelItems
colPos = (column + 0.5f) * m_cachedBarSpacing.width();
@@ -1300,15 +1667,17 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
else
rowPos = rowPosValue;
+ glPolygonOffset(GLfloat(column) / -10.0f, 1.0f);
+
QVector3D labelPos = QVector3D((colPos - m_rowWidth) / m_scaleFactor,
labelYAdjustment, // raise a bit over background to avoid depth "glimmering"
rowPos);
m_dummyBarRenderItem.setTranslation(labelPos);
- const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(column);
+ const LabelItem &axisLabelItem = *m_axisCacheX.labelItems().at(column);
m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- positionComp, labelRotation, 0, m_cachedSelectionMode,
+ zeroVector, labelRotation, 0, m_cachedSelectionMode,
m_labelShader, m_labelObj, activeCamera,
true, true, Drawer::LabelMid, alignment);
}
@@ -1319,8 +1688,12 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
GLfloat heightStep = m_axisCacheY.segmentStep();
GLfloat startLine = 0.0f;
int labelCount = m_axisCacheY.labels().size();
- if (m_hasNegativeValues)
- startLine = -m_heightNormalizer;
+ if (m_hasNegativeValues) {
+ if (m_noZeroInRange)
+ startLine = m_axisCacheY.min() - m_axisCacheY.max();
+ else
+ startLine = m_axisCacheY.min();
+ }
GLfloat labelPos = startLine;
GLfloat labelMarginXTrans = labelMargin;
GLfloat labelMarginZTrans = labelMargin;
@@ -1349,50 +1722,34 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
for (int i = 0; i < labelCount; i++) {
if (m_axisCacheY.labelItems().size() > labelNbr) {
- backLabelTrans.setY(2.0f * labelPos / m_heightNormalizer - m_yAdjustment);
+ backLabelTrans.setY(2.0f * labelPos / m_heightNormalizer);
sideLabelTrans.setY(backLabelTrans.y());
+ glPolygonOffset(GLfloat(i) / -10.0f, 1.0f);
+
const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr);
// Back wall
m_dummyBarRenderItem.setTranslation(backLabelTrans);
m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- positionComp, backLabelRotation, 0, m_cachedSelectionMode,
+ zeroVector, backLabelRotation, 0, m_cachedSelectionMode,
m_labelShader, m_labelObj, activeCamera,
true, true, Drawer::LabelMid, backAlignment);
// Side wall
m_dummyBarRenderItem.setTranslation(sideLabelTrans);
m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- positionComp, sideLabelRotation, 0, m_cachedSelectionMode,
+ zeroVector, sideLabelRotation, 0, m_cachedSelectionMode,
m_labelShader, m_labelObj, activeCamera,
true, true, Drawer::LabelMid, sideAlignment);
}
labelNbr++;
labelPos += heightStep;
}
+ glDisable(GL_POLYGON_OFFSET_FILL);
- // Handle slice activation and selection label drawing
- if (!barSelectionFound) {
- // We have no ownership, don't delete. Just NULL the pointer.
- m_selectedBar = NULL;
- if (m_cachedIsSlicingActivated
- && (m_selection == selectionSkipColor
- || QDataVis::InputStateOnOverview == m_controller->inputState())) {
- m_cachedScene->setSlicingActive(false);
- }
- } else if (m_cachedSelectionMode >= QDataVis::SelectionModeSliceRow && selectionDirty) {
- // Activate slice mode
- m_cachedScene->setSlicingActive(true);
-
- // Create label textures
- for (int col = 0; col < m_sliceSelection->size(); col++) {
- BarRenderItem *item = m_sliceSelection->at(col);
- if (item->sliceLabel().isNull())
- item->setSliceLabel(generateValueLabel(m_axisCacheY.labelFormat(), item->value()));
- m_drawer->generateLabelItem(item->sliceLabelItem(), item->sliceLabel());
- }
- } else {
+ // Handle selected bar label generation
+ if (barSelectionFound) {
// Print value of selected bar
glDisable(GL_DEPTH_TEST);
// Draw the selection label
@@ -1410,22 +1767,24 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
static const QString valueLabelTag(QStringLiteral("@valueLabel"));
// Custom format expects printf format specifier. There is no tag for it.
- labelText = generateValueLabel(itemLabelFormat(), selectedBar->value());
-
- int selBarPosX = selectedBar->position().x();
- int selBarPosY = selectedBar->position().y();
- labelText.replace(rowIndexTag, QString::number(selBarPosX));
- if (m_axisCacheX.labels().size() > selBarPosX)
- labelText.replace(rowLabelTag, m_axisCacheX.labels().at(selBarPosX));
+ labelText = generateValueLabel(
+ m_visibleSeriesList[m_visualSelectedBarSeriesIndex].itemLabelFormat(),
+ selectedBar->value());
+
+ int selBarPosRow = selectedBar->position().x();
+ int selBarPosCol = selectedBar->position().y();
+ labelText.replace(rowIndexTag, QString::number(selBarPosRow));
+ if (m_axisCacheZ.labels().size() > selBarPosRow)
+ labelText.replace(rowLabelTag, m_axisCacheZ.labels().at(selBarPosRow));
else
labelText.replace(rowLabelTag, QString());
- labelText.replace(rowTitleTag, m_axisCacheX.title());
- labelText.replace(colIndexTag, QString::number(selBarPosY));
- if (m_axisCacheZ.labels().size() > selBarPosY)
- labelText.replace(colLabelTag, m_axisCacheZ.labels().at(selBarPosY));
+ labelText.replace(rowTitleTag, m_axisCacheZ.title());
+ labelText.replace(colIndexTag, QString::number(selBarPosCol));
+ if (m_axisCacheX.labels().size() > selBarPosCol)
+ labelText.replace(colLabelTag, m_axisCacheX.labels().at(selBarPosCol));
else
labelText.replace(colLabelTag, QString());
- labelText.replace(colTitleTag, m_axisCacheZ.title());
+ labelText.replace(colTitleTag, m_axisCacheX.title());
labelText.replace(valueTitleTag, m_axisCacheY.title());
if (labelText.contains(valueLabelTag)) {
@@ -1443,7 +1802,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
}
m_drawer->drawLabel(*selectedBar, labelItem, viewMatrix, projectionMatrix,
- positionComp, zeroVector, selectedBar->height(),
+ zeroVector, zeroVector, selectedBar->height(),
m_cachedSelectionMode, m_labelShader,
m_labelObj, activeCamera, true, false);
@@ -1451,23 +1810,17 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
m_updateLabels = false;
glEnable(GL_DEPTH_TEST);
+ } else {
+ m_selectedBar = 0;
}
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
- // Release label shader
- m_labelShader->release();
-}
+ // Release shader
+ glUseProgram(0);
-void Bars3DRenderer::handleResize()
-{
- if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0)
- return;
-
- setViewPorts();
-
- Abstract3DRenderer::handleResize();
+ m_selectionDirty = false;
}
void Bars3DRenderer::updateBarSpecs(GLfloat thicknessRatio, const QSizeF &spacing, bool relative)
@@ -1477,17 +1830,24 @@ void Bars3DRenderer::updateBarSpecs(GLfloat thicknessRatio, const QSizeF &spacin
m_cachedBarThickness.setHeight(1.0f / thicknessRatio);
if (relative) {
- m_cachedBarSpacing.setWidth((m_cachedBarThickness.width() * 2) * (spacing.width() + 1.0f));
- m_cachedBarSpacing.setHeight((m_cachedBarThickness.height() * 2) * (spacing.height() + 1.0f));
+ m_cachedBarSpacing.setWidth((m_cachedBarThickness.width() * 2)
+ * (spacing.width() + 1.0f));
+ m_cachedBarSpacing.setHeight((m_cachedBarThickness.height() * 2)
+ * (spacing.height() + 1.0f));
} else {
m_cachedBarSpacing = m_cachedBarThickness * 2 + spacing * 2;
}
+ // Slice mode doesn't update correctly without this
+ if (m_cachedIsSlicingActivated)
+ m_selectionDirty = true;
+
// Calculate here and at setting sample space
calculateSceneScalingFactors();
}
-void Bars3DRenderer::updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, qreal min, qreal max)
+void Bars3DRenderer::updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, float min,
+ float max)
{
Abstract3DRenderer::updateAxisRange(orientation, min, max);
@@ -1505,44 +1865,40 @@ void Bars3DRenderer::updateAxisRange(Q3DAbstractAxis::AxisOrientation orientatio
loadBackgroundMesh();
emit needRender();
}
-
- // TODO Currently bargraph only supports zero centered or zero minimum ranges
- if (min > 0.0 || (min != 0.0 && (qFabs(min) != qFabs(max)))) {
- qWarning() << __FUNCTION__ << "Bar graph currently properly supports only "
- "zero-centered and zero minimum ranges for Y-axis.";
- }
}
}
-void Bars3DRenderer::updateSelectionMode(QDataVis::SelectionMode mode)
+void Bars3DRenderer::updateSelectedBar(const QPoint &position, const QBar3DSeries *series)
{
- Abstract3DRenderer::updateSelectionMode(mode);
+ m_selectedBarPos = position;
+ m_selectedBarSeries = series;
+ m_selectionDirty = true;
+ m_visualSelectedBarSeriesIndex = -1;
- // Create zoom selection if there isn't one
- if (mode >= QDataVis::SelectionModeSliceRow && !m_sliceSelection) {
- m_sliceSelection = new QList<BarRenderItem *>;
- if (mode == QDataVis::SelectionModeSliceRow)
- m_sliceSelection->reserve(m_cachedRowCount);
- else
- m_sliceSelection->reserve(m_cachedColumnCount);
+ if (m_renderingArrays.isEmpty()) {
+ m_visualSelectedBarPos = Bars3DController::invalidSelectionPosition();
+ return;
}
-}
-void Bars3DRenderer::updateBackgroundEnabled(bool enable)
-{
- if (enable != m_cachedIsBackgroundEnabled) {
- Abstract3DRenderer::updateBackgroundEnabled(enable);
- loadMeshFile(); // Load changed bar type
+ int adjustedZ = m_selectedBarPos.x() - int(m_axisCacheZ.min());
+ int adjustedX = m_selectedBarPos.y() - int(m_axisCacheX.min());
+ int maxZ = m_renderingArrays.at(0).size() - 1;
+ int maxX = maxZ >= 0 ? m_renderingArrays.at(0).at(0).size() - 1 : -1;
+
+ for (int i = 0; i < m_visibleSeriesList.size(); i++) {
+ if (m_visibleSeriesList.at(i).series() == series) {
+ m_visualSelectedBarSeriesIndex = i;
+ break;
+ }
}
-}
-void Bars3DRenderer::updateSelectedBarPos(const QPoint &position)
-{
- if (position == Bars3DController::noSelectionPoint())
- m_selection = selectionSkipColor;
- else
- m_selection = QVector3D(position.x(), position.y(), 0);
- emit needRender();
+ if (m_selectedBarPos == Bars3DController::invalidSelectionPosition()
+ || adjustedZ < 0 || adjustedZ > maxZ
+ || adjustedX < 0 || adjustedX > maxX) {
+ m_visualSelectedBarPos = Bars3DController::invalidSelectionPosition();
+ } else {
+ m_visualSelectedBarPos = QPoint(adjustedZ, adjustedX);
+ }
}
void Bars3DRenderer::updateShadowQuality(QDataVis::ShadowQuality quality)
@@ -1587,18 +1943,6 @@ void Bars3DRenderer::updateShadowQuality(QDataVis::ShadowQuality quality)
#endif
}
-void Bars3DRenderer::loadMeshFile()
-{
- QString objectFileName = m_cachedObjFile;
- if (m_barObj)
- delete m_barObj;
- // If background is disabled, load full version of bar mesh
- if (!m_cachedIsBackgroundEnabled)
- objectFileName.append(QStringLiteral("Full"));
- m_barObj = new ObjectHelper(objectFileName);
- m_barObj->load();
-}
-
void Bars3DRenderer::loadBackgroundMesh()
{
if (m_backgroundObj)
@@ -1614,7 +1958,7 @@ void Bars3DRenderer::loadGridLineMesh()
{
if (m_gridLineObj)
delete m_gridLineObj;
- m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar"));
+ m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
m_gridLineObj->load();
}
@@ -1622,7 +1966,7 @@ void Bars3DRenderer::loadLabelMesh()
{
if (m_labelObj)
delete m_labelObj;
- m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label"));
+ m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
m_labelObj->load();
}
@@ -1632,6 +1976,16 @@ void Bars3DRenderer::updateTextures()
m_updateLabels = true;
}
+void Bars3DRenderer::fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh)
+{
+ if (!m_cachedTheme->isBackgroundEnabled()) {
+ // Load full version of meshes that have it available
+ // Note: Minimal and Point not supported in bar charts
+ if (mesh != QAbstract3DSeries::MeshSphere)
+ fileName.append(QStringLiteral("Full"));
+ }
+}
+
void Bars3DRenderer::calculateSceneScalingFactors()
{
// Calculate scene scaling and translation factors
@@ -1642,61 +1996,81 @@ void Bars3DRenderer::calculateSceneScalingFactors()
(m_cachedRowCount * (m_maxDimension / m_maxSceneSize)));
m_scaleX = m_cachedBarThickness.width() / m_scaleFactor;
m_scaleZ = m_cachedBarThickness.height() / m_scaleFactor;
- //qDebug() << "m_scaleX" << m_scaleX << "m_scaleFactor" << m_scaleFactor;
- //qDebug() << "m_scaleZ" << m_scaleZ << "m_scaleFactor" << m_scaleFactor;
- //qDebug() << "m_rowWidth:" << m_rowWidth << "m_columnDepth:" << m_columnDepth << "m_maxDimension:" << m_maxDimension;
}
void Bars3DRenderer::calculateHeightAdjustment()
{
- m_heightNormalizer = (GLfloat)qMax(qFabs(m_axisCacheY.min()), qFabs(m_axisCacheY.max()));
+ GLfloat newAdjustment = 0.0f;
+ GLfloat maxAbs = qFabs(m_axisCacheY.max());
- // 2.0f = max difference between minimum and maximum value after scaling with m_heightNormalizer
- GLfloat newAdjustment = 2.0f - ((m_heightNormalizer - m_axisCacheY.min()) / m_heightNormalizer);
- if (newAdjustment != m_yAdjustment) {
+ if (m_axisCacheY.max() < 0.0f) {
+ m_heightNormalizer = GLfloat(qFabs(m_axisCacheY.min()) - qFabs(m_axisCacheY.max()));
+ maxAbs = qFabs(m_axisCacheY.max()) - qFabs(m_axisCacheY.min());
+ } else {
+ m_heightNormalizer = GLfloat(m_axisCacheY.max() - m_axisCacheY.min());
+ }
+
+ // Height fractions are used in gradient calculations and are therefore doubled
+ if (m_axisCacheY.max() < 0.0f || m_axisCacheY.min() > 0.0f) {
+ m_noZeroInRange = true;
+ m_gradientFraction = 2.0f;
+ } else {
+ m_noZeroInRange = false;
+ GLfloat minAbs = qFabs(m_axisCacheY.min());
+ m_gradientFraction = qMax(minAbs, maxAbs) / m_heightNormalizer * 2.0f;
+ }
+
+ // Calculate translation adjustment for negative background
+ newAdjustment = qBound(0.0f, (maxAbs / m_heightNormalizer), 1.0f) * 2.0f - 0.5f;
+
+ if (newAdjustment != m_negativeBackgroundAdjustment) {
m_hasHeightAdjustmentChanged = true;
- m_yAdjustment = newAdjustment;
+ m_negativeBackgroundAdjustment = newAdjustment;
}
- //qDebug() << m_yAdjustment;
}
-Bars3DController::SelectionType Bars3DRenderer::isSelected(GLint row, GLint bar)
+Bars3DController::SelectionType Bars3DRenderer::isSelected(int row, int bar, int seriesIndex)
{
- //static QVector3D prevSel = m_selection; // TODO: For debugging
Bars3DController::SelectionType isSelectedType = Bars3DController::SelectionNone;
- if (m_selection == selectionSkipColor)
- return isSelectedType; // skip window
-
- //#if !defined(QT_OPENGL_ES_2)
- // QVector3D current = QVector3D((GLuint)row, (GLuint)bar, 0);
- //#else
- QVector3D current = QVector3D((GLubyte)row, (GLubyte)bar, 0);
- //#endif
-
- // TODO: For debugging
- //if (selection != prevSel) {
- // qDebug() << "current" << current.x() << current .y() << current.z();
- // qDebug() << "selection" << selection.x() << selection .y() << selection.z();
- // prevSel = selection;
- //}
- if (current == m_selection) {
- isSelectedType = Bars3DController::SelectionItem;
- }
- else if (current.y() == m_selection.y()
- && (m_cachedSelectionMode == QDataVis::SelectionModeItemAndColumn
- || m_cachedSelectionMode == QDataVis::SelectionModeItemRowAndColumn
- || m_cachedSelectionMode == QDataVis::SelectionModeSliceColumn)) {
- isSelectedType = Bars3DController::SelectionColumn;
- }
- else if (current.x() == m_selection.x()
- && (m_cachedSelectionMode == QDataVis::SelectionModeItemAndRow
- || m_cachedSelectionMode == QDataVis::SelectionModeItemRowAndColumn
- || m_cachedSelectionMode == QDataVis::SelectionModeSliceRow)) {
- isSelectedType = Bars3DController::SelectionRow;
+
+ if ((m_cachedSelectionMode.testFlag(QDataVis::SelectionMultiSeries)
+ && m_visualSelectedBarSeriesIndex >= 0)
+ || seriesIndex == m_visualSelectedBarSeriesIndex) {
+ if (row == m_visualSelectedBarPos.x() && bar == m_visualSelectedBarPos.y()
+ && (m_cachedSelectionMode.testFlag(QDataVis::SelectionItem))) {
+ isSelectedType = Bars3DController::SelectionItem;
+ } else if (row == m_visualSelectedBarPos.x()
+ && (m_cachedSelectionMode.testFlag(QDataVis::SelectionRow))) {
+ isSelectedType = Bars3DController::SelectionRow;
+ } else if (bar == m_visualSelectedBarPos.y()
+ && (m_cachedSelectionMode.testFlag(QDataVis::SelectionColumn))) {
+ isSelectedType = Bars3DController::SelectionColumn;
+ }
}
+
return isSelectedType;
}
+QPoint Bars3DRenderer::selectionColorToArrayPosition(const QVector3D &selectionColor)
+{
+ QPoint position;
+ if (selectionColor == selectionSkipColor) {
+ position = Bars3DController::invalidSelectionPosition();
+ } else {
+ position = QPoint(int(selectionColor.x() + int(m_axisCacheZ.min())),
+ int(selectionColor.y()) + int(m_axisCacheX.min()));
+ }
+ return position;
+}
+
+QBar3DSeries *Bars3DRenderer::selectionColorToSeries(const QVector3D &selectionColor)
+{
+ if (selectionColor == selectionSkipColor)
+ return 0;
+ else
+ return static_cast<QBar3DSeries *>(m_visibleSeriesList.at(int(selectionColor.z())).series());
+}
+
void Bars3DRenderer::updateSlicingActive(bool isSlicing)
{
if (isSlicing == m_cachedIsSlicingActivated)
@@ -1704,35 +2078,14 @@ void Bars3DRenderer::updateSlicingActive(bool isSlicing)
m_cachedIsSlicingActivated = isSlicing;
- setViewPorts();
-
if (!m_cachedIsSlicingActivated)
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 Bars3DRenderer::setViewPorts()
-{
- // Update view ports
- if (m_cachedIsSlicingActivated) {
- m_mainViewPort = QRect(0,
- m_cachedBoundingRect.height()
- - (m_cachedBoundingRect.height() / smallerVPSize),
- m_cachedBoundingRect.width() / smallerVPSize,
- m_cachedBoundingRect.height() / smallerVPSize);
- m_sliceViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height());
- } else {
- m_mainViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height());
- m_sliceViewPort = QRect(0, 0, 0, 0);
- }
-}
-
-QRect Bars3DRenderer::mainViewPort()
-{
- return m_mainViewPort;
+ m_selectionDirty = true;
}
void Bars3DRenderer::initShaders(const QString &vertexShader, const QString &fragmentShader)
@@ -1743,12 +2096,20 @@ void Bars3DRenderer::initShaders(const QString &vertexShader, const QString &fra
m_barShader->initialize();
}
+void Bars3DRenderer::initGradientShaders(const QString &vertexShader, const QString &fragmentShader)
+{
+ if (m_barGradientShader)
+ delete m_barGradientShader;
+ m_barGradientShader = new ShaderHelper(this, vertexShader, fragmentShader);
+ m_barGradientShader->initialize();
+}
+
void Bars3DRenderer::initSelectionShader()
{
if (m_selectionShader)
delete m_selectionShader;
- m_selectionShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSelection"),
- QStringLiteral(":/shaders/fragmentSelection"));
+ m_selectionShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexPlainColor"),
+ QStringLiteral(":/shaders/fragmentPlainColor"));
m_selectionShader->initialize();
}
@@ -1759,10 +2120,10 @@ void Bars3DRenderer::initSelectionBuffer()
m_selectionTexture = 0;
}
- if (m_cachedIsSlicingActivated || m_mainViewPort.size().isEmpty())
+ if (m_cachedIsSlicingActivated || m_primarySubViewport.size().isEmpty())
return;
- m_selectionTexture = m_textureHelper->createSelectionTexture(m_mainViewPort.size(),
+ m_selectionTexture = m_textureHelper->createSelectionTexture(m_primarySubViewport.size(),
m_selectionFrameBuffer,
m_selectionDepthBuffer);
}
@@ -1784,50 +2145,15 @@ void Bars3DRenderer::updateDepthBuffer()
m_depthTexture = 0;
}
- if (m_mainViewPort.size().isEmpty())
+ if (m_primarySubViewport.size().isEmpty())
return;
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
- m_depthTexture = m_textureHelper->createDepthTexture(m_mainViewPort.size(),
- m_depthFrameBuffer,
- m_shadowQualityMultiplier);
- if (!m_depthTexture) {
- switch (m_cachedShadowQuality) {
- case QDataVis::ShadowQualityHigh:
- qWarning("Creating high quality shadows failed. Changing to medium quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityMedium);
- updateShadowQuality(QDataVis::ShadowQualityMedium);
- break;
- case QDataVis::ShadowQualityMedium:
- qWarning("Creating medium quality shadows failed. Changing to low quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityLow);
- updateShadowQuality(QDataVis::ShadowQualityLow);
- break;
- case QDataVis::ShadowQualityLow:
- qWarning("Creating low quality shadows failed. Switching shadows off.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityNone);
- updateShadowQuality(QDataVis::ShadowQualityNone);
- break;
- case QDataVis::ShadowQualitySoftHigh:
- qWarning("Creating soft high quality shadows failed. Changing to soft medium quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualitySoftMedium);
- updateShadowQuality(QDataVis::ShadowQualitySoftMedium);
- break;
- case QDataVis::ShadowQualitySoftMedium:
- qWarning("Creating soft medium quality shadows failed. Changing to soft low quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualitySoftLow);
- updateShadowQuality(QDataVis::ShadowQualitySoftLow);
- break;
- case QDataVis::ShadowQualitySoftLow:
- qWarning("Creating soft low quality shadows failed. Switching shadows off.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityNone);
- updateShadowQuality(QDataVis::ShadowQualityNone);
- break;
- default:
- // You'll never get here
- break;
- }
- }
+ m_depthTexture = m_textureHelper->createDepthTextureFrameBuffer(m_primarySubViewport.size(),
+ m_depthFrameBuffer,
+ m_shadowQualityMultiplier);
+ if (!m_depthTexture)
+ lowerShadowQuality();
}
}
#endif
diff --git a/src/datavisualization/engine/bars3drenderer_p.h b/src/datavisualization/engine/bars3drenderer_p.h
index dd80902a..16e7a476 100644
--- a/src/datavisualization/engine/bars3drenderer_p.h
+++ b/src/datavisualization/engine/bars3drenderer_p.h
@@ -51,9 +51,6 @@ class QT_DATAVISUALIZATION_EXPORT Bars3DRenderer : public Abstract3DRenderer
Q_OBJECT
private:
- // TODO: Filter to the set of attributes to be moved to the model object.
- Bars3DController *m_controller;
-
// Cached state based on emitted signals from the controller
QSizeF m_cachedBarThickness;
QSizeF m_cachedBarSpacing;
@@ -63,21 +60,19 @@ private:
// Internal state
BarRenderItem *m_selectedBar; // points to renderitem array
- QList<BarRenderItem *> *m_sliceSelection;
+ QVector<BarRenderItem *> m_sliceSelection;
AxisRenderCache *m_sliceCache; // not owned
const LabelItem *m_sliceTitleItem; // not owned
bool m_xFlipped;
bool m_zFlipped;
bool m_yFlipped;
- QRect m_mainViewPort;
- QRect m_sliceViewPort;
bool m_updateLabels;
ShaderHelper *m_barShader;
+ ShaderHelper *m_barGradientShader;
ShaderHelper *m_depthShader;
ShaderHelper *m_selectionShader;
ShaderHelper *m_backgroundShader;
ShaderHelper *m_labelShader;
- ObjectHelper *m_barObj;
ObjectHelper *m_backgroundObj;
ObjectHelper *m_gridLineObj;
ObjectHelper *m_labelObj;
@@ -90,7 +85,8 @@ private:
GLfloat m_shadowQualityToShader;
GLint m_shadowQualityMultiplier;
GLfloat m_heightNormalizer;
- GLfloat m_yAdjustment;
+ GLfloat m_gradientFraction;
+ GLfloat m_negativeBackgroundAdjustment;
GLfloat m_rowWidth;
GLfloat m_columnDepth;
GLfloat m_maxDimension;
@@ -98,55 +94,52 @@ private:
GLfloat m_scaleZ;
GLfloat m_scaleFactor;
GLfloat m_maxSceneSize;
- QVector3D m_selection;
- QVector3D m_previousSelection;
- int m_renderRows;
- int m_renderColumns;
-
+ QPoint m_visualSelectedBarPos;
+ int m_visualSelectedBarSeriesIndex;
bool m_hasHeightAdjustmentChanged;
+ QPoint m_selectedBarPos;
+ const QBar3DSeries *m_selectedBarSeries;
BarRenderItem m_dummyBarRenderItem;
-
- BarRenderItemArray m_renderItemArray;
+ QVector<BarRenderItemArray> m_renderingArrays;
+ bool m_noZeroInRange;
+ float m_seriesScale;
+ float m_seriesStep;
+ float m_seriesStart;
public:
explicit Bars3DRenderer(Bars3DController *controller);
~Bars3DRenderer();
- void updateDataModel(QBarDataProxy *dataProxy);
+ void updateData();
void updateScene(Q3DScene *scene);
void render(GLuint defaultFboHandle = 0);
- QRect mainViewPort();
-
protected:
virtual void initializeOpenGL();
- virtual void loadMeshFile();
public slots:
void updateBarSpecs(GLfloat thicknessRatio = 1.0f,
const QSizeF &spacing = QSizeF(1.0, 1.0),
bool relative = true);
- void updateSelectionMode(QDataVis::SelectionMode newMode);
void updateSlicingActive(bool isSlicing);
- void updateBackgroundEnabled(bool enable);
- void updateSelectedBarPos(const QPoint &position);
+ void updateSelectedBar(const QPoint &position, const QBar3DSeries *series);
// Overloaded from abstract renderer
- virtual void updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, qreal min, qreal max);
+ virtual void updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, float min, float max);
signals:
- void selectedBarPosChanged(QPoint position);
+ void barClicked(QPoint position, QBar3DSeries *series);
private:
virtual void initShaders(const QString &vertexShader, const QString &fragmentShader);
+ virtual void initGradientShaders(const QString &vertexShader, const QString &fragmentShader);
virtual void updateShadowQuality(QDataVis::ShadowQuality quality);
virtual void updateTextures();
+ virtual void fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh);
- void drawSlicedScene(const LabelItem &xLabel, const LabelItem &yLabel, const LabelItem &zLabel);
+ void drawSlicedScene();
void drawScene(GLuint defaultFboHandle);
- void handleResize();
- void setViewPorts();
void loadBackgroundMesh();
void loadGridLineMesh();
void loadLabelMesh();
@@ -160,7 +153,9 @@ private:
#endif
void calculateSceneScalingFactors();
void calculateHeightAdjustment();
- Abstract3DController::SelectionType isSelected(GLint row, GLint bar);
+ Abstract3DController::SelectionType isSelected(int row, int bar, int seriesIndex);
+ QPoint selectionColorToArrayPosition(const QVector3D &selectionColor);
+ QBar3DSeries *selectionColorToSeries(const QVector3D &selectionColor);
Q_DISABLE_COPY(Bars3DRenderer)
diff --git a/src/datavisualization/engine/drawer.cpp b/src/datavisualization/engine/drawer.cpp
index cf390b9d..14f0b315 100644
--- a/src/datavisualization/engine/drawer.cpp
+++ b/src/datavisualization/engine/drawer.cpp
@@ -41,17 +41,22 @@ StaticLibInitializer staticLibInitializer;
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-Drawer::Drawer(const Theme &theme, const QFont &font, QDataVis::LabelStyle style)
+// Vertex array buffer for point
+const GLfloat point_data[] = {0.0f, 0.0f, 0.0f};
+
+Drawer::Drawer(Q3DTheme *theme)
: m_theme(theme),
- m_font(font),
- m_style(style),
- m_textureHelper(0)
+ m_font(theme->font()),
+ m_labelBackground(theme->isLabelBackgroundEnabled()),
+ m_textureHelper(0),
+ m_pointbuffer(0)
{
}
Drawer::~Drawer()
{
delete m_textureHelper;
+ glDeleteBuffers(1, &m_pointbuffer);
}
void Drawer::initializeOpenGL()
@@ -62,19 +67,23 @@ void Drawer::initializeOpenGL()
}
}
-void Drawer::setTheme(const Theme &theme)
+void Drawer::setTheme(Q3DTheme *theme)
{
m_theme = theme;
+ m_font = m_theme->font();
+ m_labelBackground = m_theme->isLabelBackgroundEnabled();
emit drawerChanged();
}
-Theme Drawer::theme() const
+Q3DTheme *Drawer::theme() const
{
return m_theme;
}
void Drawer::setFont(const QFont &font)
{
+ // We need to be able to override theme's font for drawer
+ // TODO: (or do we?)
m_font = font;
emit drawerChanged();
}
@@ -84,9 +93,11 @@ QFont Drawer::font() const
return m_font;
}
-void Drawer::setStyle(QDataVis::LabelStyle style)
+void Drawer::setLabelBackground(bool enabled)
{
- m_style = style;
+ // We need to be able to override theme's label background for drawer
+ // TODO: (or do we?)
+ m_labelBackground = enabled;
emit drawerChanged();
}
@@ -137,10 +148,14 @@ void Drawer::drawObject(ShaderHelper *shader, AbstractObjectHelper *object, GLui
glDisableVertexAttribArray(shader->posAtt());
// Release textures
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, 0);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, 0);
+ if (depthTextureId) {
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+ if (textureId) {
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
}
void Drawer::drawSurfaceGrid(ShaderHelper *shader, SurfaceObject *object)
@@ -163,14 +178,36 @@ void Drawer::drawSurfaceGrid(ShaderHelper *shader, SurfaceObject *object)
glDisableVertexAttribArray(shader->posAtt());
}
+void Drawer::drawPoint(ShaderHelper *shader)
+{
+ // Generate vertex buffer for point if it does not exist
+ if (!m_pointbuffer) {
+ glGenBuffers(1, &m_pointbuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, m_pointbuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(point_data), point_data, GL_STATIC_DRAW);
+ }
+
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(shader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, m_pointbuffer);
+ glVertexAttribPointer(shader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
+
+ // Draw the point
+ glDrawArrays(GL_POINTS, 0, 1);
+
+ // Free buffers
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDisableVertexAttribArray(shader->posAtt());
+}
+
void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelItem,
const QMatrix4x4 &viewmatrix, const QMatrix4x4 &projectionmatrix,
const QVector3D &positionComp, const QVector3D &rotation,
- GLfloat itemHeight, QDataVis::SelectionMode mode,
+ GLfloat itemHeight, QDataVis::SelectionFlags mode,
ShaderHelper *shader, ObjectHelper *object,
- const Q3DCamera *camera,
- bool useDepth, bool rotateAlong,
- LabelPosition position, Qt::AlignmentFlag alignment)
+ const Q3DCamera *camera, bool useDepth, bool rotateAlong,
+ LabelPosition position, Qt::AlignmentFlag alignment, bool isSlicing)
{
// Draw label
if (!labelItem.textureId())
@@ -277,7 +314,7 @@ void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelIte
xPosition = item.translation().x();
if (useDepth)
zPosition = item.translation().z();
- else if (QDataVis::SelectionModeSliceColumn == mode)
+ else if (mode.testFlag(QDataVis::SelectionColumn) && isSlicing)
xPosition = -(item.translation().z()) + positionComp.z(); // flip first to left
}
@@ -285,21 +322,17 @@ void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelIte
modelMatrix.translate(xPosition + xAlignment, yPosition + yAlignment, zPosition + zAlignment);
// Rotate
- // TODO: We should convert rotations to use quaternions to avoid rotation order problems
- //QQuaternion rotQuatX = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, rotation.x());
- //QQuaternion rotQuatY = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, rotation.y());
- //QQuaternion rotQuatZ = QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, rotation.z());
- //QQuaternion rotQuaternion = rotQuatX + rotQuatY + rotQuatZ;
- //modelMatrix.rotate(rotQuaternion);
- modelMatrix.rotate(rotation.y(), 0.0f, 1.0f, 0.0f);
- modelMatrix.rotate(rotation.z(), 0.0f, 0.0f, 1.0f);
- modelMatrix.rotate(rotation.x(), 1.0f, 0.0f, 0.0f);
+ QQuaternion rotQuatX = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, rotation.x());
+ QQuaternion rotQuatY = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, rotation.y());
+ QQuaternion rotQuatZ = QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, rotation.z());
+ QQuaternion rotQuaternion = rotQuatY * rotQuatZ * rotQuatX;
+ modelMatrix.rotate(rotQuaternion);
if (useDepth && !rotateAlong) {
- qreal yComp = qreal(qRadiansToDegrees(qTan(positionComp.y() / cameraDistance)));
+ float yComp = float(qRadiansToDegrees(qTan(positionComp.y() / cameraDistance)));
// Apply negative camera rotations to keep labels facing camera
- qreal camRotationX = camera->xRotation();
- qreal camRotationY = camera->yRotation();
+ float camRotationX = camera->xRotation();
+ float camRotationY = camera->yRotation();
modelMatrix.rotate(-camRotationX, 0.0f, 1.0f, 0.0f);
modelMatrix.rotate(-camRotationY - yComp, 1.0f, 0.0f, 0.0f);
}
@@ -335,10 +368,10 @@ void Drawer::generateLabelItem(LabelItem &item, const QString &text, int widestL
// Print label into a QImage using QPainter
QImage label = Utils::printTextToImage(m_font,
text,
- m_theme.m_textBackgroundColor,
- m_theme.m_textColor,
- m_style,
- m_theme.m_labelBorders,
+ m_theme->labelBackgroundColor(),
+ m_theme->labelTextColor(),
+ m_labelBackground,
+ m_theme->isLabelBorderEnabled(),
widestLabel);
// Set label size
diff --git a/src/datavisualization/engine/drawer_p.h b/src/datavisualization/engine/drawer_p.h
index 89a4ce8c..8bc62209 100644
--- a/src/datavisualization/engine/drawer_p.h
+++ b/src/datavisualization/engine/drawer_p.h
@@ -31,7 +31,7 @@
#include "datavisualizationglobal_p.h"
#include "q3dbars.h"
-#include "theme_p.h"
+#include "q3dtheme.h"
#include "labelitem_p.h"
#include "abstractrenderitem_p.h"
#include <QFont>
@@ -63,28 +63,28 @@ public:
};
public:
- explicit Drawer(const Theme &theme, const QFont &font, QDataVis::LabelStyle style);
+ explicit Drawer(Q3DTheme *theme);
~Drawer();
void initializeOpenGL();
- void setTheme(const Theme &theme);
- Theme theme() const;
+ void setTheme(Q3DTheme *theme);
+ Q3DTheme *theme() const;
void setFont(const QFont &font);
QFont font() const;
- void setStyle(QDataVis::LabelStyle style);
+ void setLabelBackground(bool enabled);
void drawObject(ShaderHelper *shader, AbstractObjectHelper *object, GLuint textureId = 0,
GLuint depthTextureId = 0);
void drawSurfaceGrid(ShaderHelper *shader, SurfaceObject *object);
+ void drawPoint(ShaderHelper *shader);
void drawLabel(const AbstractRenderItem &item, const LabelItem &labelItem,
const QMatrix4x4 &viewmatrix, const QMatrix4x4 &projectionmatrix,
const QVector3D &positionComp, const QVector3D &rotation, GLfloat itemHeight,
- QDataVis::SelectionMode mode, ShaderHelper *shader, ObjectHelper *object,
- const Q3DCamera *camera,
- bool useDepth = false, bool rotateAlong = false,
+ QDataVis::SelectionFlags mode, ShaderHelper *shader, ObjectHelper *object,
+ const Q3DCamera *camera, bool useDepth = false, bool rotateAlong = false,
LabelPosition position = LabelOver,
- Qt::AlignmentFlag alignment = Qt::AlignCenter);
+ Qt::AlignmentFlag alignment = Qt::AlignCenter, bool isSlicing = false);
void generateSelectionLabelTexture(AbstractRenderItem *item);
void generateLabelItem(LabelItem &item, const QString &text, int widestLabel = 0);
@@ -93,10 +93,11 @@ Q_SIGNALS:
void drawerChanged();
private:
- Theme m_theme;
+ Q3DTheme *m_theme;
QFont m_font;
- QDataVis::LabelStyle m_style;
+ bool m_labelBackground;
TextureHelper *m_textureHelper;
+ GLuint m_pointbuffer;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/engine.pri b/src/datavisualization/engine/engine.pri
index 4c905fe9..899979e1 100644
--- a/src/datavisualization/engine/engine.pri
+++ b/src/datavisualization/engine/engine.pri
@@ -2,7 +2,6 @@ HEADERS += $$PWD/q3dwindow_p.h \
$$PWD/q3dwindow.h \
$$PWD/q3dbars.h \
$$PWD/q3dbars_p.h \
- $$PWD/theme_p.h \
$$PWD/drawer_p.h \
$$PWD/bars3dcontroller_p.h \
$$PWD/bars3drenderer_p.h \
@@ -16,6 +15,7 @@ HEADERS += $$PWD/q3dwindow_p.h \
$$PWD/scatter3dcontroller_p.h \
$$PWD/scatter3drenderer_p.h \
$$PWD/axisrendercache_p.h \
+ $$PWD/seriesrendercache_p.h \
$$PWD/abstract3drenderer_p.h \
$$PWD/selectionpointer_p.h \
$$PWD/q3dcamera.h \
@@ -30,7 +30,6 @@ HEADERS += $$PWD/q3dwindow_p.h \
SOURCES += $$PWD/q3dwindow.cpp \
$$PWD/q3dbars.cpp \
- $$PWD/theme.cpp \
$$PWD/drawer.cpp \
$$PWD/bars3dcontroller.cpp \
$$PWD/bars3drenderer.cpp \
@@ -42,6 +41,7 @@ SOURCES += $$PWD/q3dwindow.cpp \
$$PWD/scatter3dcontroller.cpp \
$$PWD/scatter3drenderer.cpp \
$$PWD/axisrendercache.cpp \
+ $$PWD/seriesrendercache.cpp \
$$PWD/abstract3drenderer.cpp \
$$PWD/selectionpointer.cpp \
$$PWD/q3dcamera.cpp \
diff --git a/src/datavisualization/engine/engine.qrc b/src/datavisualization/engine/engine.qrc
index 7420ae51..8fcaecec 100644
--- a/src/datavisualization/engine/engine.qrc
+++ b/src/datavisualization/engine/engine.qrc
@@ -8,14 +8,12 @@
<file alias="barSmooth">meshes/cubeSmooth.obj</file>
<file alias="cylinder">meshes/cylinderFlat.obj</file>
<file alias="cylinderSmooth">meshes/cylinderSmooth.obj</file>
- <file alias="background">meshes/backgroudFlat.obj</file>
- <file alias="backgroundSmooth">meshes/backgroudSmooth.obj</file>
- <file alias="label">meshes/plane.obj</file>
+ <file alias="background">meshes/background.obj</file>
+ <file alias="plane">meshes/plane.obj</file>
<file alias="sphere">meshes/sphere.obj</file>
<file alias="sphereSmooth">meshes/sphereSmooth.obj</file>
<file alias="bevelbar">meshes/barFlat.obj</file>
<file alias="bevelbarSmooth">meshes/barSmooth.obj</file>
- <file alias="negativeBackground">meshes/backgroudNegatives.obj</file>
<file alias="coneFull">meshes/coneFilledFlat.obj</file>
<file alias="coneSmoothFull">meshes/coneFilledSmooth.obj</file>
<file alias="cylinderFull">meshes/cylinderFilledFlat.obj</file>
@@ -26,18 +24,16 @@
<file alias="bevelbarSmoothFull">meshes/barFilledSmooth.obj</file>
<file alias="barFull">meshes/cubeFilledFlat.obj</file>
<file alias="barSmoothFull">meshes/cubeFilledSmooth.obj</file>
- <file alias="dotSmooth">meshes/scatterdot.obj</file>
- <file alias="dot">meshes/scatterdotFlat.obj</file>
+ <file alias="negativeBackground">meshes/backgroundNegatives.obj</file>
+ <file alias="minimal">meshes/minimalFlat.obj</file>
+ <file alias="minimalSmooth">meshes/minimalSmooth.obj</file>
</qresource>
<qresource prefix="/shaders">
<file alias="fragment">shaders/default.frag</file>
<file alias="vertex">shaders/default.vert</file>
- <file alias="fragmentAmbient">shaders/ambient.frag</file>
<file alias="fragmentColorOnY">shaders/colorOnY.frag</file>
- <file alias="fragmentSelection">shaders/selection.frag</file>
- <file alias="vertexSelection">shaders/selection.vert</file>
- <file alias="fragmentTexture">shaders/texture.frag</file>
- <file alias="vertexTexture">shaders/texture.vert</file>
+ <file alias="fragmentPlainColor">shaders/plainColor.frag</file>
+ <file alias="vertexPlainColor">shaders/plainColor.vert</file>
<file alias="fragmentLabel">shaders/label.frag</file>
<file alias="vertexLabel">shaders/label.vert</file>
<file alias="fragmentDepth">shaders/depth.frag</file>
@@ -48,15 +44,13 @@
<file alias="fragmentShadowNoTexColorOnY">shaders/shadowNoTexColorOnY.frag</file>
<file alias="fragmentColorOnYES2">shaders/colorOnY_ES2.frag</file>
<file alias="fragmentES2">shaders/default_ES2.frag</file>
- <file alias="vertexES2">shaders/default_ES2.vert</file>
- <file alias="fragmentTextureES2">shaders/texture_ES2.frag</file>
<file alias="fragmentSurface">shaders/surface.frag</file>
- <file alias="vertexSurface">shaders/surface.vert</file>
- <file alias="fragmentSurfaceGrid">shaders/surfaceGrid.frag</file>
- <file alias="vertexSurfaceGrid">shaders/surfaceGrid.vert</file>
<file alias="vertexSurfaceFlat">shaders/surfaceFlat.vert</file>
<file alias="fragmentSurfaceFlat">shaders/surfaceFlat.frag</file>
<file alias="fragmentSurfaceES2">shaders/surface_ES2.frag</file>
+ <file alias="vertexPointES2">shaders/point_ES2.vert</file>
+ <file alias="fragmentSurfaceShadowNoTex">shaders/surfaceShadowNoTex.frag</file>
+ <file alias="fragmentSurfaceShadowFlat">shaders/surfaceShadowFlat.frag</file>
+ <file alias="vertexSurfaceShadowFlat">shaders/surfaceShadowFlat.vert</file>
</qresource>
- <qresource prefix="/textures"/>
</RCC>
diff --git a/src/datavisualization/engine/meshes/backgroudNegatives.obj b/src/datavisualization/engine/meshes/backgroudNegatives.obj
deleted file mode 100644
index 4153bfd4..00000000
--- a/src/datavisualization/engine/meshes/backgroudNegatives.obj
+++ /dev/null
@@ -1,33 +0,0 @@
-# Blender v2.66 (sub 0) OBJ File: 'backgroudNegatives.blend'
-# www.blender.org
-o Cube
-v 1.000000 -1.000000 -1.000000
-v 1.000000 -1.000000 1.000000
-v -1.000000 -1.000000 1.000000
-v -1.000000 -1.000000 -1.000000
-v 1.000000 1.000000 1.000000
-v -1.000000 1.000000 1.000000
-v -1.000000 1.000000 -1.000000
-v 1.000000 -3.000000 1.000000
-v -1.000000 -3.000000 1.000000
-v -1.000000 -3.000000 -1.000000
-vt 0.000100 0.666700
-vt 0.333300 0.666700
-vt 0.333300 0.999900
-vt 0.000100 0.000100
-vt 0.333300 0.000100
-vt 0.333300 0.666500
-vt 0.666500 0.000100
-vt 0.666500 0.666500
-vt 0.000100 0.999900
-vt 0.000100 0.666500
-vn -0.000000 1.000000 0.000000
-vn 0.000000 -0.000000 -1.000000
-vn 1.000000 0.000000 0.000000
-s off
-f 1/1/1 4/2/1 3/3/1
-f 8/4/2 9/5/2 6/6/2
-f 9/5/3 10/7/3 7/8/3
-f 2/9/1 1/1/1 3/3/1
-f 5/10/2 8/4/2 6/6/2
-f 6/6/3 9/5/3 7/8/3
diff --git a/src/datavisualization/engine/meshes/backgroudSmooth.obj b/src/datavisualization/engine/meshes/backgroudSmooth.obj
deleted file mode 100644
index 27d06aea..00000000
--- a/src/datavisualization/engine/meshes/backgroudSmooth.obj
+++ /dev/null
@@ -1,36 +0,0 @@
-# Blender v2.66 (sub 0) OBJ File: 'backgroud.blend'
-# www.blender.org
-o Cube
-v 1.000000 -1.000000 -1.000000
-v 1.000000 -1.000000 1.000000
-v -1.000000 -1.000000 1.000000
-v -1.000000 -1.000000 -1.000000
-v 1.000000 1.000000 1.000000
-v -1.000000 1.000000 1.000000
-v -1.000000 1.000000 -1.000000
-vt 0.000000 0.501529
-vt 0.001529 1.000000
-vt 0.500000 0.998471
-vt 0.501529 0.500000
-vt 1.000000 0.498471
-vt 0.998471 0.000000
-vt 0.500000 0.498471
-vt 0.498471 0.000000
-vt 0.000000 0.001529
-vt 0.498471 0.500000
-vt 0.500000 0.001529
-vt 0.001529 0.500000
-vn 0.000000 1.000000 0.000000
-vn 0.707083 0.707083 0.000000
-vn 0.577349 0.577349 -0.577349
-vn 0.000000 0.707083 -0.707083
-vn 0.707083 0.000000 -0.707083
-vn 1.000000 0.000000 0.000000
-vn 0.000000 0.000000 -1.000000
-s 1
-f 1/1/1 4/2/2 3/3/3
-f 2/4/4 3/5/3 6/6/5
-f 3/7/3 4/8/2 7/9/6
-f 2/10/4 1/1/1 3/3/3
-f 5/11/7 2/4/4 6/6/5
-f 6/12/5 3/7/3 7/9/6
diff --git a/src/datavisualization/engine/meshes/backgroudFlat.obj b/src/datavisualization/engine/meshes/background.obj
index 5eeb1f26..5eeb1f26 100644
--- a/src/datavisualization/engine/meshes/backgroudFlat.obj
+++ b/src/datavisualization/engine/meshes/background.obj
diff --git a/src/datavisualization/engine/meshes/backgroundNegatives.obj b/src/datavisualization/engine/meshes/backgroundNegatives.obj
new file mode 100644
index 00000000..76c7c1d8
--- /dev/null
+++ b/src/datavisualization/engine/meshes/backgroundNegatives.obj
@@ -0,0 +1,22 @@
+# Blender v2.66 (sub 0) OBJ File: 'backgroudNegativesWall.blend'
+# www.blender.org
+o Cube
+v 0.999999 1.000000 1.000001
+v -1.000000 1.000000 1.000000
+v -1.000000 1.000000 -1.000000
+v 1.000000 -3.000000 1.000000
+v -1.000000 -3.000000 1.000000
+v -1.000000 -3.000000 -1.000000
+vt 0.000100 0.000100
+vt 0.500000 0.000100
+vt 0.500000 0.999900
+vt 0.999900 0.000100
+vt 0.999900 0.999900
+vt 0.000100 0.999900
+vn 0.000000 -0.000000 -1.000000
+vn 1.000000 0.000000 0.000000
+s off
+f 4/1/1 5/2/1 2/3/1
+f 5/2/2 6/4/2 3/5/2
+f 1/6/1 4/1/1 2/3/1
+f 2/3/2 5/2/2 3/5/2
diff --git a/src/datavisualization/engine/meshes/minimalFlat.obj b/src/datavisualization/engine/meshes/minimalFlat.obj
new file mode 100644
index 00000000..9ab60a21
--- /dev/null
+++ b/src/datavisualization/engine/meshes/minimalFlat.obj
@@ -0,0 +1,27 @@
+# Blender v2.66 (sub 0) OBJ File: 'scatterdot.blend'
+# www.blender.org
+o Cone
+v 0.000000 -1.000000 -1.414000
+v 1.224560 -1.000000 0.707000
+v 0.000000 1.000000 0.000000
+v -1.224560 -1.000000 0.707000
+vt 0.499966 0.866025
+vt 0.000000 1.153999
+vt 0.000590 0.577029
+vt 0.999376 0.000000
+vt 1.000000 0.577029
+vt 0.500000 0.288996
+vt 1.000000 0.866025
+vt 0.500000 1.154058
+vt 0.500624 0.577029
+vt 0.000000 0.577029
+vt 0.000624 0.000000
+vn -0.000000 -1.000000 0.000000
+vn 0.816510 0.333289 -0.471412
+vn -0.000000 0.333289 0.942825
+vn -0.816510 0.333289 -0.471413
+s off
+f 4/1/1 1/2/1 2/3/1
+f 1/4/2 3/5/2 2/6/2
+f 2/7/3 3/8/3 4/9/3
+f 4/6/4 3/10/4 1/11/4
diff --git a/src/datavisualization/engine/meshes/minimalSmooth.obj b/src/datavisualization/engine/meshes/minimalSmooth.obj
new file mode 100644
index 00000000..dd2e77d3
--- /dev/null
+++ b/src/datavisualization/engine/meshes/minimalSmooth.obj
@@ -0,0 +1,27 @@
+# Blender v2.66 (sub 0) OBJ File: 'scatterdot.blend'
+# www.blender.org
+o Cone
+v 0.000000 -1.000000 -1.414000
+v 1.224560 -1.000000 0.707000
+v 0.000000 1.000000 0.000000
+v -1.224560 -1.000000 0.707000
+vt 0.499966 0.866025
+vt 0.000000 1.153999
+vt 0.000590 0.577029
+vt 0.999376 0.000000
+vt 1.000000 0.577029
+vt 0.500000 0.288996
+vt 1.000000 0.866025
+vt 0.500000 1.154058
+vt 0.500624 0.577029
+vt 0.000000 0.577029
+vt 0.000624 0.000000
+vn -0.816462 -0.333354 0.471389
+vn 0.000000 -0.333354 -0.942778
+vn 0.816462 -0.333354 0.471389
+vn 0.000000 1.000000 0.000000
+s 1
+f 4/1/1 1/2/2 2/3/3
+f 1/4/2 3/5/4 2/6/3
+f 2/7/3 3/8/4 4/9/1
+f 4/6/1 3/10/4 1/11/2
diff --git a/src/datavisualization/engine/meshes/scatterdot.obj b/src/datavisualization/engine/meshes/scatterdot.obj
deleted file mode 100644
index d994a80f..00000000
--- a/src/datavisualization/engine/meshes/scatterdot.obj
+++ /dev/null
@@ -1,28 +0,0 @@
-# Blender v2.66 (sub 0) OBJ File: 'scatterdot.blend'
-# www.blender.org
-o Cone
-v 0.000000 -0.500000 -1.000000
-v 0.866025 -0.500000 0.500000
-v 0.000000 0.500000 0.000000
-v -0.866025 -0.500000 0.500000
-vt 0.999727 0.000000
-vt 1.000000 0.492691
-vt 0.522886 0.369782
-vt 0.477114 0.973202
-vt 0.000000 1.096111
-vt 0.000273 0.603420
-vt 0.523159 0.985382
-vt 0.522886 0.492691
-vt 1.000000 0.615600
-vt 0.000000 0.603420
-vt 0.000617 0.000000
-vt 0.522886 0.302245
-vn -0.833033 -0.273293 0.480941
-vn 0.000000 0.999969 0.000000
-vn 0.000000 -0.273293 -0.961913
-vn 0.833033 -0.273293 0.480941
-s 1
-f 4/1/1 3/2/2 1/3/3
-f 1/4/3 3/5/2 2/6/4
-f 2/7/4 3/8/2 4/9/1
-f 1/10/3 2/11/4 4/12/1
diff --git a/src/datavisualization/engine/meshes/scatterdotFlat.obj b/src/datavisualization/engine/meshes/scatterdotFlat.obj
deleted file mode 100644
index 4052738d..00000000
--- a/src/datavisualization/engine/meshes/scatterdotFlat.obj
+++ /dev/null
@@ -1,28 +0,0 @@
-# Blender v2.66 (sub 0) OBJ File: 'scatterdot.blend'
-# www.blender.org
-o Cone
-v 0.000000 -0.500000 -1.000000
-v 0.866025 -0.500000 0.500000
-v 0.000000 0.500000 0.000000
-v -0.866025 -0.500000 0.500000
-vt 0.999727 0.000000
-vt 1.000000 0.492691
-vt 0.522886 0.369782
-vt 0.477114 0.973202
-vt 0.000000 1.096111
-vt 0.000273 0.603420
-vt 0.523159 0.985382
-vt 0.522886 0.492691
-vt 1.000000 0.615600
-vt 0.000000 0.603420
-vt 0.000617 0.000000
-vt 0.522886 0.302245
-vn -0.774597 0.447214 -0.447214
-vn 0.774597 0.447214 -0.447214
-vn -0.000000 0.447214 0.894427
-vn 0.000000 -1.000000 -0.000000
-s off
-f 4/1/1 3/2/1 1/3/1
-f 1/4/2 3/5/2 2/6/2
-f 2/7/3 3/8/3 4/9/3
-f 1/10/4 2/11/4 4/12/4
diff --git a/src/datavisualization/engine/q3dbars.cpp b/src/datavisualization/engine/q3dbars.cpp
index d6b48e03..d4e97519 100644
--- a/src/datavisualization/engine/q3dbars.cpp
+++ b/src/datavisualization/engine/q3dbars.cpp
@@ -21,12 +21,11 @@
#include "bars3dcontroller_p.h"
#include "q3dvalueaxis.h"
#include "q3dcategoryaxis.h"
-#include "qbardataproxy.h"
#include "q3dcamera.h"
+#include "qbar3dseries_p.h"
#include <QMouseEvent>
-#include <QDebug>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -46,28 +45,30 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* These default axes can be modified via axis accessors, but as soon any axis is set explicitly
* for the orientation, the default axis for that orientation is destroyed.
*
- * Data proxies work similarly: If no data proxy is set explicitly, Q3DBars creates a default
- * proxy. If any other proxy is set as active data proxy later, the default proxy and all data
- * added to it is destroyed.
+ * Q3DBars supports more than one series visible at the same time. It is not necessary for all series
+ * to have the same amount of rows and columns.
+ * Row and column labels are taken from the first added series, unless explicitly defined to
+ * row and column axes.
*
- * Methods are provided for changing bar types, themes, bar selection modes and so on. See the
+ * Methods are provided for changing themes, bar selection modes and so on. See the
* methods for more detailed descriptions.
*
* \section1 How to construct a minimal Q3DBars graph
*
- * First, construct an instance of Q3DBars:
+ * First, construct an instance of Q3DBars. Since we are running the graph as top level window
+ * in this example, we need to clear the \c Qt::FramelessWindowHint flag, which gets set by
+ * default:
*
* \snippet doc_src_q3dbars_construction.cpp 4
*
* After constructing Q3DBars, you can set the data window by changing the range on the row and
* column axes. It is not mandatory, as data window will default to showing all of the data in
- * the data proxy. If the amount of data is large, it is usually preferable to show just a
+ * the series. If the amount of data is large, it is usually preferable to show just a
* portion of it. For the example, let's set the data window to show first five rows and columns:
*
* \snippet doc_src_q3dbars_construction.cpp 0
*
- * Now Q3DBars is ready to receive data to be rendered. Add one row of 5 qreals into the data
- * set:
+ * Now Q3DBars is ready to receive data to be rendered. Create a series with one row of 5 values:
*
* \snippet doc_src_q3dbars_construction.cpp 1
*
@@ -95,99 +96,119 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
/*!
- * Constructs a new 3D bar window.
+ * Constructs a new 3D bar graph with optional \a parent window.
*/
-Q3DBars::Q3DBars()
- : d_ptr(new Q3DBarsPrivate(this, geometry()))
+Q3DBars::Q3DBars(QWindow *parent)
+ : Q3DWindow(new Q3DBarsPrivate(this), parent)
{
- setVisualController(d_ptr->m_shared);
- d_ptr->m_shared->initializeOpenGL();
- QObject::connect(d_ptr->m_shared, &Bars3DController::selectedBarPosChanged, this,
- &Q3DBars::selectedBarPosChanged);
- QObject::connect(d_ptr->m_shared, &Abstract3DController::needRender, this,
- &Q3DWindow::renderLater);
+ dptr()->m_shared = new Bars3DController(geometry());
+ d_ptr->setVisualController(dptr()->m_shared);
+ dptr()->m_shared->initializeOpenGL();
+ QObject::connect(dptr()->m_shared, &Abstract3DController::selectionModeChanged, this,
+ &Q3DBars::selectionModeChanged);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::shadowQualityChanged, this,
+ &Q3DBars::shadowQualityChanged);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::themeChanged, this,
+ &Q3DBars::themeChanged);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::needRender, d_ptr.data(),
+ &Q3DWindowPrivate::renderLater);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::shadowQualityChanged, dptr(),
+ &Q3DBarsPrivate::handleShadowQualityUpdate);
}
/*!
- * Destroys the 3D bar window.
+ * Destroys the 3D bar graph.
*/
Q3DBars::~Q3DBars()
{
}
/*!
- * \internal
+ * Adds the \a series to the graph. A graph can contain multiple series, but only one set of axes,
+ * so the rows and columns of all series must match for the visualized data to be meaningful.
+ * If the graph has multiple visible series, only the first one added will
+ * generate the row or column labels on the axes in cases where the labels are not explicitly set
+ * to the axes. If the newly added series has specified a selected bar, it will be highlighted and
+ * any existing selection will be cleared. Only one added series can have an active selection.
*/
-void Q3DBars::mouseDoubleClickEvent(QMouseEvent *event)
+void Q3DBars::addSeries(QBar3DSeries *series)
{
- d_ptr->m_shared->mouseDoubleClickEvent(event);
+ dptr()->m_shared->addSeries(series);
}
/*!
- * \internal
+ * Removes the \a series from the graph.
*/
-void Q3DBars::touchEvent(QTouchEvent *event)
+void Q3DBars::removeSeries(QBar3DSeries *series)
{
- d_ptr->m_shared->touchEvent(event);
+ dptr()->m_shared->removeSeries(series);
}
/*!
- * \internal
+ * \return list of series added to this graph.
*/
-void Q3DBars::mousePressEvent(QMouseEvent *event)
+QList<QBar3DSeries *> Q3DBars::seriesList()
{
- d_ptr->m_shared->mousePressEvent(event, event->pos());
+ return dptr()->m_shared->barSeriesList();
}
/*!
* \internal
*/
-void Q3DBars::mouseReleaseEvent(QMouseEvent *event)
+void Q3DBars::mouseDoubleClickEvent(QMouseEvent *event)
{
- d_ptr->m_shared->mouseReleaseEvent(event, event->pos());
+ dptr()->m_shared->mouseDoubleClickEvent(event);
}
/*!
* \internal
*/
-void Q3DBars::mouseMoveEvent(QMouseEvent *event)
+void Q3DBars::touchEvent(QTouchEvent *event)
{
- d_ptr->m_shared->mouseMoveEvent(event, event->pos());
+ dptr()->m_shared->touchEvent(event);
}
/*!
* \internal
*/
-void Q3DBars::wheelEvent(QWheelEvent *event)
+void Q3DBars::mousePressEvent(QMouseEvent *event)
{
- d_ptr->m_shared->wheelEvent(event);
+ dptr()->m_shared->mousePressEvent(event, event->pos());
}
/*!
* \internal
*/
-void Q3DBars::resizeEvent(QResizeEvent *event)
+void Q3DBars::mouseReleaseEvent(QMouseEvent *event)
{
- Q_UNUSED(event);
- d_ptr->m_shared->setSize(width(), height());
+ dptr()->m_shared->mouseReleaseEvent(event, event->pos());
}
/*!
- * Sets window \a width.
+ * \internal
*/
-void Q3DBars::setWidth(const int width)
+void Q3DBars::mouseMoveEvent(QMouseEvent *event)
{
- d_ptr->m_shared->setWidth(width);
- QWindow::setWidth(width);
+ dptr()->m_shared->mouseMoveEvent(event, event->pos());
}
/*!
- * Sets window \a height.
+ * \internal
*/
-void Q3DBars::setHeight(const int height)
+void Q3DBars::wheelEvent(QWheelEvent *event)
+{
+ dptr()->m_shared->wheelEvent(event);
+}
+
+
+Q3DBarsPrivate *Q3DBars::dptr()
{
- d_ptr->m_shared->setHeight(height);
- QWindow::setHeight(height);
+ return static_cast<Q3DBarsPrivate *>(d_ptr.data());
+}
+
+const Q3DBarsPrivate *Q3DBars::dptrc() const
+{
+ return static_cast<const Q3DBarsPrivate *>(d_ptr.data());
}
/*!
@@ -196,14 +217,17 @@ void Q3DBars::setHeight(const int height)
* Bar thickness ratio between X and Z dimensions. 1.0 means bars are as wide as they are deep, 0.5
* makes them twice as deep as they are wide. It is preset to \c 1.0 by default.
*/
-void Q3DBars::setBarThickness(qreal thicknessRatio)
+void Q3DBars::setBarThickness(float thicknessRatio)
{
- d_ptr->m_shared->setBarSpecs(GLfloat(thicknessRatio), barSpacing(), isBarSpacingRelative());
+ if (thicknessRatio != barThickness()) {
+ dptr()->m_shared->setBarSpecs(GLfloat(thicknessRatio), barSpacing(), isBarSpacingRelative());
+ emit barThicknessChanged(thicknessRatio);
+ }
}
-qreal Q3DBars::barThickness()
+float Q3DBars::barThickness()
{
- return d_ptr->m_shared->barThickness();
+ return dptr()->m_shared->barThickness();
}
/*!
@@ -216,12 +240,15 @@ qreal Q3DBars::barThickness()
*/
void Q3DBars::setBarSpacing(QSizeF spacing)
{
- d_ptr->m_shared->setBarSpecs(GLfloat(barThickness()), spacing, isBarSpacingRelative());
+ if (spacing != barSpacing()) {
+ dptr()->m_shared->setBarSpecs(GLfloat(barThickness()), spacing, isBarSpacingRelative());
+ emit barSpacingChanged(spacing);
+ }
}
QSizeF Q3DBars::barSpacing()
{
- return d_ptr->m_shared->barSpacing();
+ return dptr()->m_shared->barSpacing();
}
/*!
@@ -233,112 +260,48 @@ QSizeF Q3DBars::barSpacing()
*/
void Q3DBars::setBarSpacingRelative(bool relative)
{
- d_ptr->m_shared->setBarSpecs(GLfloat(barThickness()), barSpacing(), relative);
+ if (relative != isBarSpacingRelative()) {
+ dptr()->m_shared->setBarSpecs(GLfloat(barThickness()), barSpacing(), relative);
+ emit barSpacingRelativeChanged(relative);
+ }
}
bool Q3DBars::isBarSpacingRelative()
{
- return d_ptr->m_shared->isBarSpecRelative();
+ return dptr()->m_shared->isBarSpecRelative();
}
/*!
- * Sets the bar \a style to one of the values in \c QDataVis::MeshStyle. It is preset to
- * \c QDataVis::MeshStyleBars by default. A \a smooth flag can be used to set shading to smooth.
- * It is \c false by default.
+ * \property Q3DBars::theme
*
- * \sa setMeshFileName()
+ * A \a theme to be used for the graph. Ownership of the \a theme is transferred. Previous theme
+ * is deleted when a new one is set. Properties of the \a theme can be modified even after setting
+ * it, and the modifications take effect immediately.
*/
-void Q3DBars::setBarType(QDataVis::MeshStyle style, bool smooth)
+void Q3DBars::setTheme(Q3DTheme *theme)
{
- d_ptr->m_shared->setBarType(style, smooth);
+ dptr()->m_shared->setTheme(theme);
}
-/*!
- * Sets a predefined \a theme from \c QDataVis::Theme. It is preset to \c QDataVis::ThemeQt by
- * default. Theme affects bar colors, label colors, text color, background color, window color and
- * grid color. Lighting is also adjusted by themes.
- *
- * \sa setBarColor()
- *
- * \preliminary
- */
-void Q3DBars::setTheme(QDataVis::Theme theme)
+Q3DTheme *Q3DBars::theme() const
{
- d_ptr->m_shared->setTheme(theme);
-}
-
-/*!
- * Set bar color using your own color. \a baseColor sets the base color of a bar. The \a uniform
- * -flag is used to define if color needs to be uniform throughout bar's length, or will the colors
- * be applied by height, starting with dark at the bottom. It is \c true by default.
- *
- * Calling this method overrides colors from theme.
- *
- * \sa setTheme()
- *
- * \preliminary
- */
-void Q3DBars::setBarColor(const QColor &baseColor, bool uniform)
-{
- d_ptr->m_shared->setObjectColor(baseColor, uniform);
-}
-
-/*!
- * \return bar color in use.
- */
-QColor Q3DBars::barColor() const
-{
- return d_ptr->m_shared->objectColor();
+ return dptrc()->m_shared->theme();
}
/*!
* \property Q3DBars::selectionMode
*
- * Sets bar selection \a mode to one of \c QDataVis::SelectionMode. It is preset to
- * \c QDataVis::SelectionModeItem by default.
+ * Sets bar selection \a mode to a combination of \c QDataVis::SelectionFlags. It is preset to
+ * \c QDataVis::SelectionItem by default.
*/
-void Q3DBars::setSelectionMode(QDataVis::SelectionMode mode)
+void Q3DBars::setSelectionMode(QDataVis::SelectionFlags mode)
{
- d_ptr->m_shared->setSelectionMode(mode);
+ dptr()->m_shared->setSelectionMode(mode);
}
-QDataVis::SelectionMode Q3DBars::selectionMode() const
+QDataVis::SelectionFlags Q3DBars::selectionMode() const
{
- return d_ptr->m_shared->selectionMode();
-}
-
-/*!
- * \property Q3DBars::meshFileName
- *
- * Override bar type with a mesh object located in \a objFileName.
- * \note Object needs to be in Wavefront obj format and include vertices, normals and UVs.
- * It also needs to be in triangles.
- *
- * \sa setBarType()
- */
-void Q3DBars::setMeshFileName(const QString &objFileName)
-{
- d_ptr->m_shared->setMeshFileName(objFileName);
-}
-
-QString Q3DBars::meshFileName() const
-{
- return d_ptr->m_shared->meshFileName();
-}
-
-/*!
- * \property Q3DBars::font
- *
- * Sets the \a font for labels. It is preset to \c Arial by default.
- */
-void Q3DBars::setFont(const QFont &font)
-{
- d_ptr->m_shared->setFont(font);
-}
-
-QFont Q3DBars::font() const
-{
- return d_ptr->m_shared->font();
+ return dptrc()->m_shared->selectionMode();
}
/*!
@@ -348,70 +311,7 @@ QFont Q3DBars::font() const
*/
Q3DScene *Q3DBars::scene() const
{
- return d_ptr->m_shared->scene();
-}
-
-/*!
- * \property Q3DBars::labelStyle
- *
- * Sets label \a style to one of \c QDataVis::LabelStyle. It is preset to
- * \c QDataVis::LabelStyleFromTheme by default.
- */
-void Q3DBars::setLabelStyle(QDataVis::LabelStyle style)
-{
- d_ptr->m_shared->setLabelStyle(style);
-}
-
-QDataVis::LabelStyle Q3DBars::labelStyle() const
-{
- return d_ptr->m_shared->labelStyle();
-}
-
-/*!
- * \property Q3DBars::gridVisible
- *
- * Sets grid visibility to \a visible. It is preset to \c true by default.
- */
-void Q3DBars::setGridVisible(bool visible)
-{
- d_ptr->m_shared->setGridEnabled(visible);
-}
-
-bool Q3DBars::isGridVisible() const
-{
- return d_ptr->m_shared->gridEnabled();
-}
-
-/*!
- * \property Q3DBars::backgroundVisible
- *
- * Sets background visibility to \a visible. It is preset to \c true by default.
- */
-void Q3DBars::setBackgroundVisible(bool visible)
-{
- d_ptr->m_shared->setBackgroundEnabled(visible);
-}
-
-bool Q3DBars::isBackgroundVisible() const
-{
- return d_ptr->m_shared->backgroundEnabled();
-}
-
-/*!
- * \property Q3DBars::selectedBarPos
- *
- * Selects a bar in a \a position. The position is the position in data window.
- * Only one bar can be selected at a time.
- * To clear selection, specify an illegal \a position, e.g. (-1, -1).
- */
-void Q3DBars::setSelectedBarPos(const QPoint &position)
-{
- d_ptr->m_shared->setSelectedBarPos(position);
-}
-
-QPoint Q3DBars::selectedBarPos() const
-{
- return d_ptr->m_shared->selectedBarPos();
+ return dptrc()->m_shared->scene();
}
/*!
@@ -426,12 +326,12 @@ QPoint Q3DBars::selectedBarPos() const
*/
void Q3DBars::setShadowQuality(QDataVis::ShadowQuality quality)
{
- d_ptr->m_shared->setShadowQuality(quality);
+ dptr()->m_shared->setShadowQuality(quality);
}
QDataVis::ShadowQuality Q3DBars::shadowQuality() const
{
- return d_ptr->m_shared->shadowQuality();
+ return dptrc()->m_shared->shadowQuality();
}
/*!
@@ -445,7 +345,7 @@ QDataVis::ShadowQuality Q3DBars::shadowQuality() const
*/
void Q3DBars::setRowAxis(Q3DCategoryAxis *axis)
{
- d_ptr->m_shared->setAxisX(axis);
+ dptr()->m_shared->setAxisZ(axis);
}
/*!
@@ -453,7 +353,7 @@ void Q3DBars::setRowAxis(Q3DCategoryAxis *axis)
*/
Q3DCategoryAxis *Q3DBars::rowAxis() const
{
- return static_cast<Q3DCategoryAxis *>(d_ptr->m_shared->axisX());
+ return static_cast<Q3DCategoryAxis *>(dptrc()->m_shared->axisZ());
}
/*!
@@ -467,7 +367,7 @@ Q3DCategoryAxis *Q3DBars::rowAxis() const
*/
void Q3DBars::setColumnAxis(Q3DCategoryAxis *axis)
{
- d_ptr->m_shared->setAxisZ(axis);
+ dptr()->m_shared->setAxisX(axis);
}
/*!
@@ -475,7 +375,7 @@ void Q3DBars::setColumnAxis(Q3DCategoryAxis *axis)
*/
Q3DCategoryAxis *Q3DBars::columnAxis() const
{
- return static_cast<Q3DCategoryAxis *>(d_ptr->m_shared->axisZ());
+ return static_cast<Q3DCategoryAxis *>(dptrc()->m_shared->axisX());
}
/*!
@@ -490,7 +390,7 @@ Q3DCategoryAxis *Q3DBars::columnAxis() const
*/
void Q3DBars::setValueAxis(Q3DValueAxis *axis)
{
- d_ptr->m_shared->setAxisY(axis);
+ dptr()->m_shared->setAxisY(axis);
}
/*!
@@ -498,7 +398,7 @@ void Q3DBars::setValueAxis(Q3DValueAxis *axis)
*/
Q3DValueAxis *Q3DBars::valueAxis() const
{
- return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisY());
+ return static_cast<Q3DValueAxis *>(dptrc()->m_shared->axisY());
}
/*!
@@ -510,7 +410,7 @@ Q3DValueAxis *Q3DBars::valueAxis() const
*/
void Q3DBars::addAxis(Q3DAbstractAxis *axis)
{
- d_ptr->m_shared->addAxis(axis);
+ dptr()->m_shared->addAxis(axis);
}
/*!
@@ -523,7 +423,7 @@ void Q3DBars::addAxis(Q3DAbstractAxis *axis)
*/
void Q3DBars::releaseAxis(Q3DAbstractAxis *axis)
{
- d_ptr->m_shared->releaseAxis(axis);
+ dptr()->m_shared->releaseAxis(axis);
}
/*!
@@ -533,77 +433,12 @@ void Q3DBars::releaseAxis(Q3DAbstractAxis *axis)
*/
QList<Q3DAbstractAxis *> Q3DBars::axes() const
{
- return d_ptr->m_shared->axes();
-}
-
-/*!
- * Sets the active data \a proxy. Implicitly calls addDataProxy() to transfer ownership of
- * the \a proxy to this graph.
- *
- * If the \a proxy is null, a temporary default proxy is created and activated.
- * This temporary proxy is destroyed if another \a proxy is set explicitly active via this method.
- *
- * \sa addDataProxy(), releaseDataProxy()
- */
-void Q3DBars::setActiveDataProxy(QBarDataProxy *proxy)
-{
- d_ptr->m_shared->setActiveDataProxy(proxy);
+ return dptrc()->m_shared->axes();
}
-/*!
- * \return active data proxy.
- */
-QBarDataProxy *Q3DBars::activeDataProxy() const
+Q3DBarsPrivate::Q3DBarsPrivate(Q3DBars *q)
+ : Q3DWindowPrivate(q)
{
- return static_cast<QBarDataProxy *>(d_ptr->m_shared->activeDataProxy());
-}
-
-/*!
- * Adds data \a proxy to the graph. The proxies added via addDataProxy are not yet taken to use,
- * addDataProxy is simply used to give the ownership of the data \a proxy to the graph.
- * The \a proxy must not be null or added to another graph.
- *
- * \sa releaseDataProxy(), setActiveDataProxy()
- */
-void Q3DBars::addDataProxy(QBarDataProxy *proxy)
-{
- d_ptr->m_shared->addDataProxy(proxy);
-}
-
-/*!
- * Releases the ownership of the data \a proxy back to the caller, if it is added to this graph.
- * If the released \a proxy is in use, a new empty default proxy is created and taken to use.
- *
- * If the default \a proxy is released and added back later, it behaves as any other proxy would.
- *
- * \sa addDataProxy(), setActiveDataProxy()
- */
-void Q3DBars::releaseDataProxy(QBarDataProxy *proxy)
-{
- d_ptr->m_shared->releaseDataProxy(proxy);
-}
-
-/*!
- * \return list of all added data proxies.
- *
- * \sa addDataProxy()
- */
-QList<QBarDataProxy *> Q3DBars::dataProxies() const
-{
- QList<QBarDataProxy *> retList;
- QList<QAbstractDataProxy *> abstractList = d_ptr->m_shared->dataProxies();
- foreach (QAbstractDataProxy *proxy, abstractList)
- retList.append(static_cast<QBarDataProxy *>(proxy));
-
- return retList;
-}
-
-Q3DBarsPrivate::Q3DBarsPrivate(Q3DBars *q, QRect rect)
- : q_ptr(q),
- m_shared(new Bars3DController(rect))
-{
- QObject::connect(m_shared, &Abstract3DController::shadowQualityChanged, this,
- &Q3DBarsPrivate::handleShadowQualityUpdate);
}
Q3DBarsPrivate::~Q3DBarsPrivate()
@@ -613,7 +448,12 @@ Q3DBarsPrivate::~Q3DBarsPrivate()
void Q3DBarsPrivate::handleShadowQualityUpdate(QDataVis::ShadowQuality quality)
{
- emit q_ptr->shadowQualityChanged(quality);
+ emit qptr()->shadowQualityChanged(quality);
+}
+
+Q3DBars *Q3DBarsPrivate::qptr()
+{
+ return static_cast<Q3DBars *>(q_ptr);
}
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/q3dbars.h b/src/datavisualization/engine/q3dbars.h
index d0ddf3fb..add3b11b 100644
--- a/src/datavisualization/engine/q3dbars.h
+++ b/src/datavisualization/engine/q3dbars.h
@@ -21,7 +21,9 @@
#include <QtDataVisualization/qdatavisualizationenums.h>
#include <QtDataVisualization/q3dwindow.h>
+#include <QtDataVisualization/q3dtheme.h>
#include <QFont>
+#include <QLinearGradient>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -29,40 +31,33 @@ class Q3DBarsPrivate;
class Q3DAbstractAxis;
class Q3DCategoryAxis;
class Q3DValueAxis;
-class QBarDataProxy;
class Q3DScene;
+class QBar3DSeries;
class QT_DATAVISUALIZATION_EXPORT Q3DBars : public Q3DWindow
{
Q_OBJECT
- Q_PROPERTY(QtDataVisualization::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode)
- Q_PROPERTY(QtDataVisualization::QDataVis::LabelStyle labelStyle READ labelStyle WRITE setLabelStyle)
+ Q_PROPERTY(QtDataVisualization::QDataVis::SelectionFlags selectionMode READ selectionMode WRITE setSelectionMode NOTIFY selectionModeChanged)
Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality NOTIFY shadowQualityChanged)
- Q_PROPERTY(qreal barThickness READ barThickness WRITE setBarThickness)
- Q_PROPERTY(QSizeF barSpacing READ barSpacing WRITE setBarSpacing)
- Q_PROPERTY(bool barSpacingRelative READ isBarSpacingRelative WRITE setBarSpacingRelative)
- Q_PROPERTY(QString meshFileName READ meshFileName WRITE setMeshFileName)
- Q_PROPERTY(QFont font READ font WRITE setFont)
- Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible)
- Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible)
- Q_PROPERTY(QPoint selectedBarPos READ selectedBarPos WRITE setSelectedBarPos NOTIFY selectedBarPosChanged)
+ Q_PROPERTY(float barThickness READ barThickness WRITE setBarThickness NOTIFY barThicknessChanged)
+ Q_PROPERTY(QSizeF barSpacing READ barSpacing WRITE setBarSpacing NOTIFY barSpacingChanged)
+ Q_PROPERTY(bool barSpacingRelative READ isBarSpacingRelative WRITE setBarSpacingRelative NOTIFY barSpacingRelativeChanged)
+ Q_PROPERTY(Q3DTheme* theme READ theme WRITE setTheme NOTIFY themeChanged)
Q_PROPERTY(Q3DScene* scene READ scene)
- Q_ENUMS(QtDataVisualization::QDataVis::SelectionMode)
- Q_ENUMS(QtDataVisualization::QDataVis::ShadowQuality)
- Q_ENUMS(QtDataVisualization::QDataVis::LabelStyle)
- Q_ENUMS(QtDataVisualization::QDataVis::CameraPreset)
-
public:
- explicit Q3DBars();
- ~Q3DBars();
+ explicit Q3DBars(QWindow *parent = 0);
+ virtual ~Q3DBars();
- void setBarType(QDataVis::MeshStyle style, bool smooth = false);
+ void addSeries(QBar3DSeries *series);
+ void removeSeries(QBar3DSeries *series);
+ QList<QBar3DSeries *> seriesList();
- void setTheme(QDataVis::Theme theme);
+ void setTheme(Q3DTheme *theme);
+ Q3DTheme *theme() const;
- void setBarThickness(qreal thicknessRatio);
- qreal barThickness();
+ void setBarThickness(float thicknessRatio);
+ float barThickness();
void setBarSpacing(QSizeF spacing);
QSizeF barSpacing();
@@ -70,35 +65,11 @@ public:
void setBarSpacingRelative(bool relative);
bool isBarSpacingRelative();
- void setBarColor(const QColor &baseColor, bool uniform = true);
- QColor barColor() const;
-
- void setMeshFileName(const QString &objFileName);
- QString meshFileName() const;
-
- void setSelectionMode(QDataVis::SelectionMode mode);
- QDataVis::SelectionMode selectionMode() const;
-
- void setFont(const QFont &font);
- QFont font() const;
+ void setSelectionMode(QDataVis::SelectionFlags mode);
+ QDataVis::SelectionFlags selectionMode() const;
Q3DScene *scene() const;
- void setLabelStyle(QDataVis::LabelStyle style);
- QDataVis::LabelStyle labelStyle() const;
-
- void setGridVisible(bool visible);
- bool isGridVisible() const;
-
- void setWidth(const int width);
- void setHeight(const int height);
-
- void setBackgroundVisible(bool visible);
- bool isBackgroundVisible() const;
-
- void setSelectedBarPos(const QPoint &position);
- QPoint selectedBarPos() const;
-
void setShadowQuality(QDataVis::ShadowQuality quality);
QDataVis::ShadowQuality shadowQuality() const;
@@ -112,15 +83,13 @@ public:
void releaseAxis(Q3DAbstractAxis *axis);
QList<Q3DAbstractAxis *> axes() const;
- void setActiveDataProxy(QBarDataProxy *proxy);
- QBarDataProxy *activeDataProxy() const;
- void addDataProxy(QBarDataProxy *proxy);
- void releaseDataProxy(QBarDataProxy *proxy);
- QList<QBarDataProxy *> dataProxies() const;
-
signals:
+ void selectionModeChanged(QDataVis::SelectionFlags mode);
void shadowQualityChanged(QDataVis::ShadowQuality quality);
- void selectedBarPosChanged(QPoint position);
+ void barThicknessChanged(float thicknessRatio);
+ void barSpacingChanged(QSizeF spacing);
+ void barSpacingRelativeChanged(bool relative);
+ void themeChanged(Q3DTheme *theme);
protected:
@@ -130,10 +99,10 @@ protected:
void mouseReleaseEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
- void resizeEvent(QResizeEvent *event);
private:
- QScopedPointer<Q3DBarsPrivate> d_ptr;
+ Q3DBarsPrivate *dptr();
+ const Q3DBarsPrivate *dptrc() const;
Q_DISABLE_COPY(Q3DBars)
};
diff --git a/src/datavisualization/engine/q3dbars_p.h b/src/datavisualization/engine/q3dbars_p.h
index 653db606..9a059d8d 100644
--- a/src/datavisualization/engine/q3dbars_p.h
+++ b/src/datavisualization/engine/q3dbars_p.h
@@ -26,26 +26,29 @@
//
// We mean it.
-#ifndef Q3DBARS_p_H
-#define Q3DBARS_p_H
+#ifndef Q3DBARS_P_H
+#define Q3DBARS_P_H
#include "bars3dcontroller_p.h"
#include "qdatavisualizationenums.h"
+#include "q3dwindow_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class Q3DBars;
-class Q3DBarsPrivate : public QObject
+class Q3DBarsPrivate : public Q3DWindowPrivate
{
+ Q_OBJECT
public:
- Q3DBarsPrivate(Q3DBars *q, QRect rect);
+ Q3DBarsPrivate(Q3DBars *q);
~Q3DBarsPrivate();
// Used to detect when shadow quality changes autonomously due to e.g. resizing.
void handleShadowQualityUpdate(QDataVis::ShadowQuality quality);
- Q3DBars *q_ptr;
+ Q3DBars *qptr();
+
Bars3DController *m_shared;
};
diff --git a/src/datavisualization/engine/q3dcamera.cpp b/src/datavisualization/engine/q3dcamera.cpp
index fe452739..6378051c 100644
--- a/src/datavisualization/engine/q3dcamera.cpp
+++ b/src/datavisualization/engine/q3dcamera.cpp
@@ -29,19 +29,192 @@
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
/*!
- \class Q3DCamera
- \inmodule QtDataVisualization
- \brief Representation of a camera in 3D space.
- \since Qt Data Visualization 1.0
+ * \class Q3DCamera
+ * \inmodule QtDataVisualization
+ * \brief Representation of a camera in 3D space.
+ * \since Qt Data Visualization 1.0
+ *
+ * Q3DCamera represents a basic orbit around centerpoint 3D camera that is used when rendering the
+ * data visualization. The class offers simple methods for setting the orbit point in rotations,
+ * but allows also setting the 4x4 view matrix directly in case a more customized camera behavior is
+ * needed.
+ */
+
+/*!
+ * \enum Q3DCamera::CameraPreset
+ *
+ * Predefined positions for camera.
+ *
+ * \value CameraPresetNone
+ * Used to indicate a preset has not been set, or the scene has been rotated freely.
+ * \value CameraPresetFrontLow
+ * \value CameraPresetFront
+ * \value CameraPresetFrontHigh
+ * \value CameraPresetLeftLow
+ * \value CameraPresetLeft
+ * \value CameraPresetLeftHigh
+ * \value CameraPresetRightLow
+ * \value CameraPresetRight
+ * \value CameraPresetRightHigh
+ * \value CameraPresetBehindLow
+ * \value CameraPresetBehind
+ * \value CameraPresetBehindHigh
+ * \value CameraPresetIsometricLeft
+ * \value CameraPresetIsometricLeftHigh
+ * \value CameraPresetIsometricRight
+ * \value CameraPresetIsometricRightHigh
+ * \value CameraPresetDirectlyAbove
+ * \value CameraPresetDirectlyAboveCW45
+ * \value CameraPresetDirectlyAboveCCW45
+ * \value CameraPresetFrontBelow
+ * In Q3DBars from CameraPresetFrontBelow onward these only work for graphs including negative
+ * values. They act as Preset...Low for positive-only values.
+ * \value CameraPresetLeftBelow
+ * \value CameraPresetRightBelow
+ * \value CameraPresetBehindBelow
+ * \value CameraPresetDirectlyBelow
+ * Acts as CameraPresetFrontLow for positive-only bars.
+ */
+
+/*!
+ * \qmltype Camera3D
+ * \inqmlmodule QtDataVisualization
+ * \since QtDataVisualization 1.0
+ * \ingroup datavisualization_qml
+ * \instantiates Q3DCamera
+ * \brief Representation of a camera in 3D space.
+ *
+ * Camera3D represents a basic orbit around centerpoint 3D camera that is used when rendering the
+ * data visualization. The class offers simple methods for setting the orbit point in rotations,
+ * but allows also setting the 4x4 view matrix directly in case a more customized camera behavior is
+ * needed.
+ */
+
+/*!
+ * \qmlproperty float Camera3D::xRotation
+ *
+ * This property contains the X-rotation angle of the camera around the target point in degrees
+ * starting from the current base position set by the setBaseOrientation method.
+ */
- Q3DCamera represents a basic orbit around centerpoint 3D camera that is used when rendering the data visualization.
- The class offers simple methods for setting the orbit point in rotations, but allows also setting the 4x4 viewmatrix
- directly in case a more customized camera behavior is needed.
-*/
+/*!
+ * \qmlproperty float Camera3D::yRotation
+ *
+ * This property contains the Y-rotation angle of the camera around the target point in degrees
+ * starting from the current base position set by the setBaseOrientation method.
+ */
/*!
- * Constructs a new 3D camera with position set to origo, up direction facing towards the Y-axis and looking at origo by default. An
- * optional \a parent parameter can be given and is then passed to QObject constructor.
+ * \qmlproperty float Camera3D::minXRotation
+ *
+ * This property contains the current minimum X-rotation for the camera.
+ * The full circle range is \c{[-180, 180]} and the minimum value is limited to \c -180.
+ * Also the value can't be higher than the maximum, and is adjusted if necessary.
+ *
+ * \sa wrapXRotation, maxXRotation
+ */
+
+/*!
+ * \qmlproperty float Camera3D::minYRotation
+ *
+ * This property contains the current minimum Y-rotation for the camera.
+ * The full Y angle range is \c{[-90, 90]} and the minimum value is limited to \c -90.
+ * Also the value can't be higher than the maximum, and is adjusted if necessary.
+ *
+ * \sa wrapYRotation, maxYRotation
+ */
+
+/*!
+ * \qmlproperty float Camera3D::maxXRotation
+ *
+ * This property contains the current maximum X-rotation for the camera.
+ * The full circle range is \c{[-180, 180]} and the maximum value is limited to \c 180.
+ * Also the value can't be lower than the minimum, and is adjusted if necessary.
+ *
+ * \sa wrapXRotation, minXRotation
+ */
+
+/*!
+ * \qmlproperty float Camera3D::maxYRotation
+ *
+ * This property contains the current maximum Y-rotation for the camera.
+ * The full Y angle range is \c{[-90, 90]} and the maximum value is limited to \c 90.
+ * Also the value can't be lower than the minimum, and is adjusted if necessary.
+ *
+ * \sa wrapYRotation, minYRotation
+ */
+
+/*!
+ * \qmlmethod void Camera3D::setBaseOrientation(vector3d basePosition, vector3d target, vector3d baseUp)
+ *
+ * Sets the base values for the camera that are used when calculating the camera position using the
+ * rotation values. The base position of the camera is defined by \a basePosition, expectation is
+ * that the x and y values are 0. Look at target point is defined by \a target and the camera
+ * rotates around it. Up direction for the camera is defined by \a baseUp, normally this is a
+ * vector with only y value set to 1.
+ */
+
+/*!
+ * \qmlproperty matrix4x4 Camera3D::viewMatrix
+ *
+ * This property contains the view matrix used in the 3D calculations. When the default orbiting
+ * camera behavior is sufficient, there is no need to touch this property. If the default
+ * behavior is insufficient, the view matrix can be set directly.
+ * \note When setting the view matrix directly remember to set viewMatrixAutoUpdateEnabled
+ * property to \c false.
+ */
+
+/*!
+ * \qmlproperty bool Camera3D::viewMatrixAutoUpdateEnabled
+ *
+ * This property determines if view matrix is automatically updated each render cycle using the
+ * current base orientation and rotations. If set to \c false, no automatic recalculation is done and
+ * the view matrix can be set using the viewMatrix property.
+ */
+
+/*!
+ * \qmlproperty Camera3D.CameraPreset Camera3D::cameraPreset
+ *
+ * This property contains the currently active camera preset, which is one of
+ * \l{Q3DCamera::CameraPreset}{Camera3D.CameraPreset}. If no preset is active the value
+ * is \l{Q3DCamera::CameraPresetNone}{Camera3D.CameraPresetNone}.
+ * \note The base camera orientation set by setBaseOrientation will affect the presets as all
+ * calculations are based on those values.
+ */
+
+/*!
+ * \qmlproperty float Camera3D::zoomLevel
+ *
+ * This property contains the the camera zoom level in percentage. 100.0 means there is no zoom
+ * in or out set in the camera.
+ */
+
+/*!
+ * \qmlproperty bool Camera3D::wrapXRotation
+ *
+ * This property determines the behavior of the minimum and maximum limits in the X-rotation.
+ * By default the X-rotation wraps from minimum value to maximum and from maximum to minimum.
+ *
+ * If set to \c true the X-rotation of the camera is wrapped from minimum to maximum and from maximum
+ * to minimum. If set to \c false the X-rotation of the camera is limited to the sector determined by
+ * minimum and maximum values.
+ */
+
+/*!
+ * \qmlproperty bool Camera3D::wrapYRotation
+ *
+ * This property determines the behavior of the minimum and maximum limits in the Y-rotation.
+ * By default the Y-rotation is limited between the minimum and maximum values without any wrapping.
+ *
+ * If \c true the Y-rotation of the camera is wrapped from minimum to maximum and from maximum
+ * to minimum. If \c false the Y-rotation of the camera is limited to the sector determined by minimum
+ * and maximum values.
+ */
+
+/*!
+ * Constructs a new 3D camera with position set to origin, up direction facing towards the Y-axis
+ * and looking at origin by default. An optional \a parent parameter can be given and is then passed
+ * to QObject constructor.
*/
Q3DCamera::Q3DCamera(QObject *parent) :
Q3DObject(parent),
@@ -60,59 +233,61 @@ Q3DCamera::~Q3DCamera()
* Copies the 3D camera's properties from the given source camera.
* Values are copied from the \a source to this object.
*/
-void Q3DCamera::copyValuesFrom(const Q3DCamera &source)
+void Q3DCamera::copyValuesFrom(const Q3DObject &source)
{
Q3DObject::copyValuesFrom(source);
- d_ptr->m_target.setX(source.d_ptr->m_target.x());
- d_ptr->m_target.setY(source.d_ptr->m_target.y());
- d_ptr->m_target.setZ(source.d_ptr->m_target.z());
+ const Q3DCamera &sourceCamera = static_cast<const Q3DCamera &>(source);
+
+ d_ptr->m_target.setX(sourceCamera.d_ptr->m_target.x());
+ d_ptr->m_target.setY(sourceCamera.d_ptr->m_target.y());
+ d_ptr->m_target.setZ(sourceCamera.d_ptr->m_target.z());
- d_ptr->m_up.setX(source.d_ptr->m_up.x());
- d_ptr->m_up.setY(source.d_ptr->m_up.y());
- d_ptr->m_up.setZ(source.d_ptr->m_up.z());
+ d_ptr->m_up.setX(sourceCamera.d_ptr->m_up.x());
+ d_ptr->m_up.setY(sourceCamera.d_ptr->m_up.y());
+ d_ptr->m_up.setZ(sourceCamera.d_ptr->m_up.z());
float *values = new float[16];
- source.d_ptr->m_viewMatrix.copyDataTo(values);
+ sourceCamera.d_ptr->m_viewMatrix.copyDataTo(values);
d_ptr->m_viewMatrix = QMatrix4x4(values);
delete[] values;
- d_ptr->m_xRotation = source.d_ptr->m_xRotation;
- d_ptr->m_yRotation = source.d_ptr->m_yRotation;
+ d_ptr->m_xRotation = sourceCamera.d_ptr->m_xRotation;
+ d_ptr->m_yRotation = sourceCamera.d_ptr->m_yRotation;
- d_ptr->m_minXRotation = source.d_ptr->m_minXRotation;
- d_ptr->m_minYRotation = source.d_ptr->m_minYRotation;
- d_ptr->m_maxXRotation = source.d_ptr->m_maxXRotation;
- d_ptr->m_maxYRotation = source.d_ptr->m_maxYRotation;
+ d_ptr->m_minXRotation = sourceCamera.d_ptr->m_minXRotation;
+ d_ptr->m_minYRotation = sourceCamera.d_ptr->m_minYRotation;
+ d_ptr->m_maxXRotation = sourceCamera.d_ptr->m_maxXRotation;
+ d_ptr->m_maxYRotation = sourceCamera.d_ptr->m_maxYRotation;
- d_ptr->m_wrapXRotation = source.d_ptr->m_wrapXRotation;
- d_ptr->m_wrapYRotation = source.d_ptr->m_wrapYRotation;
+ d_ptr->m_wrapXRotation = sourceCamera.d_ptr->m_wrapXRotation;
+ d_ptr->m_wrapYRotation = sourceCamera.d_ptr->m_wrapYRotation;
- d_ptr->m_zoomLevel = source.d_ptr->m_zoomLevel;
- d_ptr->m_activePreset = source.d_ptr->m_activePreset;
+ d_ptr->m_zoomLevel = sourceCamera.d_ptr->m_zoomLevel;
+ d_ptr->m_activePreset = sourceCamera.d_ptr->m_activePreset;
}
/*!
* \property Q3DCamera::xRotation
*
- * This property contains the X-rotation angle of the camera around the target point in degrees starting from
- * the current base position set by the setBaseOrientation() methods.
+ * This property contains the X-rotation angle of the camera around the target point in degrees
+ * starting from the current base position set by the setBaseOrientation() method.
*/
-qreal Q3DCamera::xRotation() const {
+float Q3DCamera::xRotation() const {
return d_ptr->m_xRotation;
}
-void Q3DCamera::setXRotation(qreal rotation)
+void Q3DCamera::setXRotation(float rotation)
{
if (d_ptr->m_wrapXRotation)
rotation = Utils::wrapValue(rotation, d_ptr->m_minXRotation, d_ptr->m_maxXRotation);
else
- rotation = qBound(qreal(d_ptr->m_minXRotation), qreal(rotation), qreal(d_ptr->m_maxXRotation));
+ rotation = qBound(float(d_ptr->m_minXRotation), float(rotation), float(d_ptr->m_maxXRotation));
if (d_ptr->m_xRotation != rotation) {
d_ptr->setXRotation(rotation);
- if (d_ptr->m_activePreset != QDataVis::CameraPresetNone) {
- d_ptr->m_activePreset = QDataVis::CameraPresetNone;
+ if (d_ptr->m_activePreset != CameraPresetNone) {
+ d_ptr->m_activePreset = CameraPresetNone;
setDirty(true);
}
@@ -123,24 +298,24 @@ void Q3DCamera::setXRotation(qreal rotation)
/*!
* \property Q3DCamera::yRotation
*
- * This property contains the Y-rotation angle of the camera around the target point in degrees starting from
- * the current base position set by the setBaseOrientation() methods.
+ * This property contains the Y-rotation angle of the camera around the target point in degrees
+ * starting from the current base position set by the setBaseOrientation() method.
*/
-qreal Q3DCamera::yRotation() const {
+float Q3DCamera::yRotation() const {
return d_ptr->m_yRotation;
}
-void Q3DCamera::setYRotation(qreal rotation)
+void Q3DCamera::setYRotation(float rotation)
{
if (d_ptr->m_wrapYRotation)
rotation = Utils::wrapValue(rotation, d_ptr->m_minYRotation, d_ptr->m_maxYRotation);
else
- rotation = qBound(qreal(d_ptr->m_minYRotation), qreal(rotation), qreal(d_ptr->m_maxYRotation));
+ rotation = qBound(float(d_ptr->m_minYRotation), float(rotation), float(d_ptr->m_maxYRotation));
if (d_ptr->m_yRotation != rotation) {
d_ptr->setYRotation(rotation);
- if (d_ptr->m_activePreset != QDataVis::CameraPresetNone) {
- d_ptr->m_activePreset = QDataVis::CameraPresetNone;
+ if (d_ptr->m_activePreset != CameraPresetNone) {
+ d_ptr->m_activePreset = CameraPresetNone;
setDirty(true);
}
@@ -152,22 +327,19 @@ void Q3DCamera::setYRotation(qreal rotation)
* \property Q3DCamera::minXRotation
*
* This property contains the current minimum X-rotation for the camera.
- * The full circle range is [-180,180] and the minimum value is limited to -180.
+ * The full circle range is \c{[-180, 180]} and the minimum value is limited to \c -180.
* Also the value can't be higher than the maximum, and is adjusted if necessary.
*
* \sa wrapXRotation, maxXRotation
*/
-qreal Q3DCamera::minXRotation() const
+float Q3DCamera::minXRotation() const
{
return d_ptr->m_minXRotation;
}
-/*!
- * \internal
- */
-void Q3DCamera::setMinXRotation(qreal minRotation)
+void Q3DCamera::setMinXRotation(float minRotation)
{
- minRotation = qBound(qreal(-180.0), minRotation, qreal(180.0));
+ minRotation = qBound(-180.0f, minRotation, 180.0f);
if (minRotation > d_ptr->m_maxXRotation)
minRotation = d_ptr->m_maxXRotation;
@@ -184,22 +356,19 @@ void Q3DCamera::setMinXRotation(qreal minRotation)
* \property Q3DCamera::minYRotation
*
* This property contains the current minimum Y-rotation for the camera.
- * The full Y angle range is [-90,90] and the minimum value is limited to -90.
+ * The full Y angle range is \c{[-90, 90]} and the minimum value is limited to \c -90.
* Also the value can't be higher than the maximum, and is adjusted if necessary.
*
* \sa wrapYRotation, maxYRotation
*/
-qreal Q3DCamera::minYRotation() const
+float Q3DCamera::minYRotation() const
{
return d_ptr->m_minYRotation;
}
-/*!
- * \internal
- */
-void Q3DCamera::setMinYRotation(qreal minRotation)
+void Q3DCamera::setMinYRotation(float minRotation)
{
- minRotation = qBound(qreal(-90.0), minRotation, qreal(90.0));
+ minRotation = qBound(-90.0f, minRotation, 90.0f);
if (minRotation > d_ptr->m_maxYRotation)
minRotation = d_ptr->m_maxYRotation;
@@ -216,22 +385,19 @@ void Q3DCamera::setMinYRotation(qreal minRotation)
* \property Q3DCamera::maxXRotation
*
* This property contains the current maximum X-rotation for the camera.
- * The full circle range is [-180,180] and the maximum value is limited to 180.
+ * The full circle range is \c{[-180, 180]} and the maximum value is limited to \c 180.
* Also the value can't be lower than the minimum, and is adjusted if necessary.
*
* \sa wrapXRotation, minXRotation
*/
-qreal Q3DCamera::maxXRotation() const
+float Q3DCamera::maxXRotation() const
{
return d_ptr->m_maxXRotation;
}
-/*!
- * \internal
- */
-void Q3DCamera::setMaxXRotation(qreal maxRotation)
+void Q3DCamera::setMaxXRotation(float maxRotation)
{
- maxRotation = qBound(qreal(-180.0), maxRotation, qreal(180.0));
+ maxRotation = qBound(-180.0f, maxRotation, 180.0f);
if (maxRotation < d_ptr->m_minXRotation)
maxRotation = d_ptr->m_minXRotation;
@@ -249,22 +415,19 @@ void Q3DCamera::setMaxXRotation(qreal maxRotation)
* \property Q3DCamera::maxYRotation
*
* This property contains the current maximum Y-rotation for the camera.
- * The full Y angle range is [-90,90] and the maximum value is limited to 90.
+ * The full Y angle range is \c{[-90, 90]} and the maximum value is limited to \c 90.
* Also the value can't be lower than the minimum, and is adjusted if necessary.
*
* \sa wrapYRotation, minYRotation
*/
-qreal Q3DCamera::maxYRotation() const
+float Q3DCamera::maxYRotation() const
{
return d_ptr->m_maxYRotation;
}
-/*!
- * \internal
- */
-void Q3DCamera::setMaxYRotation(qreal maxRotation)
+void Q3DCamera::setMaxYRotation(float maxRotation)
{
- maxRotation = qBound(qreal(-90.0), maxRotation, qreal(90.0));
+ maxRotation = qBound(-90.0f, maxRotation, 90.0f);
if (maxRotation < d_ptr->m_minYRotation)
maxRotation = d_ptr->m_minYRotation;
@@ -279,10 +442,11 @@ void Q3DCamera::setMaxYRotation(qreal maxRotation)
}
/*!
- * Sets the base values for the camera that are used when calculating the camera position using the rotation values.
- * The base position of the camera is defined by \a basePosition, expectation is that the x and y values are 0.
- * Look at target point is defined by \a target and the camera rotates around it. Up direction for the camera is
- * defined by \a baseUp, normally this is a vector with only y values set to 1.
+ * Sets the base values for the camera that are used when calculating the camera position using the
+ * rotation values. The base position of the camera is defined by \a basePosition, expectation is
+ * that the x and y values are 0. Look at target point is defined by \a target and the camera
+ * rotates around it. Up direction for the camera is defined by \a baseUp, normally this is a
+ * vector with only y value set to 1.
*/
void Q3DCamera::setBaseOrientation(const QVector3D &basePosition,
const QVector3D &target,
@@ -301,9 +465,11 @@ void Q3DCamera::setBaseOrientation(const QVector3D &basePosition,
/*!
* \property Q3DCamera::viewMatrix
*
- * This property contains the view matrix used in the 3D calculations. When the default orbiting camera behavior is sufficient,
- * there is no need to touch this property. But if the default behavior is insufficient, the view matrix can be set directly.
- * When setting the view matrix directly remember to set Q3DCamera::viewMatrixAutoUpdateEnabled to false.
+ * This property contains the view matrix used in the 3D calculations. When the default orbiting
+ * camera behavior is sufficient, there is no need to touch this property. If the default
+ * behavior is insufficient, the view matrix can be set directly.
+ * \note When setting the view matrix directly remember to set viewMatrixAutoUpdateEnabled to
+ * \c false.
*/
QMatrix4x4 Q3DCamera::viewMatrix() const
{
@@ -322,11 +488,11 @@ void Q3DCamera::setViewMatrix(const QMatrix4x4 &viewMatrix)
/*!
* \property Q3DCamera::viewMatrixAutoUpdateEnabled
*
- * This property determines if view matrix is automatically updated each render cycle using the current base orientation and
- * rotations. If set to false, no automatic recalculation is done and the view matrix can be set using the
- * Q3DMatrix::viewMatrix property.
+ * This property determines if view matrix is automatically updated each render cycle using the
+ * current base orientation and rotations. If set to \c false, no automatic recalculation is done
+ * and the view matrix can be set using the viewMatrix property.
*/
-bool Q3DCamera::isViewMatrixAutoUpdateEnabled()
+bool Q3DCamera::isViewMatrixAutoUpdateEnabled() const
{
return d_ptr->m_isViewMatrixUpdateActive;
}
@@ -340,141 +506,141 @@ void Q3DCamera::setViewMatrixAutoUpdateEnabled(bool isEnabled)
/*!
* \property Q3DCamera::cameraPreset
*
- * This property contains the currently active camera preset,
- * if no preset is active the value is QDataVis::CameraPresetNone.
+ * This property contains the currently active camera preset, if no preset is active the value
+ * is CameraPresetNone.
* \note The base camera orientation set by setBaseOrientation() will affect
* the presets as all calculations are based on those values.
*/
-QDataVis::CameraPreset Q3DCamera::cameraPreset()
+Q3DCamera::CameraPreset Q3DCamera::cameraPreset() const
{
return d_ptr->m_activePreset;
}
-void Q3DCamera::setCameraPreset(QDataVis::CameraPreset preset)
+void Q3DCamera::setCameraPreset(CameraPreset preset)
{
switch (preset) {
- case QDataVis::CameraPresetFrontLow: {
- setXRotation(0.0);
- setYRotation(0.0);
+ case CameraPresetFrontLow: {
+ setXRotation(0.0f);
+ setYRotation(0.0f);
break;
}
- case QDataVis::CameraPresetFront: {
- setXRotation(0.0);
- setYRotation(22.5);
+ case CameraPresetFront: {
+ setXRotation(0.0f);
+ setYRotation(22.5f);
break;
}
- case QDataVis::CameraPresetFrontHigh: {
- setXRotation(0.0);
- setYRotation(45.0);
+ case CameraPresetFrontHigh: {
+ setXRotation(0.0f);
+ setYRotation(45.0f);
break;
}
- case QDataVis::CameraPresetLeftLow: {
- setXRotation(90.0);
- setYRotation(0.0);
+ case CameraPresetLeftLow: {
+ setXRotation(90.0f);
+ setYRotation(0.0f);
break;
}
- case QDataVis::CameraPresetLeft: {
- setXRotation(90.0);
- setYRotation(22.5);
+ case CameraPresetLeft: {
+ setXRotation(90.0f);
+ setYRotation(22.5f);
break;
}
- case QDataVis::CameraPresetLeftHigh: {
- setXRotation(90.0);
- setYRotation(45.0);
+ case CameraPresetLeftHigh: {
+ setXRotation(90.0f);
+ setYRotation(45.0f);
break;
}
- case QDataVis::CameraPresetRightLow: {
- setXRotation(-90.0);
- setYRotation(0.0);
+ case CameraPresetRightLow: {
+ setXRotation(-90.0f);
+ setYRotation(0.0f);
break;
}
- case QDataVis::CameraPresetRight: {
- setXRotation(-90.0);
- setYRotation(22.5);
+ case CameraPresetRight: {
+ setXRotation(-90.0f);
+ setYRotation(22.5f);
break;
}
- case QDataVis::CameraPresetRightHigh: {
- setXRotation(-90.0);
- setYRotation(45.0);
+ case CameraPresetRightHigh: {
+ setXRotation(-90.0f);
+ setYRotation(45.0f);
break;
}
- case QDataVis::CameraPresetBehindLow: {
- setXRotation(180.0);
- setYRotation(0.0);
+ case CameraPresetBehindLow: {
+ setXRotation(180.0f);
+ setYRotation(0.0f);
break;
}
- case QDataVis::CameraPresetBehind: {
- setXRotation(180.0);
- setYRotation(22.5);
+ case CameraPresetBehind: {
+ setXRotation(180.0f);
+ setYRotation(22.5f);
break;
}
- case QDataVis::CameraPresetBehindHigh: {
- setXRotation(180.0);
- setYRotation(45.0);
+ case CameraPresetBehindHigh: {
+ setXRotation(180.0f);
+ setYRotation(45.0f);
break;
}
- case QDataVis::CameraPresetIsometricLeft: {
- setXRotation(45.0);
- setYRotation(22.5);
+ case CameraPresetIsometricLeft: {
+ setXRotation(45.0f);
+ setYRotation(22.5f);
break;
}
- case QDataVis::CameraPresetIsometricLeftHigh: {
- setXRotation(45.0);
- setYRotation(45.0);
+ case CameraPresetIsometricLeftHigh: {
+ setXRotation(45.0f);
+ setYRotation(45.0f);
break;
}
- case QDataVis::CameraPresetIsometricRight: {
- setXRotation(-45.0);
- setYRotation(22.5);
+ case CameraPresetIsometricRight: {
+ setXRotation(-45.0f);
+ setYRotation(22.5f);
break;
}
- case QDataVis::CameraPresetIsometricRightHigh: {
- setXRotation(-45.0);
- setYRotation(45.0);
+ case CameraPresetIsometricRightHigh: {
+ setXRotation(-45.0f);
+ setYRotation(45.0f);
break;
}
- case QDataVis::CameraPresetDirectlyAbove: {
- setXRotation(0.0);
- setYRotation(90.0);
+ case CameraPresetDirectlyAbove: {
+ setXRotation(0.0f);
+ setYRotation(90.0f);
break;
}
- case QDataVis::CameraPresetDirectlyAboveCW45: {
- setXRotation(-45.0);
- setYRotation(90.0);
+ case CameraPresetDirectlyAboveCW45: {
+ setXRotation(-45.0f);
+ setYRotation(90.0f);
break;
}
- case QDataVis::CameraPresetDirectlyAboveCCW45: {
- setXRotation(45.0);
- setYRotation(90.0);
+ case CameraPresetDirectlyAboveCCW45: {
+ setXRotation(45.0f);
+ setYRotation(90.0f);
break;
}
- case QDataVis::CameraPresetFrontBelow: {
- setXRotation(0.0);
- setYRotation(-45.0);
+ case CameraPresetFrontBelow: {
+ setXRotation(0.0f);
+ setYRotation(-45.0f);
break;
}
- case QDataVis::CameraPresetLeftBelow: {
- setXRotation(90.0);
- setYRotation(-45.0);
+ case CameraPresetLeftBelow: {
+ setXRotation(90.0f);
+ setYRotation(-45.0f);
break;
}
- case QDataVis::CameraPresetRightBelow: {
- setXRotation(-90.0);
- setYRotation(-45.0);
+ case CameraPresetRightBelow: {
+ setXRotation(-90.0f);
+ setYRotation(-45.0f);
break;
}
- case QDataVis::CameraPresetBehindBelow: {
- setXRotation(180.0);
- setYRotation(-45.0);
+ case CameraPresetBehindBelow: {
+ setXRotation(180.0f);
+ setYRotation(-45.0f);
break;
}
- case QDataVis::CameraPresetDirectlyBelow: {
- setXRotation(0.0);
- setYRotation(-90.0);
+ case CameraPresetDirectlyBelow: {
+ setXRotation(0.0f);
+ setYRotation(-90.0f);
break;
}
default:
- preset = QDataVis::CameraPresetNone;
+ preset = CameraPresetNone;
break;
}
@@ -488,10 +654,10 @@ void Q3DCamera::setCameraPreset(QDataVis::CameraPreset preset)
/*!
* \property Q3DCamera::zoomLevel
*
- * This property contains the the camera zoom level in percentages.
- * 100% means there is no zoom in or out set in the camera.
+ * This property contains the the camera zoom level in percentage. \c 100.0f means there is no zoom
+ * in or out set in the camera.
*/
-int Q3DCamera::zoomLevel()
+int Q3DCamera::zoomLevel() const
{
return d_ptr->m_zoomLevel;
}
@@ -508,14 +674,16 @@ void Q3DCamera::setZoomLevel(int zoomLevel)
/*!
* Calculates and returns a position relative to the camera using the given parameters
* and the current camera viewMatrix property.
- * \a relativePosition defines the relative 3D offset to the current camera position.
- * \a fixedRotation is optional, if given fixes rotation of the calculated point around the data visualization area to the given value in degrees.
- * \a distanceModifier is also optional, if given modifies the distance of the calculated point from the data visualization.
- * \return Calculated position relative to this camera's position.
+ * The relative 3D offset to the current camera position is defined in \a relativePosition.
+ * An optional fixed rotation of the calculated point around the data visualization area can be
+ * given in \a fixedRotation. The rotation is given in degrees.
+ * An optional \a distanceModifier modifies the distance of the calculated point from the data
+ * visualization.
+ * \return calculated position relative to this camera's position.
*/
QVector3D Q3DCamera::calculatePositionRelativeToCamera(const QVector3D &relativePosition,
- qreal fixedRotation,
- qreal distanceModifier) const
+ float fixedRotation,
+ float distanceModifier) const
{
// Move the position with camera
GLfloat radiusFactor = cameraDistance * (1.5f + distanceModifier);
@@ -545,8 +713,9 @@ QVector3D Q3DCamera::calculatePositionRelativeToCamera(const QVector3D &relative
* This property determines the behavior of the minimum and maximum limits in the X-rotation.
* By default the X-rotation wraps from minimum value to maximum and from maximum to minimum.
*
- * If set to true the X-rotation of the camera is wrapped from minimum to maximum and from maximum to minimum.
- * If set to false the X-rotation of the camera is limited to the sector determined by minimum and maximum values.
+ * If set to \c true the X-rotation of the camera is wrapped from minimum to maximum and from
+ * maximum to minimum. If set to \c false the X-rotation of the camera is limited to the sector
+ * determined by minimum and maximum values.
*/
bool Q3DCamera::wrapXRotation() const
{
@@ -564,8 +733,9 @@ void Q3DCamera::setWrapXRotation(bool isEnabled)
* This property determines the behavior of the minimum and maximum limits in the Y-rotation.
* By default the Y-rotation is limited between the minimum and maximum values without any wrapping.
*
- * If true the Y-rotation of the camera is wrapped from minimum to maximum and from maximum to minimum.
- * If false the Y-rotation of the camera is limited to the sector determined by minimum and maximum values.
+ * If \c true the Y-rotation of the camera is wrapped from minimum to maximum and from maximum to
+ * minimum. If \c false the Y-rotation of the camera is limited to the sector determined by minimum
+ * and maximum values.
*/
bool Q3DCamera::wrapYRotation() const
{
@@ -578,12 +748,14 @@ void Q3DCamera::setWrapYRotation(bool isEnabled)
}
/*!
- * Utility function that sets the camera rotations and distance.\a horizontal and \a vertical define the camera rotations to be used.
- * Optional \a zoom parameter can be given to set the zoom of the camera in range of 10-500%.
+ * Utility function that sets the camera rotations and distance.\a horizontal and \a vertical
+ * define the camera rotations to be used.
+ * Optional \a zoom parameter can be given to set the zoom percentage of the camera in range of
+ * \c{10.0f - 500.0f}.
*/
-void Q3DCamera::setCameraPosition(qreal horizontal, qreal vertical, qreal zoom)
+void Q3DCamera::setCameraPosition(float horizontal, float vertical, float zoom)
{
- setZoomLevel(qBound(qreal(10.0), zoom, qreal(500.0)));
+ setZoomLevel(qBound(10.0f, zoom, 500.0f));
setXRotation(horizontal);
setYRotation(vertical);
}
@@ -591,16 +763,16 @@ void Q3DCamera::setCameraPosition(qreal horizontal, qreal vertical, qreal zoom)
Q3DCameraPrivate::Q3DCameraPrivate(Q3DCamera *q) :
q_ptr(q),
m_isViewMatrixUpdateActive(true),
- m_xRotation(0.0),
- m_yRotation(0.0),
- m_minXRotation(-180.0),
- m_minYRotation(0.0),
- m_maxXRotation(180.0),
- m_maxYRotation(90.0),
+ m_xRotation(0.0f),
+ m_yRotation(0.0f),
+ m_minXRotation(-180.0f),
+ m_minYRotation(0.0f),
+ m_maxXRotation(180.0f),
+ m_maxYRotation(90.0f),
m_wrapXRotation(true),
m_wrapYRotation(false),
m_zoomLevel(100),
- m_activePreset(QDataVis::CameraPresetNone)
+ m_activePreset(Q3DCamera::CameraPresetNone)
{
}
@@ -619,7 +791,7 @@ void Q3DCameraPrivate::sync(Q3DCamera &other)
}
}
-void Q3DCameraPrivate::setXRotation(const qreal rotation)
+void Q3DCameraPrivate::setXRotation(const float rotation)
{
if (m_xRotation != rotation) {
m_xRotation = rotation;
@@ -627,7 +799,7 @@ void Q3DCameraPrivate::setXRotation(const qreal rotation)
}
}
-void Q3DCameraPrivate::setYRotation(const qreal rotation)
+void Q3DCameraPrivate::setYRotation(const float rotation)
{
if (m_yRotation != rotation) {
m_yRotation = rotation;
@@ -635,7 +807,7 @@ void Q3DCameraPrivate::setYRotation(const qreal rotation)
}
}
-void Q3DCameraPrivate::setMinXRotation(const qreal rotation)
+void Q3DCameraPrivate::setMinXRotation(const float rotation)
{
if (m_minXRotation != rotation) {
m_minXRotation = rotation;
@@ -643,7 +815,7 @@ void Q3DCameraPrivate::setMinXRotation(const qreal rotation)
}
}
-void Q3DCameraPrivate::setMinYRotation(const qreal rotation)
+void Q3DCameraPrivate::setMinYRotation(const float rotation)
{
if (m_minYRotation != rotation) {
m_minYRotation = rotation;
@@ -651,7 +823,7 @@ void Q3DCameraPrivate::setMinYRotation(const qreal rotation)
}
}
-void Q3DCameraPrivate::setMaxXRotation(const qreal rotation)
+void Q3DCameraPrivate::setMaxXRotation(const float rotation)
{
if (m_maxXRotation != rotation) {
m_maxXRotation = rotation;
@@ -659,7 +831,7 @@ void Q3DCameraPrivate::setMaxXRotation(const qreal rotation)
}
}
-void Q3DCameraPrivate::setMaxYRotation(const qreal rotation)
+void Q3DCameraPrivate::setMaxYRotation(const float rotation)
{
if (m_maxYRotation != rotation) {
m_maxYRotation = rotation;
@@ -669,7 +841,7 @@ void Q3DCameraPrivate::setMaxYRotation(const qreal rotation)
// Recalculates the view matrix based on the currently set base orientation, rotation and zoom level values.
// zoomAdjustment is adjustment to ensure that the 3D visualization stays inside the view area in the 100% zoom.
-void Q3DCameraPrivate::updateViewMatrix(qreal zoomAdjustment)
+void Q3DCameraPrivate::updateViewMatrix(float zoomAdjustment)
{
if (!m_isViewMatrixUpdateActive)
return;
diff --git a/src/datavisualization/engine/q3dcamera.h b/src/datavisualization/engine/q3dcamera.h
index ee750cec..9287e15a 100644
--- a/src/datavisualization/engine/q3dcamera.h
+++ b/src/datavisualization/engine/q3dcamera.h
@@ -32,34 +32,63 @@ class Q3DCameraPrivate;
class QT_DATAVISUALIZATION_EXPORT Q3DCamera : public Q3DObject
{
Q_OBJECT
- Q_PROPERTY(qreal xRotation READ xRotation WRITE setXRotation NOTIFY xRotationChanged)
- Q_PROPERTY(qreal yRotation READ yRotation WRITE setYRotation NOTIFY yRotationChanged)
- Q_PROPERTY(qreal minXRotation READ minXRotation NOTIFY minXRotationChanged)
- Q_PROPERTY(qreal minYRotation READ minYRotation NOTIFY minYRotationChanged)
- Q_PROPERTY(qreal maxXRotation READ maxXRotation NOTIFY maxXRotationChanged)
- Q_PROPERTY(qreal maxYRotation READ maxYRotation NOTIFY maxYRotationChanged)
+ Q_ENUMS(CameraPreset)
+ Q_PROPERTY(float xRotation READ xRotation WRITE setXRotation NOTIFY xRotationChanged)
+ Q_PROPERTY(float yRotation READ yRotation WRITE setYRotation NOTIFY yRotationChanged)
+ Q_PROPERTY(float minXRotation READ minXRotation NOTIFY minXRotationChanged)
+ Q_PROPERTY(float minYRotation READ minYRotation NOTIFY minYRotationChanged)
+ Q_PROPERTY(float maxXRotation READ maxXRotation NOTIFY maxXRotationChanged)
+ Q_PROPERTY(float maxYRotation READ maxYRotation NOTIFY maxYRotationChanged)
Q_PROPERTY(int zoomLevel READ zoomLevel WRITE setZoomLevel NOTIFY zoomLevelChanged)
Q_PROPERTY(QMatrix4x4 viewMatrix READ viewMatrix WRITE setViewMatrix NOTIFY viewMatrixChanged)
- Q_PROPERTY(QtDataVisualization::QDataVis::CameraPreset cameraPreset READ cameraPreset WRITE setCameraPreset NOTIFY cameraPresetChanged)
+ Q_PROPERTY(CameraPreset cameraPreset READ cameraPreset WRITE setCameraPreset NOTIFY cameraPresetChanged)
Q_PROPERTY(bool viewMatrixAutoUpdateEnabled READ isViewMatrixAutoUpdateEnabled WRITE setViewMatrixAutoUpdateEnabled NOTIFY viewMatrixAutoUpdateChanged)
- Q_PROPERTY(bool wrapXRotation READ wrapXRotation WRITE setWrapXRotation NOTIFY wrapXRotationChanged )
- Q_PROPERTY(bool wrapYRotation READ wrapYRotation WRITE setWrapYRotation NOTIFY wrapYRotationChanged )
- Q_ENUMS(QtDataVisualization::QDataVis::CameraPreset)
+ Q_PROPERTY(bool wrapXRotation READ wrapXRotation WRITE setWrapXRotation NOTIFY wrapXRotationChanged)
+ Q_PROPERTY(bool wrapYRotation READ wrapYRotation WRITE setWrapYRotation NOTIFY wrapYRotationChanged)
+
+public:
+ enum CameraPreset {
+ CameraPresetNone = -1,
+ CameraPresetFrontLow = 0,
+ CameraPresetFront,
+ CameraPresetFrontHigh,
+ CameraPresetLeftLow,
+ CameraPresetLeft,
+ CameraPresetLeftHigh,
+ CameraPresetRightLow,
+ CameraPresetRight,
+ CameraPresetRightHigh,
+ CameraPresetBehindLow,
+ CameraPresetBehind,
+ CameraPresetBehindHigh,
+ CameraPresetIsometricLeft,
+ CameraPresetIsometricLeftHigh,
+ CameraPresetIsometricRight,
+ CameraPresetIsometricRightHigh,
+ CameraPresetDirectlyAbove,
+ CameraPresetDirectlyAboveCW45,
+ CameraPresetDirectlyAboveCCW45,
+ CameraPresetFrontBelow,
+ CameraPresetLeftBelow,
+ CameraPresetRightBelow,
+ CameraPresetBehindBelow,
+ CameraPresetDirectlyBelow
+ };
public:
Q3DCamera(QObject *parent = 0);
virtual ~Q3DCamera();
- qreal xRotation() const;
- void setXRotation(qreal rotation);
- qreal yRotation() const;
- void setYRotation(qreal rotation);
+ float xRotation() const;
+ void setXRotation(float rotation);
+ float yRotation() const;
+ void setYRotation(float rotation);
- qreal minXRotation() const;
- qreal maxXRotation() const;
+ float minXRotation() const;
+ float maxXRotation() const;
- qreal minYRotation() const;
- qreal maxYRotation() const;
+ float minYRotation() const;
+ float maxYRotation() const;
bool wrapXRotation() const;
void setWrapXRotation(bool isEnabled);
@@ -67,48 +96,49 @@ public:
bool wrapYRotation() const;
void setWrapYRotation(bool isEnabled);
- void copyValuesFrom(const Q3DCamera &source);
+ virtual void copyValuesFrom(const Q3DObject &source);
QMatrix4x4 viewMatrix() const;
void setViewMatrix(const QMatrix4x4 &viewMatrix);
- bool isViewMatrixAutoUpdateEnabled();
+ bool isViewMatrixAutoUpdateEnabled() const;
void setViewMatrixAutoUpdateEnabled(bool isEnabled);
- QDataVis::CameraPreset cameraPreset();
- void setCameraPreset(QDataVis::CameraPreset preset);
+ CameraPreset cameraPreset() const;
+ void setCameraPreset(CameraPreset preset);
- int zoomLevel();
+ int zoomLevel() const;
void setZoomLevel(int zoomLevel);
- void setBaseOrientation(const QVector3D &defaultPosition,
- const QVector3D &defaultTarget,
- const QVector3D &defaultUp);
+ Q_INVOKABLE void setBaseOrientation(const QVector3D &defaultPosition,
+ const QVector3D &defaultTarget,
+ const QVector3D &defaultUp);
QVector3D calculatePositionRelativeToCamera(const QVector3D &relativePosition,
- qreal fixedRotation,
- qreal distanceModifier) const;
- void setCameraPosition(qreal horizontal, qreal vertical, qreal distance = 100.0);
+ float fixedRotation,
+ float distanceModifier) const;
+ void setCameraPosition(float horizontal, float vertical, float distance = 100.0f);
signals:
- void xRotationChanged(qreal rotation);
- void yRotationChanged(qreal rotation);
- void minXRotationChanged(qreal rotation);
- void minYRotationChanged(qreal rotation);
- void maxXRotationChanged(qreal rotation);
- void maxYRotationChanged(qreal rotation);
+ void xRotationChanged(float rotation);
+ void yRotationChanged(float rotation);
+ void minXRotationChanged(float rotation);
+ void minYRotationChanged(float rotation);
+ void maxXRotationChanged(float rotation);
+ void maxYRotationChanged(float rotation);
void zoomLevelChanged(int zoomLevel);
void viewMatrixChanged(QMatrix4x4 viewMatrix);
- void cameraPresetChanged(QDataVis::CameraPreset preset);
+ void cameraPresetChanged(CameraPreset preset);
void viewMatrixAutoUpdateChanged(bool enabled);
void wrapXRotationChanged(bool isEnabled);
void wrapYRotationChanged(bool isEnabled);
-protected:
- void setMinXRotation(qreal rotation);
- void setMinYRotation(qreal rotation);
- void setMaxXRotation(qreal rotation);
- void setMaxYRotation(qreal rotation);
+private:
+ // To be exposed in the future
+ void setMinXRotation(float rotation);
+ void setMinYRotation(float rotation);
+ void setMaxXRotation(float rotation);
+ void setMaxYRotation(float rotation);
private:
QScopedPointer<Q3DCameraPrivate> d_ptr;
@@ -117,6 +147,7 @@ private:
friend class Q3DCameraPrivate;
friend class Q3DScenePrivate;
+ friend class Abstract3DRenderer;
friend class Bars3DRenderer;
friend class Surface3DRenderer;
friend class Scatter3DRenderer;
diff --git a/src/datavisualization/engine/q3dcamera_p.h b/src/datavisualization/engine/q3dcamera_p.h
index e0528dcc..ac32248e 100644
--- a/src/datavisualization/engine/q3dcamera_p.h
+++ b/src/datavisualization/engine/q3dcamera_p.h
@@ -44,14 +44,14 @@ public:
void sync(Q3DCamera &other);
- void setXRotation(qreal rotation);
- void setYRotation(qreal rotation);
- void setMinXRotation(qreal rotation);
- void setMinYRotation(qreal rotation);
- void setMaxXRotation(qreal rotation);
- void setMaxYRotation(qreal rotation);
+ void setXRotation(float rotation);
+ void setYRotation(float rotation);
+ void setMinXRotation(float rotation);
+ void setMinYRotation(float rotation);
+ void setMaxXRotation(float rotation);
+ void setMaxYRotation(float rotation);
- void updateViewMatrix(qreal zoomAdjustment);
+ void updateViewMatrix(float zoomAdjustment);
public:
Q3DCamera *q_ptr;
@@ -71,7 +71,7 @@ public:
bool m_wrapXRotation;
bool m_wrapYRotation;
int m_zoomLevel;
- QDataVis::CameraPreset m_activePreset;
+ Q3DCamera::CameraPreset m_activePreset;
friend class Bars3DRenderer;
friend class Surface3DRenderer;
diff --git a/src/datavisualization/engine/q3dlight.cpp b/src/datavisualization/engine/q3dlight.cpp
index f1b1b4e7..bc43c3d7 100644
--- a/src/datavisualization/engine/q3dlight.cpp
+++ b/src/datavisualization/engine/q3dlight.cpp
@@ -23,16 +23,27 @@
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
/*!
- \class Q3DLight
- \inmodule QtDataVisualization
- \brief Representation of a light source in 3D space.
- \since Qt Data Visualization 1.0
+ * \class Q3DLight
+ * \inmodule QtDataVisualization
+ * \brief Representation of a light source in 3D space.
+ * \since Qt Data Visualization 1.0
+ *
+ * Q3DLight represents a monochrome non variable light source in 3D space.
+ */
- Q3DLight represents a monochrome non variable light source in 3D space.
-*/
+/*!
+ * \qmltype Light3D
+ * \inqmlmodule QtDataVisualization
+ * \since QtDataVisualization 1.0
+ * \ingroup datavisualization_qml
+ * \instantiates Q3DLight
+ * \brief Representation of a light source in 3D space.
+ *
+ * Light3D represents a monochrome non variable light source in 3D space.
+ */
/*!
- * Constructs a new 3D light located at origo. An optional \a parent parameter can be given
+ * Constructs a new 3D light located at origin. An optional \a parent parameter can be given
* and is then passed to QObject constructor.
*/
Q3DLight::Q3DLight(QObject *parent) :
@@ -42,14 +53,6 @@ Q3DLight::Q3DLight(QObject *parent) :
}
/*!
- * Copies the properties of the 3D light from the given source \a source light to this light instance.
- */
-void Q3DLight::copyValuesFrom(const Q3DLight &source)
-{
- Q3DObject::copyValuesFrom(source);
-}
-
-/*!
* Destroys the light object.
*/
Q3DLight::~Q3DLight()
diff --git a/src/datavisualization/engine/q3dlight.h b/src/datavisualization/engine/q3dlight.h
index 0a4ba174..f9109183 100644
--- a/src/datavisualization/engine/q3dlight.h
+++ b/src/datavisualization/engine/q3dlight.h
@@ -34,8 +34,6 @@ public:
Q3DLight(QObject *parent = 0);
virtual ~Q3DLight();
- void copyValuesFrom(const Q3DLight &source);
-
private:
QScopedPointer<Q3DLightPrivate> d_ptr;
diff --git a/src/datavisualization/engine/q3dobject.h b/src/datavisualization/engine/q3dobject.h
index 930bb022..b5ce7804 100644
--- a/src/datavisualization/engine/q3dobject.h
+++ b/src/datavisualization/engine/q3dobject.h
@@ -26,9 +26,10 @@
#include <QVector3D>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
class Q3DObjectPrivate;
-class Q3DObject : public QObject
+class QT_DATAVISUALIZATION_EXPORT Q3DObject : public QObject
{
Q_OBJECT
Q_PROPERTY(Q3DScene* parentScene READ parentScene)
@@ -38,7 +39,7 @@ public:
Q3DObject(QObject *parent = 0);
virtual ~Q3DObject();
- void copyValuesFrom(const Q3DObject &source);
+ virtual void copyValuesFrom(const Q3DObject &source);
Q3DScene *parentScene();
diff --git a/src/datavisualization/engine/q3dscatter.cpp b/src/datavisualization/engine/q3dscatter.cpp
index fc95842a..3c28b4a5 100644
--- a/src/datavisualization/engine/q3dscatter.cpp
+++ b/src/datavisualization/engine/q3dscatter.cpp
@@ -20,11 +20,10 @@
#include "q3dscatter_p.h"
#include "scatter3dcontroller_p.h"
#include "q3dvalueaxis.h"
-#include "qscatterdataproxy.h"
#include "q3dcamera.h"
+#include "qscatter3dseries_p.h"
#include <QMouseEvent>
-#include <QDebug>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -44,20 +43,20 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* These default axes can be modified via axis accessors, but as soon any axis is set explicitly
* for the orientation, the default axis for that orientation is destroyed.
*
- * Data proxies work similarly: if no data proxy is set explicitly, Q3DScatter creates a default
- * proxy. If any other proxy is set as active data proxy later, the default proxy and all data
- * added to it is destroyed.
+ * Q3DScatter supports more than one series visible at the same time.
*
- * Methods are provided for changing item styles, themes, item selection modes and so on. See the
+ * Methods are provided for changing themes, item selection modes and so on. See the
* methods for more detailed descriptions.
*
* \section1 How to construct a minimal Q3DScatter graph
*
- * First, construct Q3DScatter:
+ * First, construct Q3DScatter. Since we are running the graph as top level window
+ * in this example, we need to clear the \c Qt::FramelessWindowHint flag, which gets set by
+ * default:
*
* \snippet doc_src_q3dscatter_construction.cpp 0
*
- * Now Q3DScatter is ready to receive data to be rendered. Add one set of 3 QVector3D items:
+ * Now Q3DScatter is ready to receive data to be rendered. Add one series of 3 QVector3D items:
*
* \snippet doc_src_q3dscatter_construction.cpp 1
*
@@ -81,199 +80,150 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
/*!
- * Constructs a new 3D scatter window.
+ * Constructs a new 3D scatter graph with optional \a parent window.
*/
-Q3DScatter::Q3DScatter()
- : d_ptr(new Q3DScatterPrivate(this, geometry()))
+Q3DScatter::Q3DScatter(QWindow *parent)
+ : Q3DWindow(new Q3DScatterPrivate(this), parent)
{
- setVisualController(d_ptr->m_shared);
- d_ptr->m_shared->initializeOpenGL();
- QObject::connect(d_ptr->m_shared, &Scatter3DController::selectedItemIndexChanged, this,
- &Q3DScatter::selectedItemIndexChanged);
- QObject::connect(d_ptr->m_shared, &Abstract3DController::needRender, this,
- &Q3DWindow::renderLater);
+ dptr()->m_shared = new Scatter3DController(geometry());
+ d_ptr->setVisualController(dptr()->m_shared);
+ dptr()->m_shared->initializeOpenGL();
+ QObject::connect(dptr()->m_shared, &Abstract3DController::selectionModeChanged, this,
+ &Q3DScatter::selectionModeChanged);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::shadowQualityChanged, this,
+ &Q3DScatter::shadowQualityChanged);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::themeChanged, this,
+ &Q3DScatter::themeChanged);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::needRender, d_ptr.data(),
+ &Q3DWindowPrivate::renderLater);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::shadowQualityChanged, dptr(),
+ &Q3DScatterPrivate::handleShadowQualityUpdate);
}
/*!
- * Destroys the 3D scatter window.
+ * Destroys the 3D scatter graph.
*/
Q3DScatter::~Q3DScatter()
{
}
/*!
- * \internal
+ * Adds the \a series to the graph. A graph can contain multiple series, but has only one set of
+ * axes. If the newly added series has specified a selected item, it will be highlighted and
+ * any existing selection will be cleared. Only one added series can have an active selection.
*/
-void Q3DScatter::mouseDoubleClickEvent(QMouseEvent *event)
+void Q3DScatter::addSeries(QScatter3DSeries *series)
{
- d_ptr->m_shared->mouseDoubleClickEvent(event);
+ dptr()->m_shared->addSeries(series);
}
/*!
- * \internal
+ * Removes the \a series from the graph.
*/
-void Q3DScatter::touchEvent(QTouchEvent *event)
+void Q3DScatter::removeSeries(QScatter3DSeries *series)
{
- d_ptr->m_shared->touchEvent(event);
+ dptr()->m_shared->removeSeries(series);
}
/*!
- * \internal
+ * \return list of series added to this graph.
*/
-void Q3DScatter::mousePressEvent(QMouseEvent *event)
+QList<QScatter3DSeries *> Q3DScatter::seriesList()
{
- d_ptr->m_shared->mousePressEvent(event, event->pos());
+ return dptr()->m_shared->scatterSeriesList();
}
/*!
* \internal
*/
-void Q3DScatter::mouseReleaseEvent(QMouseEvent *event)
+void Q3DScatter::mouseDoubleClickEvent(QMouseEvent *event)
{
- d_ptr->m_shared->mouseReleaseEvent(event, event->pos());
+ dptr()->m_shared->mouseDoubleClickEvent(event);
}
/*!
* \internal
*/
-void Q3DScatter::mouseMoveEvent(QMouseEvent *event)
+void Q3DScatter::touchEvent(QTouchEvent *event)
{
- d_ptr->m_shared->mouseMoveEvent(event, event->pos());
+ dptr()->m_shared->touchEvent(event);
}
/*!
* \internal
*/
-void Q3DScatter::wheelEvent(QWheelEvent *event)
+void Q3DScatter::mousePressEvent(QMouseEvent *event)
{
- d_ptr->m_shared->wheelEvent(event);
+ dptr()->m_shared->mousePressEvent(event, event->pos());
}
/*!
* \internal
*/
-void Q3DScatter::resizeEvent(QResizeEvent *event)
+void Q3DScatter::mouseReleaseEvent(QMouseEvent *event)
{
- Q_UNUSED(event);
- d_ptr->m_shared->setSize(width(), height());
+ dptr()->m_shared->mouseReleaseEvent(event, event->pos());
}
/*!
- * Sets window \a width.
+ * \internal
*/
-void Q3DScatter::setWidth(const int width)
+void Q3DScatter::mouseMoveEvent(QMouseEvent *event)
{
- d_ptr->m_shared->setWidth(width);
- QWindow::setWidth(width);
+ dptr()->m_shared->mouseMoveEvent(event, event->pos());
}
/*!
- * Sets window \a height.
+ * \internal
*/
-void Q3DScatter::setHeight(const int height)
+void Q3DScatter::wheelEvent(QWheelEvent *event)
{
- d_ptr->m_shared->setHeight(height);
- QWindow::setHeight(height);
+ dptr()->m_shared->wheelEvent(event);
}
-/*!
- * Sets the item \a style to one of the values in \c QDataVis::MeshStyle. It is preset to
- * \c QDataVis::MeshStyleSpheres by default. A \a smooth flag can be used to set shading to smooth.
- * It is \c false by default.
- *
- * \sa setMeshFileName()
- */
-void Q3DScatter::setObjectType(QDataVis::MeshStyle style, bool smooth)
+Q3DScatterPrivate *Q3DScatter::dptr()
{
- d_ptr->m_shared->setObjectType(style, smooth);
+ return static_cast<Q3DScatterPrivate *>(d_ptr.data());
}
-/*!
- * Sets a predefined \a theme from \c QDataVis::Theme. It is preset to \c QDataVis::ThemeQt by
- * default. Theme affects bar colors, label colors, text color, background color, window color and
- * grid color. Lighting is also adjusted by themes.
- *
- * \sa setObjectColor()
- *
- * \preliminary
- */
-void Q3DScatter::setTheme(QDataVis::Theme theme)
+const Q3DScatterPrivate *Q3DScatter::dptrc() const
{
- d_ptr->m_shared->setTheme(theme);
+ return static_cast<const Q3DScatterPrivate *>(d_ptr.data());
}
/*!
- * Set item color using your own colors. \a baseColor sets the base color of a item. The \a uniform
- * -flag is used to define if color needs to be uniform throughout item's length, or will the colors
- * be applied by height. It is \c true by default.
- *
- * Calling this method overrides colors from theme.
- *
- * \sa setTheme()
+ * \property Q3DScatter::theme
*
- * \preliminary
+ * A \a theme to be used for the graph. Ownership of the \a theme is transferred. Previous theme
+ * is deleted when a new one is set. Properties of the \a theme can be modified even after setting
+ * it, and the modifications take effect immediately.
*/
-void Q3DScatter::setObjectColor(const QColor &baseColor, bool uniform)
+void Q3DScatter::setTheme(Q3DTheme *theme)
{
- d_ptr->m_shared->setObjectColor(baseColor, uniform);
+ dptr()->m_shared->setTheme(theme);
}
-/*!
- * \return item color in use.
- */
-QColor Q3DScatter::objectColor() const
+Q3DTheme *Q3DScatter::theme() const
{
- return d_ptr->m_shared->objectColor();
+ return dptrc()->m_shared->theme();
}
/*!
* \property Q3DScatter::selectionMode
*
- * Sets item selection \a mode to one of \c QDataVis::SelectionMode. It is preset to
- * \c QDataVis::SelectionModeItem by default.
- */
-void Q3DScatter::setSelectionMode(QDataVis::SelectionMode mode)
-{
- d_ptr->m_shared->setSelectionMode(mode);
-}
-
-QDataVis::SelectionMode Q3DScatter::selectionMode() const
-{
- return d_ptr->m_shared->selectionMode();
-}
-
-/*!
- * \property Q3DScatter::meshFileName
- *
- * Override item type with a mesh object located in \a objFileName.
- * \note Object needs to be in Wavefront obj format and include vertices, normals and UVs.
- * It also needs to be in triangles.
- *
- * \sa setObjectType()
- */
-void Q3DScatter::setMeshFileName(const QString &objFileName)
-{
- d_ptr->m_shared->setMeshFileName(objFileName);
-}
-
-QString Q3DScatter::meshFileName() const
-{
- return d_ptr->m_shared->meshFileName();
-}
-
-/*!
- * \property Q3DScatter::font
+ * Sets item selection \a mode to a combination of \c QDataVis::SelectionFlags. It is preset to
+ * \c QDataVis::SelectionItem by default.
*
- * Sets the \a font for labels. It is preset to \c Arial by default.
+ * \note Only \c QDataVis::SelectionItem and \c QDataVis::SelectionNone are supported.
*/
-void Q3DScatter::setFont(const QFont &font)
+void Q3DScatter::setSelectionMode(QDataVis::SelectionFlags mode)
{
- d_ptr->m_shared->setFont(font);
+ dptr()->m_shared->setSelectionMode(mode);
}
-QFont Q3DScatter::font() const
+QDataVis::SelectionFlags Q3DScatter::selectionMode() const
{
- return d_ptr->m_shared->font();
+ return dptrc()->m_shared->selectionMode();
}
/*!
@@ -283,69 +233,7 @@ QFont Q3DScatter::font() const
*/
Q3DScene *Q3DScatter::scene() const
{
- return d_ptr->m_shared->scene();
-}
-
-/*!
- * \property Q3DScatter::labelStyle
- *
- * Sets label \a style to one of \c QDataVis::LabelStyle. It is preset to
- * \c QDataVis::LabelStyleFromTheme by default.
- */
-void Q3DScatter::setLabelStyle(QDataVis::LabelStyle style)
-{
- d_ptr->m_shared->setLabelStyle(style);
-}
-
-QDataVis::LabelStyle Q3DScatter::labelStyle() const
-{
- return d_ptr->m_shared->labelStyle();
-}
-
-/*!
- * \property Q3DScatter::gridVisible
- *
- * Sets grid visibility to \a visible. It is preset to \c true by default.
- */
-void Q3DScatter::setGridVisible(bool visible)
-{
- d_ptr->m_shared->setGridEnabled(visible);
-}
-
-bool Q3DScatter::isGridVisible() const
-{
- return d_ptr->m_shared->gridEnabled();
-}
-
-/*!
- * \property Q3DScatter::backgroundVisible
- *
- * Sets background visibility to \a visible. It is preset to \c true by default.
- */
-void Q3DScatter::setBackgroundVisible(bool visible)
-{
- d_ptr->m_shared->setBackgroundEnabled(visible);
-}
-
-bool Q3DScatter::isBackgroundVisible() const
-{
- return d_ptr->m_shared->backgroundEnabled();
-}
-
-/*!
- * \property Q3DScatter::selectedItemIndex
- *
- * Selects an item in the \a index. Only one item can be selected at a time.
- * To clear selection, specify an illegal \a index, e.g. -1.
- */
-void Q3DScatter::setSelectedItemIndex(int index)
-{
- d_ptr->m_shared->setSelectedItemIndex(index);
-}
-
-int Q3DScatter::selectedItemIndex() const
-{
- return d_ptr->m_shared->selectedItemIndex();
+ return dptrc()->m_shared->scene();
}
/*!
@@ -360,12 +248,12 @@ int Q3DScatter::selectedItemIndex() const
*/
void Q3DScatter::setShadowQuality(QDataVis::ShadowQuality quality)
{
- return d_ptr->m_shared->setShadowQuality(quality);
+ return dptr()->m_shared->setShadowQuality(quality);
}
QDataVis::ShadowQuality Q3DScatter::shadowQuality() const
{
- return d_ptr->m_shared->shadowQuality();
+ return dptrc()->m_shared->shadowQuality();
}
/*!
@@ -380,7 +268,7 @@ QDataVis::ShadowQuality Q3DScatter::shadowQuality() const
*/
void Q3DScatter::setAxisX(Q3DValueAxis *axis)
{
- d_ptr->m_shared->setAxisX(axis);
+ dptr()->m_shared->setAxisX(axis);
}
/*!
@@ -388,7 +276,7 @@ void Q3DScatter::setAxisX(Q3DValueAxis *axis)
*/
Q3DValueAxis *Q3DScatter::axisX() const
{
- return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisX());
+ return static_cast<Q3DValueAxis *>(dptrc()->m_shared->axisX());
}
/*!
@@ -403,7 +291,7 @@ Q3DValueAxis *Q3DScatter::axisX() const
*/
void Q3DScatter::setAxisY(Q3DValueAxis *axis)
{
- d_ptr->m_shared->setAxisY(axis);
+ dptr()->m_shared->setAxisY(axis);
}
/*!
@@ -411,7 +299,7 @@ void Q3DScatter::setAxisY(Q3DValueAxis *axis)
*/
Q3DValueAxis *Q3DScatter::axisY() const
{
- return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisY());
+ return static_cast<Q3DValueAxis *>(dptrc()->m_shared->axisY());
}
/*!
@@ -426,7 +314,7 @@ Q3DValueAxis *Q3DScatter::axisY() const
*/
void Q3DScatter::setAxisZ(Q3DValueAxis *axis)
{
- d_ptr->m_shared->setAxisZ(axis);
+ dptr()->m_shared->setAxisZ(axis);
}
/*!
@@ -434,7 +322,7 @@ void Q3DScatter::setAxisZ(Q3DValueAxis *axis)
*/
Q3DValueAxis *Q3DScatter::axisZ() const
{
- return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisZ());
+ return static_cast<Q3DValueAxis *>(dptrc()->m_shared->axisZ());
}
/*!
@@ -446,7 +334,7 @@ Q3DValueAxis *Q3DScatter::axisZ() const
*/
void Q3DScatter::addAxis(Q3DValueAxis *axis)
{
- d_ptr->m_shared->addAxis(axis);
+ dptr()->m_shared->addAxis(axis);
}
/*!
@@ -459,7 +347,7 @@ void Q3DScatter::addAxis(Q3DValueAxis *axis)
*/
void Q3DScatter::releaseAxis(Q3DValueAxis *axis)
{
- d_ptr->m_shared->releaseAxis(axis);
+ dptr()->m_shared->releaseAxis(axis);
}
/*!
@@ -469,7 +357,7 @@ void Q3DScatter::releaseAxis(Q3DValueAxis *axis)
*/
QList<Q3DValueAxis *> Q3DScatter::axes() const
{
- QList<Q3DAbstractAxis *> abstractAxes = d_ptr->m_shared->axes();
+ QList<Q3DAbstractAxis *> abstractAxes = dptrc()->m_shared->axes();
QList<Q3DValueAxis *> retList;
foreach (Q3DAbstractAxis *axis, abstractAxes)
retList.append(static_cast<Q3DValueAxis *>(axis));
@@ -478,90 +366,29 @@ QList<Q3DValueAxis *> Q3DScatter::axes() const
}
/*!
- * Sets the active data \a proxy. Implicitly calls addDataProxy() to transfer ownership of
- * the \a proxy to this graph.
- *
- * If the \a proxy is null, a temporary default proxy is created and activated.
- * This temporary proxy is destroyed if another \a proxy is set explicitly active via this method.
- *
- * \sa addDataProxy(), releaseDataProxy()
- */
-void Q3DScatter::setActiveDataProxy(QScatterDataProxy *proxy)
-{
- d_ptr->m_shared->setActiveDataProxy(proxy);
-}
-
-/*!
- * \return active data proxy.
- */
-QScatterDataProxy *Q3DScatter::activeDataProxy() const
-{
- return static_cast<QScatterDataProxy *>(d_ptr->m_shared->activeDataProxy());
-}
-
-/*!
- * Adds data \a proxy to the graph. The proxies added via addDataProxy are not yet taken to use,
- * addDataProxy is simply used to give the ownership of the data \a proxy to the graph.
- * The \a proxy must not be null or added to another graph.
- *
- * \sa releaseDataProxy(), setActiveDataProxy()
- */
-void Q3DScatter::addDataProxy(QScatterDataProxy *proxy)
-{
- d_ptr->m_shared->addDataProxy(proxy);
-}
-
-/*!
- * Releases the ownership of the data \a proxy back to the caller, if it is added to this graph.
- * If the released \a proxy is in use, a new empty default proxy is created and taken to use.
- *
- * If the default \a proxy is released and added back later, it behaves as any other proxy would.
- *
- * \sa addDataProxy(), setActiveDataProxy()
- */
-void Q3DScatter::releaseDataProxy(QScatterDataProxy *proxy)
-{
- d_ptr->m_shared->releaseDataProxy(proxy);
-}
-
-/*!
- * \return list of all added data proxies.
- *
- * \sa addDataProxy()
- */
-QList<QScatterDataProxy *> Q3DScatter::dataProxies() const
-{
- QList<QScatterDataProxy *> retList;
- QList<QAbstractDataProxy *> abstractList = d_ptr->m_shared->dataProxies();
- foreach (QAbstractDataProxy *proxy, abstractList)
- retList.append(static_cast<QScatterDataProxy *>(proxy));
-
- return retList;
-}
-
-/*!
* \fn void Q3DScatter::shadowQualityChanged(QDataVis::ShadowQuality quality)
*
* This signal is emitted when shadow \a quality changes.
*/
-Q3DScatterPrivate::Q3DScatterPrivate(Q3DScatter *q, QRect rect)
- : q_ptr(q),
- m_shared(new Scatter3DController(rect))
+Q3DScatterPrivate::Q3DScatterPrivate(Q3DScatter *q)
+ : Q3DWindowPrivate(q)
{
- QObject::connect(m_shared, &Abstract3DController::shadowQualityChanged, this,
- &Q3DScatterPrivate::handleShadowQualityUpdate);
}
Q3DScatterPrivate::~Q3DScatterPrivate()
{
- qDebug() << "Destroying Q3DScatterPrivate";
delete m_shared;
}
void Q3DScatterPrivate::handleShadowQualityUpdate(QDataVis::ShadowQuality quality)
{
- emit q_ptr->shadowQualityChanged(quality);
+ emit qptr()->shadowQualityChanged(quality);
+}
+
+Q3DScatter *Q3DScatterPrivate::qptr()
+{
+ return static_cast<Q3DScatter *>(q_ptr);
}
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/q3dscatter.h b/src/datavisualization/engine/q3dscatter.h
index fdea604e..e58146a1 100644
--- a/src/datavisualization/engine/q3dscatter.h
+++ b/src/datavisualization/engine/q3dscatter.h
@@ -22,7 +22,9 @@
#include <QtDataVisualization/qdatavisualizationenums.h>
#include <QtDataVisualization/q3dwindow.h>
#include <QtDataVisualization/q3dscene.h>
+#include <QtDataVisualization/q3dtheme.h>
#include <QFont>
+#include <QLinearGradient>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -30,62 +32,33 @@ class Q3DScatterPrivate;
class LabelItem;
class Q3DValueAxis;
class Q3DCategoryAxis;
-class QScatterDataProxy;
+class QScatter3DSeries;
+class Q3DTheme;
class QT_DATAVISUALIZATION_EXPORT Q3DScatter : public Q3DWindow
{
Q_OBJECT
- Q_PROPERTY(QtDataVisualization::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode)
- Q_PROPERTY(QtDataVisualization::QDataVis::LabelStyle labelStyle READ labelStyle WRITE setLabelStyle)
- Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality)
- Q_PROPERTY(QString meshFileName READ meshFileName WRITE setMeshFileName)
- Q_PROPERTY(QFont font READ font WRITE setFont)
- Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible)
- Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible)
- Q_PROPERTY(int selectedItemIndex READ selectedItemIndex WRITE setSelectedItemIndex NOTIFY selectedItemIndexChanged)
+ Q_PROPERTY(QtDataVisualization::QDataVis::SelectionFlags selectionMode READ selectionMode WRITE setSelectionMode NOTIFY selectionModeChanged)
+ Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality NOTIFY shadowQualityChanged)
+ Q_PROPERTY(Q3DTheme* theme READ theme WRITE setTheme NOTIFY themeChanged)
Q_PROPERTY(Q3DScene* scene READ scene)
- Q_ENUMS(QtDataVisualization::QDataVis::SelectionMode)
- Q_ENUMS(QtDataVisualization::QDataVis::ShadowQuality)
- Q_ENUMS(QtDataVisualization::QDataVis::LabelStyle)
- Q_ENUMS(QtDataVisualization::QDataVis::CameraPreset)
public:
- explicit Q3DScatter();
- ~Q3DScatter();
+ explicit Q3DScatter(QWindow *parent = 0);
+ virtual ~Q3DScatter();
- void setObjectType(QDataVis::MeshStyle style, bool smooth = false);
+ void addSeries(QScatter3DSeries *series);
+ void removeSeries(QScatter3DSeries *series);
+ QList<QScatter3DSeries *> seriesList();
- void setTheme(QDataVis::Theme theme);
+ void setTheme(Q3DTheme *theme);
+ Q3DTheme *theme() const;
- void setObjectColor(const QColor &baseColor, bool uniform = true);
- QColor objectColor() const;
-
- void setMeshFileName(const QString &objFileName);
- QString meshFileName() const;
-
- void setSelectionMode(QDataVis::SelectionMode mode);
- QDataVis::SelectionMode selectionMode() const;
-
- void setFont(const QFont &font);
- QFont font() const;
+ void setSelectionMode(QDataVis::SelectionFlags mode);
+ QDataVis::SelectionFlags selectionMode() const;
Q3DScene *scene() const;
- void setLabelStyle(QDataVis::LabelStyle style);
- QDataVis::LabelStyle labelStyle() const;
-
- void setGridVisible(bool visible);
- bool isGridVisible() const;
-
- void setWidth(const int width);
- void setHeight(const int height);
-
- void setBackgroundVisible(bool visible);
- bool isBackgroundVisible() const;
-
- void setSelectedItemIndex(int index);
- int selectedItemIndex() const;
-
void setShadowQuality(QDataVis::ShadowQuality quality);
QDataVis::ShadowQuality shadowQuality() const;
@@ -99,15 +72,10 @@ public:
void releaseAxis(Q3DValueAxis *axis);
QList<Q3DValueAxis *> axes() const;
- void setActiveDataProxy(QScatterDataProxy *proxy);
- QScatterDataProxy *activeDataProxy() const;
- void addDataProxy(QScatterDataProxy *proxy);
- void releaseDataProxy(QScatterDataProxy *proxy);
- QList<QScatterDataProxy *> dataProxies() const;
-
signals:
+ void selectionModeChanged(QDataVis::SelectionFlags mode);
void shadowQualityChanged(QDataVis::ShadowQuality quality);
- void selectedItemIndexChanged(int index);
+ void themeChanged(Q3DTheme* theme);
protected:
void mouseDoubleClickEvent(QMouseEvent *event);
@@ -116,10 +84,10 @@ protected:
void mouseReleaseEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
- void resizeEvent(QResizeEvent *event);
private:
- QScopedPointer<Q3DScatterPrivate> d_ptr;
+ Q3DScatterPrivate *dptr();
+ const Q3DScatterPrivate *dptrc() const;
Q_DISABLE_COPY(Q3DScatter)
};
diff --git a/src/datavisualization/engine/q3dscatter_p.h b/src/datavisualization/engine/q3dscatter_p.h
index 775344d0..d65776c5 100644
--- a/src/datavisualization/engine/q3dscatter_p.h
+++ b/src/datavisualization/engine/q3dscatter_p.h
@@ -26,26 +26,29 @@
//
// We mean it.
-#ifndef Q3DSCATTER_p_H
-#define Q3DSCATTER_p_H
+#ifndef Q3DSCATTER_P_H
+#define Q3DSCATTER_P_H
#include "scatter3dcontroller_p.h"
#include "qdatavisualizationenums.h"
+#include "q3dwindow_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class Q3DScatter;
-class Q3DScatterPrivate : public QObject
+class Q3DScatterPrivate : public Q3DWindowPrivate
{
+ Q_OBJECT
public:
- Q3DScatterPrivate(Q3DScatter *q, QRect rect);
+ Q3DScatterPrivate(Q3DScatter *q);
~Q3DScatterPrivate();
// Used to detect when shadow quality changes autonomously due to e.g. resizing.
void handleShadowQualityUpdate(QDataVis::ShadowQuality quality);
- Q3DScatter *q_ptr;
+ Q3DScatter *qptr();
+
Scatter3DController *m_shared;
};
diff --git a/src/datavisualization/engine/q3dscene.cpp b/src/datavisualization/engine/q3dscene.cpp
index 3789ea9f..d8104b3a 100644
--- a/src/datavisualization/engine/q3dscene.cpp
+++ b/src/datavisualization/engine/q3dscene.cpp
@@ -26,6 +26,7 @@
#include "q3dlight_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
/*!
* \class Q3DScene
* \inmodule QtDataVisualization
@@ -37,6 +38,27 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*
* The 3D scene also keeps track of the viewport in which visualization rendering is done,
* the primary subviewport inside the viewport where the main 3D data visualization view resides
+ * and the secondary subviewport where the 2D sliced view of the data resides. The subviewports are
+ * by default resized by the \a Q3DScene. To override the resize behavior you need to listen to both
+ * \l viewportChanged() and \l slicingActiveChanged() signals and recalculate the subviewports accordingly.
+ *
+ * Also the scene has flag for tracking if the secondary 2D slicing view is currently active or not.
+ * \note Not all visualizations support the secondary 2D slicing view.
+ */
+
+/*!
+ * \qmltype Scene3D
+ * \inqmlmodule QtDataVisualization
+ * \since QtDataVisualization 1.0
+ * \ingroup datavisualization_qml
+ * \instantiates Q3DScene
+ * \brief Scene3D type provides description of the 3D scene being visualized.
+ *
+ * The 3D scene contains a single active camera and a single active light source.
+ * Visualized data is assumed to be at a fixed location.
+ *
+ * The 3D scene also keeps track of the viewport in which visualization rendering is done,
+ * the primary subviewport inside the viewport where the main 3D data visualization view resides
* and the secondary subviewport where the 2D sliced view of the data resides.
*
* Also the scene has flag for tracking if the secondary 2D slicing view is currently active or not.
@@ -44,6 +66,71 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
/*!
+ * \qmlproperty rect Scene3D::viewport
+ *
+ * This property contains the current viewport rectangle where all 3D rendering
+ * is targeted.
+ */
+
+/*!
+ * \qmlproperty rect Scene3D::primarySubViewport
+ *
+ * This property contains the current subviewport rectangle inside the viewport where the
+ * primary view of the data visualization is targeted to.
+ */
+
+/*!
+ * \qmlproperty rect Scene3D::secondarySubViewport
+ *
+ * This property contains the secondary viewport rectangle inside the viewport. The secondary
+ * viewport is used for drawing the 2D slice view in some visualizations.
+ */
+
+/*!
+ * \qmlproperty point Scene3D::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 \c{(-1, -1)} the
+ * graph tries to select a data item at the given point within the primary viewport.
+ * After the rendering pass the property is returned to its default state of \c{(-1, -1)}.
+ */
+
+/*!
+ * \qmlproperty bool Scene3D::slicingActive
+ *
+ * This property contains whether 2D slicing view is currently active or not.
+ * \note Not all visualizations support the 2D slicing view.
+ */
+
+/*!
+ * \qmlproperty bool Scene3D::secondarySubviewOnTop
+ *
+ * This property contains whether 2D slicing view is currently drawn on top or if the 3D view is
+ * drawn on top.
+ */
+
+/*!
+ * \qmlproperty Camera3D Scene3D::activeCamera
+ *
+ * This property contains the currently active camera in the 3D scene.
+ * When a Camera3D is set in the property it gets automatically added as child of the scene.
+ */
+
+/*!
+ * \qmlproperty Light3D Scene3D::activeLight
+ *
+ * This property contains the currently active light in the 3D scene.
+ * When a Light3D is set in the property it gets automatically added as child of the scene.
+ */
+
+/*!
+ * \qmlproperty float Scene3D::devicePixelRatio
+ *
+ * This property contains the current device pixel ratio that is used when mapping input
+ * coordinates to pixel coordinates.
+ */
+
+/*!
* Constructs a basic scene with one light and one camera in it. An
* optional \a parent parameter can be given and is then passed to QObject constructor.
*/
@@ -65,7 +152,7 @@ Q3DScene::~Q3DScene()
/*!
* \property Q3DScene::viewport
*
- * This property contains the current viewport rectangle where all 3D rendering
+ * This read only property contains the current viewport rectangle where all 3D rendering
* is targeted.
*/
QRect Q3DScene::viewport() const
@@ -73,36 +160,10 @@ QRect Q3DScene::viewport() const
return d_ptr->m_viewport;
}
-void Q3DScene::setViewport(const QRect &viewport)
-{
- if (d_ptr->m_viewport.width() != viewport.width()
- || d_ptr->m_viewport.height() != viewport.height()) {
- d_ptr->m_viewport = viewport;
- d_ptr->m_viewport.setX(0);
- d_ptr->m_viewport.setY(0);
- d_ptr->m_changeTracker.viewportChanged = true;
- emit viewportChanged(viewport);
- }
-}
-
-/*!
- * Sets the \a width and \a height of the viewport only, without changing its location.
- */
-void Q3DScene::setViewportSize(int width, int height)
-{
- if (d_ptr->m_viewport.width() != width
- || d_ptr->m_viewport.height() != height) {
- d_ptr->m_viewport.setWidth(width);
- d_ptr->m_viewport.setHeight(height);
- d_ptr->m_changeTracker.viewportChanged = true;
- emit viewportChanged(d_ptr->m_viewport);
- }
-}
-
/*!
* \property Q3DScene::primarySubViewport
*
- * This property contains the current main viewport rectangle inside the viewport where the
+ * This property contains the current subviewport rectangle inside the viewport where the
* primary view of the data visualization is targeted to.
*/
QRect Q3DScene::primarySubViewport() const
@@ -112,10 +173,14 @@ QRect Q3DScene::primarySubViewport() const
void Q3DScene::setPrimarySubViewport(const QRect &primarySubViewport)
{
- if (d_ptr->m_primarySubViewport != primarySubViewport) {
- d_ptr->m_primarySubViewport = primarySubViewport;
+ QRect clipRect = QRect(0, 0, d_ptr->m_viewport.width(), d_ptr->m_viewport.height());
+ QRect intersectedViewport = primarySubViewport.intersected(clipRect);
+ if (d_ptr->m_primarySubViewport != intersectedViewport) {
+ d_ptr->m_primarySubViewport = intersectedViewport;
+ d_ptr->updateGLSubViewports();
d_ptr->m_changeTracker.primarySubViewportChanged = true;
- emit primarySubViewportChanged(primarySubViewport);
+ emit primarySubViewportChanged(intersectedViewport);
+ emit d_ptr->needRender();
}
}
@@ -123,7 +188,7 @@ void Q3DScene::setPrimarySubViewport(const QRect &primarySubViewport)
* Returns whether the given \a point resides inside the primary subview or not.
* The method takes care of correctly mapping between OpenGL coordinates used in the
* viewport definitions and the Qt event coordinate system used in the input system.
- * \return true if the point is inside the primary subview.
+ * \return \c true if the point is inside the primary subview.
*/
bool Q3DScene::isPointInPrimarySubView(const QPoint &point)
{
@@ -131,9 +196,9 @@ bool Q3DScene::isPointInPrimarySubView(const QPoint &point)
int x = point.x();
int y = point.y();
int areaMinX = d_ptr->m_primarySubViewport.x();
- int areaMaxX = d_ptr->m_primarySubViewport.x() + d_ptr->m_primarySubViewport.width();
- int areaMaxY = d_ptr->m_viewport.height() - d_ptr->m_primarySubViewport.y();
- int areaMinY = d_ptr->m_viewport.height() - (d_ptr->m_primarySubViewport.y() + d_ptr->m_primarySubViewport.height());
+ int areaMaxX = d_ptr->m_viewport.x() + d_ptr->m_primarySubViewport.x() + d_ptr->m_primarySubViewport.width();
+ int areaMaxY = d_ptr->m_viewport.y() + d_ptr->m_primarySubViewport.y() + d_ptr->m_primarySubViewport.height();
+ int areaMinY = d_ptr->m_viewport.y() + d_ptr->m_primarySubViewport.y();
return ( x > areaMinX && x < areaMaxX && y > areaMinY && y < areaMaxY );
}
@@ -142,7 +207,7 @@ bool Q3DScene::isPointInPrimarySubView(const QPoint &point)
* Returns whether the given \a point resides inside the secondary subview or not.
* The method takes care of correctly mapping between OpenGL coordinates used in the
* viewport definitions and the Qt event coordinate system used in the input system.
- * \return true if the point is inside the secondary subview.
+ * \return \c true if the point is inside the secondary subview.
*/
bool Q3DScene::isPointInSecondarySubView(const QPoint &point)
{
@@ -150,9 +215,9 @@ bool Q3DScene::isPointInSecondarySubView(const QPoint &point)
int x = point.x();
int y = point.y();
int areaMinX = d_ptr->m_secondarySubViewport.x();
- int areaMaxX = d_ptr->m_secondarySubViewport.x() + d_ptr->m_secondarySubViewport.width();
- int areaMaxY = d_ptr->m_viewport.height() - d_ptr->m_secondarySubViewport.y();
- int areaMinY = d_ptr->m_viewport.height() - (d_ptr->m_secondarySubViewport.y() + d_ptr->m_secondarySubViewport.height());
+ int areaMaxX = d_ptr->m_viewport.x() + d_ptr->m_secondarySubViewport.x() + d_ptr->m_secondarySubViewport.width();
+ int areaMaxY = d_ptr->m_viewport.y() + d_ptr->m_secondarySubViewport.y() + d_ptr->m_secondarySubViewport.height();
+ int areaMinY = d_ptr->m_viewport.y() + d_ptr->m_secondarySubViewport.y();
return ( x > areaMinX && x < areaMaxX && y > areaMinY && y < areaMaxY );
}
@@ -170,14 +235,50 @@ QRect Q3DScene::secondarySubViewport() const
void Q3DScene::setSecondarySubViewport(const QRect &secondarySubViewport)
{
- if (d_ptr->m_secondarySubViewport != secondarySubViewport) {
- d_ptr->m_secondarySubViewport = secondarySubViewport;
+ QRect clipRect = QRect(0, 0, d_ptr->m_viewport.width(), d_ptr->m_viewport.height());
+ QRect intersectedViewport = secondarySubViewport.intersected(clipRect);
+ if (d_ptr->m_secondarySubViewport != intersectedViewport) {
+ d_ptr->m_secondarySubViewport = intersectedViewport;
+ d_ptr->updateGLSubViewports();
d_ptr->m_changeTracker.secondarySubViewportChanged = true;
- emit secondarySubViewportChanged(secondarySubViewport);
+ emit secondarySubViewportChanged(intersectedViewport);
+ emit d_ptr->needRender();
}
}
/*!
+ * \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
+ * graph tries to select a data item at the given \a point within the primary viewport.
+ * After the rendering pass the property is returned to its default state of invalidSelectionPoint().
+ */
+void Q3DScene::setSelectionQueryPosition(const QPoint &point)
+{
+ if (point != d_ptr->m_selectionQueryPosition) {
+ d_ptr->m_selectionQueryPosition = point;
+ d_ptr->m_changeTracker.selectionQueryPositionChanged = true;
+ emit selectionQueryPositionChanged(point);
+ emit d_ptr->needRender();
+ }
+}
+
+QPoint Q3DScene::selectionQueryPosition() const
+{
+ return d_ptr->m_selectionQueryPosition;
+}
+
+/*!
+ * \return a QPoint signifying an invalid selection position.
+ */
+const QPoint Q3DScene::invalidSelectionPoint()
+{
+ static const QPoint invalidSelectionPos(-1, -1);
+ return invalidSelectionPos;
+}
+
+/*!
* \property Q3DScene::slicingActive
*
* This property contains whether 2D slicing view is currently active or not.
@@ -193,8 +294,30 @@ void Q3DScene::setSlicingActive(bool isSlicing)
if (d_ptr->m_isSlicingActive != isSlicing) {
d_ptr->m_isSlicingActive = isSlicing;
d_ptr->m_changeTracker.slicingActivatedChanged = true;
+ d_ptr->calculateSubViewports();
emit slicingActiveChanged(isSlicing);
- emitNeedRender();
+ emit d_ptr->needRender();
+ }
+}
+
+/*!
+ * \property Q3DScene::secondarySubviewOnTop
+ *
+ * This property contains whether 2D slicing view is currently drawn on top or if the 3D view is
+ * drawn on top.
+ */
+bool Q3DScene::isSecondarySubviewOnTop() const
+{
+ return d_ptr->m_isSecondarySubviewOnTop;
+}
+
+void Q3DScene::setSecondarySubviewOnTop(bool isSecondaryOnTop)
+{
+ if (d_ptr->m_isSecondarySubviewOnTop != isSecondaryOnTop) {
+ d_ptr->m_isSecondarySubviewOnTop = isSecondaryOnTop;
+ d_ptr->m_changeTracker.subViewportOrderChanged = true;
+ emit secondarySubviewOnTopChanged(isSecondaryOnTop);
+ emit d_ptr->needRender();
}
}
@@ -202,7 +325,8 @@ void Q3DScene::setSlicingActive(bool isSlicing)
* \property Q3DScene::activeCamera
*
* This property contains the currently active camera in the 3D scene.
- * When a new Q3DCamera objects is set in the property it gets automatically added as child of the scene.
+ * When a new Q3DCamera objects is set in the property it gets automatically added as child of
+ * the scene.
*/
Q3DCamera *Q3DScene::activeCamera() const
{
@@ -219,37 +343,37 @@ void Q3DScene::setActiveCamera(Q3DCamera *camera)
if (camera != d_ptr->m_camera) {
if (d_ptr->m_camera) {
- disconnect(d_ptr->m_camera, &Q3DCamera::xRotationChanged, this,
- &Q3DScene::emitNeedRender);
- disconnect(d_ptr->m_camera, &Q3DCamera::yRotationChanged, this,
- &Q3DScene::emitNeedRender);
+ disconnect(d_ptr->m_camera, &Q3DCamera::xRotationChanged, d_ptr.data(),
+ &Q3DScenePrivate::needRender);
+ disconnect(d_ptr->m_camera, &Q3DCamera::yRotationChanged, d_ptr.data(),
+ &Q3DScenePrivate::needRender);
+ disconnect(d_ptr->m_camera, &Q3DCamera::zoomLevelChanged, d_ptr.data(),
+ &Q3DScenePrivate::needRender);
}
d_ptr->m_camera = camera;
d_ptr->m_changeTracker.cameraChanged = true;
if (camera) {
- connect(camera, &Q3DCamera::xRotationChanged, this,
- &Q3DScene::emitNeedRender);
- connect(camera, &Q3DCamera::yRotationChanged, this,
- &Q3DScene::emitNeedRender);
+ connect(camera, &Q3DCamera::xRotationChanged, d_ptr.data(),
+ &Q3DScenePrivate::needRender);
+ connect(camera, &Q3DCamera::yRotationChanged, d_ptr.data(),
+ &Q3DScenePrivate::needRender);
+ connect(camera, &Q3DCamera::zoomLevelChanged, d_ptr.data(),
+ &Q3DScenePrivate::needRender);
}
emit activeCameraChanged(camera);
- emitNeedRender();
+ emit d_ptr->needRender();
}
}
-void Q3DScene::emitNeedRender()
-{
- emit needRender();
-}
-
/*!
* \property Q3DScene::activeLight
*
* This property contains the currently active light in the 3D scene.
- * When a new Q3DLight objects is set in the property it gets automatically added as child of the scene.
+ * When a new Q3DLight objects is set in the property it gets automatically added as child of
+ * the scene.
*/
Q3DLight *Q3DScene::activeLight() const
{
@@ -277,27 +401,32 @@ void Q3DScene::setActiveLight(Q3DLight *light)
* This property contains the current device pixel ratio that is used when mapping input
* coordinates to pixel coordinates.
*/
-qreal Q3DScene::devicePixelRatio() const
+float Q3DScene::devicePixelRatio() const
{
return d_ptr->m_devicePixelRatio;
}
-void Q3DScene::setDevicePixelRatio(qreal pixelRatio)
+void Q3DScene::setDevicePixelRatio(float pixelRatio)
{
if (d_ptr->m_devicePixelRatio != pixelRatio) {
d_ptr->m_devicePixelRatio = pixelRatio;
+ d_ptr->m_changeTracker.devicePixelRatioChanged = true;
emit devicePixelRatioChanged(pixelRatio);
+ d_ptr->updateGLViewport();
+ emit d_ptr->needRender();
}
}
/*!
- * Calculates and sets the light position relative to the currently active camera using the given parameters.
- * \a relativePosition defines the relative 3D offset to the current camera position.
- * Optional \a fixedRotation fixes the light rotation around the data visualization area to the given value in degrees.
+ * Calculates and sets the light position relative to the currently active camera using the given
+ * parameters.
+ * The relative 3D offset to the current camera position is defined in \a relativePosition.
+ * Optional \a fixedRotation fixes the light rotation around the data visualization area to the
+ * given value in degrees.
* Optional \a distanceModifier modifies the distance of the light from the data visualization.
*/
void Q3DScene::setLightPositionRelativeToCamera(const QVector3D &relativePosition,
- qreal fixedRotation, qreal distanceModifier)
+ float fixedRotation, float distanceModifier)
{
d_ptr->m_light->setPosition(
d_ptr->m_camera->calculatePositionRelativeToCamera(relativePosition,
@@ -305,18 +434,16 @@ void Q3DScene::setLightPositionRelativeToCamera(const QVector3D &relativePositio
distanceModifier));
}
-/*!
- * \fn Q3DScene::needRender()
- * \internal
- */
-
Q3DScenePrivate::Q3DScenePrivate(Q3DScene *q) :
+ QObject(0),
q_ptr(q),
+ m_isSecondarySubviewOnTop(true),
m_devicePixelRatio(1.f),
m_camera(),
m_light(),
m_isUnderSideCameraEnabled(false),
- m_isSlicingActive(false)
+ m_isSlicingActive(false),
+ m_selectionQueryPosition(Q3DScene::invalidSelectionPoint())
{
}
@@ -330,11 +457,21 @@ Q3DScenePrivate::~Q3DScenePrivate()
// those changes are discarded.
void Q3DScenePrivate::sync(Q3DScenePrivate &other)
{
+ if (m_changeTracker.windowSizeChanged) {
+ other.setWindowSize(windowSize());
+ m_changeTracker.windowSizeChanged = false;
+ other.m_changeTracker.windowSizeChanged = false;
+ }
if (m_changeTracker.viewportChanged) {
- other.q_ptr->setViewport(q_ptr->viewport());
+ other.setViewport(m_viewport);
m_changeTracker.viewportChanged = false;
other.m_changeTracker.viewportChanged = false;
}
+ if (m_changeTracker.subViewportOrderChanged) {
+ other.q_ptr->setSecondarySubviewOnTop(q_ptr->isSecondarySubviewOnTop());
+ m_changeTracker.subViewportOrderChanged = false;
+ other.m_changeTracker.subViewportOrderChanged = false;
+ }
if (m_changeTracker.primarySubViewportChanged) {
other.q_ptr->setPrimarySubViewport(q_ptr->primarySubViewport());
m_changeTracker.primarySubViewportChanged = false;
@@ -345,6 +482,11 @@ void Q3DScenePrivate::sync(Q3DScenePrivate &other)
m_changeTracker.secondarySubViewportChanged = false;
other.m_changeTracker.secondarySubViewportChanged = false;
}
+ if (m_changeTracker.selectionQueryPositionChanged) {
+ other.q_ptr->setSelectionQueryPosition(q_ptr->selectionQueryPosition());
+ m_changeTracker.selectionQueryPositionChanged = false;
+ other.m_changeTracker.selectionQueryPositionChanged = false;
+ }
if (m_changeTracker.cameraChanged) {
m_camera->setDirty(true);
m_changeTracker.cameraChanged = false;
@@ -372,4 +514,107 @@ void Q3DScenePrivate::sync(Q3DScenePrivate &other)
}
}
+void Q3DScenePrivate::setViewport(const QRect &viewport)
+{
+ if (m_viewport != viewport) {
+ m_viewport = viewport;
+ calculateSubViewports();
+ emit needRender();
+ }
+}
+
+void Q3DScenePrivate::setViewportSize(int width, int height)
+{
+ if (m_viewport.width() != width
+ || m_viewport.height() != height) {
+ m_viewport.setWidth(width);
+ m_viewport.setHeight(height);
+ calculateSubViewports();
+ emit needRender();
+ }
+}
+
+/*!
+ * \internal
+ * Sets the size of the window being rendered to. With widget based graphs, this
+ * is equal to the size of the QWindow and is same as the bounding rectangle.
+ * With declarative graphs this is equal to the size of the QQuickWindow and
+ * can be different from the bounding rectangle.
+ */
+void Q3DScenePrivate::setWindowSize(const QSize &size)
+{
+ if (m_windowSize != size) {
+ m_windowSize = size;
+ updateGLViewport();
+ m_changeTracker.windowSizeChanged = true;
+ emit needRender();
+ }
+}
+
+QSize Q3DScenePrivate::windowSize() const
+{
+ return m_windowSize;
+}
+
+void Q3DScenePrivate::calculateSubViewports()
+{
+ // Calculates the default subviewport layout
+ const float smallerViewPortRatio = 0.2f;
+ if (m_isSlicingActive) {
+ q_ptr->setPrimarySubViewport(QRect(0,
+ 0,
+ m_viewport.width() * smallerViewPortRatio,
+ m_viewport.height() * smallerViewPortRatio));
+ q_ptr->setSecondarySubViewport(QRect(0, 0, m_viewport.width(), m_viewport.height()));
+ } else {
+ q_ptr->setPrimarySubViewport(QRect(0, 0, m_viewport.width(), m_viewport.height()));
+ q_ptr->setSecondarySubViewport(QRect(0, 0, 0, 0));
+ }
+
+ updateGLViewport();
+}
+
+void Q3DScenePrivate::updateGLViewport()
+{
+ // Update GL viewport
+ m_glViewport.setX(m_viewport.x() * m_devicePixelRatio);
+ m_glViewport.setY((m_windowSize.height() - (m_viewport.y() + m_viewport.height())) * m_devicePixelRatio);
+ m_glViewport.setWidth(m_viewport.width() * m_devicePixelRatio);
+ m_glViewport.setHeight(m_viewport.height() * m_devicePixelRatio);
+
+ m_changeTracker.viewportChanged = true;
+
+ // Do default subviewport changes first, then allow signal listeners to override.
+ updateGLSubViewports();
+ emit q_ptr->viewportChanged(m_viewport);
+}
+
+void Q3DScenePrivate::updateGLSubViewports()
+{
+ m_glPrimarySubViewport.setX((m_primarySubViewport.x() + m_viewport.x()) * m_devicePixelRatio);
+ m_glPrimarySubViewport.setY((m_windowSize.height() - (m_primarySubViewport.y() + m_viewport.y() + m_primarySubViewport.height())) * m_devicePixelRatio);
+ m_glPrimarySubViewport.setWidth(m_primarySubViewport.width() * m_devicePixelRatio);
+ m_glPrimarySubViewport.setHeight(m_primarySubViewport.height() * m_devicePixelRatio);
+
+ m_glSecondarySubViewport.setX(m_secondarySubViewport.x() * m_devicePixelRatio);
+ m_glSecondarySubViewport.setY((m_windowSize.height() - (m_secondarySubViewport.y() + m_viewport.y() + m_secondarySubViewport.height())) * m_devicePixelRatio);
+ m_glSecondarySubViewport.setWidth(m_secondarySubViewport.width() * m_devicePixelRatio);
+ m_glSecondarySubViewport.setHeight(m_secondarySubViewport.height() * m_devicePixelRatio);
+}
+
+QRect Q3DScenePrivate::glViewport()
+{
+ return m_glViewport;
+}
+
+QRect Q3DScenePrivate::glPrimarySubViewport()
+{
+ return m_glPrimarySubViewport;
+}
+
+QRect Q3DScenePrivate::glSecondarySubViewport()
+{
+ return m_glSecondarySubViewport;
+}
+
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/q3dscene.h b/src/datavisualization/engine/q3dscene.h
index 745cef72..b0dadff9 100644
--- a/src/datavisualization/engine/q3dscene.h
+++ b/src/datavisualization/engine/q3dscene.h
@@ -33,21 +33,21 @@ class Q3DScenePrivate;
class QT_DATAVISUALIZATION_EXPORT Q3DScene : public QObject
{
Q_OBJECT
- Q_PROPERTY(QRect viewport READ viewport WRITE setViewport NOTIFY viewportChanged)
+ Q_PROPERTY(QRect viewport READ viewport NOTIFY viewportChanged)
Q_PROPERTY(QRect primarySubViewport READ primarySubViewport WRITE setPrimarySubViewport NOTIFY primarySubViewportChanged)
Q_PROPERTY(QRect secondarySubViewport READ secondarySubViewport WRITE setSecondarySubViewport NOTIFY secondarySubViewportChanged)
+ Q_PROPERTY(QPoint selectionQueryPosition READ selectionQueryPosition WRITE setSelectionQueryPosition NOTIFY selectionQueryPositionChanged)
+ Q_PROPERTY(bool secondarySubviewOnTop READ isSecondarySubviewOnTop WRITE setSecondarySubviewOnTop NOTIFY secondarySubviewOnTopChanged)
Q_PROPERTY(bool slicingActive READ isSlicingActive WRITE setSlicingActive NOTIFY slicingActiveChanged)
Q_PROPERTY(Q3DCamera* activeCamera READ activeCamera WRITE setActiveCamera NOTIFY activeCameraChanged)
Q_PROPERTY(Q3DLight* activeLight READ activeLight WRITE setActiveLight NOTIFY activeLightChanged)
- Q_PROPERTY(qreal devicePixelRatio READ devicePixelRatio WRITE setDevicePixelRatio NOTIFY devicePixelRatioChanged)
+ Q_PROPERTY(float devicePixelRatio READ devicePixelRatio WRITE setDevicePixelRatio NOTIFY devicePixelRatioChanged)
public:
Q3DScene(QObject *parent = 0);
~Q3DScene();
QRect viewport() const;
- void setViewport(const QRect &viewport);
- void setViewportSize(int width, int height);
QRect primarySubViewport() const;
void setPrimarySubViewport(const QRect &primarySubViewport);
@@ -57,39 +57,47 @@ public:
void setSecondarySubViewport(const QRect &secondarySubViewport);
bool isPointInSecondarySubView(const QPoint &point);
+ void setSelectionQueryPosition(const QPoint &point);
+ QPoint selectionQueryPosition() const;
+ static const QPoint invalidSelectionPoint();
+
void setSlicingActive(bool isSlicing);
bool isSlicingActive() const;
+ void setSecondarySubviewOnTop(bool isSecondaryOnTop);
+ bool isSecondarySubviewOnTop() const;
+
Q3DCamera *activeCamera() const;
void setActiveCamera(Q3DCamera *camera);
Q3DLight *activeLight() const;
void setActiveLight(Q3DLight *light);
- qreal devicePixelRatio() const;
- void setDevicePixelRatio(qreal pixelRatio);
-
- void setLightPositionRelativeToCamera(const QVector3D &relativePosition,
- qreal fixedRotation = 0.0,
- qreal distanceModifier = 0.0);
-private:
- void emitNeedRender();
+ float devicePixelRatio() const;
+ void setDevicePixelRatio(float pixelRatio);
+ Q_INVOKABLE void setLightPositionRelativeToCamera(const QVector3D &relativePosition,
+ float fixedRotation = 0.0f,
+ float distanceModifier = 0.0f);
signals:
void viewportChanged(QRect viewport);
void primarySubViewportChanged(QRect subViewport);
void secondarySubViewportChanged(QRect subViewport);
+ void secondarySubviewOnTopChanged(bool isSecondaryOnTop);
void slicingActiveChanged(bool isSlicingActive);
void activeCameraChanged(const Q3DCamera *camera);
void activeLightChanged(const Q3DLight *light);
- void devicePixelRatioChanged(qreal pixelRatio);
- void needRender();
+ void devicePixelRatioChanged(float pixelRatio);
+ void selectionQueryPositionChanged(const QPoint position);
private:
QScopedPointer<Q3DScenePrivate> d_ptr;
Q_DISABLE_COPY(Q3DScene)
+ friend class AbstractDeclarative;
+ friend class Q3DWindow;
+ friend class Abstract3DController;
friend class Q3DScenePrivate;
friend class Abstract3DRenderer;
friend class Bars3DRenderer;
diff --git a/src/datavisualization/engine/q3dscene_p.h b/src/datavisualization/engine/q3dscene_p.h
index b28baaae..c9d9d1f6 100644
--- a/src/datavisualization/engine/q3dscene_p.h
+++ b/src/datavisualization/engine/q3dscene_p.h
@@ -42,42 +42,71 @@ struct Q3DSceneChangeBitField {
bool viewportChanged : 1;
bool primarySubViewportChanged : 1;
bool secondarySubViewportChanged : 1;
+ bool subViewportOrderChanged : 1;
bool cameraChanged : 1;
bool lightChanged : 1;
bool slicingActivatedChanged : 1;
bool devicePixelRatioChanged : 1;
+ bool selectionQueryPositionChanged : 1;
+ bool windowSizeChanged : 1;
Q3DSceneChangeBitField()
: viewportChanged(true),
primarySubViewportChanged(true),
secondarySubViewportChanged(true),
+ subViewportOrderChanged(true),
cameraChanged(true),
lightChanged(true),
slicingActivatedChanged(true),
- devicePixelRatioChanged(true)
+ devicePixelRatioChanged(true),
+ selectionQueryPositionChanged(false),
+ windowSizeChanged(true)
{
}
};
-class Q3DScenePrivate
+class QT_DATAVISUALIZATION_EXPORT Q3DScenePrivate : public QObject
{
+ Q_OBJECT
public:
Q3DScenePrivate(Q3DScene *q);
~Q3DScenePrivate();
void sync(Q3DScenePrivate &other);
+ void setViewport(const QRect &viewport);
+ void setViewportSize(int width, int height);
+ void setWindowSize(const QSize &size);
+ QSize windowSize() const;
+ void calculateSubViewports();
+ void updateGLViewport();
+ void updateGLSubViewports();
+
+ QRect glViewport();
+ QRect glPrimarySubViewport();
+ QRect glSecondarySubViewport();
+
+signals:
+ void needRender();
+
+public:
Q3DScene *q_ptr;
Q3DSceneChangeBitField m_changeTracker;
QRect m_viewport;
QRect m_primarySubViewport;
QRect m_secondarySubViewport;
- qreal m_devicePixelRatio;
+ bool m_isSecondarySubviewOnTop;
+ float m_devicePixelRatio;
Q3DCamera *m_camera;
Q3DLight *m_light;
bool m_isUnderSideCameraEnabled;
bool m_isSlicingActive;
+ QPoint m_selectionQueryPosition;
+ QSize m_windowSize;
+ QRect m_glViewport;
+ QRect m_glPrimarySubViewport;
+ QRect m_glSecondarySubViewport;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/q3dsurface.cpp b/src/datavisualization/engine/q3dsurface.cpp
index 42260e8b..ce738685 100644
--- a/src/datavisualization/engine/q3dsurface.cpp
+++ b/src/datavisualization/engine/q3dsurface.cpp
@@ -21,6 +21,7 @@
#include "q3dvalueaxis.h"
#include "qsurfacedataproxy.h"
#include "q3dcamera.h"
+#include "qsurface3dseries_p.h"
#include <QMouseEvent>
@@ -33,17 +34,15 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* \since Qt Data Visualization 1.0
*
* This class enables developers to render 3D surface plots and to view them by rotating the scene
- * freely. The class provides configurable gradient texture to illustrate the height on the data. The
- * surface plotting includes also gridline that can be set on or off. The visual appearance of the
- * surface can be changed by controlling the smooth status.
+ * freely. The surface plotting includes also gridline that can be set on or off.
+ * The visual appearance of the surface can be changed by controlling the smooth status.
*
* The Q3DSurface supports selection by showing a highlighted ball on the data point where the user has clicked
- * with left mouse button (when default input handler is in use). The selection pointer is accompanied with
- * a label which in default case shows the value of the data point and the coordinates of the point.
+ * with left mouse button (when default input handler is in use) or selected via QSurface3DSeries.
+ * The selection pointer is accompanied with a label which in default case shows the value of the
+ * data point and the coordinates of the point.
*
* The value range and the label format shown on the axis can be controlled through Q3DValueAxis.
- * The Q3DSurface supports only a grid with fixed steps, so when setting ranges set a value that matches
- * the grid step. To calculate the steps divide the whole data range with the number of segments.
*
* To rotate the graph, hold down the right mouse button and move the mouse. Zooming is done using mouse
* wheel. Both assume the default input handler is in use.
@@ -52,13 +51,13 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* These default axes can be modified via axis accessors, but as soon any axis is set explicitly
* for the orientation, the default axis for that orientation is destroyed.
*
- * Data proxies work similarly: if no data proxy is set explicitly, Q3DSurface creates a default
- * proxy. If any other proxy is set as active data proxy later, the default proxy and all data
- * added to it is destroyed.
+ * Q3DSurface supports only single series at a time.
*
* \section1 How to construct a minimal Q3DSurface graph
*
- * First, construct Q3DSurface:
+ * First, construct Q3DSurface. Since we are running the graph as top level window
+ * in this example, we need to clear the \c Qt::FramelessWindowHint flag, which gets set by
+ * default:
*
* \snippet doc_src_q3dsurface_construction.cpp 0
*
@@ -70,7 +69,7 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*
* \snippet doc_src_q3dsurface_construction.cpp 2
*
- * For the active data proxy set pointer of the data element:
+ * Create a new series and set data to it:
*
* \snippet doc_src_q3dsurface_construction.cpp 3
*
@@ -94,129 +93,132 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
/*!
- * Constructs a new 3D surface window.
+ * Constructs a new 3D surface graph with optional \a parent window.
*/
-Q3DSurface::Q3DSurface()
- : d_ptr(new Q3DSurfacePrivate(this, geometry()))
+Q3DSurface::Q3DSurface(QWindow *parent)
+ : Q3DWindow(new Q3DSurfacePrivate(this), parent)
{
- setVisualController(d_ptr->m_shared);
- d_ptr->m_shared->initializeOpenGL();
- QObject::connect(d_ptr->m_shared, &Abstract3DController::needRender, this,
- &Q3DWindow::renderLater);
+ dptr()->m_shared = new Surface3DController(geometry());
+ d_ptr->setVisualController(dptr()->m_shared);
+ dptr()->m_shared->initializeOpenGL();
+ QObject::connect(dptr()->m_shared, &Abstract3DController::selectionModeChanged, this,
+ &Q3DSurface::selectionModeChanged);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::themeChanged, this,
+ &Q3DSurface::themeChanged);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::shadowQualityChanged, this,
+ &Q3DSurface::shadowQualityChanged);
+ QObject::connect(dptr()->m_shared, &Abstract3DController::needRender, d_ptr.data(),
+ &Q3DWindowPrivate::renderLater);
}
/*!
- * Destroys the 3D surface window.
+ * Destroys the 3D surface graph.
*/
Q3DSurface::~Q3DSurface()
{
}
/*!
- * \internal
+ * Adds the \a series to the graph.
+ *
+ * \note The surface graph currently supports only a single series at a time.
*/
-void Q3DSurface::mouseDoubleClickEvent(QMouseEvent *event)
+void Q3DSurface::addSeries(QSurface3DSeries *series)
{
- d_ptr->m_shared->mouseDoubleClickEvent(event);
+ dptr()->m_shared->addSeries(series);
}
/*!
- * \internal
+ * Removes the \a series from the graph.
*/
-void Q3DSurface::touchEvent(QTouchEvent *event)
+void Q3DSurface::removeSeries(QSurface3DSeries *series)
{
- d_ptr->m_shared->touchEvent(event);
+ dptr()->m_shared->removeSeries(series);
}
/*!
- * \internal
+ * \return list of series added to this graph.
+ *
+ * \note The surface graph currently supports only a single series at a time.
*/
-void Q3DSurface::mousePressEvent(QMouseEvent *event)
+QList<QSurface3DSeries *> Q3DSurface::seriesList()
{
- d_ptr->m_shared->mousePressEvent(event, event->pos());
+ return dptr()->m_shared->surfaceSeriesList();
}
/*!
* \internal
*/
-void Q3DSurface::mouseReleaseEvent(QMouseEvent *event)
+void Q3DSurface::mouseDoubleClickEvent(QMouseEvent *event)
{
- d_ptr->m_shared->mouseReleaseEvent(event, event->pos());
+ dptr()->m_shared->mouseDoubleClickEvent(event);
}
/*!
* \internal
*/
-void Q3DSurface::mouseMoveEvent(QMouseEvent *event)
+void Q3DSurface::touchEvent(QTouchEvent *event)
{
- d_ptr->m_shared->mouseMoveEvent(event, event->pos());
+ dptr()->m_shared->touchEvent(event);
}
/*!
* \internal
*/
-void Q3DSurface::wheelEvent(QWheelEvent *event)
+void Q3DSurface::mousePressEvent(QMouseEvent *event)
{
- d_ptr->m_shared->wheelEvent(event);
+ dptr()->m_shared->mousePressEvent(event, event->pos());
}
/*!
* \internal
*/
-void Q3DSurface::resizeEvent(QResizeEvent *event)
+void Q3DSurface::mouseReleaseEvent(QMouseEvent *event)
{
- Q_UNUSED(event);
- d_ptr->m_shared->setWidth(width());
- d_ptr->m_shared->setHeight(height());
+ dptr()->m_shared->mouseReleaseEvent(event, event->pos());
}
/*!
- * \property Q3DSurface::gridVisible
- *
- * Sets grid visibility to \a visible. It is preset to \c true by default.
+ * \internal
*/
-void Q3DSurface::setGridVisible(bool visible)
+void Q3DSurface::mouseMoveEvent(QMouseEvent *event)
{
- d_ptr->m_shared->setGridEnabled(visible);
+ dptr()->m_shared->mouseMoveEvent(event, event->pos());
}
-bool Q3DSurface::isGridVisible() const
+/*!
+ * \internal
+ */
+void Q3DSurface::wheelEvent(QWheelEvent *event)
{
- return d_ptr->m_shared->gridEnabled();
+ dptr()->m_shared->wheelEvent(event);
}
-/*!
- * \property Q3DSurface::backgroundVisible
- *
- * Sets background visibility to \a visible. It is preset to \c true by default.
- */
-void Q3DSurface::setBackgroundVisible(bool visible)
+Q3DSurfacePrivate *Q3DSurface::dptr()
{
- d_ptr->m_shared->setBackgroundEnabled(visible);
+ return static_cast<Q3DSurfacePrivate *>(d_ptr.data());
}
-bool Q3DSurface::isBackgroundVisible() const
+const Q3DSurfacePrivate *Q3DSurface::dptrc() const
{
- return d_ptr->m_shared->backgroundEnabled();
+ return static_cast<const Q3DSurfacePrivate *>(d_ptr.data());
}
/*!
* \property Q3DSurface::theme
*
- * A predefined \a theme from \c QDataVis::Theme. It is preset to \c QDataVis::ThemeQt by
- * default. Theme affects label colors, text color, background color, window color and
- * grid color. Lighting is also adjusted by themes.
- *
- * \preliminary
+ * A \a theme to be used for the graph. Ownership of the \a theme is transferred. Previous theme
+ * is deleted when a new one is set. Properties of the \a theme can be modified even after setting
+ * it, and the modifications take effect immediately.
*/
-void Q3DSurface::setTheme(QDataVis::Theme theme)
+void Q3DSurface::setTheme(Q3DTheme *theme)
{
- d_ptr->m_shared->setTheme(theme);
+ dptr()->m_shared->setTheme(theme);
}
-QDataVis::Theme Q3DSurface::theme() const
+Q3DTheme *Q3DSurface::theme() const
{
- return d_ptr->m_shared->theme().theme();
+ return dptrc()->m_shared->theme();
}
/*!
@@ -231,93 +233,29 @@ QDataVis::Theme Q3DSurface::theme() const
*/
void Q3DSurface::setShadowQuality(QDataVis::ShadowQuality quality)
{
- return d_ptr->m_shared->setShadowQuality(quality);
+ return dptr()->m_shared->setShadowQuality(quality);
}
QDataVis::ShadowQuality Q3DSurface::shadowQuality() const
{
- return d_ptr->m_shared->shadowQuality();
-}
-
-/*!
- * \property Q3DSurface::smoothSurfaceEnabled
- *
- * Sets surface smoothing to \a enabled. It is preset to \c false by default.
- * When enabled the normals on the surface are interpolated making edges looking round. If turned
- * off the normals are kept same on a triangle making the color of the triangle solid. This makes
- * the data more readable from the model.
- */
-void Q3DSurface::setSmoothSurfaceEnabled(bool enabled)
-{
- d_ptr->m_shared->setSmoothSurface(enabled);
-}
-
-bool Q3DSurface::isSmoothSurfaceEnabled() const
-{
- return d_ptr->m_shared->smoothSurface();
+ return dptrc()->m_shared->shadowQuality();
}
/*!
* \property Q3DSurface::selectionMode
*
- * Sets point selection \a mode to one of \c QDataVis::SelectionMode. Surface supports SelectionModeItem,
- * SelectionModeSliceRow and SelectionModeSliceColumn. It is preset to \c QDataVis::SelectionModeItem 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.
- */
-void Q3DSurface::setSurfaceGridEnabled(bool enabled)
-{
- d_ptr->m_shared->setSurfaceGrid(enabled);
-}
-
-bool Q3DSurface::isSurfaceGridEnabled() const
-{
- return d_ptr->m_shared->surfaceGrid();
-}
-
-/*!
- * \property Q3DSurface::gradient
- *
- * The current surface gradient. Setting this property replaces the previous gradient with
- * the given \a gradient.
- */
-void Q3DSurface::setGradient(const QLinearGradient &gradient)
-{
- d_ptr->m_shared->setGradient(gradient);
-}
-
-QLinearGradient Q3DSurface::gradient() const
-{
- return d_ptr->m_shared->gradient();
-}
-
-/*!
- * \property Q3DSurface::font
- *
- * Sets the \a font for labels. It is preset to \c Arial by default.
+ * Sets point selection \a mode to a combination of \c QDataVis::SelectionFlags. Surface supports
+ * \c SelectionItem and \c SelectionSlice with either \c SelectionRow or \c SelectionColumn.
+ * It is preset to \c SelectionItem by default.
*/
-void Q3DSurface::setFont(const QFont &font)
+void Q3DSurface::setSelectionMode(QDataVis::SelectionFlags mode)
{
- d_ptr->m_shared->setFont(font);
+ dptr()->m_shared->setSelectionMode(mode);
}
-QFont Q3DSurface::font() const
+QDataVis::SelectionFlags Q3DSurface::selectionMode() const
{
- return d_ptr->m_shared->font();
+ return dptrc()->m_shared->selectionMode();
}
/*!
@@ -327,23 +265,7 @@ QFont Q3DSurface::font() const
*/
Q3DScene *Q3DSurface::scene() const
{
- return d_ptr->m_shared->scene();
-}
-
-/*!
- * \property Q3DSurface::labelStyle
- *
- * Sets label \a style to one of \c QDataVis::LabelStyle. It is preset to
- * \c QDataVis::LabelStyleFromTheme by default.
- */
-void Q3DSurface::setLabelStyle(QDataVis::LabelStyle style)
-{
- d_ptr->m_shared->setLabelStyle(style);
-}
-
-QDataVis::LabelStyle Q3DSurface::labelStyle() const
-{
- return d_ptr->m_shared->labelStyle();
+ return dptrc()->m_shared->scene();
}
/*!
@@ -358,7 +280,7 @@ QDataVis::LabelStyle Q3DSurface::labelStyle() const
*/
void Q3DSurface::setAxisX(Q3DValueAxis *axis)
{
- d_ptr->m_shared->setAxisX(axis);
+ dptr()->m_shared->setAxisX(axis);
}
/*!
@@ -366,7 +288,7 @@ void Q3DSurface::setAxisX(Q3DValueAxis *axis)
*/
Q3DValueAxis *Q3DSurface::axisX() const
{
- return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisX());
+ return static_cast<Q3DValueAxis *>(dptrc()->m_shared->axisX());
}
/*!
@@ -381,7 +303,7 @@ Q3DValueAxis *Q3DSurface::axisX() const
*/
void Q3DSurface::setAxisY(Q3DValueAxis *axis)
{
- d_ptr->m_shared->setAxisY(axis);
+ dptr()->m_shared->setAxisY(axis);
}
/*!
@@ -389,7 +311,7 @@ void Q3DSurface::setAxisY(Q3DValueAxis *axis)
*/
Q3DValueAxis *Q3DSurface::axisY() const
{
- return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisY());
+ return static_cast<Q3DValueAxis *>(dptrc()->m_shared->axisY());
}
/*!
@@ -404,7 +326,7 @@ Q3DValueAxis *Q3DSurface::axisY() const
*/
void Q3DSurface::setAxisZ(Q3DValueAxis *axis)
{
- d_ptr->m_shared->setAxisZ(axis);
+ dptr()->m_shared->setAxisZ(axis);
}
/*!
@@ -412,7 +334,7 @@ void Q3DSurface::setAxisZ(Q3DValueAxis *axis)
*/
Q3DValueAxis *Q3DSurface::axisZ() const
{
- return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisZ());
+ return static_cast<Q3DValueAxis *>(dptrc()->m_shared->axisZ());
}
/*!
@@ -424,7 +346,7 @@ Q3DValueAxis *Q3DSurface::axisZ() const
*/
void Q3DSurface::addAxis(Q3DValueAxis *axis)
{
- d_ptr->m_shared->addAxis(axis);
+ dptr()->m_shared->addAxis(axis);
}
/*!
@@ -437,7 +359,7 @@ void Q3DSurface::addAxis(Q3DValueAxis *axis)
*/
void Q3DSurface::releaseAxis(Q3DValueAxis *axis)
{
- d_ptr->m_shared->releaseAxis(axis);
+ dptr()->m_shared->releaseAxis(axis);
}
/*!
@@ -447,7 +369,7 @@ void Q3DSurface::releaseAxis(Q3DValueAxis *axis)
*/
QList<Q3DValueAxis *> Q3DSurface::axes() const
{
- QList<Q3DAbstractAxis *> abstractAxes = d_ptr->m_shared->axes();
+ QList<Q3DAbstractAxis *> abstractAxes = dptrc()->m_shared->axes();
QList<Q3DValueAxis *> retList;
foreach (Q3DAbstractAxis *axis, abstractAxes)
retList.append(static_cast<Q3DValueAxis *>(axis));
@@ -455,82 +377,10 @@ QList<Q3DValueAxis *> Q3DSurface::axes() const
return retList;
}
-/*!
- * Sets the active data \a proxy. Implicitly calls addDataProxy() to transfer ownership of
- * the \a proxy to this graph.
- *
- * If the \a proxy is null, a temporary default proxy is created and activated.
- * This temporary proxy is destroyed if another \a proxy is set explicitly active via this method.
- *
- * \sa addDataProxy(), releaseDataProxy()
- */
-void Q3DSurface::setActiveDataProxy(QSurfaceDataProxy *proxy)
-{
- d_ptr->m_shared->setActiveDataProxy(proxy);
-}
-
-/*!
- * \return active data proxy.
- */
-QSurfaceDataProxy *Q3DSurface::activeDataProxy() const
-{
- return static_cast<QSurfaceDataProxy *>(d_ptr->m_shared->activeDataProxy());
-}
-
-/*!
- * Adds data \a proxy to the graph. The proxies added via addDataProxy are not yet taken to use,
- * addDataProxy is simply used to give the ownership of the data \a proxy to the graph.
- * The \a proxy must not be null or added to another graph.
- *
- * \sa releaseDataProxy(), setActiveDataProxy()
- */
-void Q3DSurface::addDataProxy(QSurfaceDataProxy *proxy)
-{
- d_ptr->m_shared->addDataProxy(proxy);
-}
-
-/*!
- * Releases the ownership of the data \a proxy back to the caller, if it is added to this graph.
- * If the released \a proxy is in use, a new empty default proxy is created and taken to use.
- *
- * If the default \a proxy is released and added back later, it behaves as any other proxy would.
- *
- * \sa addDataProxy(), setActiveDataProxy()
- */
-void Q3DSurface::releaseDataProxy(QSurfaceDataProxy *proxy)
-{
- d_ptr->m_shared->releaseDataProxy(proxy);
-}
-
-/*!
- * \return list of all added data proxies.
- *
- * \sa addDataProxy()
- */
-QList<QSurfaceDataProxy *> Q3DSurface::dataProxies() const
-{
- QList<QSurfaceDataProxy *> retList;
- QList<QAbstractDataProxy *> abstractList = d_ptr->m_shared->dataProxies();
- foreach (QAbstractDataProxy *proxy, abstractList)
- retList.append(static_cast<QSurfaceDataProxy *>(proxy));
-
- return retList;
-}
-
-
-/*!
- * Modifies the current surface gradient. Sets gradient color to \a color at \a pos.
- */
-void Q3DSurface::setGradientColorAt(qreal pos, const QColor &color)
-{
- d_ptr->m_shared->setGradientColorAt(pos, color);
-}
-
/////////////////// PRIVATE ///////////////////////////////////
-Q3DSurfacePrivate::Q3DSurfacePrivate(Q3DSurface *q, QRect rect)
- : q_ptr(q),
- m_shared(new Surface3DController(rect))
+Q3DSurfacePrivate::Q3DSurfacePrivate(Q3DSurface *q)
+ : Q3DWindowPrivate(q)
{
}
@@ -539,4 +389,9 @@ Q3DSurfacePrivate::~Q3DSurfacePrivate()
delete m_shared;
}
+Q3DSurface *Q3DSurfacePrivate::qptr()
+{
+ return static_cast<Q3DSurface *>(q_ptr);
+}
+
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/q3dsurface.h b/src/datavisualization/engine/q3dsurface.h
index 1b572a36..bdbe65f5 100644
--- a/src/datavisualization/engine/q3dsurface.h
+++ b/src/datavisualization/engine/q3dsurface.h
@@ -23,61 +23,38 @@
#include <QtDataVisualization/q3dwindow.h>
#include <QtDataVisualization/q3dscene.h>
#include <QFont>
-#include <QLinearGradient>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class Q3DSurfacePrivate;
class Q3DValueAxis;
-class QSurfaceDataProxy;
+class QSurface3DSeries;
+class Q3DTheme;
class QT_DATAVISUALIZATION_EXPORT Q3DSurface : public Q3DWindow
{
Q_OBJECT
- Q_PROPERTY(QtDataVisualization::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode)
- Q_PROPERTY(QtDataVisualization::QDataVis::LabelStyle labelStyle READ labelStyle WRITE setLabelStyle)
- Q_PROPERTY(QtDataVisualization::QDataVis::Theme theme READ theme WRITE setTheme)
- Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality)
- Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible)
- Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible)
- Q_PROPERTY(bool smoothSurfaceEnabled READ isSmoothSurfaceEnabled WRITE setSmoothSurfaceEnabled)
- Q_PROPERTY(bool surfaceGridEnabled READ isSurfaceGridEnabled WRITE setSurfaceGridEnabled)
- Q_PROPERTY(QLinearGradient gradient READ gradient WRITE setGradient)
- Q_PROPERTY(QFont font READ font WRITE setFont)
+ Q_PROPERTY(QtDataVisualization::QDataVis::SelectionFlags selectionMode READ selectionMode WRITE setSelectionMode NOTIFY selectionModeChanged)
+ Q_PROPERTY(Q3DTheme* theme READ theme WRITE setTheme NOTIFY themeChanged)
+ Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality NOTIFY shadowQualityChanged)
Q_PROPERTY(Q3DScene* scene READ scene)
- Q_ENUMS(QtDataVisualization::QDataVis::SelectionMode)
- Q_ENUMS(QtDataVisualization::QDataVis::ShadowQuality)
- Q_ENUMS(QtDataVisualization::QDataVis::LabelStyle)
- Q_ENUMS(QtDataVisualization::QDataVis::CameraPreset)
public:
- explicit Q3DSurface();
- ~Q3DSurface();
+ explicit Q3DSurface(QWindow *parent = 0);
+ virtual ~Q3DSurface();
- void setGridVisible(bool visible);
- bool isGridVisible() const;
+ void addSeries(QSurface3DSeries *series);
+ void removeSeries(QSurface3DSeries *series);
+ QList<QSurface3DSeries *> seriesList();
- void setBackgroundVisible(bool visible);
- bool isBackgroundVisible() const;
-
- void setTheme(QDataVis::Theme theme);
- QDataVis::Theme theme() const;
+ void setTheme(Q3DTheme *theme);
+ Q3DTheme *theme() const;
void setShadowQuality(QDataVis::ShadowQuality quality);
QDataVis::ShadowQuality shadowQuality() const;
- void setSmoothSurfaceEnabled(bool enabled);
- bool isSmoothSurfaceEnabled() const;
-
- void setSelectionMode(QDataVis::SelectionMode mode);
- QDataVis::SelectionMode selectionMode() const;
- void setSurfaceGridEnabled(bool enabled);
- bool isSurfaceGridEnabled() const;
-
- void setGradient(const QLinearGradient &gradient);
- QLinearGradient gradient() const;
-
- void setGradientColorAt(qreal pos, const QColor &color);
+ void setSelectionMode(QDataVis::SelectionFlags mode);
+ QDataVis::SelectionFlags selectionMode() const;
// Axes
void setAxisX(Q3DValueAxis *axis);
@@ -90,19 +67,12 @@ public:
void releaseAxis(Q3DValueAxis *axis);
QList<Q3DValueAxis *> axes() const;
- void setActiveDataProxy(QSurfaceDataProxy *proxy);
- QSurfaceDataProxy *activeDataProxy() const;
- void addDataProxy(QSurfaceDataProxy *proxy);
- void releaseDataProxy(QSurfaceDataProxy *proxy);
- QList<QSurfaceDataProxy *> dataProxies() const;
-
- void setFont(const QFont &font);
- QFont font() const;
-
Q3DScene *scene() const;
- void setLabelStyle(QDataVis::LabelStyle style);
- QDataVis::LabelStyle labelStyle() const;
+signals:
+ void selectionModeChanged(QDataVis::SelectionFlags mode);
+ void themeChanged(Q3DTheme *theme);
+ void shadowQualityChanged(QDataVis::ShadowQuality quality);
protected:
void mouseDoubleClickEvent(QMouseEvent *event);
@@ -111,10 +81,10 @@ protected:
void mouseReleaseEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
- void resizeEvent(QResizeEvent *event);
private:
- QScopedPointer<Q3DSurfacePrivate> d_ptr;
+ Q3DSurfacePrivate *dptr();
+ const Q3DSurfacePrivate *dptrc() const;
Q_DISABLE_COPY(Q3DSurface)
};
diff --git a/src/datavisualization/engine/q3dsurface_p.h b/src/datavisualization/engine/q3dsurface_p.h
index 7c70d08c..de2a518c 100644
--- a/src/datavisualization/engine/q3dsurface_p.h
+++ b/src/datavisualization/engine/q3dsurface_p.h
@@ -31,6 +31,7 @@
#include "surface3dcontroller_p.h"
#include "qdatavisualizationenums.h"
+#include "q3dwindow_p.h"
#include <QList>
@@ -38,13 +39,15 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class Q3DSurface;
-class Q3DSurfacePrivate : public QObject
+class Q3DSurfacePrivate : public Q3DWindowPrivate
{
+ Q_OBJECT
public:
- Q3DSurfacePrivate(Q3DSurface *q, QRect rect);
+ Q3DSurfacePrivate(Q3DSurface *q);
~Q3DSurfacePrivate();
- Q3DSurface *q_ptr;
+ Q3DSurface *qptr();
+
Surface3DController *m_shared;
};
diff --git a/src/datavisualization/engine/q3dwindow.cpp b/src/datavisualization/engine/q3dwindow.cpp
index 2c0729ba..5285b585 100644
--- a/src/datavisualization/engine/q3dwindow.cpp
+++ b/src/datavisualization/engine/q3dwindow.cpp
@@ -19,13 +19,14 @@
#include "q3dwindow.h"
#include "q3dwindow_p.h"
#include "abstract3dcontroller_p.h"
-#include <QGuiApplication>
+#include "qabstract3dinputhandler_p.h"
+#include "q3dscene_p.h"
+#include <QGuiApplication>
#include <QOpenGLContext>
#include <QOpenGLPaintDevice>
#include <QPainter>
-#include <QDebug>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -36,19 +37,31 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* \since Qt Data Visualization 1.0
*
* This class creates a QWindow and provides render loop for visualization types inheriting it.
- * \warning This class is not intended to be used directly by developers.
+ *
+ * You should not need to use this class directly, but one of its subclasses instead.
+ *
+ * \note Q3DWindow sets window flag \c{Qt::FramelessWindowHint} on by default. If you want to display
+ * graph windows as standalone windows with regular window frame, clear this flag after constructing
+ * the graph. For example:
+ *
+ * \code
+ * Q3DBars *graphWindow = new Q3DBars;
+ * graphWindow->setFlags(graphWindow->flags() ^ Qt::FramelessWindowHint);
+ * \endcode
*
* \sa Q3DBars, Q3DScatter, Q3DSurface, {Qt Data Visualization C++ Classes}
*/
/*!
- * Constructs Q3DWindow with \a parent. It creates a QWindow and an OpenGL context. It also sets
- * surface format and initializes OpenGL functions for use.
+ * \internal
*/
-Q3DWindow::Q3DWindow(QWindow *parent)
+Q3DWindow::Q3DWindow(Q3DWindowPrivate *d, QWindow *parent)
: QWindow(parent),
- d_ptr(new Q3DWindowPrivate(this))
+ d_ptr(d)
{
+ d_ptr->m_context = new QOpenGLContext(this);
+
+ setFlags(flags() | Qt::FramelessWindowHint);
setSurfaceType(QWindow::OpenGLSurface);
QSurfaceFormat surfaceFormat;
surfaceFormat.setDepthBufferSize(24);
@@ -67,7 +80,6 @@ Q3DWindow::Q3DWindow(QWindow *parent)
d_ptr->m_context->create();
d_ptr->m_context->makeCurrent(this);
- qDebug() << "initializeOpenGLFunctions()";
initializeOpenGLFunctions();
const GLubyte *version = glGetString(GL_VERSION);
@@ -80,7 +92,7 @@ Q3DWindow::Q3DWindow(QWindow *parent)
if (splitversionstr[0].toFloat() < 1.2)
qFatal("GLSL version must be 1.20 or higher. Try installing latest display drivers.");
#endif
- renderLater();
+ d_ptr->renderLater();
}
/*!
@@ -91,46 +103,49 @@ Q3DWindow::~Q3DWindow()
}
/*!
- * \internal
+ * Adds the given \a inputHandler to the graph. The input handlers added via addInputHandler
+ * are not taken in to use directly. Only the ownership of the a\ inputHandler is given to the graph.
+ * The \a inputHandler must not be null or already added to another graph.
+ *
+ * \sa releaseInputHandler(), setActiveInputHandler()
*/
-void Q3DWindow::setVisualController(Abstract3DController *controller)
+void Q3DWindow::addInputHandler(QAbstract3DInputHandler *inputHandler)
{
- d_ptr->m_visualController = controller;
+ d_ptr->m_visualController->addInputHandler(inputHandler);
}
/*!
- * \internal
+ * Releases the ownership of the \a inputHandler back to the caller, if it was added to this graph.
+ * If the released \a inputHandler is in use there will be no input handler active after this call.
+ *
+ * If the default input handler is released and added back later, it behaves as any other input handler would.
+ *
+ * \sa addInputHandler(), setActiveInputHandler()
*/
-void Q3DWindow::handleDevicePixelRatioChange()
+void Q3DWindow::releaseInputHandler(QAbstract3DInputHandler *inputHandler)
{
- if (QWindow::devicePixelRatio() == d_ptr->m_devicePixelRatio || !d_ptr->m_visualController)
- return;
-
- // Device pixel ratio changed, resize accordingly and inform the scene
- d_ptr->m_devicePixelRatio = QWindow::devicePixelRatio();
- d_ptr->m_visualController->updateDevicePixelRatio(d_ptr->m_devicePixelRatio);
-
+ d_ptr->m_visualController->releaseInputHandler(inputHandler);
}
/*!
- * \internal
+ * Sets the active \a inputHandler. Implicitly calls addInputHandler() to transfer ownership of
+ * the \a inputHandler to this graph.
+ *
+ * If the \a inputHandler is null, no input handler will be active after this call.
+ *
+ * \sa addInputHandler(), releaseInputHandler()
*/
-void Q3DWindow::render()
+void Q3DWindow::setActiveInputHandler(QAbstract3DInputHandler *inputHandler)
{
- handleDevicePixelRatioChange();
- d_ptr->m_visualController->synchDataToRenderer();
- d_ptr->m_visualController->render();
+ d_ptr->m_visualController->setActiveInputHandler(inputHandler);
}
/*!
- * \internal
+ * \return currently active input handler.
*/
-void Q3DWindow::renderLater()
+QAbstract3DInputHandler *Q3DWindow::activeInputHandler()
{
- if (!d_ptr->m_updatePending) {
- d_ptr->m_updatePending = true;
- QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
- }
+ return d_ptr->m_visualController->activeInputHandler();
}
/*!
@@ -140,7 +155,7 @@ bool Q3DWindow::event(QEvent *event)
{
switch (event->type()) {
case QEvent::UpdateRequest:
- renderNow();
+ d_ptr->renderNow();
return true;
case QEvent::TouchBegin:
case QEvent::TouchCancel:
@@ -156,35 +171,30 @@ bool Q3DWindow::event(QEvent *event)
/*!
* \internal
*/
-void Q3DWindow::exposeEvent(QExposeEvent *event)
+void Q3DWindow::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
- if (isExposed())
- renderNow();
+ Q3DScene *scene = d_ptr->m_visualController->scene();
+ scene->d_ptr->setWindowSize(QSize(width(), height()));
+ scene->d_ptr->setViewport(QRect(0, 0, width(), height()));
}
/*!
* \internal
*/
-void Q3DWindow::renderNow()
+void Q3DWindow::exposeEvent(QExposeEvent *event)
{
- if (!isExposed())
- return;
-
- d_ptr->m_updatePending = false;
-
- d_ptr->m_context->makeCurrent(this);
-
- render();
+ Q_UNUSED(event);
- d_ptr->m_context->swapBuffers(this);
+ if (isExposed())
+ d_ptr->renderNow();
}
Q3DWindowPrivate::Q3DWindowPrivate(Q3DWindow *q)
- : q_ptr(q),
+ : QObject(0),
+ q_ptr(q),
m_updatePending(false),
- m_context(new QOpenGLContext(q)),
m_visualController(0),
m_devicePixelRatio(1.f)
{
@@ -194,4 +204,47 @@ Q3DWindowPrivate::~Q3DWindowPrivate()
{
}
+void Q3DWindowPrivate::render()
+{
+ handleDevicePixelRatioChange();
+ m_visualController->synchDataToRenderer();
+ m_visualController->render();
+}
+
+void Q3DWindowPrivate::renderLater()
+{
+ if (!m_updatePending) {
+ m_updatePending = true;
+ QCoreApplication::postEvent(q_ptr, new QEvent(QEvent::UpdateRequest));
+ }
+}
+
+void Q3DWindowPrivate::renderNow()
+{
+ if (!q_ptr->isExposed())
+ return;
+
+ m_updatePending = false;
+
+ m_context->makeCurrent(q_ptr);
+
+ render();
+
+ m_context->swapBuffers(q_ptr);
+}
+
+void Q3DWindowPrivate::setVisualController(Abstract3DController *controller)
+{
+ m_visualController = controller;
+}
+
+void Q3DWindowPrivate::handleDevicePixelRatioChange()
+{
+ if (q_ptr->devicePixelRatio() == m_devicePixelRatio || !m_visualController)
+ return;
+
+ m_devicePixelRatio = q_ptr->devicePixelRatio();
+ m_visualController->scene()->setDevicePixelRatio(m_devicePixelRatio);
+}
+
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/q3dwindow.h b/src/datavisualization/engine/q3dwindow.h
index 1848ff29..cdffc6b9 100644
--- a/src/datavisualization/engine/q3dwindow.h
+++ b/src/datavisualization/engine/q3dwindow.h
@@ -31,26 +31,26 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class Q3DWindowPrivate;
class Abstract3DController;
+class QAbstract3DInputHandler;
class QT_DATAVISUALIZATION_EXPORT Q3DWindow : public QWindow, protected QOpenGLFunctions
{
Q_OBJECT
+protected:
+ explicit Q3DWindow(Q3DWindowPrivate *d, QWindow *parent = 0);
public:
- explicit Q3DWindow(QWindow *parent = 0);
virtual ~Q3DWindow();
-protected slots:
- void renderLater();
- void renderNow();
+ void addInputHandler(QAbstract3DInputHandler *inputHandler);
+ void releaseInputHandler(QAbstract3DInputHandler *inputHandler);
+ void setActiveInputHandler(QAbstract3DInputHandler *inputHandler);
+ QAbstract3DInputHandler *activeInputHandler();
protected:
- virtual void render();
-
bool event(QEvent *event);
+ void resizeEvent(QResizeEvent *event);
void exposeEvent(QExposeEvent *event);
- void setVisualController(Abstract3DController *controller);
- void handleDevicePixelRatioChange();
private:
QScopedPointer<Q3DWindowPrivate> d_ptr;
diff --git a/src/datavisualization/engine/q3dwindow_p.h b/src/datavisualization/engine/q3dwindow_p.h
index 6bef7e10..ba8c67da 100644
--- a/src/datavisualization/engine/q3dwindow_p.h
+++ b/src/datavisualization/engine/q3dwindow_p.h
@@ -26,11 +26,13 @@
//
// We mean it.
-#ifndef Q3DWINDOW_p_H
-#define Q3DWINDOW_p_H
+#ifndef Q3DWINDOW_P_H
+#define Q3DWINDOW_P_H
#include "datavisualizationglobal_p.h"
+#include <QObject>
+
class QOpenGLContext;
class QOpenGLPaintDevice;
@@ -39,19 +41,29 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class Q3DWindow;
class Abstract3DController;
-class Q3DWindowPrivate
+class Q3DWindowPrivate : public QObject
{
+ Q_OBJECT
public:
Q3DWindowPrivate(Q3DWindow *q);
~Q3DWindowPrivate();
+ void render();
+
+ void setVisualController(Abstract3DController *controller);
+ void handleDevicePixelRatioChange();
+
+public slots:
+ void renderLater();
+ void renderNow();
+
public:
Q3DWindow *q_ptr;
bool m_updatePending;
QOpenGLContext *m_context;
Abstract3DController *m_visualController;
- qreal m_devicePixelRatio;
+ float m_devicePixelRatio;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/scatter3dcontroller.cpp b/src/datavisualization/engine/scatter3dcontroller.cpp
index 9f43d94e..0a506f19 100644
--- a/src/datavisualization/engine/scatter3dcontroller.cpp
+++ b/src/datavisualization/engine/scatter3dcontroller.cpp
@@ -22,6 +22,7 @@
#include "q3dabstractaxis_p.h"
#include "q3dvalueaxis_p.h"
#include "qscatterdataproxy_p.h"
+#include "qscatter3dseries_p.h"
#include <QMatrix4x4>
#include <qmath.h>
@@ -31,13 +32,9 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
Scatter3DController::Scatter3DController(QRect boundRect)
: Abstract3DController(boundRect),
m_renderer(0),
- m_selectedItemIndex(noSelectionIndex())
+ m_selectedItem(invalidSelectionIndex()),
+ m_selectedItemSeries(0)
{
- // Default object type; specific to scatter
- setObjectType(QDataVis::MeshStyleSpheres, false);
-
- setActiveDataProxy(new QScatterDataProxy);
-
// Setting a null axis creates a new default axis according to orientation and graph type.
// Note: These cannot be set in Abstract3DController constructor, as they will call virtual
// functions implemented by subclasses.
@@ -60,8 +57,8 @@ void Scatter3DController::initializeOpenGL()
setRenderer(m_renderer);
synchDataToRenderer();
- QObject::connect(m_renderer, &Scatter3DRenderer::selectedItemIndexChanged, this,
- &Scatter3DController::handleSelectedItemIndexChanged, Qt::QueuedConnection);
+ QObject::connect(m_renderer, &Scatter3DRenderer::itemClicked, this,
+ &Scatter3DController::handleItemClicked, Qt::QueuedConnection);
emitNeedRender();
}
@@ -73,61 +70,59 @@ void Scatter3DController::synchDataToRenderer()
return;
// Notify changes to renderer
- if (m_changeTracker.slicingActiveChanged) {
- // TODO: Add notification.
- m_changeTracker.slicingActiveChanged = false;
+ if (m_changeTracker.selectedItemChanged) {
+ m_renderer->updateSelectedItem(m_selectedItem, m_selectedItemSeries);
+ m_changeTracker.selectedItemChanged = false;
}
+}
- if (m_changeTracker.selectedItemIndexChanged) {
- m_renderer->updateSelectedItemIndex(m_selectedItemIndex);
- m_changeTracker.selectedItemIndexChanged = false;
- }
+void Scatter3DController::addSeries(QAbstract3DSeries *series)
+{
+ Q_ASSERT(series && series->type() == QAbstract3DSeries::SeriesTypeScatter);
- if (m_isDataDirty) {
- m_renderer->updateDataModel(static_cast<QScatterDataProxy *>(m_data));
- m_isDataDirty = false;
- }
-}
+ bool firstAdded = !m_seriesList.size();
+
+ Abstract3DController::addSeries(series);
+ if (firstAdded)
+ adjustValueAxisRange();
+
+ QScatter3DSeries *scatterSeries = static_cast<QScatter3DSeries *>(series);
+ if (scatterSeries->selectedItem() != invalidSelectionIndex())
+ setSelectedItem(scatterSeries->selectedItem(), scatterSeries);
+}
-void Scatter3DController::setActiveDataProxy(QAbstractDataProxy *proxy)
+void Scatter3DController::removeSeries(QAbstract3DSeries *series)
{
- // Setting null proxy indicates default proxy
- if (!proxy) {
- proxy = new QScatterDataProxy;
- proxy->d_ptr->setDefaultProxy(true);
- }
+ bool firstRemoved = (m_seriesList.size() && m_seriesList.at(0) == series);
- Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeScatter);
+ Abstract3DController::removeSeries(series);
- Abstract3DController::setActiveDataProxy(proxy);
+ if (m_selectedItemSeries == series)
+ setSelectedItem(invalidSelectionIndex(), 0);
- QScatterDataProxy *scatterDataProxy = static_cast<QScatterDataProxy *>(m_data);
+ if (firstRemoved)
+ adjustValueAxisRange();
+}
- QObject::connect(scatterDataProxy, &QScatterDataProxy::arrayReset,
- this, &Scatter3DController::handleArrayReset);
- QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsAdded,
- this, &Scatter3DController::handleItemsAdded);
- QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsChanged,
- this, &Scatter3DController::handleItemsChanged);
- QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsRemoved,
- this, &Scatter3DController::handleItemsRemoved);
- QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsInserted,
- this, &Scatter3DController::handleItemsInserted);
+QList<QScatter3DSeries *> Scatter3DController::scatterSeriesList()
+{
+ QList<QAbstract3DSeries *> abstractSeriesList = seriesList();
+ QList<QScatter3DSeries *> scatterSeriesList;
+ foreach (QAbstract3DSeries *abstractSeries, abstractSeriesList) {
+ QScatter3DSeries *scatterSeries = qobject_cast<QScatter3DSeries *>(abstractSeries);
+ if (scatterSeries)
+ scatterSeriesList.append(scatterSeries);
+ }
- adjustValueAxisRange();
- setSelectedItemIndex(noSelectionIndex());
- setSlicingActive(false);
- m_isDataDirty = true;
- emitNeedRender();
+ return scatterSeriesList;
}
void Scatter3DController::handleArrayReset()
{
- setSlicingActive(false);
adjustValueAxisRange();
m_isDataDirty = true;
- setSelectedItemIndex(noSelectionIndex());
+ setSelectedItem(m_selectedItem, m_selectedItemSeries);
emitNeedRender();
}
@@ -158,8 +153,10 @@ void Scatter3DController::handleItemsRemoved(int startIndex, int count)
// TODO should dirty only affected values?
adjustValueAxisRange();
m_isDataDirty = true;
- if (startIndex >= static_cast<QScatterDataProxy *>(m_data)->itemCount())
- setSelectedItemIndex(noSelectionIndex());
+
+ // Clear selection unless it is still valid
+ setSelectedItem(m_selectedItem, m_selectedItemSeries);
+
emitNeedRender();
}
@@ -173,13 +170,12 @@ void Scatter3DController::handleItemsInserted(int startIndex, int count)
emitNeedRender();
}
-void Scatter3DController::handleSelectedItemIndexChanged(int index)
+void Scatter3DController::handleItemClicked(int index, QScatter3DSeries *series)
{
- if (index != m_selectedItemIndex) {
- m_selectedItemIndex = index;
- emit selectedItemIndexChanged(index);
- emitNeedRender();
- }
+ setSelectedItem(index, series);
+
+ // TODO: pass clicked to parent. (QTRD-2517)
+ // TODO: Also hover needed? (QTRD-2131)
}
void Scatter3DController::handleAxisAutoAdjustRangeChangedInOrientation(
@@ -190,80 +186,163 @@ void Scatter3DController::handleAxisAutoAdjustRangeChangedInOrientation(
adjustValueAxisRange();
}
-void Scatter3DController::setObjectType(QDataVis::MeshStyle style, bool smooth)
+void Scatter3DController::handleAxisRangeChangedBySender(QObject *sender)
{
- QString objFile;
- if (style == QDataVis::MeshStyleSpheres) {
- if (smooth)
- objFile = QStringLiteral(":/defaultMeshes/sphereSmooth");
- else
- objFile = QStringLiteral(":/defaultMeshes/sphere");
- } else {
- if (smooth)
- objFile = QStringLiteral(":/defaultMeshes/dotSmooth");
- else
- objFile = QStringLiteral(":/defaultMeshes/dot");
- }
- Abstract3DController::setMeshFileName(objFile);
+ Abstract3DController::handleAxisRangeChangedBySender(sender);
+
+ // Update selected index - may be moved offscreen
+ setSelectedItem(m_selectedItem, m_selectedItemSeries);
}
-void Scatter3DController::setSelectionMode(QDataVis::SelectionMode mode)
+void Scatter3DController::setSelectionMode(QDataVis::SelectionFlags mode)
{
- if (mode > QDataVis::SelectionModeItem) {
- qWarning("Unsupported selection mode.");
+ // We only support single item selection mode and no selection mode
+ if (mode != QDataVis::SelectionItem && mode != QDataVis::SelectionNone) {
+ qWarning("Unsupported selection mode - only none and item selection modes are supported.");
return;
}
- // Disable zoom if selection mode changes
- setSlicingActive(false);
+
Abstract3DController::setSelectionMode(mode);
}
-void Scatter3DController::setSelectedItemIndex(int index)
+void Scatter3DController::setSelectedItem(int index, QScatter3DSeries *series)
{
- // TODO If items not within axis ranges are culled from drawing, should they be
- // TODO unselectable as well?
- if (index < 0 || index >= static_cast<QScatterDataProxy *>(m_data)->itemCount())
- index = noSelectionIndex();
-
- if (index != m_selectedItemIndex) {
- m_selectedItemIndex = index;
- m_changeTracker.selectedItemIndexChanged = true;
- emit selectedItemIndexChanged(index);
+ const QScatterDataProxy *proxy = 0;
+
+ // Series may already have been removed, so check it before setting the selection.
+ if (!m_seriesList.contains(series))
+ series = 0;
+
+ if (series)
+ proxy = series->dataProxy();
+
+ if (!proxy || index < 0 || index >= proxy->itemCount())
+ index = invalidSelectionIndex();
+
+ if (index != m_selectedItem || series != m_selectedItemSeries) {
+ m_selectedItem = index;
+ m_selectedItemSeries = series;
+ m_changeTracker.selectedItemChanged = true;
+
+ // Clear selection from other series and finally set new selection to the specified series
+ foreach (QAbstract3DSeries *otherSeries, m_seriesList) {
+ QScatter3DSeries *scatterSeries = static_cast<QScatter3DSeries *>(otherSeries);
+ if (scatterSeries != m_selectedItemSeries)
+ scatterSeries->dptr()->setSelectedItem(invalidSelectionIndex());
+ }
+ if (m_selectedItemSeries)
+ m_selectedItemSeries->dptr()->setSelectedItem(m_selectedItem);
+
emitNeedRender();
}
}
-int Scatter3DController::selectedItemIndex() const
-{
- return m_selectedItemIndex;
-}
-
void Scatter3DController::adjustValueAxisRange()
{
- if (m_data) {
- QVector3D limits = static_cast<QScatterDataProxy *>(m_data)->dptr()->limitValues();
- Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(m_axisX);
- if (valueAxis && valueAxis->isAutoAdjustRange()) {
- if (limits.x() > 0)
- valueAxis->dptr()->setRange(-limits.x(), limits.x());
- else
- valueAxis->dptr()->setRange(-1.0, 1.0); // Only zero value values in data set, set range to default.
+ Q3DValueAxis *valueAxisX = static_cast<Q3DValueAxis *>(m_axisX);
+ Q3DValueAxis *valueAxisY = static_cast<Q3DValueAxis *>(m_axisY);
+ Q3DValueAxis *valueAxisZ = static_cast<Q3DValueAxis *>(m_axisZ);
+ bool adjustX = (valueAxisX && valueAxisX->isAutoAdjustRange());
+ bool adjustY = (valueAxisY && valueAxisY->isAutoAdjustRange());
+ bool adjustZ = (valueAxisZ && valueAxisZ->isAutoAdjustRange());
+
+ if (adjustX || adjustY || adjustZ) {
+ float minValueX = 0.0f;
+ float maxValueX = 0.0f;
+ float minValueY = 0.0f;
+ float maxValueY = 0.0f;
+ float minValueZ = 0.0f;
+ float maxValueZ = 0.0f;
+ int seriesCount = m_seriesList.size();
+ for (int series = 0; series < seriesCount; series++) {
+ const QScatter3DSeries *scatterSeries =
+ static_cast<QScatter3DSeries *>(m_seriesList.at(series));
+ const QScatterDataProxy *proxy = scatterSeries->dataProxy();
+ if (scatterSeries->isVisible() && proxy) {
+ QVector3D minLimits;
+ QVector3D maxLimits;
+ proxy->dptrc()->limitValues(minLimits, maxLimits);
+ if (adjustX) {
+ if (!series) {
+ // First series initializes the values
+ minValueX = minLimits.x();
+ maxValueX = maxLimits.x();
+ } else {
+ minValueX = qMin(minValueX, minLimits.x());
+ maxValueX = qMax(maxValueX, maxLimits.x());
+ }
+ }
+ if (adjustY) {
+ if (!series) {
+ // First series initializes the values
+ minValueY = minLimits.y();
+ maxValueY = maxLimits.y();
+ } else {
+ minValueY = qMin(minValueY, minLimits.y());
+ maxValueY = qMax(maxValueY, maxLimits.y());
+ }
+ }
+ if (adjustZ) {
+ if (!series) {
+ // First series initializes the values
+ minValueZ = minLimits.z();
+ maxValueZ = maxLimits.z();
+ } else {
+ minValueZ = qMin(minValueZ, minLimits.z());
+ maxValueZ = qMax(maxValueZ, maxLimits.z());
+ }
+ }
+ }
}
- valueAxis = static_cast<Q3DValueAxis *>(m_axisY);
- if (valueAxis && valueAxis->isAutoAdjustRange()) {
- if (limits.y() > 0)
- valueAxis->dptr()->setRange(-limits.y(), limits.y());
- else
- valueAxis->dptr()->setRange(-1.0, 1.0); // Only zero value values in data set, set range to default.
+ static const float adjustmentRatio = 20.0f;
+ static const float defaultAdjustment = 1.0f;
+
+ if (adjustX) {
+ // If all points at same coordinate, need to default to some valid range
+ float adjustment = 0.0f;
+ if (minValueX == maxValueX) {
+ if (adjustZ) {
+ // X and Z are linked to have similar unit size, so choose the valid range based on it
+ if (minValueZ == maxValueZ)
+ adjustment = defaultAdjustment;
+ else
+ adjustment = qAbs(maxValueZ - minValueZ) / adjustmentRatio;
+ } else {
+ if (valueAxisZ)
+ adjustment = qAbs(valueAxisZ->max() - valueAxisZ->min()) / adjustmentRatio;
+ else
+ adjustment = defaultAdjustment;
+ }
+ }
+ valueAxisX->dptr()->setRange(minValueX - adjustment, maxValueX + adjustment);
}
-
- valueAxis = static_cast<Q3DValueAxis *>(m_axisZ);
- if (valueAxis && valueAxis->isAutoAdjustRange()) {
- if (limits.z() > 0)
- valueAxis->dptr()->setRange(-limits.z(), limits.z());
- else
- valueAxis->dptr()->setRange(-1.0, 1.0); // Only zero value values in data set, set range to default.
+ if (adjustY) {
+ // If all points at same coordinate, need to default to some valid range
+ // Y-axis unit is not dependent on other axes, so simply adjust +-1.0f
+ float adjustment = 0.0f;
+ if (minValueY == maxValueY)
+ adjustment = defaultAdjustment;
+ valueAxisY->dptr()->setRange(minValueY - adjustment, maxValueY + adjustment);
+ }
+ if (adjustZ) {
+ // If all points at same coordinate, need to default to some valid range
+ float adjustment = 0.0f;
+ if (minValueZ == maxValueZ) {
+ if (adjustX) {
+ // X and Z are linked to have similar unit size, so choose the valid range based on it
+ if (minValueX == maxValueX)
+ adjustment = defaultAdjustment;
+ else
+ adjustment = qAbs(maxValueX - minValueX) / adjustmentRatio;
+ } else {
+ if (valueAxisX)
+ adjustment = qAbs(valueAxisX->max() - valueAxisX->min()) / adjustmentRatio;
+ else
+ adjustment = defaultAdjustment;
+ }
+ }
+ valueAxisZ->dptr()->setRange(minValueZ - adjustment, maxValueZ + adjustment);
}
}
}
diff --git a/src/datavisualization/engine/scatter3dcontroller_p.h b/src/datavisualization/engine/scatter3dcontroller_p.h
index 63735aca..00c87d4f 100644
--- a/src/datavisualization/engine/scatter3dcontroller_p.h
+++ b/src/datavisualization/engine/scatter3dcontroller_p.h
@@ -38,14 +38,13 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class Scatter3DRenderer;
class QScatterDataProxy;
+class QScatter3DSeries;
struct Scatter3DChangeBitField {
- bool slicingActiveChanged : 1;
- bool selectedItemIndexChanged : 1;
+ bool selectedItemChanged : 1;
Scatter3DChangeBitField() :
- slicingActiveChanged(true),
- selectedItemIndexChanged(true)
+ selectedItemChanged(true)
{
}
};
@@ -59,29 +58,30 @@ private:
// Rendering
Scatter3DRenderer *m_renderer;
- int m_selectedItemIndex;
+ int m_selectedItem;
+ QScatter3DSeries *m_selectedItemSeries; // Points to the series for which the bar is selected
+ // in single series selection cases.
public:
explicit Scatter3DController(QRect rect);
~Scatter3DController();
- void initializeOpenGL();
-
- // Object type
- void setObjectType(QDataVis::MeshStyle style, bool smooth = false);
+ virtual void initializeOpenGL();
// Change selection mode
- void setSelectionMode(QDataVis::SelectionMode mode);
-
- void setSelectedItemIndex(int index);
- int selectedItemIndex() const;
- static inline int noSelectionIndex() { return -1; }
+ void setSelectionMode(QDataVis::SelectionFlags mode);
- virtual void setActiveDataProxy(QAbstractDataProxy *proxy);
+ void setSelectedItem(int index, QScatter3DSeries *series);
+ static inline int invalidSelectionIndex() { return -1; }
void synchDataToRenderer();
+ virtual void addSeries(QAbstract3DSeries *series);
+ virtual void removeSeries(QAbstract3DSeries *series);
+ virtual QList<QScatter3DSeries *> scatterSeriesList();
+
virtual void handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust);
+ virtual void handleAxisRangeChangedBySender(QObject *sender);
public slots:
void handleArrayReset();
@@ -89,10 +89,9 @@ public slots:
void handleItemsChanged(int startIndex, int count);
void handleItemsRemoved(int startIndex, int count);
void handleItemsInserted(int startIndex, int count);
- void handleSelectedItemIndexChanged(int index);
-signals:
- void selectedItemIndexChanged(int index);
+ // Renderer callback handlers
+ void handleItemClicked(int index, QScatter3DSeries *series);
private:
void adjustValueAxisRange();
diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp
index a457b545..00452cf7 100644
--- a/src/datavisualization/engine/scatter3drenderer.cpp
+++ b/src/datavisualization/engine/scatter3drenderer.cpp
@@ -25,6 +25,7 @@
#include "texturehelper_p.h"
#include "utils_p.h"
#include "q3dlight.h"
+#include "qscatter3dseries_p.h"
#include <QMatrix4x4>
#include <QMouseEvent>
@@ -46,25 +47,28 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
const GLfloat aspectRatio = 2.0f; // Forced ratio of x and z to y. Dynamic will make it look odd.
const GLfloat labelMargin = 0.05f;
-// TODO: Make margin modifiable?
-const GLfloat backgroundMargin = 1.1f; // Margin for background (1.1f = make it 10% larger to avoid items being drawn inside background)
+const GLfloat defaultMinSize = 0.01f;
+const GLfloat defaultMaxSize = 0.1f;
+const GLfloat defaultMargin = 1.0f + defaultMaxSize; // Default margin for background
+const GLfloat itemScaler = 3.0f;
const GLfloat gridLineWidth = 0.005f;
-static QVector3D selectionSkipColor = QVector3D(255, 255, 255); // Selection texture's background color
Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller)
: Abstract3DRenderer(controller),
- m_controller(controller),
m_selectedItem(0),
m_xFlipped(false),
m_zFlipped(false),
m_yFlipped(false),
m_updateLabels(false),
m_dotShader(0),
+ m_dotGradientShader(0),
+ #if defined(QT_OPENGL_ES_2)
+ m_pointShader(0),
+ #endif
m_depthShader(0),
m_selectionShader(0),
m_backgroundShader(0),
m_labelShader(0),
- m_dotObj(0),
m_backgroundObj(0),
m_gridLineObj(0),
m_labelObj(0),
@@ -78,11 +82,15 @@ Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller)
m_shadowQualityMultiplier(3),
m_heightNormalizer(1.0f),
m_scaleFactor(0),
- m_selection(selectionSkipColor),
- m_previousSelection(selectionSkipColor),
+ m_selectedItemIndex(Scatter3DController::invalidSelectionIndex()),
+ m_selectedItemTotalIndex(Scatter3DController::invalidSelectionIndex()),
+ m_selectedItemSeriesIndex(Scatter3DController::invalidSelectionIndex()),
+ m_selectedSeries(0),
m_areaSize(QSizeF(0.0, 0.0)),
m_dotSizeScale(1.0f),
- m_hasHeightAdjustmentChanged(true)
+ m_hasHeightAdjustmentChanged(true),
+ m_backgroundMargin(defaultMargin),
+ m_maxItemSize(0.0f)
{
initializeOpenGLFunctions();
initializeOpenGL();
@@ -96,11 +104,11 @@ Scatter3DRenderer::~Scatter3DRenderer()
m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer);
m_textureHelper->deleteTexture(&m_bgrTexture);
delete m_dotShader;
+ delete m_dotGradientShader;
delete m_depthShader;
delete m_selectionShader;
delete m_backgroundShader;
delete m_labelShader;
- delete m_dotObj;
delete m_backgroundObj;
delete m_gridLineObj;
delete m_labelObj;
@@ -111,14 +119,15 @@ void Scatter3DRenderer::initializeOpenGL()
Abstract3DRenderer::initializeOpenGL();
// Initialize shaders
- handleShadowQualityChange();
-
initLabelShaders(QStringLiteral(":/shaders/vertexLabel"),
QStringLiteral(":/shaders/fragmentLabel"));
#if !defined(QT_OPENGL_ES_2)
// Init depth shader (for shadows). Init in any case, easier to handle shadow activation if done via api.
initDepthShader();
+#else
+ // Init point shader
+ initPointShader();
#endif
// Init selection shader
@@ -131,52 +140,81 @@ void Scatter3DRenderer::initializeOpenGL()
loadLabelMesh();
// Set view port
- glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
- m_mainViewPort.width(), m_mainViewPort.height());
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
// Load background mesh (we need to be initialized first)
loadBackgroundMesh();
}
-void Scatter3DRenderer::updateDataModel(QScatterDataProxy *dataProxy)
+void Scatter3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList,
+ bool updateVisibility)
{
- const QScatterDataArray &dataArray = *dataProxy->array();
+ Abstract3DRenderer::updateSeries(seriesList, updateVisibility);
+
+ int seriesCount = m_visibleSeriesList.size();
+ float maxItemSize = 0.0f;
+ float itemSize = 0.0f;
+
+ for (int series = 0; series < seriesCount; series++) {
+ itemSize = static_cast<QScatter3DSeries *>(m_visibleSeriesList.at(series).series())->itemSize();
+ if (maxItemSize < itemSize)
+ maxItemSize = itemSize;
+ }
+ m_backgroundMargin = defaultMargin;
+ m_maxItemSize = maxItemSize;
+ if (maxItemSize > defaultMaxSize)
+ m_backgroundMargin += maxItemSize / itemScaler;
+}
+
+void Scatter3DRenderer::updateData()
+{
+ int seriesCount = m_visibleSeriesList.size();
calculateSceneScalingFactors();
- int dataSize = dataArray.size();
float minX = float(m_axisCacheX.min());
float maxX = float(m_axisCacheX.max());
float minY = float(m_axisCacheY.min());
float maxY = float(m_axisCacheY.max());
float minZ = float(m_axisCacheZ.min());
float maxZ = float(m_axisCacheZ.max());
-
- if (dataSize != m_renderItemArray.size())
- m_renderItemArray.resize(dataSize);
- for (int i = 0; i < dataSize ; i++) {
- QVector3D dotPos = dataArray.at(i).position();
- // TODO: Check if this still works always when ranges are no longer required to be zero centered
- // TODO: qreal -> float conversion for axis min/max may cause issues like in surface
- if ((dotPos.x() >= minX && dotPos.x() <= maxX )
- && (dotPos.y() >= minY && dotPos.y() <= maxY)
- && (dotPos.z() >= minZ && dotPos.z() <= maxZ)) {
- m_renderItemArray[i].setPosition(dotPos);
- m_renderItemArray[i].setVisible(true);
- calculateTranslation(m_renderItemArray[i]);
- } else {
- m_renderItemArray[i].setVisible(false);
+ int totalDataSize = 0;
+
+ if (m_renderingArrays.size() != seriesCount)
+ m_renderingArrays.resize(seriesCount);
+
+ for (int series = 0; series < seriesCount; series++) {
+ QScatterDataProxy *dataProxy =
+ static_cast<QScatter3DSeries *>(m_visibleSeriesList.at(series).series())->dataProxy();
+ const QScatterDataArray &dataArray = *dataProxy->array();
+ int dataSize = dataArray.size();
+ totalDataSize += dataSize;
+
+ if (dataSize != m_renderingArrays.at(series).size())
+ m_renderingArrays[series].resize(dataSize);
+
+ for (int i = 0; i < dataSize; i++) {
+ QVector3D dotPos = dataArray.at(i).position();
+ if ((dotPos.x() >= minX && dotPos.x() <= maxX )
+ && (dotPos.y() >= minY && dotPos.y() <= maxY)
+ && (dotPos.z() >= minZ && dotPos.z() <= maxZ)) {
+ m_renderingArrays[series][i].setPosition(dotPos);
+ m_renderingArrays[series][i].setVisible(true);
+ calculateTranslation(m_renderingArrays[series][i]);
+ } else {
+ m_renderingArrays[series][i].setVisible(false);
+ }
}
}
- m_dotSizeScale = (GLfloat)qBound(0.01, (2.0 / qSqrt((qreal)dataSize)), 0.1);
- m_selectedItem = 0;
+ m_dotSizeScale = GLfloat(qBound(defaultMinSize, 2.0f / float(qSqrt(qreal(totalDataSize))),
+ defaultMaxSize));
- Abstract3DRenderer::updateDataModel(dataProxy);
+ updateSelectedItem(m_selectedItemIndex, m_selectedSeries);
}
void Scatter3DRenderer::updateScene(Q3DScene *scene)
{
- // TODO: Move these to more suitable place e.g. controller should be controlling the viewports.
- scene->setPrimarySubViewport(m_mainViewPort);
-
// TODO: See QTRD-2374
scene->activeCamera()->setMinYRotation(-90.0f);
@@ -186,10 +224,6 @@ void Scatter3DRenderer::updateScene(Q3DScene *scene)
m_hasHeightAdjustmentChanged = false;
}
- scene->activeCamera()->d_ptr->updateViewMatrix(m_autoScaleAdjustment);
- // Set light position (rotate light with m_cachedScene->activeCamera(), a bit above it (as set in defaultLightPos))
- scene->setLightPositionRelativeToCamera(defaultLightPos);
-
Abstract3DRenderer::updateScene(scene);
}
@@ -209,19 +243,22 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
const Q3DCamera *activeCamera = m_cachedScene->activeCamera();
// Specify viewport
- glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
- m_mainViewPort.width(), m_mainViewPort.height());
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
// Set up projection matrix
QMatrix4x4 projectionMatrix;
- GLfloat viewPortRatio = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height();
+ GLfloat viewPortRatio = (GLfloat)m_primarySubViewport.width() / (GLfloat)m_primarySubViewport.height();
projectionMatrix.perspective(45.0f, viewPortRatio, 0.1f, 100.0f);
// Calculate view matrix
QMatrix4x4 viewMatrix = activeCamera->viewMatrix();
-
QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix;
+ int seriesCount = m_visibleSeriesList.size();
+
// Calculate label flipping
if (viewMatrix.row(0).x() > 0)
m_zFlipped = false;
@@ -249,25 +286,36 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
backgroundRotation = 0.0f;
// Get light position from the scene
- QVector3D lightPos = m_cachedScene->activeLight()->position();
-
- // Map adjustment direction to model matrix scaling
- // TODO: Let's use these for testing the autoscaling of dots based on their number
- GLfloat heightMultiplier = m_dotSizeScale; //1.0f;
- GLfloat widthMultiplier = m_dotSizeScale; //1.0f;
- GLfloat depthMultiplier = m_dotSizeScale; //1.0f;
- GLfloat heightScaler = 0.0f;
- GLfloat widthScaler = 0.0f;
- GLfloat depthScaler = 0.0f;
- QVector3D modelScaler(widthMultiplier + widthScaler,
- heightMultiplier + heightScaler,
- depthMultiplier + depthScaler);
+ QVector3D lightPos = m_cachedScene->activeLight()->position();
+
// Introduce regardless of shadow quality to simplify logic
QMatrix4x4 depthViewMatrix;
QMatrix4x4 depthProjectionMatrix;
QMatrix4x4 depthProjectionViewMatrix;
+ // Check if we have any series with points
+ bool havePointSeries = false;
+ bool haveMeshSeries = false;
+ bool haveUniformColorMeshSeries = false;
+ bool haveGradientMeshSeries = false;
+ for (int i = 0; i < seriesCount; i++) {
+ if (m_visibleSeriesList.at(i).mesh() == QAbstract3DSeries::MeshPoint) {
+ havePointSeries = true;
+ } else {
+ haveMeshSeries = true;
+ if (m_visibleSeriesList.at(i).colorStyle() == Q3DTheme::ColorStyleUniform)
+ haveUniformColorMeshSeries = true;
+ else
+ haveGradientMeshSeries = true;
+ }
+ }
+
#if !defined(QT_OPENGL_ES_2)
+ if (havePointSeries) {
+ glEnable(GL_POINT_SMOOTH);
+ glEnable(GL_PROGRAM_POINT_SIZE);
+ }
+
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
// Render scene into a depth texture for using with shadow mapping
// Bind depth shader
@@ -275,8 +323,8 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
// Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows.
glViewport(0, 0,
- m_mainViewPort.width() * m_shadowQualityMultiplier,
- m_mainViewPort.height() * m_shadowQualityMultiplier);
+ m_primarySubViewport.width() * m_shadowQualityMultiplier,
+ m_primarySubViewport.height() * m_shadowQualityMultiplier);
// Enable drawing to framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer);
@@ -310,40 +358,61 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
depthProjectionViewMatrix = depthProjectionMatrix * depthViewMatrix;
// Draw dots to depth buffer
- for (int dot = 0; dot < m_renderItemArray.size(); dot++) {
- const ScatterRenderItem &item = m_renderItemArray.at(dot);
- if (!item.isVisible())
- continue;
+ for (int series = 0; series < seriesCount; series++) {
+ ObjectHelper *dotObj = m_visibleSeriesList.at(series).object();
+ bool drawingPoints = (m_visibleSeriesList.at(series).mesh() == QAbstract3DSeries::MeshPoint);
+
+ // TODO: Accessing series directly during rendering
+ float itemSize =
+ static_cast<QScatter3DSeries *>(m_visibleSeriesList.at(series).series())->itemSize()
+ / itemScaler;
+ if (itemSize == 0.0f)
+ itemSize = m_dotSizeScale;
+ if (drawingPoints) {
+ // Scale points based on shadow quality for shadows, not by zoom level
+ glPointSize(itemSize * 100.0f * m_shadowQualityMultiplier);
+ }
+ QVector3D modelScaler(itemSize, itemSize, itemSize);
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
+ for (int dot = 0; dot < m_renderingArrays.at(series).size(); dot++) {
+ const ScatterRenderItem &item = m_renderingArrays.at(series).at(dot);
+ if (!item.isVisible())
+ continue;
- modelMatrix.translate(item.translation());
- modelMatrix.scale(modelScaler);
- //modelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler,
- // heightMultiplier * item.size() + heightScaler,
- // depthMultiplier * item.size() + depthScaler));
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
- MVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ modelMatrix.translate(item.translation());
+ if (!drawingPoints)
+ modelMatrix.scale(modelScaler);
- m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix);
+ MVPMatrix = depthProjectionViewMatrix * modelMatrix;
- // 1st attribute buffer : vertices
- glEnableVertexAttribArray(m_depthShader->posAtt());
- glBindBuffer(GL_ARRAY_BUFFER, m_dotObj->vertexBuf());
- glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
+ m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix);
- // Index buffer
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_dotObj->elementBuf());
+ if (drawingPoints) {
+ m_drawer->drawPoint(m_depthShader);
+ } else {
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(m_depthShader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, dotObj->vertexBuf());
+ glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0,
+ (void *)0);
- // Draw the triangles
- glDrawElements(GL_TRIANGLES, m_dotObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0);
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dotObj->elementBuf());
- // Free buffers
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, dotObj->indexCount(), GL_UNSIGNED_SHORT,
+ (void *)0);
- glDisableVertexAttribArray(m_depthShader->posAtt());
+ // Free buffers
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDisableVertexAttribArray(m_depthShader->posAtt());
+ }
+ }
}
// Disable drawing to framebuffer (= enable drawing to screen)
@@ -352,12 +421,11 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
// Reset culling to normal
glCullFace(GL_BACK);
- // Release depth shader
- m_depthShader->release();
-
// Revert to original viewport
- glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
- m_mainViewPort.width(), m_mainViewPort.height());
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
#if 0 // Use this if you want to see what is being drawn to the framebuffer
// You'll also have to comment out GL_COMPARE_R_TO_TEXTURE -line in texturehelper (if using it)
@@ -370,16 +438,18 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix);
m_drawer->drawObject(m_labelShader, m_labelObj, m_depthTexture);
glDisable(GL_TEXTURE_2D);
- m_labelShader->release();
#endif
}
+
+ ShaderHelper *pointSelectionShader = m_selectionShader;
+#else
+ ShaderHelper *pointSelectionShader = m_pointShader;
#endif
+ ShaderHelper *selectionShader = m_selectionShader;
// Skip selection mode drawing if we have no selection mode
- if (m_cachedSelectionMode > QDataVis::SelectionModeNone) {
- // Bind selection shader
- m_selectionShader->bind();
-
+ if (m_cachedSelectionMode > QDataVis::SelectionNone
+ && SelectOnScene == m_selectionState && seriesCount > 0) {
// Draw dots to selection buffer
glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer);
glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used
@@ -387,62 +457,101 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer
glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled
- int arraySize = m_renderItemArray.size();
- if (arraySize > 0xfffffe) // Max possible different selection colors, 0xffffff being skipColor
- qFatal("Too many objects");
+ int arraySize = 0;
+ int totalArraySize = 0;
+ int dotNo = 0;
+
+ // Init previous to opposite of first to ensure we change binding for first series
+ bool previousDrawingPoints = (m_visibleSeriesList.at(0).mesh() != QAbstract3DSeries::MeshPoint);
+ for (int series = 0; series < seriesCount; series++) {
+ ObjectHelper *dotObj = m_visibleSeriesList.at(series).object();
+ bool drawingPoints = (m_visibleSeriesList.at(series).mesh() == QAbstract3DSeries::MeshPoint);
+
+ // TODO: Accessing series directly during rendering
+ float itemSize =
+ static_cast<QScatter3DSeries *>(m_visibleSeriesList.at(series).series())->itemSize()
+ / itemScaler;
+ if (itemSize == 0.0f)
+ itemSize = m_dotSizeScale;
+#if !defined(QT_OPENGL_ES_2)
+ if (drawingPoints)
+ glPointSize(itemSize * activeCamera->zoomLevel()); // Scale points based on zoom
+#endif
+ QVector3D modelScaler(itemSize, itemSize, itemSize);
- for (int dot = 0; dot < arraySize; dot++) {
- const ScatterRenderItem &item = m_renderItemArray.at(dot);
- if (!item.isVisible())
- continue;
+ // Rebind selection shader if it has changed
+ if (drawingPoints != previousDrawingPoints) {
+ previousDrawingPoints = drawingPoints;
+ if (drawingPoints)
+ selectionShader = pointSelectionShader;
+ else
+ selectionShader = m_selectionShader;
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
+ selectionShader->bind();
+ }
+ arraySize = m_renderingArrays.at(series).size();
+ totalArraySize += arraySize;
- modelMatrix.translate(item.translation());
- modelMatrix.scale(modelScaler);
- //modelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler,
- // heightMultiplier * item.size() + heightScaler,
- // depthMultiplier * item.size() + depthScaler));
+ if (totalArraySize > 0xfffffe) // Max possible different selection colors, 0xffffff being skipColor
+ qFatal("Too many objects");
- MVPMatrix = projectionViewMatrix * modelMatrix;
+ for (int dot = 0; dot < arraySize; dot++) {
+ const ScatterRenderItem &item = m_renderingArrays.at(series).at(dot);
+ if (!item.isVisible())
+ continue;
- QVector3D dotColor = indexToSelectionColor(dot);
- dotColor /= 255.0f;
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+
+ modelMatrix.translate(item.translation());
+ if (!drawingPoints)
+ modelMatrix.scale(modelScaler);
+
+ MVPMatrix = projectionViewMatrix * modelMatrix;
- m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix);
- m_selectionShader->setUniformValue(m_selectionShader->color(), dotColor);
+ QVector3D dotColor = indexToSelectionColor(dotNo);
+ dotColor /= 255.0f;
- // 1st attribute buffer : vertices
- glEnableVertexAttribArray(m_selectionShader->posAtt());
- glBindBuffer(GL_ARRAY_BUFFER, m_dotObj->vertexBuf());
- glVertexAttribPointer(m_selectionShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
+ selectionShader->setUniformValue(selectionShader->MVP(), MVPMatrix);
+ selectionShader->setUniformValue(selectionShader->color(), dotColor);
- // Index buffer
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_dotObj->elementBuf());
+ if (drawingPoints) {
+ m_drawer->drawPoint(selectionShader);
+ } else {
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(selectionShader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, dotObj->vertexBuf());
+ glVertexAttribPointer(selectionShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0,
+ (void *)0);
- // Draw the triangles
- glDrawElements(GL_TRIANGLES, m_dotObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0);
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dotObj->elementBuf());
- // Free buffers
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, dotObj->indexCount(), GL_UNSIGNED_SHORT,
+ (void *)0);
- glDisableVertexAttribArray(m_selectionShader->posAtt());
+ // Free buffers
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDisableVertexAttribArray(selectionShader->posAtt());
+ }
+ dotNo++;
+ }
}
glEnable(GL_DITHER);
// Read color under cursor
- if (QDataVis::InputStateOnScene == m_controller->inputState()) {
- m_selection = Utils::getSelection(m_controller->inputPosition(),
- m_cachedBoundingRect.height());
- }
+ QVector3D clickedColor = Utils::getSelection(m_inputPosition,
+ m_viewport.height());
+ int clickedIndex = 0;
+ QScatter3DSeries *clickedSeries = 0;
+ selectionColorToSeriesAndIndex(clickedColor, clickedIndex, clickedSeries);
+ emit itemClicked(clickedIndex, clickedSeries);
glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle);
- // Release selection shader
- m_selectionShader->release();
-
#if 0 // Use this if you want to see what is being drawn to the framebuffer
m_labelShader->bind();
glDisable(GL_DEPTH_TEST);
@@ -454,114 +563,189 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix);
m_drawer->drawObject(m_labelShader, m_labelObj, m_selectionTexture);
glDisable(GL_TEXTURE_2D);
- m_labelShader->release();
#endif
}
- // Bind dot shader
- m_dotShader->bind();
-
- // Set unchanging shader bindings
- m_dotShader->setUniformValue(m_dotShader->lightP(), lightPos);
- m_dotShader->setUniformValue(m_dotShader->view(), viewMatrix);
- m_dotShader->setUniformValue(m_dotShader->ambientS(), m_cachedTheme.m_ambientStrength);
-
- // Enable texture
- glEnable(GL_TEXTURE_2D);
-
// Draw dots
+ ShaderHelper *dotShader = 0;
+ GLuint gradientTexture = 0;
bool dotSelectionFound = false;
- int selectedIndex;
- if (m_selection == selectionSkipColor) {
- selectedIndex = Scatter3DController::noSelectionIndex();
+ ScatterRenderItem *selectedItem(0);
+ int dotNo = 0;
+ QVector3D baseColor;
+ QVector3D dotColor;
+
+ bool previousDrawingPoints = false;
+ Q3DTheme::ColorStyle previousMeshColorStyle = Q3DTheme::ColorStyleUniform;
+ if (haveMeshSeries) {
+ // Set unchanging shader bindings
+ if (haveGradientMeshSeries) {
+ m_dotGradientShader->bind();
+ m_dotGradientShader->setUniformValue(m_dotGradientShader->lightP(), lightPos);
+ m_dotGradientShader->setUniformValue(m_dotGradientShader->view(), viewMatrix);
+ m_dotGradientShader->setUniformValue(m_dotGradientShader->ambientS(), m_cachedTheme->ambientLightStrength());
+ }
+ if (haveUniformColorMeshSeries) {
+ m_dotShader->bind();
+ m_dotShader->setUniformValue(m_dotShader->lightP(), lightPos);
+ m_dotShader->setUniformValue(m_dotShader->view(), viewMatrix);
+ m_dotShader->setUniformValue(m_dotShader->ambientS(), m_cachedTheme->ambientLightStrength());
+ dotShader = m_dotShader;
+ } else {
+ dotShader = m_dotGradientShader;
+ previousMeshColorStyle = Q3DTheme::ColorStyleRangeGradient;
+ m_dotGradientShader->setUniformValue(m_dotGradientShader->gradientHeight(), 0.0f);
+ }
+ glEnable(GL_TEXTURE_2D);
} else {
- selectedIndex = int(m_selection.x())
- + (int(m_selection.y()) << 8)
- + (int(m_selection.z()) << 16);
+ dotShader = pointSelectionShader;
+ previousDrawingPoints = true;
+ dotShader->bind();
}
- if (m_selection != m_previousSelection) {
- emit selectedItemIndexChanged(selectedIndex);
- m_previousSelection = m_selection;
- }
+ for (int series = 0; series < seriesCount; series++) {
+ const SeriesRenderCache &currentSeries = m_visibleSeriesList.at(series);
+ ObjectHelper *dotObj = currentSeries.object();
+ bool drawingPoints = (currentSeries.mesh() == QAbstract3DSeries::MeshPoint);
+ Q3DTheme::ColorStyle colorStyle = currentSeries.colorStyle();
+ bool colorStyleIsUniform = (colorStyle == Q3DTheme::ColorStyleUniform);
+ bool useColor = colorStyleIsUniform || drawingPoints;
+
+ // TODO: Accessing series directly during rendering
+ float itemSize =
+ static_cast<QScatter3DSeries *>(currentSeries.series())->itemSize()
+ / itemScaler;
+ if (itemSize == 0.0f)
+ itemSize = m_dotSizeScale;
+#if !defined(QT_OPENGL_ES_2)
+ if (drawingPoints)
+ glPointSize(itemSize * activeCamera->zoomLevel()); // Scale points based on zoom
+#endif
+ QVector3D modelScaler(itemSize, itemSize, itemSize);
+
+ // Rebind shader if it has changed
+ if (drawingPoints != previousDrawingPoints
+ || (!drawingPoints &&
+ (colorStyleIsUniform != (previousMeshColorStyle == Q3DTheme::ColorStyleUniform)))) {
+ previousDrawingPoints = drawingPoints;
+ if (drawingPoints) {
+ dotShader = pointSelectionShader;
+ } else {
+ if (colorStyleIsUniform)
+ dotShader = m_dotShader;
+ else
+ dotShader = m_dotGradientShader;
+ }
+ dotShader->bind();
+ }
- ScatterRenderItem *selectedItem(0);
+ if (!drawingPoints && !colorStyleIsUniform && previousMeshColorStyle != colorStyle) {
+ if (colorStyle == Q3DTheme::ColorStyleObjectGradient) {
+ m_dotGradientShader->setUniformValue(m_dotGradientShader->gradientMin(), 0.0f);
+ m_dotGradientShader->setUniformValue(m_dotGradientShader->gradientHeight(), 0.5f);
+ } else {
+ // Each ball is of uniform color according to its Y-coordinate
+ m_dotGradientShader->setUniformValue(m_dotGradientShader->gradientHeight(), 0.0f);
+ }
+ }
- QVector3D baseColor = Utils::vectorFromColor(m_cachedTheme.m_baseColor);
+ if (!drawingPoints)
+ previousMeshColorStyle = colorStyle;
- for (int dot = 0; dot < m_renderItemArray.size(); dot++) {
- ScatterRenderItem &item = m_renderItemArray[dot];
- if (!item.isVisible())
- continue;
+ if (useColor) {
+ baseColor = currentSeries.baseColor();
+ dotColor = baseColor;
+ }
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
- QMatrix4x4 itModelMatrix;
+ int seriesSize = m_renderingArrays.at(series).size();
+ for (int dot = 0; dot < seriesSize; dot++) {
+ ScatterRenderItem &item = m_renderingArrays[series][dot];
+ if (!item.isVisible())
+ continue;
- modelMatrix.translate(item.translation());
- modelMatrix.scale(modelScaler);
- //modelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler,
- // heightMultiplier * item.size() + heightScaler,
- // depthMultiplier * item.size() + depthScaler));
- itModelMatrix.scale(modelScaler);
- //itModelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler,
- // heightMultiplier * item.size() + heightScaler,
- // depthMultiplier * item.size() + depthScaler));
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+ QMatrix4x4 itModelMatrix;
+ modelMatrix.translate(item.translation());
+ if (!drawingPoints) {
+ modelMatrix.scale(modelScaler);
+ itModelMatrix.scale(modelScaler);
+ }
#ifdef SHOW_DEPTH_TEXTURE_SCENE
- MVPMatrix = depthProjectionViewMatrix * modelMatrix;
-#else
- MVPMatrix = projectionViewMatrix * modelMatrix;
-#endif
-
-#if 0
- QVector3D heightColor =
- Utils::vectorFromColor(m_cachedTheme.m_heightColor) * item.translation().y();
-
- QVector3D dotColor = baseColor + heightColor;
+ MVPMatrix = depthProjectionViewMatrix * modelMatrix;
#else
- QVector3D dotColor = baseColor;
+ MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
- GLfloat lightStrength = m_cachedTheme.m_lightStrength;
- if (m_cachedSelectionMode > QDataVis::SelectionModeNone && (selectedIndex == dot)) {
- dotColor = Utils::vectorFromColor(m_cachedTheme.m_highlightBarColor);
- lightStrength = m_cachedTheme.m_highlightLightStrength;
- // Insert data to ScatterRenderItem. We have no ownership, don't delete the previous one
- selectedItem = &item;
- dotSelectionFound = true;
- }
+ if (useColor)
+ dotColor = baseColor;
+ else
+ gradientTexture = currentSeries.baseGradientTexture();
- // Set shader bindings
- m_dotShader->setUniformValue(m_dotShader->model(), modelMatrix);
- m_dotShader->setUniformValue(m_dotShader->nModel(),
- itModelMatrix.inverted().transposed());
- m_dotShader->setUniformValue(m_dotShader->MVP(), MVPMatrix);
- m_dotShader->setUniformValue(m_dotShader->color(), dotColor);
+ GLfloat lightStrength = m_cachedTheme->lightStrength();
+ if (m_cachedSelectionMode > QDataVis::SelectionNone && (m_selectedItemTotalIndex == dotNo)) {
+ if (useColor)
+ dotColor = currentSeries.singleHighlightColor();
+ else
+ gradientTexture = currentSeries.singleHighlightGradientTexture();
+ lightStrength = m_cachedTheme->highlightLightStrength();
+ // Insert data to ScatterRenderItem. We have no ownership, don't delete the previous one
+ selectedItem = &item;
+ dotSelectionFound = true;
+ }
+ if (!drawingPoints) {
+ // Set shader bindings
+ dotShader->setUniformValue(dotShader->model(), modelMatrix);
+ dotShader->setUniformValue(dotShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ }
+ dotShader->setUniformValue(dotShader->MVP(), MVPMatrix);
+ if (useColor) {
+ dotShader->setUniformValue(dotShader->color(), dotColor);
+ } else if (colorStyle == Q3DTheme::ColorStyleRangeGradient) {
+ dotShader->setUniformValue(dotShader->gradientMin(),
+ (item.position().y() + 1.0f) / 2.0f);
+ }
#if !defined(QT_OPENGL_ES_2)
- if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
- // Set shadow shader bindings
- QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix;
- m_dotShader->setUniformValue(m_dotShader->shadowQ(), m_shadowQualityToShader);
- m_dotShader->setUniformValue(m_dotShader->depth(), depthMVPMatrix);
- m_dotShader->setUniformValue(m_dotShader->lightS(), lightStrength / 10.0f);
+ if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
+ if (!drawingPoints) {
+ // Set shadow shader bindings
+ QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ dotShader->setUniformValue(dotShader->shadowQ(), m_shadowQualityToShader);
+ dotShader->setUniformValue(dotShader->depth(), depthMVPMatrix);
+ dotShader->setUniformValue(dotShader->lightS(), lightStrength / 10.0f);
- // Draw the object
- m_drawer->drawObject(m_dotShader, m_dotObj, 0, m_depthTexture);
- } else
+ // Draw the object
+ m_drawer->drawObject(dotShader, dotObj, gradientTexture, m_depthTexture);
+ } else {
+ // Draw the object
+ m_drawer->drawPoint(dotShader);
+ }
+ } else
#endif
- {
- // Set shadowless shader bindings
- m_dotShader->setUniformValue(m_dotShader->lightS(), lightStrength);
-
- // Draw the object
- m_drawer->drawObject(m_dotShader, m_dotObj);
+ {
+ if (!drawingPoints) {
+ // Set shadowless shader bindings
+ dotShader->setUniformValue(dotShader->lightS(), lightStrength);
+ // Draw the object
+ m_drawer->drawObject(dotShader, dotObj, gradientTexture);
+ } else {
+ // Draw the object
+ m_drawer->drawPoint(dotShader);
+ }
+ }
+ dotNo++;
}
}
- // Release dot shader
- m_dotShader->release();
+#if !defined(QT_OPENGL_ES_2)
+ if (havePointSeries) {
+ glDisable(GL_POINT_SMOOTH);
+ glDisable(GL_PROGRAM_POINT_SIZE);
+ }
+#endif
// Bind background shader
m_backgroundShader->bind();
@@ -569,19 +753,23 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
glCullFace(GL_BACK);
// Draw background
- if (m_cachedIsBackgroundEnabled && m_backgroundObj) {
+ if (m_cachedTheme->isBackgroundEnabled() && m_backgroundObj) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z
- QVector3D bgScale((aspectRatio * backgroundMargin * m_areaSize.width()) / m_scaleFactor,
- backgroundMargin,
- (aspectRatio * backgroundMargin * m_areaSize.height()) / m_scaleFactor);
+ GLfloat xScale = (aspectRatio * m_backgroundMargin * m_areaSize.width()) / m_scaleFactor;
+ GLfloat zScale = (aspectRatio * m_backgroundMargin * m_areaSize.height()) / m_scaleFactor;
+ if (m_maxItemSize > xScale)
+ xScale = m_maxItemSize;
+ if (m_maxItemSize > zScale)
+ zScale = m_maxItemSize;
+ QVector3D bgScale(xScale, m_backgroundMargin, zScale);
#else // ..and this if we want uniform scaling based on largest dimension
- QVector3D bgScale((aspectRatio * backgroundMargin),
- backgroundMargin,
- (aspectRatio * backgroundMargin));
+ QVector3D bgScale((aspectRatio * m_backgroundMargin),
+ m_backgroundMargin,
+ (aspectRatio * m_backgroundMargin));
#endif
modelMatrix.scale(bgScale);
// If we're viewing from below, background object must be flipped
@@ -598,7 +786,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
#else
MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
- QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme.m_backgroundColor);
+ QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme->backgroundColor());
// Set shader bindings
m_backgroundShader->setUniformValue(m_backgroundShader->lightP(), lightPos);
@@ -609,7 +797,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
m_backgroundShader->setUniformValue(m_backgroundShader->MVP(), MVPMatrix);
m_backgroundShader->setUniformValue(m_backgroundShader->color(), backgroundColor);
m_backgroundShader->setUniformValue(m_backgroundShader->ambientS(),
- m_cachedTheme.m_ambientStrength * 2.0f);
+ m_cachedTheme->ambientLightStrength() * 2.0f);
#if !defined(QT_OPENGL_ES_2)
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
@@ -619,7 +807,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
m_shadowQualityToShader);
m_backgroundShader->setUniformValue(m_backgroundShader->depth(), depthMVPMatrix);
m_backgroundShader->setUniformValue(m_backgroundShader->lightS(),
- m_cachedTheme.m_lightStrength / 10.0f);
+ m_cachedTheme->lightStrength() / 10.0f);
// Draw the object
m_drawer->drawObject(m_backgroundShader, m_backgroundObj, 0, m_depthTexture);
@@ -628,16 +816,13 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
{
// Set shadowless shader bindings
m_backgroundShader->setUniformValue(m_backgroundShader->lightS(),
- m_cachedTheme.m_lightStrength);
+ m_cachedTheme->lightStrength());
// Draw the object
m_drawer->drawObject(m_backgroundShader, m_backgroundObj);
}
}
- // Release background shader
- m_backgroundShader->release();
-
// Disable textures
glDisable(GL_TEXTURE_2D);
@@ -650,37 +835,54 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
axisCacheMax = &m_axisCacheX;
#endif
- if (m_cachedIsGridEnabled && m_heightNormalizer) {
+ if (m_cachedTheme->isGridEnabled() && m_heightNormalizer) {
ShaderHelper *lineShader = m_backgroundShader;
// Bind line shader
lineShader->bind();
// Set unchanging shader bindings
- QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme.m_gridLine);
+ QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
lineShader->setUniformValue(lineShader->lightP(), lightPos);
lineShader->setUniformValue(lineShader->view(), viewMatrix);
lineShader->setUniformValue(lineShader->color(), lineColor);
- lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme.m_ambientStrength);
+ lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme->ambientLightStrength());
#if !defined(QT_OPENGL_ES_2)
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
// Set shadowed shader bindings
lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader);
lineShader->setUniformValue(lineShader->lightS(),
- m_cachedTheme.m_lightStrength / 20.0f);
+ m_cachedTheme->lightStrength() / 20.0f);
} else
#endif
{
// Set shadowless shader bindings
- lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme.m_lightStrength / 2.5f);
+ lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme->lightStrength() / 2.5f);
}
+ QQuaternion lineYRotation = QQuaternion();
+ QQuaternion lineXRotation = QQuaternion();
+
+ if (m_xFlipped)
+ lineYRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, -90.0f);
+ else
+ lineYRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f);
+
+ if (m_yFlipped)
+ lineXRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 90.0f);
+ else
+ lineXRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, -90.0f);
+
+ GLfloat yFloorLinePosition = -m_backgroundMargin + gridLineOffset;
+ if (m_yFlipped)
+ yFloorLinePosition = -yFloorLinePosition;
+
// Rows (= Z)
if (m_axisCacheZ.segmentCount() > 0) {
// Floor lines
#ifndef USE_UNIFORM_SCALING
GLfloat lineStep = aspectRatio * m_axisCacheZ.subSegmentStep();
- GLfloat linePos = -aspectRatio * m_axisCacheZ.min(); // Start line
+ GLfloat linePos = -aspectRatio * (m_axisCacheZ.min() - m_translationOffset.z()); // Start line
int lastSegment = m_axisCacheZ.subSegmentCount() * m_axisCacheZ.segmentCount();
#else
GLfloat lineStep = aspectRatio * axisCacheMax->subSegmentStep();
@@ -689,11 +891,12 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
#endif
#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z
- QVector3D gridLineScaler(
- (aspectRatio * backgroundMargin * m_areaSize.width()) / m_scaleFactor,
- gridLineWidth, gridLineWidth);
+ GLfloat xScale = (aspectRatio * m_backgroundMargin * m_areaSize.width()) / m_scaleFactor;
+ if (m_maxItemSize > xScale)
+ xScale = m_maxItemSize;
+ QVector3D gridLineScaler(xScale, gridLineWidth, gridLineWidth);
#else // ..and this if we want uniform scaling based on largest dimension
- QVector3D gridLineScaler((aspectRatio * backgroundMargin),
+ QVector3D gridLineScaler((aspectRatio * m_backgroundMargin),
gridLineWidth, gridLineWidth);
#endif
@@ -702,19 +905,13 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- if (m_yFlipped)
- modelMatrix.translate(0.0f, backgroundMargin, linePos / m_scaleFactor);
- else
- modelMatrix.translate(0.0f, -backgroundMargin, linePos / m_scaleFactor);
+ modelMatrix.translate(0.0f, yFloorLinePosition, linePos / m_scaleFactor);
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
- // If we're viewing from below, grid line object must be flipped
- if (m_yFlipped) {
- modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- itModelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- }
+ modelMatrix.rotate(lineXRotation);
+ itModelMatrix.rotate(lineXRotation);
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -741,13 +938,15 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
}
// Side wall lines
- gridLineScaler = QVector3D(gridLineWidth, backgroundMargin, gridLineWidth);
+ gridLineScaler = QVector3D(gridLineWidth, m_backgroundMargin, gridLineWidth);
#ifndef USE_UNIFORM_SCALING
- GLfloat lineXTrans = (aspectRatio * backgroundMargin * m_areaSize.width())
- / m_scaleFactor;
- linePos = -aspectRatio * m_axisCacheZ.min(); // Start line
+ GLfloat lineXTrans = (aspectRatio * m_backgroundMargin * m_areaSize.width())
+ / m_scaleFactor - gridLineOffset;
+ if (m_maxItemSize > lineXTrans)
+ lineXTrans = m_maxItemSize - gridLineOffset;
+ linePos = -aspectRatio * (m_axisCacheZ.min() - m_translationOffset.z()); // Start line
#else
- GLfloat lineXTrans = aspectRatio * backgroundMargin;
+ GLfloat lineXTrans = aspectRatio * m_backgroundMargin - gridLineOffset;
linePos = -aspectRatio * m_scaleFactor; // Start line
#endif
if (!m_xFlipped)
@@ -759,9 +958,13 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
QMatrix4x4 itModelMatrix;
modelMatrix.translate(lineXTrans, 0.0f, linePos / m_scaleFactor);
+
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
+ modelMatrix.rotate(lineYRotation);
+ itModelMatrix.rotate(lineYRotation);
+
MVPMatrix = projectionViewMatrix * modelMatrix;
// Set the rest of the shader bindings
@@ -792,17 +995,18 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
// Floor lines
#ifndef USE_UNIFORM_SCALING
GLfloat lineStep = aspectRatio * m_axisCacheX.subSegmentStep();
- GLfloat linePos = aspectRatio * m_axisCacheX.min();
+ GLfloat linePos = aspectRatio * (m_axisCacheX.min() - m_translationOffset.x());
int lastSegment = m_axisCacheX.subSegmentCount() * m_axisCacheX.segmentCount();
- QVector3D gridLineScaler(
- gridLineWidth, gridLineWidth,
- (aspectRatio * backgroundMargin * m_areaSize.height()) / m_scaleFactor);
+ GLfloat zScale = (aspectRatio * m_backgroundMargin * m_areaSize.height()) / m_scaleFactor;
+ if (m_maxItemSize > zScale)
+ zScale = m_maxItemSize;
+ QVector3D gridLineScaler(gridLineWidth, gridLineWidth, zScale);
#else
GLfloat lineStep = aspectRatio * axisCacheMax->subSegmentStep();
GLfloat linePos = -aspectRatio * m_scaleFactor;
int lastSegment = axisCacheMax->subSegmentCount() * axisCacheMax->segmentCount();
QVector3D gridLineScaler(gridLineWidth, gridLineWidth,
- aspectRatio * backgroundMargin);
+ aspectRatio * m_backgroundMargin);
#endif
for (int segment = 0; segment <= lastSegment; segment++) {
@@ -810,18 +1014,13 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- if (m_yFlipped)
- modelMatrix.translate(linePos / m_scaleFactor, backgroundMargin, 0.0f);
- else
- modelMatrix.translate(linePos / m_scaleFactor, -backgroundMargin, 0.0f);
+ modelMatrix.translate(linePos / m_scaleFactor, yFloorLinePosition, 0.0f);
+
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
- // If we're viewing from below, grid line object must be flipped
- if (m_yFlipped) {
- modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- itModelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- }
+ modelMatrix.rotate(lineXRotation);
+ itModelMatrix.rotate(lineXRotation);
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -849,17 +1048,19 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
// Back wall lines
#ifndef USE_UNIFORM_SCALING
- GLfloat lineZTrans = (aspectRatio * backgroundMargin * m_areaSize.height())
- / m_scaleFactor;
- linePos = aspectRatio * m_axisCacheX.min();
+ GLfloat lineZTrans = (aspectRatio * m_backgroundMargin * m_areaSize.height())
+ / m_scaleFactor - gridLineOffset;
+ if (m_maxItemSize > lineZTrans)
+ lineZTrans = m_maxItemSize - gridLineOffset;
+ linePos = aspectRatio * (m_axisCacheX.min() - m_translationOffset.x());
#else
- GLfloat lineZTrans = aspectRatio * backgroundMargin;
+ GLfloat lineZTrans = aspectRatio * m_backgroundMargin - gridLineOffset;
linePos = -aspectRatio * m_scaleFactor;
#endif
if (!m_zFlipped)
lineZTrans = -lineZTrans;
- gridLineScaler = QVector3D(gridLineWidth, backgroundMargin, gridLineWidth);
+ gridLineScaler = QVector3D(gridLineWidth, m_backgroundMargin, gridLineWidth);
for (int segment = 0; segment <= lastSegment; segment++) {
QMatrix4x4 modelMatrix;
@@ -867,9 +1068,15 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
QMatrix4x4 itModelMatrix;
modelMatrix.translate(linePos / m_scaleFactor, 0.0f, lineZTrans);
+
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
+ if (m_zFlipped) {
+ modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ itModelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ }
+
MVPMatrix = projectionViewMatrix * modelMatrix;
// Set the rest of the shader bindings
@@ -899,18 +1106,21 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
if (m_axisCacheY.segmentCount() > 0) {
// Back wall
GLfloat lineStep = m_axisCacheY.subSegmentStep();
- GLfloat linePos = m_axisCacheY.min();
+ GLfloat linePos = m_axisCacheY.min() - m_translationOffset.y();
int lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount();
#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z
- GLfloat lineZTrans = (aspectRatio * backgroundMargin * m_areaSize.height())
- / m_scaleFactor;
- QVector3D gridLineScaler(
- (aspectRatio * backgroundMargin * m_areaSize.width() / m_scaleFactor),
- gridLineWidth, gridLineWidth);
+ GLfloat lineZTrans = (aspectRatio * m_backgroundMargin * m_areaSize.height())
+ / m_scaleFactor - gridLineOffset;
+ if (m_maxItemSize > lineZTrans)
+ lineZTrans = m_maxItemSize - gridLineOffset;
+ GLfloat xScale = (aspectRatio * m_backgroundMargin * m_areaSize.width()) / m_scaleFactor;
+ if (m_maxItemSize > xScale)
+ xScale = m_maxItemSize;
+ QVector3D gridLineScaler(xScale, gridLineWidth, gridLineWidth);
#else // ..and this if we want uniform scaling based on largest dimension
- GLfloat lineZTrans = aspectRatio * backgroundMargin;
- QVector3D gridLineScaler((aspectRatio * backgroundMargin),
+ GLfloat lineZTrans = aspectRatio * m_backgroundMargin - gridLineOffset;
+ QVector3D gridLineScaler((aspectRatio * m_backgroundMargin),
gridLineWidth, gridLineWidth);
#endif
if (!m_zFlipped)
@@ -926,6 +1136,11 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
+ if (m_zFlipped) {
+ modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ itModelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ }
+
MVPMatrix = projectionViewMatrix * modelMatrix;
// Set the rest of the shader bindings
@@ -951,18 +1166,22 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
}
// Side wall
- linePos = m_axisCacheY.min();
+ linePos = m_axisCacheY.min() - m_translationOffset.y();
lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount();
#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z
- GLfloat lineXTrans = (aspectRatio * backgroundMargin * m_areaSize.width())
+ GLfloat lineXTrans = (aspectRatio * m_backgroundMargin * m_areaSize.width())
+ / m_scaleFactor - gridLineOffset;
+ if (m_maxItemSize > lineXTrans)
+ lineXTrans = m_maxItemSize - gridLineOffset;
+ GLfloat zScale = (aspectRatio * m_backgroundMargin * m_areaSize.height())
/ m_scaleFactor;
- gridLineScaler = QVector3D(
- gridLineWidth, gridLineWidth,
- (aspectRatio * backgroundMargin * m_areaSize.height()) / m_scaleFactor);
+ if (m_maxItemSize > zScale)
+ zScale = m_maxItemSize;
+ gridLineScaler = QVector3D(gridLineWidth, gridLineWidth, zScale);
#else // ..and this if we want uniform scaling based on largest dimension
- GLfloat lineXTrans = aspectRatio * backgroundMargin;
+ GLfloat lineXTrans = aspectRatio * m_backgroundMargin - gridLineOffset;
gridLineScaler = QVector3D(gridLineWidth, gridLineWidth,
- aspectRatio * backgroundMargin);
+ aspectRatio * m_backgroundMargin);
#endif
if (!m_xFlipped)
lineXTrans = -lineXTrans;
@@ -977,6 +1196,9 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
+ modelMatrix.rotate(lineYRotation);
+ itModelMatrix.rotate(lineYRotation);
+
MVPMatrix = projectionViewMatrix * modelMatrix;
// Set the rest of the shader bindings
@@ -1001,9 +1223,6 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
linePos += lineStep;
}
}
-
- // Release line shader
- lineShader->release();
}
// Draw axis labels
@@ -1015,23 +1234,26 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_POLYGON_OFFSET_FILL);
// Z Labels
if (m_axisCacheZ.segmentCount() > 0) {
#ifndef USE_UNIFORM_SCALING
GLfloat posStep = aspectRatio * m_axisCacheZ.segmentStep();
- GLfloat labelPos = -aspectRatio * m_axisCacheZ.min();
+ GLfloat labelPos = -aspectRatio * (m_axisCacheZ.min() - m_translationOffset.z());
int lastSegment = m_axisCacheZ.segmentCount();
- GLfloat labelXTrans = (aspectRatio * backgroundMargin * m_areaSize.width())
+ GLfloat labelXTrans = (aspectRatio * m_backgroundMargin * m_areaSize.width())
/ m_scaleFactor + labelMargin;
+ if (m_maxItemSize > labelXTrans)
+ labelXTrans = m_maxItemSize + labelMargin;
#else
GLfloat posStep = aspectRatio * axisCacheMax->segmentStep();
GLfloat labelPos = aspectRatio * m_scaleFactor;
int lastSegment = axisCacheMax->segmentCount();
- GLfloat labelXTrans = aspectRatio * backgroundMargin + labelMargin;
+ GLfloat labelXTrans = aspectRatio * m_backgroundMargin + labelMargin;
#endif
int labelNbr = 0;
- GLfloat labelYTrans = -backgroundMargin;
+ GLfloat labelYTrans = -m_backgroundMargin;
GLfloat rotLabelX = -90.0f;
GLfloat rotLabelY = 0.0f;
GLfloat rotLabelZ = 0.0f;
@@ -1057,6 +1279,8 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
#endif
labelTrans.setZ(labelPos / m_scaleFactor);
+ glPolygonOffset(GLfloat(segment) / -10.0f, 1.0f);
+
// Draw the label here
m_dummyRenderItem.setTranslation(labelTrans);
#ifndef USE_UNIFORM_SCALING
@@ -1078,18 +1302,20 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
if (m_axisCacheX.segmentCount() > 0) {
#ifndef USE_UNIFORM_SCALING
GLfloat posStep = aspectRatio * m_axisCacheX.segmentStep();
- GLfloat labelPos = aspectRatio * m_axisCacheX.min();
+ GLfloat labelPos = aspectRatio * (m_axisCacheX.min() - m_translationOffset.x());
int lastSegment = m_axisCacheX.segmentCount();
- GLfloat labelZTrans = (aspectRatio * backgroundMargin * m_areaSize.height())
+ GLfloat labelZTrans = (aspectRatio * m_backgroundMargin * m_areaSize.height())
/ m_scaleFactor + labelMargin;
+ if (m_maxItemSize > labelZTrans)
+ labelZTrans = m_maxItemSize + labelMargin;
#else
GLfloat posStep = aspectRatio * axisCacheMax->segmentStep();
GLfloat labelPos = -aspectRatio * m_scaleFactor;
int lastSegment = axisCacheMax->segmentCount();
- GLfloat labelZTrans = aspectRatio * backgroundMargin + labelMargin;
+ GLfloat labelZTrans = aspectRatio * m_backgroundMargin + labelMargin;
#endif
int labelNbr = 0;
- GLfloat labelYTrans = -backgroundMargin;
+ GLfloat labelYTrans = -m_backgroundMargin;
GLfloat rotLabelX = -90.0f;
GLfloat rotLabelY = 90.0f;
GLfloat rotLabelZ = 0.0f;
@@ -1115,6 +1341,8 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
#endif
labelTrans.setX(labelPos / m_scaleFactor);
+ glPolygonOffset(GLfloat(segment) / -10.0f, 1.0f);
+
// Draw the label here
m_dummyRenderItem.setTranslation(labelTrans);
#ifndef USE_UNIFORM_SCALING
@@ -1135,15 +1363,19 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
// Y Labels
if (m_axisCacheY.segmentCount() > 0) {
GLfloat posStep = m_axisCacheY.segmentStep();
- GLfloat labelPos = m_axisCacheY.min();
+ GLfloat labelPos = m_axisCacheY.min() - m_translationOffset.y();
int labelNbr = 0;
#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z
- GLfloat labelXTrans = (aspectRatio * backgroundMargin * m_areaSize.width())
+ GLfloat labelXTrans = (aspectRatio * m_backgroundMargin * m_areaSize.width())
/ m_scaleFactor;
- GLfloat labelZTrans = (aspectRatio * backgroundMargin * m_areaSize.height())
+ GLfloat labelZTrans = (aspectRatio * m_backgroundMargin * m_areaSize.height())
/ m_scaleFactor;
+ if (m_maxItemSize > labelXTrans)
+ labelXTrans = m_maxItemSize;
+ if (m_maxItemSize > labelZTrans)
+ labelZTrans = m_maxItemSize;
#else // ..and this if we want uniform scaling based on largest dimension
- GLfloat labelXTrans = aspectRatio * backgroundMargin;
+ GLfloat labelXTrans = aspectRatio * m_backgroundMargin;
GLfloat labelZTrans = labelXTrans;
#endif
// Back wall init
@@ -1185,6 +1417,8 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr);
const GLfloat labelYTrans = labelPos / m_heightNormalizer;
+ glPolygonOffset(GLfloat(segment) / -10.0f, 1.0f);
+
// Back wall
labelTransBack.setY(labelYTrans);
m_dummyRenderItem.setTranslation(labelTransBack);
@@ -1205,6 +1439,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
labelPos += posStep;
}
}
+ glDisable(GL_POLYGON_OFFSET_FILL);
// Handle selection clearing and selection label drawing
if (!dotSelectionFound) {
@@ -1225,7 +1460,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
static const QString yLabelTag(QStringLiteral("@yLabel"));
static const QString zLabelTag(QStringLiteral("@zLabel"));
- labelText = itemLabelFormat();
+ labelText = m_visibleSeriesList[m_selectedItemSeriesIndex].itemLabelFormat();
labelText.replace(xTitleTag, m_axisCacheX.title());
labelText.replace(yTitleTag, m_axisCacheY.title());
@@ -1274,34 +1509,31 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
- // Release label shader
- m_labelShader->release();
-}
+ // Release shader
+ glUseProgram(0);
-void Scatter3DRenderer::updateSelectedItemIndex(int index)
-{
- if (index == Scatter3DController::noSelectionIndex())
- m_selection = selectionSkipColor;
- else
- m_selection = indexToSelectionColor(index);
+ m_selectionDirty = false;
}
-void Scatter3DRenderer::handleResize()
+void Scatter3DRenderer::updateSelectedItem(int index, const QScatter3DSeries *series)
{
- if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0)
- return;
-
- // Set view port
- m_mainViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height());
-
- Abstract3DRenderer::handleResize();
-}
-
-void Scatter3DRenderer::updateBackgroundEnabled(bool enable)
-{
- if (enable != m_cachedIsBackgroundEnabled) {
- Abstract3DRenderer::updateBackgroundEnabled(enable);
- loadMeshFile(); // Load changed dot type
+ m_selectionDirty = true;
+ m_selectedSeries = series;
+ m_selectedItemIndex = Scatter3DController::invalidSelectionIndex();
+ m_selectedItemTotalIndex = Scatter3DController::invalidSelectionIndex();
+ m_selectedItemSeriesIndex = Scatter3DController::invalidSelectionIndex();
+
+ if (!m_renderingArrays.isEmpty() && index != Scatter3DController::invalidSelectionIndex()) {
+ int totalIndex = 0;
+ for (int i = 0; i < m_visibleSeriesList.size(); i++) {
+ if (m_visibleSeriesList.at(i).series() == series) {
+ m_selectedItemSeriesIndex = i;
+ m_selectedItemIndex = index;
+ m_selectedItemTotalIndex = index + totalIndex;
+ break;
+ }
+ totalIndex += m_renderingArrays.at(i).size();
+ }
}
}
@@ -1347,15 +1579,6 @@ void Scatter3DRenderer::updateShadowQuality(QDataVis::ShadowQuality quality)
#endif
}
-void Scatter3DRenderer::loadMeshFile()
-{
- QString objectFileName = m_cachedObjFile;
- if (m_dotObj)
- delete m_dotObj;
- m_dotObj = new ObjectHelper(objectFileName);
- m_dotObj->load();
-}
-
void Scatter3DRenderer::loadBackgroundMesh()
{
if (m_backgroundObj)
@@ -1368,7 +1591,7 @@ void Scatter3DRenderer::loadGridLineMesh()
{
if (m_gridLineObj)
delete m_gridLineObj;
- m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar"));
+ m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
m_gridLineObj->load();
}
@@ -1376,7 +1599,7 @@ void Scatter3DRenderer::loadLabelMesh()
{
if (m_labelObj)
delete m_labelObj;
- m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label"));
+ m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
m_labelObj->load();
}
@@ -1386,37 +1609,44 @@ void Scatter3DRenderer::updateTextures()
m_updateLabels = true;
}
+void Scatter3DRenderer::fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh)
+{
+ // Load full version of meshes that have it available
+ if (mesh != QAbstract3DSeries::MeshSphere
+ && mesh != QAbstract3DSeries::MeshMinimal
+ && mesh != QAbstract3DSeries::MeshPoint) {
+ fileName.append(QStringLiteral("Full"));
+ }
+}
+
void Scatter3DRenderer::updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation,
- qreal min, qreal max)
+ float min, float max)
{
Abstract3DRenderer::updateAxisRange(orientation, min, max);
}
void Scatter3DRenderer::calculateTranslation(ScatterRenderItem &item)
{
- // Origin should be in the center of scene, ie. both positive and negative values are drawn
- // above background
-
// We need to normalize translations
- GLfloat xTrans = (aspectRatio * item.position().x()) / m_scaleFactor;
- GLfloat zTrans = -(aspectRatio * item.position().z()) / m_scaleFactor;
- GLfloat yTrans = item.position().y() / m_heightNormalizer;
+ GLfloat xTrans = (aspectRatio * (item.position().x() - m_translationOffset.x()))
+ / m_scaleFactor;
+ GLfloat zTrans = -(aspectRatio * (item.position().z() - m_translationOffset.z()))
+ / m_scaleFactor;
+ GLfloat yTrans = (item.position().y() - m_translationOffset.y()) / m_heightNormalizer;
item.setTranslation(QVector3D(xTrans, yTrans, zTrans));
- //qDebug() << item.translation();
}
void Scatter3DRenderer::calculateSceneScalingFactors()
{
- m_heightNormalizer = (GLfloat)qMax(qAbs(m_axisCacheY.max()), qAbs(m_axisCacheY.min()));
- m_areaSize.setHeight(qMax(qAbs(m_axisCacheZ.max()), qAbs(m_axisCacheZ.min())));
- m_areaSize.setWidth(qMax(qAbs(m_axisCacheX.max()), qAbs(m_axisCacheX.min())));
+ m_heightNormalizer = GLfloat(m_axisCacheY.max() - m_axisCacheY.min()) / 2.0f;
+ m_areaSize.setHeight((m_axisCacheZ.max() - m_axisCacheZ.min()) / 2.0f);
+ m_areaSize.setWidth((m_axisCacheX.max() - m_axisCacheX.min()) / 2.0f);
m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height());
- //qDebug() << m_heightNormalizer << m_areaSize << m_scaleFactor << m_axisCacheY.max() << m_axisCacheX.max() << m_axisCacheZ.max();
-}
-QRect Scatter3DRenderer::mainViewPort()
-{
- return m_mainViewPort;
+ // Calculate translation offsets
+ m_translationOffset = QVector3D((m_axisCacheX.max() + m_axisCacheX.min()) / 2.0f,
+ (m_axisCacheY.max() + m_axisCacheY.min()) / 2.0f,
+ (m_axisCacheZ.max() + m_axisCacheZ.min()) / 2.0f);
}
void Scatter3DRenderer::initShaders(const QString &vertexShader, const QString &fragmentShader)
@@ -1427,12 +1657,20 @@ void Scatter3DRenderer::initShaders(const QString &vertexShader, const QString &
m_dotShader->initialize();
}
+void Scatter3DRenderer::initGradientShaders(const QString &vertexShader, const QString &fragmentShader)
+{
+ if (m_dotGradientShader)
+ delete m_dotGradientShader;
+ m_dotGradientShader = new ShaderHelper(this, vertexShader, fragmentShader);
+ m_dotGradientShader->initialize();
+}
+
void Scatter3DRenderer::initSelectionShader()
{
if (m_selectionShader)
delete m_selectionShader;
- m_selectionShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSelection"),
- QStringLiteral(":/shaders/fragmentSelection"));
+ m_selectionShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexPlainColor"),
+ QStringLiteral(":/shaders/fragmentPlainColor"));
m_selectionShader->initialize();
}
@@ -1443,10 +1681,10 @@ void Scatter3DRenderer::initSelectionBuffer()
m_selectionTexture = 0;
}
- if (m_mainViewPort.size().isEmpty())
+ if (m_primarySubViewport.size().isEmpty())
return;
- m_selectionTexture = m_textureHelper->createSelectionTexture(m_mainViewPort.size(),
+ m_selectionTexture = m_textureHelper->createSelectionTexture(m_primarySubViewport.size(),
m_selectionFrameBuffer,
m_selectionDepthBuffer);
}
@@ -1468,52 +1706,26 @@ void Scatter3DRenderer::updateDepthBuffer()
m_depthTexture = 0;
}
- if (m_mainViewPort.size().isEmpty())
+ if (m_primarySubViewport.size().isEmpty())
return;
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
- m_depthTexture = m_textureHelper->createDepthTexture(m_mainViewPort.size(),
- m_depthFrameBuffer,
- m_shadowQualityMultiplier);
- if (!m_depthTexture) {
- switch (m_cachedShadowQuality) {
- case QDataVis::ShadowQualityHigh:
- qWarning("Creating high quality shadows failed. Changing to medium quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityMedium);
- updateShadowQuality(QDataVis::ShadowQualityMedium);
- break;
- case QDataVis::ShadowQualityMedium:
- qWarning("Creating medium quality shadows failed. Changing to low quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityLow);
- updateShadowQuality(QDataVis::ShadowQualityLow);
- break;
- case QDataVis::ShadowQualityLow:
- qWarning("Creating low quality shadows failed. Switching shadows off.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityNone);
- updateShadowQuality(QDataVis::ShadowQualityNone);
- break;
- case QDataVis::ShadowQualitySoftHigh:
- qWarning("Creating soft high quality shadows failed. Changing to soft medium quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualitySoftMedium);
- updateShadowQuality(QDataVis::ShadowQualitySoftMedium);
- break;
- case QDataVis::ShadowQualitySoftMedium:
- qWarning("Creating soft medium quality shadows failed. Changing to soft low quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualitySoftLow);
- updateShadowQuality(QDataVis::ShadowQualitySoftLow);
- break;
- case QDataVis::ShadowQualitySoftLow:
- qWarning("Creating soft low quality shadows failed. Switching shadows off.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityNone);
- updateShadowQuality(QDataVis::ShadowQualityNone);
- break;
- default:
- // You'll never get here
- break;
- }
- }
+ m_depthTexture = m_textureHelper->createDepthTextureFrameBuffer(m_primarySubViewport.size(),
+ m_depthFrameBuffer,
+ m_shadowQualityMultiplier);
+ if (!m_depthTexture)
+ lowerShadowQuality();
}
}
+#else
+void Scatter3DRenderer::initPointShader()
+{
+ if (m_pointShader)
+ delete m_pointShader;
+ m_pointShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexPointES2"),
+ QStringLiteral(":/shaders/fragmentPlainColor"));
+ m_pointShader->initialize();
+}
#endif
void Scatter3DRenderer::initBackgroundShaders(const QString &vertexShader,
@@ -1542,4 +1754,26 @@ QVector3D Scatter3DRenderer::indexToSelectionColor(GLint index)
return QVector3D(dotIdxRed, dotIdxGreen, dotIdxBlue);
}
+void Scatter3DRenderer::selectionColorToSeriesAndIndex(const QVector3D &color, int &index, QScatter3DSeries *&series)
+{
+ if (color != selectionSkipColor) {
+ index = int(color.x())
+ + (int(color.y()) << 8)
+ + (int(color.z()) << 16);
+ // Find the series and adjust the index accordingly
+ for (int i = 0; i < m_renderingArrays.size(); i++) {
+ if (index < m_renderingArrays.at(i).size()) {
+ series = static_cast<QScatter3DSeries *>(m_visibleSeriesList.at(i).series());
+ return; // Valid found and already set to return parameters, so we can return
+ } else {
+ index -= m_renderingArrays.at(i).size();
+ }
+ }
+ }
+
+ // No valid match found
+ index = Scatter3DController::invalidSelectionIndex();
+ series = 0;
+}
+
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/scatter3drenderer_p.h b/src/datavisualization/engine/scatter3drenderer_p.h
index f444f891..30ec7489 100644
--- a/src/datavisualization/engine/scatter3drenderer_p.h
+++ b/src/datavisualization/engine/scatter3drenderer_p.h
@@ -52,25 +52,21 @@ class QT_DATAVISUALIZATION_EXPORT Scatter3DRenderer : public Abstract3DRenderer
Q_OBJECT
private:
- // TODO: Filter to the set of attributes to be moved to the model object.
- // * All GL rendering only related attribs should be moved out of this public set.
- // * All attribs that are modifiable from QML need to e in this set.
-
- Scatter3DController *m_controller;
-
// Internal state
ScatterRenderItem *m_selectedItem; // points to renderitem array
bool m_xFlipped;
bool m_zFlipped;
bool m_yFlipped;
- QRect m_mainViewPort;
bool m_updateLabels;
ShaderHelper *m_dotShader;
+ ShaderHelper *m_dotGradientShader;
+#if defined(QT_OPENGL_ES_2)
+ ShaderHelper *m_pointShader;
+#endif
ShaderHelper *m_depthShader;
ShaderHelper *m_selectionShader;
ShaderHelper *m_backgroundShader;
ShaderHelper *m_labelShader;
- ObjectHelper *m_dotObj;
ObjectHelper *m_backgroundObj;
ObjectHelper *m_gridLineObj;
ObjectHelper *m_labelObj;
@@ -84,37 +80,40 @@ private:
GLint m_shadowQualityMultiplier;
GLfloat m_heightNormalizer;
GLfloat m_scaleFactor;
- QVector3D m_selection;
- QVector3D m_previousSelection;
+ int m_selectedItemIndex;
+ int m_selectedItemTotalIndex;
+ int m_selectedItemSeriesIndex;
+ const QScatter3DSeries *m_selectedSeries;
QSizeF m_areaSize;
GLfloat m_dotSizeScale;
-
+ QVector3D m_translationOffset;
bool m_hasHeightAdjustmentChanged;
ScatterRenderItem m_dummyRenderItem;
-
- ScatterRenderItemArray m_renderItemArray;
+ QVector<ScatterRenderItemArray> m_renderingArrays;
+ GLfloat m_backgroundMargin;
+ GLfloat m_maxItemSize;
public:
explicit Scatter3DRenderer(Scatter3DController *controller);
~Scatter3DRenderer();
- void updateDataModel(QScatterDataProxy *dataProxy);
+ void updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility);
+ void updateData();
void updateScene(Q3DScene *scene);
- void render(GLuint defaultFboHandle);
- QRect mainViewPort();
+ void render(GLuint defaultFboHandle);
protected:
virtual void initializeOpenGL();
- virtual void loadMeshFile();
private:
virtual void initShaders(const QString &vertexShader, const QString &fragmentShader);
+ virtual void initGradientShaders(const QString &vertexShader, const QString &fragmentShader);
virtual void updateShadowQuality(QDataVis::ShadowQuality quality);
virtual void updateTextures();
+ virtual void fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh);
void drawScene(GLuint defaultFboHandle);
- void handleResize();
void loadBackgroundMesh();
void loadGridLineMesh();
@@ -126,6 +125,8 @@ private:
#if !defined(QT_OPENGL_ES_2)
void initDepthShader();
void updateDepthBuffer();
+#else
+ void initPointShader();
#endif
void calculateTranslation(ScatterRenderItem &item);
void calculateSceneScalingFactors();
@@ -135,19 +136,17 @@ private:
friend class ScatterRenderItem;
public slots:
- void updateBackgroundEnabled(bool enable);
-
// Overloaded from abstract renderer
- virtual void updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, qreal min, qreal max);
+ virtual void updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, float min, float max);
- void updateSelectedItemIndex(int index);
+ void updateSelectedItem(int index, const QScatter3DSeries *series);
signals:
- void selectionUpdated(QVector3D selection);
- void selectedItemIndexChanged(int index);
+ void itemClicked(int index, QScatter3DSeries *series);
private:
QVector3D indexToSelectionColor(GLint index);
+ void selectionColorToSeriesAndIndex(const QVector3D &color, int &index, QScatter3DSeries *&series);
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/selectionpointer.cpp b/src/datavisualization/engine/selectionpointer.cpp
index 19294ac8..c4eced30 100644
--- a/src/datavisualization/engine/selectionpointer.cpp
+++ b/src/datavisualization/engine/selectionpointer.cpp
@@ -43,9 +43,8 @@ SelectionPointer::SelectionPointer(Drawer *drawer)
m_labelObj(0),
m_pointObj(0),
m_textureHelper(0),
- m_isInitialized(false),
m_cachedTheme(drawer->theme()),
- m_labelStyle(QDataVis::LabelStyleFromTheme),
+ m_labelBackground(false),
m_drawer(drawer),
m_cachedScene(0)
{
@@ -60,27 +59,18 @@ SelectionPointer::~SelectionPointer()
delete m_labelShader;
delete m_pointShader;
delete m_labelObj;
- delete m_pointObj;
delete m_textureHelper;
}
void SelectionPointer::initializeOpenGL()
{
- if (m_isInitialized)
- return;
-
initializeOpenGLFunctions();
m_textureHelper = new TextureHelper();
m_drawer->initializeOpenGL();
initShaders();
-
loadLabelMesh();
- loadPointMesh();
-
- // Set initialized -flag
- m_isInitialized = true;
}
void SelectionPointer::updateScene(Q3DScene *scene)
@@ -142,16 +132,13 @@ void SelectionPointer::render(GLuint defaultFboHandle)
m_pointShader->setUniformValue(m_pointShader->view(), viewMatrix);
m_pointShader->setUniformValue(m_pointShader->model(), modelMatrix);
m_pointShader->setUniformValue(m_pointShader->nModel(), itModelMatrix.inverted().transposed());
- m_pointShader->setUniformValue(m_pointShader->color(),
- Utils::vectorFromColor(m_cachedTheme.m_highlightBarColor));
+ m_pointShader->setUniformValue(m_pointShader->color(), m_highlightColor);
m_pointShader->setUniformValue(m_pointShader->MVP(), MVPMatrix);
- m_pointShader->setUniformValue(m_pointShader->ambientS(), m_cachedTheme.m_ambientStrength);
- m_pointShader->setUniformValue(m_pointShader->lightS(), m_cachedTheme.m_lightStrength * 2.0f);
+ m_pointShader->setUniformValue(m_pointShader->ambientS(), m_cachedTheme->ambientLightStrength());
+ m_pointShader->setUniformValue(m_pointShader->lightS(), m_cachedTheme->lightStrength() * 2.0f);
m_drawer->drawObject(m_pointShader, m_pointObj);
- m_pointShader->release();
-
//
// Draw the label
//
@@ -162,8 +149,8 @@ void SelectionPointer::render(GLuint defaultFboHandle)
modelMatrixLabel.translate(m_position + labelAlign);
// Position the label towards the camera
- qreal camRotationsX = camera->xRotation();
- qreal camRotationsY = camera->yRotation();
+ float camRotationsX = camera->xRotation();
+ float camRotationsY = camera->yRotation();
if (!m_cachedIsSlicingActivated) {
modelMatrixLabel.rotate(-camRotationsX, 0.0f, 1.0f, 0.0f);
modelMatrixLabel.rotate(-camRotationsY, 1.0f, 0.0f, 0.0f);
@@ -190,7 +177,8 @@ void SelectionPointer::render(GLuint defaultFboHandle)
// Draw the object
m_drawer->drawObject(m_labelShader, m_labelObj, m_labelItem.textureId());
- m_labelShader->release();
+ // Release shader
+ glUseProgram(0);
// Disable textures
glDisable(GL_TEXTURE_2D);
@@ -213,13 +201,22 @@ void SelectionPointer::updateSliceData(bool sliceActivated, GLfloat autoScaleAdj
m_autoScaleAdjustment = autoScaleAdjustment;
}
-void SelectionPointer::setLabel(QString label)
+void SelectionPointer::setHighlightColor(QVector3D colorVector)
{
- m_label = label;
+ m_highlightColor = colorVector;
+}
+void SelectionPointer::setLabel(const QString &label)
+{
+ m_label = label;
m_drawer->generateLabelItem(m_labelItem, m_label);
}
+void SelectionPointer::setPointerObject(ObjectHelper *object)
+{
+ m_pointObj = object;
+}
+
void SelectionPointer::handleDrawerChange()
{
m_cachedTheme = m_drawer->theme();
@@ -247,7 +244,7 @@ void SelectionPointer::initShaders()
m_pointShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragment"));
#else
- m_pointShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexES2"),
+ m_pointShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragmentES2"));
#endif
m_pointShader->initialize();
@@ -258,16 +255,8 @@ void SelectionPointer::loadLabelMesh()
{
if (m_labelObj)
delete m_labelObj;
- m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label"));
+ m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
m_labelObj->load();
}
-void SelectionPointer::loadPointMesh()
-{
- if (m_pointObj)
- delete m_pointObj;
- m_pointObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/sphereSmooth"));
- m_pointObj->load();
-}
-
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/selectionpointer_p.h b/src/datavisualization/engine/selectionpointer_p.h
index 0e766035..8faeb9ac 100644
--- a/src/datavisualization/engine/selectionpointer_p.h
+++ b/src/datavisualization/engine/selectionpointer_p.h
@@ -51,7 +51,7 @@ class Theme;
class Drawer;
class Q3DCamera;
-class QT_DATAVISUALIZATION_EXPORT SelectionPointer : public QObject, protected QOpenGLFunctions
+class SelectionPointer : public QObject, protected QOpenGLFunctions
{
Q_OBJECT
@@ -59,29 +59,29 @@ public:
explicit SelectionPointer(Drawer *drawer);
~SelectionPointer();
- void initializeOpenGL();
void render(GLuint defaultFboHandle = 0);
void setPosition(QVector3D position);
- void setLabel(QString label);
+ void setLabel(const QString &label);
+ void setPointerObject(ObjectHelper *object);
void handleDrawerChange();
void updateBoundingRect(QRect rect);
void updateScene(Q3DScene *scene);
void updateSliceData(bool sliceActivated, GLfloat autoScaleAdjustment);
+ void setHighlightColor(QVector3D colorVector);
private:
+ void initializeOpenGL();
void initShaders();
void loadLabelMesh();
- void loadPointMesh();
private:
ShaderHelper *m_labelShader;
ShaderHelper *m_pointShader;
ObjectHelper *m_labelObj;
- ObjectHelper *m_pointObj;
+ ObjectHelper *m_pointObj; // Not owned
TextureHelper *m_textureHelper;
- bool m_isInitialized;
- Theme m_cachedTheme;
- QDataVis::LabelStyle m_labelStyle;
+ Q3DTheme *m_cachedTheme;
+ bool m_labelBackground;
LabelItem m_labelItem;
Drawer *m_drawer;
QRect m_mainViewPort;
@@ -90,6 +90,7 @@ private:
QString m_label;
bool m_cachedIsSlicingActivated;
GLfloat m_autoScaleAdjustment;
+ QVector3D m_highlightColor;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/seriesrendercache.cpp b/src/datavisualization/engine/seriesrendercache.cpp
new file mode 100644
index 00000000..04b2249d
--- /dev/null
+++ b/src/datavisualization/engine/seriesrendercache.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "seriesrendercache_p.h"
+#include "objecthelper_p.h"
+#include "abstract3drenderer_p.h"
+#include "texturehelper_p.h"
+#include "utils_p.h"
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+const QString smoothString(QStringLiteral("Smooth"));
+
+SeriesRenderCache::SeriesRenderCache()
+ : m_series(0),
+ m_object(0),
+ m_mesh(QAbstract3DSeries::MeshCube),
+ m_baseGradientTexture(0),
+ m_singleHighlightGradientTexture(0),
+ m_multiHighlightGradientTexture(0)
+{
+}
+
+SeriesRenderCache::~SeriesRenderCache()
+{
+}
+
+void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer *renderer)
+{
+ Q_ASSERT(series);
+
+ bool seriesChanged = false;
+
+ if (m_series != series) {
+ m_series = series;
+ seriesChanged = true;
+ }
+
+ QAbstract3DSeriesChangeBitField &changeTracker = series->d_ptr->m_changeTracker;
+
+ if (seriesChanged || changeTracker.itemLabelFormatChanged) {
+ m_itemLabelFormat = series->itemLabelFormat();
+ changeTracker.itemLabelFormatChanged = false;
+ }
+
+ if (seriesChanged || changeTracker.meshChanged || changeTracker.meshSmoothChanged
+ || changeTracker.userDefinedMeshChanged) {
+ m_mesh = series->mesh();
+ changeTracker.meshChanged = false;
+ changeTracker.meshSmoothChanged = false;
+ changeTracker.userDefinedMeshChanged = false;
+
+ QString meshFileName;
+
+ // Compose mesh filename
+ if (m_mesh == QAbstract3DSeries::MeshUserDefined) {
+ // Always use the supplied mesh directly
+ meshFileName = series->userDefinedMesh();
+ } else {
+ switch (m_mesh) {
+ case QAbstract3DSeries::MeshBar:
+ case QAbstract3DSeries::MeshCube:
+ meshFileName = QStringLiteral(":/defaultMeshes/bar");
+ break;
+ case QAbstract3DSeries::MeshPyramid:
+ meshFileName = QStringLiteral(":/defaultMeshes/pyramid");
+ break;
+ case QAbstract3DSeries::MeshCone:
+ meshFileName = QStringLiteral(":/defaultMeshes/cone");
+ break;
+ case QAbstract3DSeries::MeshCylinder:
+ meshFileName = QStringLiteral(":/defaultMeshes/cylinder");
+ break;
+ case QAbstract3DSeries::MeshBevelBar:
+ case QAbstract3DSeries::MeshBevelCube:
+ meshFileName = QStringLiteral(":/defaultMeshes/bevelbar");
+ break;
+ case QAbstract3DSeries::MeshSphere:
+ meshFileName = QStringLiteral(":/defaultMeshes/sphere");
+ break;
+ case QAbstract3DSeries::MeshMinimal:
+ meshFileName = QStringLiteral(":/defaultMeshes/minimal");
+ break;
+ case QAbstract3DSeries::MeshPoint:
+#if defined(QT_OPENGL_ES_2)
+ qWarning("QAbstract3DSeries::MeshPoint is not fully supported on OpenGL ES2");
+#endif
+ break;
+ default:
+ // Default to cube
+ meshFileName = QStringLiteral(":/defaultMeshes/bar");
+ break;
+ }
+
+ if (series->isMeshSmooth() && m_mesh != QAbstract3DSeries::MeshPoint)
+ meshFileName += smoothString;
+
+ // Give renderer an opportunity to customize the mesh
+ renderer->fixMeshFileName(meshFileName, m_mesh);
+ }
+
+ // TODO: Optimize by having some kind of object cache in renderer instead of having separate ObjectHelper for each series?
+ delete m_object;
+ if (meshFileName.isEmpty()) {
+ m_object = 0;
+ } else {
+ m_object = new ObjectHelper(meshFileName);
+ m_object->load();
+ }
+ }
+
+ if (seriesChanged || changeTracker.colorStyleChanged) {
+ m_colorStyle = series->colorStyle();
+ changeTracker.colorStyleChanged = false;
+ }
+
+ if (seriesChanged || changeTracker.baseColorChanged) {
+ m_baseColor = Utils::vectorFromColor(series->baseColor());
+ changeTracker.baseColorChanged = false;
+ }
+
+ if (seriesChanged || changeTracker.baseGradientChanged) {
+ QLinearGradient gradient = series->baseGradient();
+ renderer->fixGradientAndGenerateTexture(&gradient, &m_baseGradientTexture);
+ changeTracker.baseGradientChanged = false;
+ }
+
+ if (seriesChanged || changeTracker.singleHighlightColorChanged) {
+ m_singleHighlightColor = Utils::vectorFromColor(series->singleHighlightColor());
+ changeTracker.singleHighlightColorChanged = false;
+ }
+
+ if (seriesChanged || changeTracker.singleHighlightGradientChanged) {
+ QLinearGradient gradient = series->singleHighlightGradient();
+ renderer->fixGradientAndGenerateTexture(&gradient, &m_singleHighlightGradientTexture);
+ changeTracker.singleHighlightGradientChanged = false;
+ }
+
+ if (seriesChanged || changeTracker.multiHighlightColorChanged) {
+ m_multiHighlightColor = Utils::vectorFromColor(series->multiHighlightColor());
+ changeTracker.multiHighlightColorChanged = false;
+ }
+
+ if (seriesChanged || changeTracker.multiHighlightGradientChanged) {
+ QLinearGradient gradient = series->multiHighlightGradient();
+ renderer->fixGradientAndGenerateTexture(&gradient, &m_multiHighlightGradientTexture);
+ changeTracker.multiHighlightGradientChanged = false;
+ }
+}
+
+void SeriesRenderCache::cleanup(TextureHelper *texHelper)
+{
+ delete m_object;
+ texHelper->deleteTexture(&m_baseGradientTexture);
+ texHelper->deleteTexture(&m_singleHighlightGradientTexture);
+ texHelper->deleteTexture(&m_multiHighlightGradientTexture);
+}
+
+QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/seriesrendercache_p.h b/src/datavisualization/engine/seriesrendercache_p.h
new file mode 100644
index 00000000..906a6c0d
--- /dev/null
+++ b/src/datavisualization/engine/seriesrendercache_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the QtDataVisualization module.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the QtDataVisualization API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef SERIESRENDERCACHE_P_H
+#define SERIESRENDERCACHE_P_H
+
+#include "datavisualizationglobal_p.h"
+#include "qabstract3dseries_p.h"
+
+QT_DATAVISUALIZATION_BEGIN_NAMESPACE
+
+class Abstract3DRenderer;
+class ObjectHelper;
+class TextureHelper;
+
+class SeriesRenderCache
+{
+public:
+ SeriesRenderCache();
+ virtual ~SeriesRenderCache();
+
+ void populate(QAbstract3DSeries *series, Abstract3DRenderer *renderer);
+ void cleanup(TextureHelper *texHelper);
+
+ // NOTE: Series pointer can only be used to access the series when syncing with controller.
+ // It is not guaranteed to be valid while rendering and should only be used as an identifier.
+ inline QAbstract3DSeries *series() const { return m_series; }
+
+ inline const QString &itemLabelFormat() const { return m_itemLabelFormat; }
+ inline const QAbstract3DSeries::Mesh &mesh() const { return m_mesh; }
+ inline ObjectHelper *object() const { return m_object; }
+ inline const Q3DTheme::ColorStyle &colorStyle() const { return m_colorStyle; }
+ inline const QVector3D &baseColor() const { return m_baseColor; }
+ inline const GLuint &baseGradientTexture() const { return m_baseGradientTexture; }
+ inline const QVector3D &singleHighlightColor() const { return m_singleHighlightColor; }
+ inline const GLuint &singleHighlightGradientTexture() const { return m_singleHighlightGradientTexture; }
+ inline const QVector3D &multiHighlightColor() const { return m_multiHighlightColor; }
+ inline const GLuint &multiHighlightGradientTexture() const { return m_multiHighlightGradientTexture; }
+
+protected:
+ QAbstract3DSeries *m_series;
+ QString m_itemLabelFormat;
+ ObjectHelper *m_object;
+ QAbstract3DSeries::Mesh m_mesh;
+
+ Q3DTheme::ColorStyle m_colorStyle;
+ QVector3D m_baseColor;
+ GLuint m_baseGradientTexture;
+ QVector3D m_singleHighlightColor;
+ GLuint m_singleHighlightGradientTexture;
+ QVector3D m_multiHighlightColor;
+ GLuint m_multiHighlightGradientTexture;
+};
+
+QT_DATAVISUALIZATION_END_NAMESPACE
+
+#endif
+
diff --git a/src/datavisualization/engine/shaders/ambient.frag b/src/datavisualization/engine/shaders/ambient.frag
deleted file mode 100644
index 88f850f3..00000000
--- a/src/datavisualization/engine/shaders/ambient.frag
+++ /dev/null
@@ -1,32 +0,0 @@
-#version 120
-
-uniform highp vec3 lightPosition_wrld;
-uniform highp vec3 color_mdl;
-
-varying highp vec3 position_wrld;
-varying highp vec3 normal_cmr;
-varying highp vec3 eyeDirection_cmr;
-varying highp vec3 lightDirection_cmr;
-
-void main() {
- highp vec3 lightColor = vec3(1.0, 1.0, 1.0);
- highp float lightPower = 10.0;
- highp vec3 materialAmbientColor = vec3(0.5, 0.5, 0.5) * color_mdl;
- highp vec3 materialSpecularColor = vec3(0.3, 0.3, 0.3) * color_mdl;
-
- highp float distance = length(lightPosition_wrld - position_wrld);
-
- highp vec3 n = normalize(normal_cmr);
- highp vec3 l = normalize(lightDirection_cmr);
- highp float cosTheta = clamp(dot(n, l), 0.0, 1.0);
-
- highp vec3 E = normalize(eyeDirection_cmr);
- highp vec3 R = reflect(-l, n);
- highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0);
-
- gl_FragColor.rgb =
- materialAmbientColor +
- materialSpecularColor * lightColor * lightPower * pow(cosAlpha, 5) / (distance * distance);
- gl_FragColor.a = 1.0;
-}
-
diff --git a/src/datavisualization/engine/shaders/colorOnY.frag b/src/datavisualization/engine/shaders/colorOnY.frag
index 80e54a61..caea959b 100644
--- a/src/datavisualization/engine/shaders/colorOnY.frag
+++ b/src/datavisualization/engine/shaders/colorOnY.frag
@@ -1,9 +1,11 @@
#version 120
uniform highp vec3 lightPosition_wrld;
-uniform highp vec3 color_mdl;
uniform highp float lightStrength;
uniform highp float ambientStrength;
+uniform sampler2D textureSampler;
+uniform highp float gradMin;
+uniform highp float gradHeight;
varying highp vec3 position_wrld;
varying highp vec3 normal_cmr;
@@ -12,8 +14,8 @@ varying highp vec3 lightDirection_cmr;
varying highp vec2 coords_mdl;
void main() {
- highp float heightMod = (coords_mdl.y * 0.3) + 0.7; // Add 30% black to the bottom
- highp vec3 materialDiffuseColor = heightMod * color_mdl;
+ highp vec2 gradientUV = vec2(0.0, gradMin + ((coords_mdl.y + 1.0) * gradHeight));
+ highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz;
highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
diff --git a/src/datavisualization/engine/shaders/colorOnY_ES2.frag b/src/datavisualization/engine/shaders/colorOnY_ES2.frag
index aba52cfe..bb6e28c7 100644
--- a/src/datavisualization/engine/shaders/colorOnY_ES2.frag
+++ b/src/datavisualization/engine/shaders/colorOnY_ES2.frag
@@ -1,7 +1,9 @@
uniform highp vec3 lightPosition_wrld;
-uniform highp vec3 color_mdl;
uniform highp float lightStrength;
uniform highp float ambientStrength;
+uniform sampler2D textureSampler;
+uniform highp float gradMin;
+uniform highp float gradHeight;
varying highp vec3 position_wrld;
varying highp vec3 normal_cmr;
@@ -10,8 +12,8 @@ varying highp vec3 lightDirection_cmr;
varying highp vec2 coords_mdl;
void main() {
- highp float heightMod = (coords_mdl.y * 0.3) + 0.7; // Add 30% black to the bottom
- highp vec3 materialDiffuseColor = heightMod * color_mdl;
+ highp vec2 gradientUV = vec2(0.0, gradMin + ((coords_mdl.y + 1.0) * gradHeight));
+ highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz;
highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
diff --git a/src/datavisualization/engine/shaders/default.vert b/src/datavisualization/engine/shaders/default.vert
index 14f77773..efb40862 100644
--- a/src/datavisualization/engine/shaders/default.vert
+++ b/src/datavisualization/engine/shaders/default.vert
@@ -1,5 +1,3 @@
-#version 120
-
attribute highp vec3 vertexPosition_mdl;
attribute highp vec2 vertexUV;
attribute highp vec3 vertexNormal_mdl;
diff --git a/src/datavisualization/engine/shaders/default_ES2.vert b/src/datavisualization/engine/shaders/default_ES2.vert
deleted file mode 100644
index efb40862..00000000
--- a/src/datavisualization/engine/shaders/default_ES2.vert
+++ /dev/null
@@ -1,26 +0,0 @@
-attribute highp vec3 vertexPosition_mdl;
-attribute highp vec2 vertexUV;
-attribute highp vec3 vertexNormal_mdl;
-
-uniform highp mat4 MVP;
-uniform highp mat4 V;
-uniform highp mat4 M;
-uniform highp mat4 itM;
-uniform highp vec3 lightPosition_wrld;
-
-varying highp vec3 position_wrld;
-varying highp vec3 normal_cmr;
-varying highp vec3 eyeDirection_cmr;
-varying highp vec3 lightDirection_cmr;
-varying highp vec2 coords_mdl;
-
-void main() {
- gl_Position = MVP * vec4(vertexPosition_mdl, 1.0);
- coords_mdl = vertexPosition_mdl.xy;
- position_wrld = (M * vec4(vertexPosition_mdl, 1.0)).xyz;
- vec3 vertexPosition_cmr = (V * M * vec4(vertexPosition_mdl, 1.0)).xyz;
- eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr;
- vec3 lightPosition_cmr = (V * vec4(lightPosition_wrld, 1.0)).xyz;
- lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr;
- normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz;
-}
diff --git a/src/datavisualization/engine/shaders/selection.frag b/src/datavisualization/engine/shaders/plainColor.frag
index 099c87a1..099c87a1 100644
--- a/src/datavisualization/engine/shaders/selection.frag
+++ b/src/datavisualization/engine/shaders/plainColor.frag
diff --git a/src/datavisualization/engine/shaders/selection.vert b/src/datavisualization/engine/shaders/plainColor.vert
index 64d17e15..64d17e15 100644
--- a/src/datavisualization/engine/shaders/selection.vert
+++ b/src/datavisualization/engine/shaders/plainColor.vert
diff --git a/src/datavisualization/engine/shaders/surfaceGrid.vert b/src/datavisualization/engine/shaders/point_ES2.vert
index 5582d633..b2dfdd7b 100644
--- a/src/datavisualization/engine/shaders/surfaceGrid.vert
+++ b/src/datavisualization/engine/shaders/point_ES2.vert
@@ -1,6 +1,8 @@
-attribute highp vec3 vertexPosition_mdl;
uniform highp mat4 MVP;
+attribute highp vec3 vertexPosition_mdl;
+
void main() {
+ gl_PointSize = 5.0;
gl_Position = MVP * vec4(vertexPosition_mdl, 1.0);
}
diff --git a/src/datavisualization/engine/shaders/shadowNoTexColorOnY.frag b/src/datavisualization/engine/shaders/shadowNoTexColorOnY.frag
index 68ba2368..9882cd92 100644
--- a/src/datavisualization/engine/shaders/shadowNoTexColorOnY.frag
+++ b/src/datavisualization/engine/shaders/shadowNoTexColorOnY.frag
@@ -3,8 +3,10 @@
uniform highp float lightStrength;
uniform highp float ambientStrength;
uniform highp float shadowQuality;
-uniform highp vec3 color_mdl;
uniform highp sampler2DShadow shadowMap;
+uniform sampler2D textureSampler;
+uniform highp float gradMin;
+uniform highp float gradHeight;
varying highp vec4 shadowCoord;
varying highp vec3 position_wrld;
@@ -37,8 +39,8 @@ highp vec2 poissonDisk[16] = vec2[16](vec2(-0.94201624, -0.39906216),
}*/
void main() {
- highp float heightMod = (coords_mdl.y * 0.3) + 0.7; // Add 30% black to the bottom
- highp vec3 materialDiffuseColor = heightMod * color_mdl;
+ highp vec2 gradientUV = vec2(0.0, gradMin + ((coords_mdl.y + 1.0) * gradHeight));
+ highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz;
highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
diff --git a/src/datavisualization/engine/shaders/surface.frag b/src/datavisualization/engine/shaders/surface.frag
index 4b1357b1..576cc51f 100644
--- a/src/datavisualization/engine/shaders/surface.frag
+++ b/src/datavisualization/engine/shaders/surface.frag
@@ -1,6 +1,6 @@
#version 120
-varying highp vec3 coords_mdl;
+varying highp vec2 coords_mdl;
varying highp vec3 position_wrld;
varying highp vec3 normal_cmr;
varying highp vec3 eyeDirection_cmr;
@@ -12,7 +12,7 @@ uniform highp float lightStrength;
uniform highp float ambientStrength;
void main() {
- highp vec2 gradientUV = vec2(0.0, (coords_mdl.y + 1.001) / 2.0); // 1000 pixel texture, we need a margin for 1/1000 rounding error
+ highp vec2 gradientUV = vec2(0.0, (coords_mdl.y + 1.0) / 2.0);
highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz;
highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
diff --git a/src/datavisualization/engine/shaders/surfaceFlat.frag b/src/datavisualization/engine/shaders/surfaceFlat.frag
index 1f2a3822..fd42a289 100644
--- a/src/datavisualization/engine/shaders/surfaceFlat.frag
+++ b/src/datavisualization/engine/shaders/surfaceFlat.frag
@@ -14,7 +14,7 @@ uniform highp float lightStrength;
uniform highp float ambientStrength;
void main() {
- highp vec2 gradientUV = vec2(0.0, (coords_mdl.y + 1.001) / 2.0); // 1000 pixel texture, we need a margin for 1/1000 rounding error
+ highp vec2 gradientUV = vec2(0.0, (coords_mdl.y + 1.0) / 2.0);
highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz;
highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
diff --git a/src/datavisualization/engine/shaders/surfaceGrid.frag b/src/datavisualization/engine/shaders/surfaceGrid.frag
deleted file mode 100644
index 1658b316..00000000
--- a/src/datavisualization/engine/shaders/surfaceGrid.frag
+++ /dev/null
@@ -1,6 +0,0 @@
-uniform highp vec3 color_mdl;
-
-void main() {
- gl_FragColor.rgb = color_mdl;
-}
-
diff --git a/src/datavisualization/engine/shaders/surfaceShadowFlat.frag b/src/datavisualization/engine/shaders/surfaceShadowFlat.frag
new file mode 100644
index 00000000..6341136e
--- /dev/null
+++ b/src/datavisualization/engine/shaders/surfaceShadowFlat.frag
@@ -0,0 +1,70 @@
+#version 120
+
+#extension GL_EXT_gpu_shader4 : require
+
+varying highp vec3 coords_mdl;
+varying highp vec3 position_wrld;
+flat varying highp vec3 normal_cmr;
+varying highp vec3 eyeDirection_cmr;
+varying highp vec3 lightDirection_cmr;
+
+uniform highp sampler2DShadow shadowMap;
+uniform sampler2D textureSampler;
+varying highp vec4 shadowCoord;
+uniform highp vec3 lightPosition_wrld;
+uniform highp float lightStrength;
+uniform highp float ambientStrength;
+uniform highp float shadowQuality;
+
+highp vec2 poissonDisk[16] = vec2[16](vec2(-0.94201624, -0.39906216),
+ vec2(0.94558609, -0.76890725),
+ vec2(-0.094184101, -0.92938870),
+ vec2(0.34495938, 0.29387760),
+ vec2(-0.91588581, 0.45771432),
+ vec2(-0.81544232, -0.87912464),
+ vec2(-0.38277543, 0.27676845),
+ vec2(0.97484398, 0.75648379),
+ vec2(0.44323325, -0.97511554),
+ vec2(0.53742981, -0.47373420),
+ vec2(-0.26496911, -0.41893023),
+ vec2(0.79197514, 0.19090188),
+ vec2(-0.24188840, 0.99706507),
+ vec2(-0.81409955, 0.91437590),
+ vec2(0.19984126, 0.78641367),
+ vec2(0.14383161, -0.14100790));
+
+void main() {
+ highp vec2 gradientUV = vec2(0.0, (coords_mdl.y + 1.0) / 2.0);
+ highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz;
+ highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
+ highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
+
+ highp vec3 n = normalize(normal_cmr);
+ highp vec3 l = normalize(lightDirection_cmr);
+ highp float cosTheta = clamp(dot(n, l), 0.0, 1.0);
+
+ highp vec3 E = normalize(eyeDirection_cmr);
+ highp vec3 R = reflect(-l, n);
+ highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0);
+
+ highp float bias = 0.005 * tan(acos(cosTheta));
+ bias = clamp(bias, 0.0, 0.01);
+
+ vec4 shadCoords = shadowCoord;
+ shadCoords.z -= bias;
+
+ highp float visibility = 0.6;
+ for (int i = 0; i < 15; i++) {
+ vec4 shadCoordsPD = shadCoords;
+ shadCoordsPD.x += cos(poissonDisk[i].x) / shadowQuality;
+ shadCoordsPD.y += sin(poissonDisk[i].y) / shadowQuality;
+ visibility += 0.025 * shadow2DProj(shadowMap, shadCoordsPD).r;
+ }
+
+ gl_FragColor.rgb =
+ visibility * (materialAmbientColor +
+ materialDiffuseColor * lightStrength * cosTheta +
+ materialSpecularColor * lightStrength * pow(cosAlpha, 10));
+ gl_FragColor.a = 1.0;
+}
+
diff --git a/src/datavisualization/engine/shaders/surface.vert b/src/datavisualization/engine/shaders/surfaceShadowFlat.vert
index 28152abc..0a6e967f 100644
--- a/src/datavisualization/engine/shaders/surface.vert
+++ b/src/datavisualization/engine/shaders/surfaceShadowFlat.vert
@@ -1,3 +1,7 @@
+#version 120
+
+#extension GL_EXT_gpu_shader4 : require
+
attribute highp vec3 vertexPosition_mdl;
attribute highp vec3 vertexNormal_mdl;
@@ -5,17 +9,25 @@ uniform highp mat4 MVP;
uniform highp mat4 V;
uniform highp mat4 M;
uniform highp mat4 itM;
+uniform highp mat4 depthMVP;
uniform highp vec3 lightPosition_wrld;
varying highp vec3 position_wrld;
-varying highp vec3 normal_cmr;
+flat varying highp vec3 normal_cmr;
varying highp vec3 eyeDirection_cmr;
varying highp vec3 lightDirection_cmr;
+varying highp vec4 shadowCoord;
varying highp vec3 coords_mdl;
+const highp mat4 bias = mat4(0.5, 0.0, 0.0, 0.0,
+ 0.0, 0.5, 0.0, 0.0,
+ 0.0, 0.0, 0.5, 0.0,
+ 0.5, 0.5, 0.5, 1.0);
+
void main() {
gl_Position = MVP * vec4(vertexPosition_mdl, 1.0);
coords_mdl = vertexPosition_mdl;
+ shadowCoord = bias * depthMVP * vec4(vertexPosition_mdl, 1.0);
position_wrld = (M * vec4(vertexPosition_mdl, 1.0)).xyz;
vec3 vertexPosition_cmr = (V * M * vec4(vertexPosition_mdl, 1.0)).xyz;
eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr;
diff --git a/src/datavisualization/engine/shaders/surfaceShadowNoTex.frag b/src/datavisualization/engine/shaders/surfaceShadowNoTex.frag
new file mode 100644
index 00000000..755be3f1
--- /dev/null
+++ b/src/datavisualization/engine/shaders/surfaceShadowNoTex.frag
@@ -0,0 +1,68 @@
+#version 120
+
+varying highp vec2 coords_mdl;
+varying highp vec3 position_wrld;
+varying highp vec3 normal_cmr;
+varying highp vec3 eyeDirection_cmr;
+varying highp vec3 lightDirection_cmr;
+
+uniform highp sampler2DShadow shadowMap;
+uniform sampler2D textureSampler;
+varying highp vec4 shadowCoord;
+uniform highp vec3 lightPosition_wrld;
+uniform highp float lightStrength;
+uniform highp float ambientStrength;
+uniform highp float shadowQuality;
+
+highp vec2 poissonDisk[16] = vec2[16](vec2(-0.94201624, -0.39906216),
+ vec2(0.94558609, -0.76890725),
+ vec2(-0.094184101, -0.92938870),
+ vec2(0.34495938, 0.29387760),
+ vec2(-0.91588581, 0.45771432),
+ vec2(-0.81544232, -0.87912464),
+ vec2(-0.38277543, 0.27676845),
+ vec2(0.97484398, 0.75648379),
+ vec2(0.44323325, -0.97511554),
+ vec2(0.53742981, -0.47373420),
+ vec2(-0.26496911, -0.41893023),
+ vec2(0.79197514, 0.19090188),
+ vec2(-0.24188840, 0.99706507),
+ vec2(-0.81409955, 0.91437590),
+ vec2(0.19984126, 0.78641367),
+ vec2(0.14383161, -0.14100790));
+
+void main() {
+ highp vec2 gradientUV = vec2(0.0, (coords_mdl.y + 1.0) / 2.0);
+ highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz;
+ highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
+ highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
+
+ highp vec3 n = normalize(normal_cmr);
+ highp vec3 l = normalize(lightDirection_cmr);
+ highp float cosTheta = clamp(dot(n, l), 0.0, 1.0);
+
+ highp vec3 E = normalize(eyeDirection_cmr);
+ highp vec3 R = reflect(-l, n);
+ highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0);
+
+ highp float bias = 0.005 * tan(acos(cosTheta));
+ bias = clamp(bias, 0.0, 0.01);
+
+ vec4 shadCoords = shadowCoord;
+ shadCoords.z -= bias;
+
+ highp float visibility = 0.6;
+ for (int i = 0; i < 15; i++) {
+ vec4 shadCoordsPD = shadCoords;
+ shadCoordsPD.x += cos(poissonDisk[i].x) / shadowQuality;
+ shadCoordsPD.y += sin(poissonDisk[i].y) / shadowQuality;
+ visibility += 0.025 * shadow2DProj(shadowMap, shadCoordsPD).r;
+ }
+
+ gl_FragColor.rgb =
+ visibility * (materialAmbientColor +
+ materialDiffuseColor * lightStrength * cosTheta +
+ materialSpecularColor * lightStrength * pow(cosAlpha, 10));
+ gl_FragColor.a = 1.0;
+}
+
diff --git a/src/datavisualization/engine/shaders/surface_ES2.frag b/src/datavisualization/engine/shaders/surface_ES2.frag
index 7f40ba4d..c7e75594 100644
--- a/src/datavisualization/engine/shaders/surface_ES2.frag
+++ b/src/datavisualization/engine/shaders/surface_ES2.frag
@@ -1,5 +1,5 @@
varying highp vec2 UV;
-varying highp vec3 coords_mdl;
+varying highp vec2 coords_mdl;
varying highp vec3 position_wrld;
varying highp vec3 normal_cmr;
varying highp vec3 eyeDirection_cmr;
@@ -11,7 +11,7 @@ uniform highp float lightStrength;
uniform highp float ambientStrength;
void main() {
- highp vec2 gradientUV = vec2(0.0, (coords_mdl.y + 1.001) / 2.0); // ~1000 pixel texture, we need a margin for 1/1000 rounding error
+ highp vec2 gradientUV = vec2(0.0, (coords_mdl.y + 1.0) / 2.0);
highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz;
highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
diff --git a/src/datavisualization/engine/shaders/texture.frag b/src/datavisualization/engine/shaders/texture.frag
deleted file mode 100644
index a6d7b2eb..00000000
--- a/src/datavisualization/engine/shaders/texture.frag
+++ /dev/null
@@ -1,35 +0,0 @@
-#version 120
-
-uniform highp vec3 lightPosition_wrld;
-uniform highp vec3 color_mdl;
-uniform highp float lightStrength;
-uniform highp float ambientStrength;
-uniform sampler2D textureSampler;
-
-varying highp vec2 UV;
-varying highp vec3 position_wrld;
-varying highp vec3 normal_cmr;
-varying highp vec3 eyeDirection_cmr;
-varying highp vec3 lightDirection_cmr;
-
-void main() {
- highp vec3 materialDiffuseColor = texture2D(textureSampler, UV).rgb;
- highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
- highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
-
- highp float distance = length(lightPosition_wrld - position_wrld);
- highp vec3 n = normalize(normal_cmr);
- highp vec3 l = normalize(lightDirection_cmr);
- highp float cosTheta = clamp(dot(n, l), 0.0, 1.0);
-
- highp vec3 E = normalize(eyeDirection_cmr);
- highp vec3 R = reflect(-l, n);
- highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0);
-
- gl_FragColor.rgb =
- materialAmbientColor +
- materialDiffuseColor * lightStrength * (cosTheta * cosTheta) / distance +
- materialSpecularColor * lightStrength * pow(cosAlpha, 10) / distance;
- gl_FragColor.a = texture2D(textureSampler, UV).a;
-}
-
diff --git a/src/datavisualization/engine/shaders/texture.vert b/src/datavisualization/engine/shaders/texture.vert
deleted file mode 100644
index 01f922e0..00000000
--- a/src/datavisualization/engine/shaders/texture.vert
+++ /dev/null
@@ -1,26 +0,0 @@
-uniform highp mat4 MVP;
-uniform highp mat4 V;
-uniform highp mat4 M;
-uniform highp mat4 itM;
-uniform highp vec3 lightPosition_wrld;
-
-attribute highp vec3 vertexPosition_mdl;
-attribute highp vec2 vertexUV;
-attribute highp vec3 vertexNormal_mdl;
-
-varying highp vec2 UV;
-varying highp vec3 position_wrld;
-varying highp vec3 normal_cmr;
-varying highp vec3 eyeDirection_cmr;
-varying highp vec3 lightDirection_cmr;
-
-void main() {
- gl_Position = MVP * vec4(vertexPosition_mdl, 1.0);
- position_wrld = (M * vec4(vertexPosition_mdl, 1.0)).xyz;
- vec3 vertexPosition_cmr = (V * M * vec4(vertexPosition_mdl, 1.0)).xyz;
- eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr;
- vec3 lightPosition_cmr = (V * vec4(lightPosition_wrld, 1.0)).xyz;
- lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr;
- normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz;
- UV = vertexUV;
-}
diff --git a/src/datavisualization/engine/shaders/texture_ES2.frag b/src/datavisualization/engine/shaders/texture_ES2.frag
deleted file mode 100644
index 58097ba5..00000000
--- a/src/datavisualization/engine/shaders/texture_ES2.frag
+++ /dev/null
@@ -1,37 +0,0 @@
-uniform highp vec3 lightPosition_wrld;
-uniform highp vec3 color_mdl;
-uniform highp float lightStrength;
-uniform highp float ambientStrength;
-uniform sampler2D textureSampler;
-
-varying highp vec2 UV;
-varying highp vec3 position_wrld;
-varying highp vec3 normal_cmr;
-varying highp vec3 eyeDirection_cmr;
-varying highp vec3 lightDirection_cmr;
-
-void main() {
- highp vec3 materialDiffuseColor = texture2D(textureSampler, UV).rgb;
- highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor;
- highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0);
-
- highp float distance = length(lightPosition_wrld - position_wrld);
- highp vec3 n = normalize(normal_cmr);
- highp vec3 l = normalize(lightDirection_cmr);
- highp float cosTheta = dot(n, l);
- if (cosTheta < 0.0) cosTheta = 0.0;
- else if (cosTheta > 1.0) cosTheta = 1.0;
-
- highp vec3 E = normalize(eyeDirection_cmr);
- highp vec3 R = reflect(-l, n);
- highp float cosAlpha = dot(E, R);
- if (cosAlpha < 0.0) cosAlpha = 0.0;
- else if (cosAlpha > 1.0) cosAlpha = 1.0;
-
- gl_FragColor.rgb =
- materialAmbientColor +
- materialDiffuseColor * lightStrength * (cosTheta * cosTheta) / distance +
- materialSpecularColor * lightStrength * (cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha) / distance;
- gl_FragColor.a = texture2D(textureSampler, UV).a;
-}
-
diff --git a/src/datavisualization/engine/surface3dcontroller.cpp b/src/datavisualization/engine/surface3dcontroller.cpp
index 8d1bcf85..3cec72d1 100644
--- a/src/datavisualization/engine/surface3dcontroller.cpp
+++ b/src/datavisualization/engine/surface3dcontroller.cpp
@@ -23,6 +23,8 @@
#include "q3dvalueaxis_p.h"
#include "q3dcategoryaxis.h"
#include "qsurfacedataproxy_p.h"
+#include "qsurface3dseries_p.h"
+#include "shaderhelper_p.h"
#include <QMatrix4x4>
@@ -33,20 +35,16 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
Surface3DController::Surface3DController(QRect rect)
: Abstract3DController(rect),
m_renderer(0),
- m_isSmoothSurfaceEnabled(false),
- m_isSurfaceGridEnabled(true)
+ m_selectedPoint(invalidSelectionPosition()),
+ m_selectedSeries(0),
+ m_flatShadingSupported(true)
{
- setActiveDataProxy(0);
-
// Setting a null axis creates a new default axis according to orientation and graph type.
// Note: these cannot be set in the Abstract3DController constructor, as they will call virtual
// functions implemented by subclasses.
setAxisX(0);
setAxisY(0);
setAxisZ(0);
-
- // Set the default from the theme
- m_userDefinedGradient = theme().m_surfaceGradient;
}
Surface3DController::~Surface3DController()
@@ -62,38 +60,34 @@ void Surface3DController::initializeOpenGL()
m_renderer = new Surface3DRenderer(this);
setRenderer(m_renderer);
synchDataToRenderer();
+ QObject::connect(m_renderer, &Surface3DRenderer::pointClicked, this,
+ &Surface3DController::handlePointClicked, Qt::QueuedConnection);
emitNeedRender();
}
void Surface3DController::synchDataToRenderer()
{
- Abstract3DController::synchDataToRenderer();
-
if (!isInitialized())
return;
- // Notify changes to renderer
- if (m_changeTracker.gradientColorChanged) {
- m_renderer->updateSurfaceGradient(m_userDefinedGradient);
- m_changeTracker.gradientColorChanged = false;
- }
+ Abstract3DController::synchDataToRenderer();
- if (m_changeTracker.smoothStatusChanged) {
- bool oldSmoothStatus = m_isSmoothSurfaceEnabled;
- m_isSmoothSurfaceEnabled = m_renderer->updateSmoothStatus(m_isSmoothSurfaceEnabled);
- m_changeTracker.smoothStatusChanged = false;
- if (oldSmoothStatus != m_isSmoothSurfaceEnabled)
- emit smoothSurfaceEnabledChanged(m_isSmoothSurfaceEnabled);
+ // Notify changes to renderer
+ if (m_changeTracker.rowsChanged) {
+ m_renderer->updateRows(m_changedRows);
+ m_changeTracker.rowsChanged = false;
+ m_changedRows.clear();
}
- if (m_changeTracker.surfaceGridChanged) {
- m_renderer->updateSurfaceGridStatus(m_isSurfaceGridEnabled);
- m_changeTracker.surfaceGridChanged = false;
+ if (m_changeTracker.itemChanged) {
+ m_renderer->updateItem(m_changedItems);
+ m_changeTracker.itemChanged = false;
+ m_changedItems.clear();
}
- if (m_isDataDirty) {
- m_renderer->updateDataModel(static_cast<QSurfaceDataProxy *>(m_data));
- m_isDataDirty = false;
+ if (m_changeTracker.selectedPointChanged) {
+ m_renderer->updateSelectedPoint(m_selectedPoint, m_selectedSeries);
+ m_changeTracker.selectedPointChanged = false;
}
}
@@ -107,132 +101,392 @@ void Surface3DController::handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstr
void Surface3DController::handleAxisRangeChangedBySender(QObject *sender)
{
- scene()->setSlicingActive(false);
Abstract3DController::handleAxisRangeChangedBySender(sender);
+
+ // Update selected point - may be moved offscreen
+ setSelectedPoint(m_selectedPoint, m_selectedSeries);
}
-void Surface3DController::setSmoothSurface(bool enable)
+void Surface3DController::handleSeriesVisibilityChangedBySender(QObject *sender)
{
- bool changed = m_isSmoothSurfaceEnabled != enable;
- m_isSmoothSurfaceEnabled = enable;
- m_changeTracker.smoothStatusChanged = true;
- emitNeedRender();
+ Abstract3DController::handleSeriesVisibilityChangedBySender(sender);
- if (changed)
- emit smoothSurfaceEnabledChanged(m_isSmoothSurfaceEnabled);
+ // Visibility changes may require disabling/enabling slicing,
+ // so just reset selection to ensure everything is still valid.
+ setSelectedPoint(m_selectedPoint, m_selectedSeries);
}
-bool Surface3DController::smoothSurface()
+QPoint Surface3DController::invalidSelectionPosition()
{
- return m_isSmoothSurfaceEnabled;
+ static QPoint invalidSelectionPoint(-1, -1);
+ return invalidSelectionPoint;
}
-void Surface3DController::setSurfaceGrid(bool enable)
+bool Surface3DController::isFlatShadingSupported()
{
- m_isSurfaceGridEnabled = enable;
- m_changeTracker.surfaceGridChanged = true;
- emitNeedRender();
+ return m_flatShadingSupported;
}
-bool Surface3DController::surfaceGrid()
+void Surface3DController::addSeries(QAbstract3DSeries *series)
{
- return m_isSurfaceGridEnabled;
-}
+ Q_ASSERT(series && series->type() == QAbstract3DSeries::SeriesTypeSurface);
-void Surface3DController::setGradient(const QLinearGradient &gradient)
-{
- m_userDefinedGradient = gradient;
- m_userDefinedGradient.setStart(2, 1024);
- m_userDefinedGradient.setFinalStop(0, 0);
- m_changeTracker.gradientColorChanged = true;
- emitNeedRender();
+ if (!m_seriesList.size()) {
+ Abstract3DController::addSeries(series);
+
+ adjustValueAxisRange();
+ } else {
+ qWarning("Surface graph only supports a single series.");
+ }
+
+ QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(series);
+ if (surfaceSeries->selectedPoint() != invalidSelectionPosition())
+ setSelectedPoint(surfaceSeries->selectedPoint(), surfaceSeries);
}
-QLinearGradient Surface3DController::gradient() const
+void Surface3DController::removeSeries(QAbstract3DSeries *series)
{
- return m_userDefinedGradient;
+ if (series && series->d_ptr->m_controller == this) {
+ Abstract3DController::removeSeries(series);
+
+ if (m_selectedSeries == series)
+ setSelectedPoint(invalidSelectionPosition(), 0);
+
+ adjustValueAxisRange();
+ }
}
-void Surface3DController::setGradientColorAt(qreal pos, const QColor &color)
+QList<QSurface3DSeries *> Surface3DController::surfaceSeriesList()
{
- m_userDefinedGradient.setColorAt(pos, color);
- m_changeTracker.gradientColorChanged = true;
- emitNeedRender();
+ QList<QAbstract3DSeries *> abstractSeriesList = seriesList();
+ QList<QSurface3DSeries *> surfaceSeriesList;
+ foreach (QAbstract3DSeries *abstractSeries, abstractSeriesList) {
+ QSurface3DSeries *surfaceSeries = qobject_cast<QSurface3DSeries *>(abstractSeries);
+ if (surfaceSeries)
+ surfaceSeriesList.append(surfaceSeries);
+ }
+
+ return surfaceSeriesList;
}
-void Surface3DController::setSelectionMode(QDataVis::SelectionMode mode)
+void Surface3DController::setSelectionMode(QDataVis::SelectionFlags mode)
{
- if (!(mode == QDataVis::SelectionModeNone || mode == QDataVis::SelectionModeItem
- || mode == QDataVis::SelectionModeSliceRow
- || mode == QDataVis::SelectionModeSliceColumn)) {
+ // Currently surface only supports row and column modes when also slicing
+ if ((mode.testFlag(QDataVis::SelectionRow) || mode.testFlag(QDataVis::SelectionColumn))
+ && !mode.testFlag(QDataVis::SelectionSlice)) {
qWarning("Unsupported selection mode.");
return;
+ } else if (mode.testFlag(QDataVis::SelectionSlice)
+ && (mode.testFlag(QDataVis::SelectionRow) == mode.testFlag(QDataVis::SelectionColumn))) {
+ qWarning("Must specify one of either row or column selection mode in conjunction with slicing mode.");
+ } else {
+ QDataVis::SelectionFlags oldMode = selectionMode();
+
+ Abstract3DController::setSelectionMode(mode);
+
+ if (mode != oldMode) {
+ // Refresh selection upon mode change to ensure slicing is correctly updated
+ // according to series the visibility.
+ setSelectedPoint(m_selectedPoint, m_selectedSeries);
+
+ // Special case: Always deactivate slicing when changing away from slice
+ // automanagement, as this can't be handled in setSelectedBar.
+ if (!mode.testFlag(QDataVis::SelectionSlice)
+ && oldMode.testFlag(QDataVis::SelectionSlice)) {
+ scene()->setSlicingActive(false);
+ }
+ }
}
- // Disable zoom if selection mode changes
- setSlicingActive(false);
- Abstract3DController::setSelectionMode(mode);
}
+void Surface3DController::setSelectedPoint(const QPoint &position, QSurface3DSeries *series)
+{
+ // If the selection targets non-existent point, clear selection instead.
+ QPoint pos = position;
+
+ // Series may already have been removed, so check it before setting the selection.
+ if (!m_seriesList.contains(series))
+ series = 0;
+
+ const QSurfaceDataProxy *proxy = 0;
+ if (series)
+ proxy = series->dataProxy();
+
+ if (!proxy)
+ pos = invalidSelectionPosition();
+
+ if (pos != invalidSelectionPosition()) {
+ int maxRow = proxy->rowCount() - 1;
+ int maxCol = proxy->columnCount() - 1;
+
+ if (pos.x() < 0 || pos.x() > maxRow || pos.y() < 0 || pos.y() > maxCol)
+ pos = invalidSelectionPosition();
+ }
+
+ if (selectionMode().testFlag(QDataVis::SelectionSlice)) {
+ if (pos == invalidSelectionPosition() || !series->isVisible()) {
+ scene()->setSlicingActive(false);
+ } else {
+ // If the selected point is outside data window, or there is no selected point, disable slicing
+ // TODO: (QTRD-2351) This logic doesn't match the renderer logic for non straight surfaces,
+ // but that logic needs to change anyway, so this is good for now.
+ float axisMinX = m_axisX->min();
+ float axisMaxX = m_axisX->max();
+ float axisMinZ = m_axisZ->min();
+ float axisMaxZ = m_axisZ->max();
+
+ QSurfaceDataItem item = proxy->array()->at(pos.x())->at(pos.y());
+ if (item.x() < axisMinX || item.x() > axisMaxX
+ || item.z() < axisMinZ || item.z() > axisMaxZ) {
+ scene()->setSlicingActive(false);
+ } else {
+ scene()->setSlicingActive(true);
+ }
+ }
+ emitNeedRender();
+ }
+
+ if (pos != m_selectedPoint) {
+ m_selectedPoint = pos;
+ m_selectedSeries = series;
+ m_changeTracker.selectedPointChanged = true;
+
+ // Clear selection from other series and finally set new selection to the specified series
+ foreach (QAbstract3DSeries *otherSeries, m_seriesList) {
+ QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(otherSeries);
+ if (surfaceSeries != m_selectedSeries)
+ surfaceSeries->dptr()->setSelectedPoint(invalidSelectionPosition());
+ }
+ if (m_selectedSeries)
+ m_selectedSeries->dptr()->setSelectedPoint(m_selectedPoint);
-void Surface3DController::setActiveDataProxy(QAbstractDataProxy *proxy)
+ emitNeedRender();
+ }
+}
+
+void Surface3DController::handleArrayReset()
+{
+ adjustValueAxisRange();
+ m_isDataDirty = true;
+ // Clear selection unless still valid
+ setSelectedPoint(m_selectedPoint, m_selectedSeries);
+ emitNeedRender();
+}
+
+void Surface3DController::handlePointClicked(const QPoint &position, QSurface3DSeries *series)
{
- // Setting null proxy indicates default proxy
- if (!proxy) {
- proxy = new QSurfaceDataProxy;
- proxy->d_ptr->setDefaultProxy(true);
+ setSelectedPoint(position, series);
+ // TODO: pass clicked to parent. (QTRD-2517)
+ // TODO: Also hover needed? (QTRD-2131)
+}
+
+void Surface3DController::handleFlatShadingSupportedChange(bool supported)
+{
+ // Handle renderer flat surface support indicator signal. This happens exactly once per renderer.
+ if (m_flatShadingSupported != supported) {
+ m_flatShadingSupported = supported;
+ // Emit the change for all added surfaces
+ foreach (QAbstract3DSeries *series, m_seriesList) {
+ QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(series);
+ emit surfaceSeries->flatShadingSupportedChanged(m_flatShadingSupported);
+ }
}
+}
- Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeSurface);
+void Surface3DController::handleRowsChanged(int startIndex, int count)
+{
+ QSurfaceDataProxy *sender = static_cast<QSurfaceDataProxy *>(QObject::sender());
+ if (m_changedRows.size() == 0)
+ m_changedRows.reserve(sender->rowCount());
+
+ if (static_cast<QSurface3DSeries *>(m_seriesList.at(0)) == sender->series()) {
+ // Change is for the visible series, put the change to queue
+ int oldChangeCount = m_changedRows.size();
+ for (int i = 0; i < count; i++) {
+ bool newItem = true;
+ int candidate = startIndex + i;
+ for (int i = 0; i < oldChangeCount; i++) {
+ if (m_changedRows.at(i) == candidate) {
+ newItem = false;
+ break;
+ }
+ }
+ if (newItem)
+ m_changedRows.append(candidate);
+ }
+ if (m_changedRows.size()) {
+ m_changeTracker.rowsChanged = true;
- Abstract3DController::setActiveDataProxy(proxy);
+ adjustValueAxisRange();
+ // Clear selection unless still valid
+ setSelectedPoint(m_selectedPoint, m_selectedSeries);
+ emitNeedRender();
+ }
+ }
+}
- QSurfaceDataProxy *surfaceDataProxy = static_cast<QSurfaceDataProxy *>(m_data);
+void Surface3DController::handleItemChanged(int rowIndex, int columnIndex)
+{
+ QSurfaceDataProxy *sender = static_cast<QSurfaceDataProxy *>(QObject::sender());
+ if (static_cast<QSurface3DSeries *>(m_seriesList.at(0)) == sender->series()) {
+ // Change is for the visible series, put the change to queue
+ bool newItem = true;
+ QPoint candidate(columnIndex, rowIndex);
+ foreach (QPoint item, m_changedItems) {
+ if (item == candidate) {
+ newItem = false;
+ break;
+ }
+ }
+ if (newItem) {
+ m_changedItems.append(candidate);
+ m_changeTracker.itemChanged = true;
+
+ adjustValueAxisRange();
+ // Clear selection unless still valid
+ setSelectedPoint(m_selectedPoint, m_selectedSeries);
+ emitNeedRender();
+ }
+ }
+}
- QObject::connect(surfaceDataProxy, &QSurfaceDataProxy::arrayReset,
- this, &Surface3DController::handleArrayReset);
+void Surface3DController::handleRowsAdded(int startIndex, int count)
+{
+ Q_UNUSED(startIndex)
+ Q_UNUSED(count)
+ adjustValueAxisRange();
+ m_isDataDirty = true;
+ emitNeedRender();
+}
- scene()->setSlicingActive(false);
+void Surface3DController::handleRowsInserted(int startIndex, int count)
+{
+ Q_UNUSED(startIndex)
+ Q_UNUSED(count)
adjustValueAxisRange();
m_isDataDirty = true;
emitNeedRender();
}
-void Surface3DController::handleArrayReset()
+void Surface3DController::handleRowsRemoved(int startIndex, int count)
{
- scene()->setSlicingActive(false);
+ Q_UNUSED(startIndex)
+ Q_UNUSED(count)
adjustValueAxisRange();
m_isDataDirty = true;
+
+ // Clear selection unless still valid
+ setSelectedPoint(m_selectedPoint, m_selectedSeries);
+
emitNeedRender();
}
void Surface3DController::adjustValueAxisRange()
{
- if (m_data) {
- QVector3D minLimits;
- QVector3D maxLimits;
- static_cast<QSurfaceDataProxy *>(m_data)->dptr()->limitValues(minLimits, maxLimits);
- Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(m_axisX);
- if (valueAxis && valueAxis->isAutoAdjustRange()) {
- if (minLimits.x() != maxLimits.x())
- valueAxis->dptr()->setRange(minLimits.x(), maxLimits.x());
- else
- valueAxis->dptr()->setRange(minLimits.x() - 1.0f, minLimits.x() + 1.0f); // Default to some valid range
+ Q3DValueAxis *valueAxisX = static_cast<Q3DValueAxis *>(m_axisX);
+ Q3DValueAxis *valueAxisY = static_cast<Q3DValueAxis *>(m_axisY);
+ Q3DValueAxis *valueAxisZ = static_cast<Q3DValueAxis *>(m_axisZ);
+ bool adjustX = (valueAxisX && valueAxisX->isAutoAdjustRange());
+ bool adjustY = (valueAxisY && valueAxisY->isAutoAdjustRange());
+ bool adjustZ = (valueAxisZ && valueAxisZ->isAutoAdjustRange());
+
+ if (adjustX || adjustY || adjustZ) {
+ float minValueX = 0.0f;
+ float maxValueX = 0.0f;
+ float minValueY = 0.0f;
+ float maxValueY = 0.0f;
+ float minValueZ = 0.0f;
+ float maxValueZ = 0.0f;
+ int seriesCount = m_seriesList.size();
+ for (int series = 0; series < seriesCount; series++) {
+ const QSurface3DSeries *surfaceSeries =
+ static_cast<QSurface3DSeries *>(m_seriesList.at(series));
+ const QSurfaceDataProxy *proxy = surfaceSeries->dataProxy();
+ if (surfaceSeries->isVisible() && proxy) {
+ QVector3D minLimits;
+ QVector3D maxLimits;
+ proxy->dptrc()->limitValues(minLimits, maxLimits);
+ if (adjustX) {
+ if (!series) {
+ // First series initializes the values
+ minValueX = minLimits.x();
+ maxValueX = maxLimits.x();
+ } else {
+ minValueX = qMin(minValueX, minLimits.x());
+ maxValueX = qMax(maxValueX, maxLimits.x());
+ }
+ }
+ if (adjustY) {
+ if (!series) {
+ // First series initializes the values
+ minValueY = minLimits.y();
+ maxValueY = maxLimits.y();
+ } else {
+ minValueY = qMin(minValueY, minLimits.y());
+ maxValueY = qMax(maxValueY, maxLimits.y());
+ }
+ }
+ if (adjustZ) {
+ if (!series) {
+ // First series initializes the values
+ minValueZ = minLimits.z();
+ maxValueZ = maxLimits.z();
+ } else {
+ minValueZ = qMin(minValueZ, minLimits.z());
+ maxValueZ = qMax(maxValueZ, maxLimits.z());
+ }
+ }
+ }
}
- valueAxis = static_cast<Q3DValueAxis *>(m_axisY);
- if (valueAxis && valueAxis->isAutoAdjustRange()) {
- if (minLimits.y() != maxLimits.y())
- valueAxis->dptr()->setRange(minLimits.y(), maxLimits.y());
- else
- valueAxis->dptr()->setRange(minLimits.y() - 1.0f, minLimits.y() + 1.0f); // Default to some valid range
+ static const float adjustmentRatio = 20.0f;
+ static const float defaultAdjustment = 1.0f;
+
+ if (adjustX) {
+ // If all points at same coordinate, need to default to some valid range
+ float adjustment = 0.0f;
+ if (minValueX == maxValueX) {
+ if (adjustZ) {
+ // X and Z are linked to have similar unit size, so choose the valid range based on it
+ if (minValueZ == maxValueZ)
+ adjustment = defaultAdjustment;
+ else
+ adjustment = qAbs(maxValueZ - minValueZ) / adjustmentRatio;
+ } else {
+ if (valueAxisZ)
+ adjustment = qAbs(valueAxisZ->max() - valueAxisZ->min()) / adjustmentRatio;
+ else
+ adjustment = defaultAdjustment;
+ }
+ }
+ valueAxisX->dptr()->setRange(minValueX - adjustment, maxValueX + adjustment);
}
-
- valueAxis = static_cast<Q3DValueAxis *>(m_axisZ);
- if (valueAxis && valueAxis->isAutoAdjustRange()) {
- if (minLimits.z() != maxLimits.z())
- valueAxis->dptr()->setRange(minLimits.z(), maxLimits.z());
- else
- valueAxis->dptr()->setRange(minLimits.z() - 1.0f, minLimits.z() + 1.0f); // Default to some valid range
+ if (adjustY) {
+ // If all points at same coordinate, need to default to some valid range
+ // Y-axis unit is not dependent on other axes, so simply adjust +-1.0f
+ float adjustment = 0.0f;
+ if (minValueY == maxValueY)
+ adjustment = defaultAdjustment;
+ valueAxisY->dptr()->setRange(minValueY - adjustment, maxValueY + adjustment);
+ }
+ if (adjustZ) {
+ // If all points at same coordinate, need to default to some valid range
+ float adjustment = 0.0f;
+ if (minValueZ == maxValueZ) {
+ if (adjustX) {
+ // X and Z are linked to have similar unit size, so choose the valid range based on it
+ if (minValueX == maxValueX)
+ adjustment = defaultAdjustment;
+ else
+ adjustment = qAbs(maxValueX - minValueX) / adjustmentRatio;
+ } else {
+ if (valueAxisX)
+ adjustment = qAbs(valueAxisX->max() - valueAxisX->min()) / adjustmentRatio;
+ else
+ adjustment = defaultAdjustment;
+ }
+ }
+ valueAxisZ->dptr()->setRange(minValueZ - adjustment, maxValueZ + adjustment);
}
}
}
diff --git a/src/datavisualization/engine/surface3dcontroller_p.h b/src/datavisualization/engine/surface3dcontroller_p.h
index 0698c291..714420a4 100644
--- a/src/datavisualization/engine/surface3dcontroller_p.h
+++ b/src/datavisualization/engine/surface3dcontroller_p.h
@@ -32,21 +32,25 @@
#include "abstract3dcontroller_p.h"
#include "datavisualizationglobal_p.h"
-#include <QLinearGradient>
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class Surface3DRenderer;
+class QSurface3DSeries;
struct Surface3DChangeBitField {
- bool gradientColorChanged : 1;
bool smoothStatusChanged : 1;
bool surfaceGridChanged : 1;
+ bool selectedPointChanged : 1;
+ bool rowsChanged : 1;
+ bool itemChanged : 1;
Surface3DChangeBitField() :
- gradientColorChanged(true),
smoothStatusChanged(true),
- surfaceGridChanged(true)
+ surfaceGridChanged(true),
+ selectedPointChanged(true),
+ rowsChanged(false),
+ itemChanged(false)
{
}
};
@@ -57,43 +61,47 @@ class QT_DATAVISUALIZATION_EXPORT Surface3DController : public Abstract3DControl
private:
Surface3DChangeBitField m_changeTracker;
-
- // Rendering
Surface3DRenderer *m_renderer;
- bool m_isSmoothSurfaceEnabled;
- bool m_isSurfaceGridEnabled;
- QLinearGradient m_userDefinedGradient;
+ QPoint m_selectedPoint;
+ QSurface3DSeries *m_selectedSeries; // Points to the series for which the point is selected in
+ // single series selection cases.
+ bool m_flatShadingSupported;
+ QVector<QPoint> m_changedItems;
+ QVector<int> m_changedRows;
public:
explicit Surface3DController(QRect rect);
~Surface3DController();
- void initializeOpenGL();
+ virtual void initializeOpenGL();
virtual void synchDataToRenderer();
- void setSmoothSurface(bool enable);
- bool smoothSurface();
-
- void setSurfaceGrid(bool enable);
- bool surfaceGrid();
-
- void setGradient(const QLinearGradient &gradient);
- QLinearGradient gradient() const;
-
- void setGradientColorAt(qreal pos, const QColor &color);
-
- void setSelectionMode(QDataVis::SelectionMode mode);
-
- virtual void setActiveDataProxy(QAbstractDataProxy *proxy);
+ void setSelectionMode(QDataVis::SelectionFlags mode);
+ void setSelectedPoint(const QPoint &position, QSurface3DSeries *series);
virtual void handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust);
virtual void handleAxisRangeChangedBySender(QObject *sender);
+ virtual void handleSeriesVisibilityChangedBySender(QObject *sender);
+
+ static QPoint invalidSelectionPosition();
+ bool isFlatShadingSupported();
+
+ virtual void addSeries(QAbstract3DSeries *series);
+ virtual void removeSeries(QAbstract3DSeries *series);
+ virtual QList<QSurface3DSeries *> surfaceSeriesList();
public slots:
void handleArrayReset();
+ void handleRowsAdded(int startIndex, int count);
+ void handleRowsChanged(int startIndex, int count);
+ void handleRowsRemoved(int startIndex, int count);
+ void handleRowsInserted(int startIndex, int count);
+ void handleItemChanged(int rowIndex, int columnIndex);
+
+ // Renderer callback handlers
+ void handlePointClicked(const QPoint &position, QSurface3DSeries *series);
-signals:
- void smoothSurfaceEnabledChanged(bool enable);
+ void handleFlatShadingSupportedChange(bool supported);
private:
void adjustValueAxisRange();
diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp
index 63bd93a7..7049632d 100644
--- a/src/datavisualization/engine/surface3drenderer.cpp
+++ b/src/datavisualization/engine/surface3drenderer.cpp
@@ -25,18 +25,15 @@
#include "surfaceobject_p.h"
#include "texturehelper_p.h"
#include "selectionpointer_p.h"
-#include "theme_p.h"
#include "utils_p.h"
#include "drawer_p.h"
#include "q3dlight.h"
+#include "qsurface3dseries_p.h"
#include <QMatrix4x4>
#include <QMouseEvent>
#include <qmath.h>
-#include <QLinearGradient>
-#include <QPainter>
-
#include <QDebug>
static const int ID_TO_RGBA_MASK = 0xff;
@@ -56,13 +53,14 @@ const GLfloat gridLineWidth = 0.005f;
const GLfloat sliceZScale = 0.1f;
const GLfloat sliceUnits = 2.5f;
const int subViewDivider = 5;
+const uint invalidSelectionId = uint(-1);
Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
: Abstract3DRenderer(controller),
- m_controller(controller),
- m_labelStyle(QDataVis::LabelStyleFromTheme),
+ m_labelBackground(false),
m_font(QFont(QStringLiteral("Arial"))),
m_isGridEnabled(true),
+ m_cachedIsSlicingActivated(false),
m_shader(0),
m_depthShader(0),
m_backgroundShader(0),
@@ -95,11 +93,13 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_depthFrameBuffer(0),
m_selectionFrameBuffer(0),
m_selectionDepthBuffer(0),
- m_gradientTexture(0),
m_selectionTexture(0),
m_selectionResultTexture(0),
m_shadowQualityToShader(33.3f),
+ m_cachedFlatShading(false),
m_flatSupported(true),
+ m_cachedSurfaceVisible(true),
+ m_cachedSurfaceGridOn(true),
m_selectionPointer(0),
m_selectionActive(false),
m_xFlipped(false),
@@ -107,28 +107,29 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_yFlipped(false),
m_sampleSpace(QRect(0, 0, 0, 0)),
m_shadowQualityMultiplier(3),
- m_cachedSelectionId(0),
- m_selectionModeChanged(false),
- m_hasHeightAdjustmentChanged(true)
+ m_clickedPointId(invalidSelectionId),
+ m_hasHeightAdjustmentChanged(true),
+ m_selectedPoint(Surface3DController::invalidSelectionPosition()),
+ m_selectedSeries(0),
+ m_uniformGradientTexture(0)
{
// Check if flat feature is supported
ShaderHelper tester(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
QStringLiteral(":/shaders/fragmentSurfaceFlat"));
if (!tester.testCompile()) {
m_flatSupported = false;
- m_controller->setSmoothSurface(true);
+ connect(this, &Surface3DRenderer::flatShadingSupportedChanged,
+ controller, &Surface3DController::handleFlatShadingSupportedChange);
+ emit flatShadingSupportedChanged(m_flatSupported);
qWarning() << "Warning: Flat qualifier not supported on your platform's GLSL language."
" Requires at least GLSL version 1.2 with GL_EXT_gpu_shader4 extension.";
}
- m_cachedSmoothSurface = m_controller->smoothSurface();
- updateSurfaceGridStatus(m_controller->surfaceGrid());
-
- // Shadows are disabled for Q3DSurface in Tech Preview
- updateShadowQuality(QDataVis::ShadowQualityNone);
-
initializeOpenGLFunctions();
initializeOpenGL();
+
+ // Create initial uniform gradient
+ generateUniformGradient(m_uniformGradientTextureColor);
}
Surface3DRenderer::~Surface3DRenderer()
@@ -138,9 +139,10 @@ Surface3DRenderer::~Surface3DRenderer()
m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer);
m_textureHelper->deleteTexture(&m_depthTexture);
- m_textureHelper->deleteTexture(&m_gradientTexture);
+ m_textureHelper->deleteTexture(&m_depthModelTexture);
m_textureHelper->deleteTexture(&m_selectionTexture);
m_textureHelper->deleteTexture(&m_selectionResultTexture);
+ m_textureHelper->deleteTexture(&m_uniformGradientTexture);
delete m_shader;
delete m_depthShader;
@@ -172,10 +174,7 @@ void Surface3DRenderer::initializeOpenGL()
Abstract3DRenderer::initializeOpenGL();
// Initialize shaders
- handleShadowQualityChange();
-
initSurfaceShaders();
-
initLabelShaders(QStringLiteral(":/shaders/vertexLabel"),
QStringLiteral(":/shaders/fragmentLabel"));
@@ -201,15 +200,22 @@ void Surface3DRenderer::initializeOpenGL()
loadBackgroundMesh();
}
-void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy)
+void Surface3DRenderer::updateData()
{
- calculateSceneScalingFactors();
+ // Surface only supports single series for now, so we are only interested in the first series
+ const QSurfaceDataArray *array = 0;
+ if (m_visibleSeriesList.size()) {
+ QSurface3DSeries *firstSeries = static_cast<QSurface3DSeries *>(m_visibleSeriesList.at(0).series());
+ QSurfaceDataProxy *dataProxy = firstSeries->dataProxy();
+ if (dataProxy)
+ array = dataProxy->array();
+ }
- const QSurfaceDataArray &array = *dataProxy->array();
+ calculateSceneScalingFactors();
// Need minimum of 2x2 array to draw a surface
- if (array.size() >= 2 && array.at(0)->size() >= 2) {
- QRect sampleSpace = calculateSampleRect(array);
+ if (array && array->size() >= 2 && array->at(0)->size() >= 2) {
+ QRect sampleSpace = calculateSampleRect(*array);
bool dimensionChanged = false;
if (m_sampleSpace != sampleSpace) {
@@ -230,7 +236,7 @@ void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy)
}
for (int i = 0; i < sampleSpace.height(); i++) {
for (int j = 0; j < sampleSpace.width(); j++)
- (*(m_dataArray.at(i)))[j] = array.at(i + sampleSpace.y())->at(j + sampleSpace.x());
+ (*(m_dataArray.at(i)))[j] = array->at(i + sampleSpace.y())->at(j + sampleSpace.x());
}
if (m_dataArray.size() > 0) {
@@ -238,7 +244,7 @@ void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy)
loadSurfaceObj();
// Note: Data setup can change sample space (as min width/height is 1)
- if (m_cachedSmoothSurface) {
+ if (!m_cachedFlatShading) {
m_surfaceObj->setUpSmoothData(m_dataArray, m_sampleSpace, m_heightNormalizer,
m_axisCacheY.min(), dimensionChanged);
} else {
@@ -250,21 +256,134 @@ void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy)
updateSelectionTexture();
}
}
+ } else {
+ for (int i = 0; i < m_dataArray.size(); i++)
+ delete m_dataArray.at(i);
+ m_dataArray.clear();
+ m_sampleSpace = QRect();
+
+ delete m_surfaceObj;
+ m_surfaceObj = 0;
}
- m_selectionActive = false;
- m_cachedSelectionId = 0;
for (int i = 0; i < m_sliceDataArray.size(); i++)
delete m_sliceDataArray.at(i);
m_sliceDataArray.clear();
- Abstract3DRenderer::updateDataModel(dataProxy);
+ updateSelectedPoint(m_selectedPoint, m_selectedSeries);
+}
+
+void Surface3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility)
+{
+ Abstract3DRenderer::updateSeries(seriesList, updateVisibility);
+
+ // TODO: move to render cache when multiseries support implemented QTRD-2657
+ // TODO: until then just update them always.
+ if (m_visibleSeriesList.size()) {
+ QSurface3DSeries *series = static_cast<QSurface3DSeries *>(m_visibleSeriesList.at(0).series());
+ updateFlatStatus(series->isFlatShadingEnabled());
+
+ QSurface3DSeries::DrawFlags drawMode = series->drawMode();
+ m_cachedSurfaceVisible = drawMode.testFlag(QSurface3DSeries::DrawSurface);
+ m_cachedSurfaceGridOn = drawMode.testFlag(QSurface3DSeries::DrawWireframe);
+
+ QVector3D seriesColor = Utils::vectorFromColor(series->baseColor());
+ if (m_uniformGradientTextureColor != seriesColor)
+ generateUniformGradient(seriesColor);
+ if (m_selectionPointer) {
+ m_selectionPointer->setHighlightColor(Utils::vectorFromColor(series->singleHighlightColor()));
+ // Make sure selection pointer object reference is still good
+ m_selectionPointer->setPointerObject(m_visibleSeriesList.at(0).object());
+ }
+ }
+}
+
+void Surface3DRenderer::updateRows(const QVector<int> &rows)
+{
+ // Surface only supports single series for now, so we are only interested in the first series
+ const QSurfaceDataArray *array = 0;
+ if (m_visibleSeriesList.size()) {
+ QSurface3DSeries *firstSeries = static_cast<QSurface3DSeries *>(m_visibleSeriesList.at(0).series());
+ if (m_cachedSurfaceGridOn || m_cachedSurfaceVisible) {
+ QSurfaceDataProxy *dataProxy = firstSeries->dataProxy();
+ if (dataProxy)
+ array = dataProxy->array();
+ }
+ }
+
+ if (array && array->size() >= 2 && array->at(0)->size() >= 2 &&
+ m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) {
+ bool updateBuffers = false;
+ int sampleSpaceTop = m_sampleSpace.y() + m_sampleSpace.height();
+ foreach (int row, rows) {
+ if (row >= m_sampleSpace.y() && row <= sampleSpaceTop) {
+ updateBuffers = true;
+ for (int j = 0; j < m_sampleSpace.width(); j++)
+ (*(m_dataArray.at(row - m_sampleSpace.y())))[j] =
+ array->at(row)->at(j + m_sampleSpace.x());
+
+ if (m_cachedFlatShading) {
+ m_surfaceObj->updateCoarseRow(m_dataArray, row - m_sampleSpace.y(), m_heightNormalizer,
+ m_axisCacheY.min());
+ } else {
+ m_surfaceObj->updateSmoothRow(m_dataArray, row - m_sampleSpace.y(), m_heightNormalizer,
+ m_axisCacheY.min());
+ }
+ }
+ }
+ if (updateBuffers)
+ m_surfaceObj->uploadBuffers();
+ }
+
+ updateSelectedPoint(m_selectedPoint, m_selectedSeries);
}
-void Surface3DRenderer::updateSliceDataModel(int selectionId)
+void Surface3DRenderer::updateItem(const QVector<QPoint> &points)
{
- int column = (selectionId - 1) % m_sampleSpace.width();
- int row = (selectionId - 1) / m_sampleSpace.width();
+ // TODO: Properly support non-straight rows and columns (QTRD-2643)
+
+ // Surface only supports single series for now, so we are only interested in the first series
+ const QSurfaceDataArray *array = 0;
+ if (m_visibleSeriesList.size()) {
+ QSurface3DSeries *firstSeries = static_cast<QSurface3DSeries *>(m_visibleSeriesList.at(0).series());
+ if (m_cachedSurfaceGridOn || m_cachedSurfaceVisible) {
+ QSurfaceDataProxy *dataProxy = firstSeries->dataProxy();
+ if (dataProxy)
+ array = dataProxy->array();
+ }
+ }
+
+ if (array && array->size() >= 2 && array->at(0)->size() >= 2 &&
+ m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) {
+ int sampleSpaceTop = m_sampleSpace.y() + m_sampleSpace.height();
+ int sampleSpaceRight = m_sampleSpace.x() + m_sampleSpace.width();
+ bool updateBuffers = false;
+ foreach (QPoint item, points) {
+ if (item.y() <= sampleSpaceTop && item.y() >= m_sampleSpace.y() &&
+ item.x() <= sampleSpaceRight && item.x() >= m_sampleSpace.x()) {
+ updateBuffers = true;
+ int x = item.x() - m_sampleSpace.x();
+ int y = item.y() - m_sampleSpace.y();
+ (*(m_dataArray.at(y)))[x] = array->at(item.y())->at(item.x());
+
+ if (m_cachedFlatShading) {
+ m_surfaceObj->updateCoarseItem(m_dataArray, y, x, m_heightNormalizer, m_axisCacheY.min());
+ } else {
+ m_surfaceObj->updateSmoothItem(m_dataArray, y, x, m_heightNormalizer, m_axisCacheY.min());
+ }
+ }
+ }
+ if (updateBuffers)
+ m_surfaceObj->uploadBuffers();
+ }
+
+ updateSelectedPoint(m_selectedPoint, m_selectedSeries);
+}
+
+void Surface3DRenderer::updateSliceDataModel(const QPoint &point)
+{
+ int column = point.y();
+ int row = point.x();
for (int i = 0; i < m_sliceDataArray.size(); i++)
delete m_sliceDataArray.at(i);
@@ -273,19 +392,19 @@ void Surface3DRenderer::updateSliceDataModel(int selectionId)
m_sliceDataArray.reserve(2);
QSurfaceDataRow *sliceRow;
- qreal adjust = (0.025 * m_heightNormalizer) / 2.0;
- qreal stepDown = 2.0 * adjust;
- if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) {
+ float adjust = (0.025f * m_heightNormalizer) / 2.0f;
+ float stepDown = 2.0f * adjust;
+ if (m_cachedSelectionMode.testFlag(QDataVis::SelectionRow)) {
QSurfaceDataRow *src = m_dataArray.at(row);
sliceRow = new QSurfaceDataRow(src->size());
for (int i = 0; i < sliceRow->size(); i++)
- (*sliceRow)[i].setPosition(QVector3D(src->at(i).x(), src->at(i).y() + adjust, -1.0));
+ (*sliceRow)[i].setPosition(QVector3D(src->at(i).x(), src->at(i).y() + adjust, -1.0f));
} else {
sliceRow = new QSurfaceDataRow(m_sampleSpace.height());
for (int i = 0; i < m_sampleSpace.height(); i++) {
(*sliceRow)[i].setPosition(QVector3D(m_dataArray.at(i)->at(column).z(),
m_dataArray.at(i)->at(column).y() + adjust,
- -1.0));
+ -1.0f));
}
}
@@ -294,7 +413,7 @@ void Surface3DRenderer::updateSliceDataModel(int selectionId)
// Make a duplicate, so that we get a little bit depth
QSurfaceDataRow *duplicateRow = new QSurfaceDataRow(*sliceRow);
for (int i = 0; i < sliceRow->size(); i++)
- (*sliceRow)[i].setPosition(QVector3D(sliceRow->at(i).x(), sliceRow->at(i).y() - stepDown, 1.0));
+ (*sliceRow)[i].setPosition(QVector3D(sliceRow->at(i).x(), sliceRow->at(i).y() - stepDown, 1.0f));
m_sliceDataArray << duplicateRow;
@@ -304,7 +423,7 @@ void Surface3DRenderer::updateSliceDataModel(int selectionId)
if (!m_sliceSurfaceObj)
loadSliceSurfaceObj();
- if (m_cachedSmoothSurface) {
+ if (!m_cachedFlatShading) {
m_sliceSurfaceObj->setUpSmoothData(m_sliceDataArray, sliceRect, m_heightNormalizer,
m_axisCacheY.min(), true);
} else {
@@ -323,20 +442,10 @@ QRect Surface3DRenderer::calculateSampleRect(const QSurfaceDataArray &array)
int i;
bool found;
- float axisMinX = float(m_axisCacheX.min());
- float axisMaxX = float(m_axisCacheX.max());
- float axisMinZ = float(m_axisCacheZ.min());
- float axisMaxZ = float(m_axisCacheZ.max());
-
- // Comparisons between float and double are not accurate, so fudge our comparison values
- //a little to get all rows and columns into view that need to be visible.
- const float fudgeFactor = 0.00001f;
- float fudgedAxisXRange = (axisMaxX - axisMinX) * fudgeFactor;
- float fudgedAxisZRange = (axisMaxZ - axisMinZ) * fudgeFactor;
- axisMinX -= fudgedAxisXRange;
- axisMinZ -= fudgedAxisZRange;
- axisMaxX += fudgedAxisXRange;
- axisMaxZ += fudgedAxisZRange;
+ float axisMinX = m_axisCacheX.min();
+ float axisMaxX = m_axisCacheX.max();
+ float axisMinZ = m_axisCacheZ.min();
+ float axisMaxZ = m_axisCacheZ.max();
// m_minVisibleColumnValue
for (i = 0, found = false; i < columnCount; i++) {
@@ -414,10 +523,6 @@ QRect Surface3DRenderer::calculateSampleRect(const QSurfaceDataArray &array)
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);
-
// Set initial camera position
// X must be 0 for rotation to work - we can use "setCameraRotation" for setting it later
if (m_hasHeightAdjustmentChanged) {
@@ -426,41 +531,28 @@ void Surface3DRenderer::updateScene(Q3DScene *scene)
m_hasHeightAdjustmentChanged = false;
}
- scene->activeCamera()->d_ptr->updateViewMatrix(m_autoScaleAdjustment);
- scene->setLightPositionRelativeToCamera(defaultLightPos);
-
Abstract3DRenderer::updateScene(scene);
if (m_selectionPointer)
m_selectionPointer->updateScene(m_cachedScene);
+
+ updateSlicingActive(scene->isSlicingActive());
}
void Surface3DRenderer::render(GLuint defaultFboHandle)
{
- bool slicingActivated = m_cachedScene->isSlicingActive();
- bool slicingChanged = m_cachedIsSlicingActivated != slicingActivated;
-
- updateSlicingActive(slicingActivated);
-
// Handle GL state setup for FBO buffers and clearing of the render surface
Abstract3DRenderer::render(defaultFboHandle);
- // Draw the surface scene
drawScene(defaultFboHandle);
-
- // In slice mode; draw slice and render selection ball
if (m_cachedIsSlicingActivated)
drawSlicedScene();
- // Render selection ball if not in slice mode
- if (m_selectionPointer && m_selectionActive)
+ // Render selection ball
+ if (m_selectionPointer && m_selectionActive
+ && m_cachedSelectionMode.testFlag(QDataVis::SelectionItem)) {
m_selectionPointer->render(defaultFboHandle);
-
- // If slicing has been activated by this render pass, we need another render
- // Also trigger another render always when slicing changes in general to ensure
- // final draw is correct.
- if (slicingActivated != m_cachedScene->isSlicingActive() || slicingChanged)
- emit needRender();
+ }
}
void Surface3DRenderer::drawSlicedScene()
@@ -468,13 +560,15 @@ void Surface3DRenderer::drawSlicedScene()
QVector3D lightPos;
// Specify viewport
- glViewport(m_sliceViewPort.x(), m_sliceViewPort.y(),
- m_sliceViewPort.width(), m_sliceViewPort.height());
+ glViewport(m_secondarySubViewport.x(),
+ m_secondarySubViewport.y(),
+ m_secondarySubViewport.width(),
+ m_secondarySubViewport.height());
// Set up projection matrix
QMatrix4x4 projectionMatrix;
- GLfloat aspect = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height();
+ GLfloat aspect = (GLfloat)m_secondarySubViewport.width() / (GLfloat)m_secondarySubViewport.height();
projectionMatrix.ortho(-sliceUnits * aspect, sliceUnits * aspect,
-sliceUnits, sliceUnits, -1.0f, 4.0f);
@@ -487,30 +581,24 @@ void Surface3DRenderer::drawSlicedScene()
QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix;
+ bool rowMode = m_cachedSelectionMode.testFlag(QDataVis::SelectionRow);
+
GLfloat scaleX = 0.0f;
GLfloat scaleXBackground = 0.0f;
GLfloat offset = 0.0f;
- if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) {
+ if (rowMode) {
scaleX = m_surfaceScaleX;
scaleXBackground = m_scaleXWithBackground;
offset = m_surfaceOffsetX;
- } else if (m_cachedSelectionMode == QDataVis::SelectionModeSliceColumn) {
+ } else {
scaleX = m_surfaceScaleZ;
scaleXBackground = m_scaleZWithBackground;
offset = -m_surfaceOffsetZ;
}
if (m_surfaceObj) {
- ShaderHelper *surfaceShader = m_shader;
- surfaceShader->bind();
-
- if (m_cachedSurfaceGridOn) {
- glEnable(GL_POLYGON_OFFSET_FILL);
- glPolygonOffset(0.5f, 1.0f);
- }
-
- QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
+ QMatrix4x4 modelMatrix;
QMatrix4x4 itModelMatrix;
modelMatrix.translate(offset, 0.0f, 0.0f);
@@ -520,36 +608,40 @@ void Surface3DRenderer::drawSlicedScene()
MVPMatrix = projectionViewMatrix * modelMatrix;
- QVector3D color;
- if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow)
- 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->lightS(), 0.25f);
- surfaceShader->setUniformValue(surfaceShader->ambientS(),
- m_cachedTheme.m_ambientStrength * 2.0f);
-
- m_drawer->drawObject(surfaceShader, m_sliceSurfaceObj);
+ if (m_cachedSurfaceVisible) {
+ if (m_cachedSurfaceGridOn) {
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(0.5f, 1.0f);
+ }
- surfaceShader->release();
+ ShaderHelper *surfaceShader = m_shader;
+ surfaceShader->bind();
+
+ QVector3D color;
+ color = Utils::vectorFromColor(m_cachedTheme->multiHighlightColor());
+
+ // 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->lightS(), 0.25f);
+ surfaceShader->setUniformValue(surfaceShader->ambientS(),
+ m_cachedTheme->ambientLightStrength() * 2.0f);
+
+ m_drawer->drawObject(surfaceShader, m_sliceSurfaceObj);
+ }
// Draw surface grid
if (m_cachedSurfaceGridOn) {
m_surfaceGridShader->bind();
m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(),
- Utils::vectorFromColor(m_cachedTheme.m_gridLine));
+ Utils::vectorFromColor(m_cachedTheme->gridLineColor()));
m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), MVPMatrix);
m_drawer->drawSurfaceGrid(m_surfaceGridShader, m_sliceSurfaceObj);
- m_surfaceGridShader->release();
glDisable(GL_POLYGON_OFFSET_FILL);
}
@@ -559,17 +651,17 @@ void Surface3DRenderer::drawSlicedScene()
glDisable(GL_TEXTURE_2D);
// Grid lines
- if (m_cachedIsGridEnabled && m_heightNormalizer) {
+ if (m_cachedTheme->isGridEnabled() && m_heightNormalizer) {
ShaderHelper *lineShader = m_backgroundShader;
// Bind line shader
lineShader->bind();
// Set unchanging shader bindings
- QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme.m_gridLine);
+ QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
lineShader->setUniformValue(lineShader->lightP(), lightPos);
lineShader->setUniformValue(lineShader->view(), viewMatrix);
lineShader->setUniformValue(lineShader->color(), lineColor);
- lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme.m_ambientStrength * 2.0f);
+ lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme->ambientLightStrength() * 2.0f);
lineShader->setUniformValue(lineShader->lightS(), 0.25f);
// Horizontal lines
@@ -611,7 +703,7 @@ void Surface3DRenderer::drawSlicedScene()
int lastSegment;
GLfloat lineStep;
GLfloat linePos;
- if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) {
+ if (rowMode) {
lineStep = -2.0f * aspectRatio * m_axisCacheX.subSegmentStep() / m_scaleFactor;
lastSegment = m_axisCacheX.subSegmentCount() * m_axisCacheX.segmentCount();
linePos = m_scaleX;
@@ -643,9 +735,6 @@ void Surface3DRenderer::drawSlicedScene()
linePos += lineStep;
}
-
- // Release line shader
- lineShader->release();
}
// Draw axis labels
@@ -653,10 +742,8 @@ void Surface3DRenderer::drawSlicedScene()
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glCullFace(GL_BACK);
- if (m_cachedLabelStyle > QDataVis::LabelStyleOpaque) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
+ 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;
@@ -676,7 +763,7 @@ void Surface3DRenderer::drawSlicedScene()
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);
+ true, true, Drawer::LabelMid, Qt::AlignRight, true);
}
labelNbr++;
labelPos += posStep;
@@ -685,7 +772,7 @@ void Surface3DRenderer::drawSlicedScene()
// X Labels to ground
int countLabelItems;
int lastSegment;
- if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) {
+ if (rowMode) {
posStep = 2.0f * aspectRatio * m_axisCacheX.segmentStep() / m_scaleFactor;
labelPos = -m_scaleX;
lastSegment = m_axisCacheX.segmentCount();
@@ -709,15 +796,15 @@ void Surface3DRenderer::drawSlicedScene()
m_dummyRenderItem.setTranslation(labelTrans);
LabelItem *axisLabelItem;
- if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow)
+ if (rowMode)
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::SelectionModeSliceRow,
+ positionComp, rotation, 0, QDataVis::SelectionRow,
m_labelShader, m_labelObj, m_cachedScene->activeCamera(),
- false, false, Drawer::LabelBelow, Qt::AlignTop);
+ false, false, Drawer::LabelBelow, Qt::AlignTop, true);
}
labelNbr++;
labelPos += posStep;
@@ -725,26 +812,26 @@ void Surface3DRenderer::drawSlicedScene()
glDisable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
- if (m_cachedLabelStyle > QDataVis::LabelStyleOpaque)
- glDisable(GL_BLEND);
+ glDisable(GL_BLEND);
- // Release label shader
- m_labelShader->release();
+ // Release shader
+ glUseProgram(0);
}
void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
{
GLfloat backgroundRotation = 0;
- uint selectionId = 0;
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
// Specify viewport
- glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
- m_mainViewPort.width(), m_mainViewPort.height());
// Set up projection matrix
QMatrix4x4 projectionMatrix;
- projectionMatrix.perspective(45.0f, (GLfloat)m_mainViewPort.width()
- / (GLfloat)m_mainViewPort.height(), 0.1f, 100.0f);
+ projectionMatrix.perspective(45.0f, (GLfloat)m_primarySubViewport.width()
+ / (GLfloat)m_primarySubViewport.height(), 0.1f, 100.0f);
// Calculate view matrix
QMatrix4x4 viewMatrix = m_cachedScene->activeCamera()->viewMatrix();
@@ -782,11 +869,13 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Draw depth buffer
#if !defined(QT_OPENGL_ES_2)
- GLfloat adjustedLightStrength = m_cachedTheme.m_lightStrength / 10.0f;
- if (m_cachedShadowQuality > QDataVis::ShadowQualityNone && m_surfaceObj) {
+ GLfloat adjustedLightStrength = m_cachedTheme->lightStrength() / 10.0f;
+ if (m_cachedShadowQuality > QDataVis::ShadowQualityNone && m_surfaceObj && m_cachedSurfaceVisible) {
// Render scene into a depth texture for using with shadow mapping
// Enable drawing to depth framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer);
+ // Attach texture to depth attachment
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthTexture, 0);
glClear(GL_DEPTH_BUFFER_BIT);
// Bind depth shader
@@ -794,8 +883,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows.
glViewport(0, 0,
- m_mainViewPort.width() * m_shadowQualityMultiplier,
- m_mainViewPort.height() * m_shadowQualityMultiplier);
+ m_primarySubViewport.width() * m_shadowQualityMultiplier,
+ m_primarySubViewport.height() * m_shadowQualityMultiplier);
// Get the depth view matrix
// It may be possible to hack lightPos here if we want to make some tweaks to shadow
@@ -809,8 +898,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Set the depth projection matrix
#ifndef USE_WIDER_SHADOWS
// Use this for perspective shadows
- depthProjectionMatrix.perspective(10.0f, (GLfloat)m_mainViewPort.width()
- / (GLfloat)m_mainViewPort.height(), 3.0f, 100.0f);
+ depthProjectionMatrix.perspective(10.0f, (GLfloat)m_primarySubViewport.width()
+ / (GLfloat)m_primarySubViewport.height(), 3.0f, 100.0f);
#else
// Use these for orthographic shadows
depthProjectionMatrix.ortho(-2.0f * 2.0f, 2.0f * 2.0f,
@@ -819,7 +908,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
#endif
depthProjectionViewMatrix = depthProjectionMatrix * depthViewMatrix;
- glCullFace(GL_FRONT);
+ glDisable(GL_CULL_FACE);
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
@@ -841,7 +930,17 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_surfaceObj->elementBuf());
// Draw the triangles
- glDrawElements(GL_TRIANGLES, m_surfaceObj->indexCount(), GL_UNSIGNED_SHORT,
+ glDrawElements(GL_TRIANGLES, m_surfaceObj->indexCount(), m_surfaceObj->indicesType(),
+ (void *)0);
+
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_FRONT);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthModelTexture, 0);
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, m_surfaceObj->indexCount(), m_surfaceObj->indicesType(),
(void *)0);
// Free buffers
@@ -853,14 +952,14 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Disable drawing to depth framebuffer (= enable drawing to screen)
glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle);
- // Release depth shader
- m_depthShader->release();
-
// Revert to original viewport
- glViewport(m_mainViewPort.x(), m_mainViewPort.y(),
- m_mainViewPort.width(), m_mainViewPort.height());
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
// Reset culling to normal
+ glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
#if 0 // Use this if you want to see what is being drawn to the framebuffer
@@ -875,24 +974,27 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix);
m_drawer->drawObject(m_labelShader, m_labelObj, m_depthTexture);
glDisable(GL_TEXTURE_2D);
- m_labelShader->release();
}
#endif
}
#endif
-
- bool selectionDirty = false;
-
// Enable texturing
glEnable(GL_TEXTURE_2D);
// Draw selection buffer
- if (!m_cachedIsSlicingActivated && m_controller->inputState() == QDataVis::InputStateOnScene
- && m_surfaceObj && m_cachedSelectionMode > QDataVis::SelectionModeNone) {
+ if (!m_cachedIsSlicingActivated && m_surfaceObj && m_selectionState == SelectOnScene
+ && m_cachedSelectionMode > QDataVis::SelectionNone
+ && (m_cachedSurfaceVisible || m_cachedSurfaceGridOn)
+ && m_visibleSeriesList.size() > 0) {
m_selectionShader->bind();
glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer);
+ glViewport(0,
+ 0,
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
+
glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used
- glClearColor(0, 0, 0, 0);
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer
glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled
@@ -912,30 +1014,32 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glEnable(GL_DITHER);
- QPoint point = m_controller->inputPosition();
- GLubyte pixel[4] = {0};
- glReadPixels(point.x(), m_cachedBoundingRect.height() - point.y(), 1, 1,
- GL_RGBA, GL_UNSIGNED_BYTE, (void *)pixel);
+ GLubyte pixel[4] = {0, 0, 0, 0};
+ glReadPixels(m_inputPosition.x(), m_viewport.height() - m_inputPosition.y(),
+ 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void *)pixel);
glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle);
- // Release selection shader
- m_selectionShader->release();
-
// Put the RGBA value back to uint
#if !defined(QT_OPENGL_ES_2)
- selectionId = pixel[0] + pixel[1] * 256 + pixel[2] * 65536 + pixel[3] * 16777216;
+ uint selectionId = pixel[0] + pixel[1] * 256 + pixel[2] * 65536 + pixel[3] * 16777216;
#else
- selectionId = pixel[0] + pixel[1] * 256 + pixel[2] * 65536;
+ uint selectionId = pixel[0] + pixel[1] * 256 + pixel[2] * 65536;
#endif
- selectionDirty = true;
+ emit pointClicked(QPoint(selectionIdToSurfacePoint(selectionId)),
+ static_cast<QSurface3DSeries *>(m_visibleSeriesList.at(0).series()));
+
+ // Revert to original viewport
+ glViewport(m_primarySubViewport.x(),
+ m_primarySubViewport.y(),
+ m_primarySubViewport.width(),
+ m_primarySubViewport.height());
}
// Draw the surface
if (m_surfaceObj && m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) {
m_surfaceShader->bind();
-
// For surface we can see climpses from underneath
glDisable(GL_CULL_FACE);
if (m_cachedSurfaceGridOn) {
@@ -956,49 +1060,55 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
#else
MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
- // Set shader bindings
- m_surfaceShader->setUniformValue(m_surfaceShader->lightP(), lightPos);
- m_surfaceShader->setUniformValue(m_surfaceShader->view(), viewMatrix);
- m_surfaceShader->setUniformValue(m_surfaceShader->model(), modelMatrix);
- m_surfaceShader->setUniformValue(m_surfaceShader->nModel(),
- itModelMatrix.inverted().transposed());
- m_surfaceShader->setUniformValue(m_surfaceShader->MVP(), MVPMatrix);
- m_surfaceShader->setUniformValue(m_surfaceShader->ambientS(),
- m_cachedTheme.m_ambientStrength);
+
+ if (m_cachedSurfaceVisible) {
+ // Set shader bindings
+ m_surfaceShader->setUniformValue(m_surfaceShader->lightP(), lightPos);
+ m_surfaceShader->setUniformValue(m_surfaceShader->view(), viewMatrix);
+ m_surfaceShader->setUniformValue(m_surfaceShader->model(), modelMatrix);
+ m_surfaceShader->setUniformValue(m_surfaceShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ m_surfaceShader->setUniformValue(m_surfaceShader->MVP(), MVPMatrix);
+ m_surfaceShader->setUniformValue(m_surfaceShader->ambientS(),
+ m_cachedTheme->ambientLightStrength());
+
+ // TODO: Do properly when multiseries support implemented QTRD-2657
+ GLuint gradientTexture;
+ if (m_visibleSeriesList.at(0).colorStyle() == Q3DTheme::ColorStyleUniform)
+ gradientTexture = m_uniformGradientTexture;
+ else
+ gradientTexture = m_visibleSeriesList.at(0).baseGradientTexture();
#if !defined(QT_OPENGL_ES_2)
- if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
- // Set shadow shader bindings
- QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix;
- m_surfaceShader->setUniformValue(m_surfaceShader->shadowQ(), m_shadowQualityToShader);
- m_surfaceShader->setUniformValue(m_surfaceShader->depth(), depthMVPMatrix);
- m_surfaceShader->setUniformValue(m_surfaceShader->lightS(), adjustedLightStrength);
+ if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
+ // Set shadow shader bindings
+ QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ m_surfaceShader->setUniformValue(m_surfaceShader->shadowQ(), m_shadowQualityToShader);
+ m_surfaceShader->setUniformValue(m_surfaceShader->depth(), depthMVPMatrix);
+ m_surfaceShader->setUniformValue(m_surfaceShader->lightS(), adjustedLightStrength);
- // Draw the object
- m_drawer->drawObject(m_surfaceShader, m_surfaceObj, m_gradientTexture, m_depthTexture);
- } else
+ // Draw the object
+ m_drawer->drawObject(m_surfaceShader, m_surfaceObj, gradientTexture, m_depthModelTexture);
+ } else
#endif
- {
- // Set shadowless shader bindings
- m_surfaceShader->setUniformValue(m_surfaceShader->lightS(),
- m_cachedTheme.m_lightStrength);
+ {
+ // Set shadowless shader bindings
+ m_surfaceShader->setUniformValue(m_surfaceShader->lightS(),
+ m_cachedTheme->lightStrength());
- // Draw the object
- m_drawer->drawObject(m_surfaceShader, m_surfaceObj, m_gradientTexture);
+ // Draw the object
+ m_drawer->drawObject(m_surfaceShader, m_surfaceObj, gradientTexture);
+ }
+ glEnable(GL_CULL_FACE);
}
- m_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));
+ Utils::vectorFromColor(m_cachedTheme->gridLineColor()));
m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), MVPMatrix);
m_drawer->drawSurfaceGrid(m_surfaceGridShader, m_surfaceObj);
- m_surfaceGridShader->release();
glDisable(GL_POLYGON_OFFSET_FILL);
}
@@ -1009,7 +1119,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glCullFace(GL_BACK);
// Draw background
- if (m_cachedIsBackgroundEnabled && m_backgroundObj) {
+ if (m_cachedTheme->isBackgroundEnabled() && m_backgroundObj) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
@@ -1019,7 +1129,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// If we're viewing from below, background object must be flipped
if (m_yFlipped) {
- modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
+ modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
modelMatrix.rotate(270.0f - backgroundRotation, 0.0f, 1.0f, 0.0f);
} else {
modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f);
@@ -1033,7 +1143,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
- QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme.m_backgroundColor);
+ QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme->backgroundColor());
// Set shader bindings
m_backgroundShader->setUniformValue(m_backgroundShader->lightP(), lightPos);
@@ -1044,7 +1154,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_backgroundShader->setUniformValue(m_backgroundShader->MVP(), MVPMatrix);
m_backgroundShader->setUniformValue(m_backgroundShader->color(), backgroundColor);
m_backgroundShader->setUniformValue(m_backgroundShader->ambientS(),
- m_cachedTheme.m_ambientStrength * 2.0f);
+ m_cachedTheme->ambientLightStrength() * 2.0f);
#if !defined(QT_OPENGL_ES_2)
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
@@ -1063,46 +1173,60 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
{
// Set shadowless shader bindings
m_backgroundShader->setUniformValue(m_backgroundShader->lightS(),
- m_cachedTheme.m_lightStrength);
+ m_cachedTheme->lightStrength());
// Draw the object
m_drawer->drawObject(m_backgroundShader, m_backgroundObj);
}
}
- // Release background shader
- m_backgroundShader->release();
-
// Draw grid lines
QVector3D gridLineScaleX(m_scaleXWithBackground, gridLineWidth, gridLineWidth);
QVector3D gridLineScaleZ(gridLineWidth, gridLineWidth, m_scaleZWithBackground);
QVector3D gridLineScaleY(gridLineWidth, backgroundMargin, gridLineWidth);
- if (m_cachedIsGridEnabled && m_heightNormalizer) {
+ if (m_cachedTheme->isGridEnabled() && m_heightNormalizer) {
ShaderHelper *lineShader = m_backgroundShader;
// Bind line shader
lineShader->bind();
// Set unchanging shader bindings
- QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme.m_gridLine);
+ QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
lineShader->setUniformValue(lineShader->lightP(), lightPos);
lineShader->setUniformValue(lineShader->view(), viewMatrix);
lineShader->setUniformValue(lineShader->color(), lineColor);
- lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme.m_ambientStrength);
+ lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme->ambientLightStrength());
#if !defined(QT_OPENGL_ES_2)
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
// Set shadowed shader bindings
lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader);
lineShader->setUniformValue(lineShader->lightS(),
- m_cachedTheme.m_lightStrength / 20.0f);
+ m_cachedTheme->lightStrength() / 20.0f);
} else
#endif
{
// Set shadowless shader bindings
- lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme.m_lightStrength / 2.5f);
+ lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme->lightStrength() / 2.5f);
}
+ QQuaternion lineYRotation = QQuaternion();
+ QQuaternion lineXRotation = QQuaternion();
+
+ if (m_xFlipped)
+ lineYRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, -90.0f);
+ else
+ lineYRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f);
+
+ if (m_yFlipped)
+ lineXRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 90.0f);
+ else
+ lineXRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, -90.0f);
+
+ GLfloat yFloorLinePosition = -backgroundMargin + gridLineOffset;
+ if (m_yFlipped)
+ yFloorLinePosition = -yFloorLinePosition;
+
// Rows (= Z)
if (m_axisCacheZ.segmentCount() > 0) {
// Floor lines
@@ -1115,19 +1239,13 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- if (m_yFlipped)
- modelMatrix.translate(0.0f, backgroundMargin, linePos);
- else
- modelMatrix.translate(0.0f, -backgroundMargin, linePos);
+ modelMatrix.translate(0.0f, yFloorLinePosition, linePos);
modelMatrix.scale(gridLineScaleX);
itModelMatrix.scale(gridLineScaleX);
- // If we're viewing from below, grid line object must be flipped
- if (m_yFlipped) {
- modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- itModelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- }
+ modelMatrix.rotate(lineXRotation);
+ itModelMatrix.rotate(lineXRotation);
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -1154,7 +1272,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
}
// Side wall lines
- GLfloat lineXTrans = m_scaleXWithBackground;
+ GLfloat lineXTrans = m_scaleXWithBackground - gridLineOffset;
linePos = m_scaleZ; // Start line
if (!m_xFlipped)
@@ -1166,9 +1284,13 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
QMatrix4x4 itModelMatrix;
modelMatrix.translate(lineXTrans, 0.0f, linePos);
+
modelMatrix.scale(gridLineScaleY);
itModelMatrix.scale(gridLineScaleY);
+ modelMatrix.rotate(lineYRotation);
+ itModelMatrix.rotate(lineYRotation);
+
MVPMatrix = projectionViewMatrix * modelMatrix;
// Set the rest of the shader bindings
@@ -1206,19 +1328,13 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- if (m_yFlipped)
- modelMatrix.translate(linePos, backgroundMargin, 0.0f);
- else
- modelMatrix.translate(linePos, -backgroundMargin, 0.0f);
+ modelMatrix.translate(linePos, yFloorLinePosition, 0.0f);
modelMatrix.scale(gridLineScaleZ);
itModelMatrix.scale(gridLineScaleZ);
- // If we're viewing from below, grid line object must be flipped
- if (m_yFlipped) {
- modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- itModelMatrix.rotate(180.0f, 1.0, 0.0, 0.0);
- }
+ modelMatrix.rotate(lineXRotation);
+ itModelMatrix.rotate(lineXRotation);
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -1245,7 +1361,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
}
// Back wall lines
- GLfloat lineZTrans = m_scaleZWithBackground;
+ GLfloat lineZTrans = m_scaleZWithBackground - gridLineOffset;
linePos = m_scaleX;
if (!m_zFlipped)
@@ -1257,9 +1373,15 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
QMatrix4x4 itModelMatrix;
modelMatrix.translate(linePos, 0.0f, lineZTrans);
+
modelMatrix.scale(gridLineScaleY);
itModelMatrix.scale(gridLineScaleY);
+ if (m_zFlipped) {
+ modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ itModelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ }
+
MVPMatrix = projectionViewMatrix * modelMatrix;
// Set the rest of the shader bindings
@@ -1292,7 +1414,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
GLfloat linePos = -1.0f;
int lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount();
- GLfloat lineZTrans = m_scaleZWithBackground;
+ GLfloat lineZTrans = m_scaleZWithBackground - gridLineOffset;
if (!m_zFlipped)
lineZTrans = -lineZTrans;
@@ -1307,6 +1429,11 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
modelMatrix.scale(gridLineScaleX);
itModelMatrix.scale(gridLineScaleX);
+ if (m_zFlipped) {
+ modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ itModelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
+ }
+
MVPMatrix = projectionViewMatrix * modelMatrix;
// Set the rest of the shader bindings
@@ -1334,7 +1461,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Side wall
linePos = -1.0f;
lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount();
- GLfloat lineXTrans = m_scaleXWithBackground;
+ GLfloat lineXTrans = m_scaleXWithBackground - gridLineOffset;
if (!m_xFlipped)
lineXTrans = -lineXTrans;
@@ -1349,6 +1476,9 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
modelMatrix.scale(gridLineScaleZ);
itModelMatrix.scale(gridLineScaleZ);
+ modelMatrix.rotate(lineYRotation);
+ itModelMatrix.rotate(lineYRotation);
+
MVPMatrix = projectionViewMatrix * modelMatrix;
// Set the rest of the shader bindings
@@ -1373,9 +1503,6 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
linePos += lineStep;
}
}
-
- // Release line shader
- lineShader->release();
}
// Draw axis labels
@@ -1383,6 +1510,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_POLYGON_OFFSET_FILL);
// Z Labels
QVector3D positionZComp(0.0f, 0.0f, 0.0f);
@@ -1415,9 +1543,9 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
for (int segment = 0; segment <= lastSegment; segment++) {
if (m_axisCacheZ.labelItems().size() > labelNbr) {
- labelTrans.setZ(labelPos);
-
+ glPolygonOffset(GLfloat(segment) / -10.0f, 1.0f);
// Draw the label here
+ labelTrans.setZ(labelPos);
m_dummyRenderItem.setTranslation(labelTrans);
const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(labelNbr);
@@ -1461,6 +1589,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
for (int segment = 0; segment <= lastSegment; segment++) {
if (m_axisCacheX.labelItems().size() > labelNbr) {
+ glPolygonOffset(GLfloat(segment) / -10.0f, 1.0f);
// Draw the label here
labelTrans.setX(labelPos);
m_dummyRenderItem.setTranslation(labelTrans);
@@ -1521,6 +1650,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
if (m_axisCacheY.labelItems().size() > labelNbr) {
const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr);
+ glPolygonOffset(GLfloat(segment) / -10.0f, 1.0f);
+
// Back wall
labelTransBack.setY(labelPos);
m_dummyRenderItem.setTranslation(labelTransBack);
@@ -1541,65 +1672,40 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
labelPos += posStep;
}
}
+ glDisable(GL_POLYGON_OFFSET_FILL);
glDisable(GL_TEXTURE_2D);
-
glDisable(GL_BLEND);
- // Release label shader
- m_labelShader->release();
+ // Release shader
+ glUseProgram(0);
// Selection handling
- if (m_selectionModeChanged || selectionDirty) {
- if (selectionDirty)
- m_cachedSelectionId = selectionId;
- if (m_cachedSelectionMode == QDataVis::SelectionModeNone) {
- m_cachedSelectionId = 0;
- m_selectionActive = false;
- }
- if (m_cachedSelectionMode == QDataVis::SelectionModeItem) {
- if (m_cachedSelectionId)
- surfacePointSelected(m_cachedSelectionId);
- else
- m_selectionActive = false;
- }
- if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow
- || m_cachedSelectionMode == QDataVis::SelectionModeSliceColumn) {
- if (m_cachedSelectionId) {
- updateSliceDataModel(m_cachedSelectionId);
- m_cachedScene->setSlicingActive(true);
-
- surfacePointSelected(m_cachedSelectionId);
-
- emit needRender();
+ if (m_selectionDirty) {
+ QPoint visiblePoint = Surface3DController::invalidSelectionPosition();
+ if (m_selectedPoint != Surface3DController::invalidSelectionPosition()) {
+ int x = m_selectedPoint.x() - m_sampleSpace.y();
+ int y = m_selectedPoint.y() - m_sampleSpace.x();
+ if (x >= 0 && y >= 0 && x < m_sampleSpace.height() && y < m_sampleSpace.width()
+ && m_dataArray.size()) {
+ visiblePoint = QPoint(x, y);
}
}
- m_selectionModeChanged = false;
- }
- if (m_controller->inputState() == QDataVis::InputStateOnOverview) {
- if (m_cachedIsSlicingActivated) {
- m_cachedScene->setSlicingActive(false);
+ if (m_cachedSelectionMode == QDataVis::SelectionNone
+ || visiblePoint == Surface3DController::invalidSelectionPosition()) {
m_selectionActive = false;
- m_cachedSelectionId = 0;
+ } else {
+ // TODO: Need separate selection ball for slice and main surface view QTRD-2515
+ if (m_cachedIsSlicingActivated)
+ updateSliceDataModel(visiblePoint);
+ if (m_cachedSelectionMode.testFlag(QDataVis::SelectionItem))
+ surfacePointSelected(visiblePoint);
+ m_selectionActive = true;
}
- }
-}
-void Surface3DRenderer::updateSurfaceGradient(const QLinearGradient &gradient)
-{
- QImage image(QSize(2, 1024), QImage::Format_RGB32);
- QPainter pmp(&image);
- pmp.setBrush(QBrush(gradient));
- pmp.setPen(Qt::NoPen);
- pmp.drawRect(0, 0, 2, 1024);
-
- if (m_gradientTexture) {
- m_textureHelper->deleteTexture(&m_gradientTexture);
- m_gradientTexture = 0;
+ m_selectionDirty = false;
}
-
- m_gradientTexture = m_textureHelper->create2DTexture(image, false, true);
}
// This one needs to be called when the data size changes
@@ -1656,7 +1762,7 @@ void Surface3DRenderer::initSelectionBuffer()
m_selectionResultTexture = 0;
}
- m_selectionResultTexture = m_textureHelper->createSelectionTexture(m_mainViewPort.size(),
+ m_selectionResultTexture = m_textureHelper->createSelectionTexture(m_primarySubViewport.size(),
m_selectionFrameBuffer,
m_selectionDepthBuffer);
}
@@ -1689,11 +1795,6 @@ void Surface3DRenderer::idToRGBA(uint id, uchar *r, uchar *g, uchar *b, uchar *a
*a = (id >> 24) & ID_TO_RGBA_MASK;
}
-void Surface3DRenderer::updateTextures()
-{
- updateSurfaceGradient(m_cachedTheme.m_surfaceGradient);
-}
-
void Surface3DRenderer::calculateSceneScalingFactors()
{
// Calculate scene scaling and translation factors
@@ -1714,24 +1815,24 @@ void Surface3DRenderer::calculateSceneScalingFactors()
#endif
}
-bool Surface3DRenderer::updateSmoothStatus(bool enable)
+bool Surface3DRenderer::updateFlatStatus(bool enable)
{
- if (!enable && !m_flatSupported) {
+ if (enable && !m_flatSupported) {
qWarning() << "Warning: Flat qualifier not supported on your platform's GLSL language."
" Requires at least GLSL version 1.2 with GL_EXT_gpu_shader4 extension.";
- enable = true;
+ enable = false;
}
bool changed = false;
- if (enable != m_cachedSmoothSurface) {
- m_cachedSmoothSurface = enable;
+ if (enable != m_cachedFlatShading) {
+ m_cachedFlatShading = enable;
changed = true;
initSurfaceShaders();
}
// If no surface object created yet, don't try to update the object
if (m_surfaceObj && changed && m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) {
- if (m_cachedSmoothSurface) {
+ if (!m_cachedFlatShading) {
m_surfaceObj->setUpSmoothData(m_dataArray, m_sampleSpace, m_heightNormalizer,
m_axisCacheY.min(), true);
} else {
@@ -1740,15 +1841,14 @@ bool Surface3DRenderer::updateSmoothStatus(bool enable)
}
}
- return m_cachedSmoothSurface;
+ return m_cachedFlatShading;
}
-void Surface3DRenderer::updateSelectionMode(QDataVis::SelectionMode mode)
+void Surface3DRenderer::updateSelectedPoint(const QPoint &position, const QSurface3DSeries *series)
{
- if (mode != m_cachedSelectionMode)
- m_selectionModeChanged = true;
-
- Abstract3DRenderer::updateSelectionMode(mode);
+ m_selectedPoint = position;
+ m_selectedSeries = series;
+ m_selectionDirty = true;
}
void Surface3DRenderer::updateSurfaceGridStatus(bool enable)
@@ -1782,65 +1882,63 @@ void Surface3DRenderer::loadGridLineMesh()
{
if (m_gridLineObj)
delete m_gridLineObj;
- m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar"));
+ m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
m_gridLineObj->load();
}
-void Surface3DRenderer::handleResize()
+void Surface3DRenderer::surfacePointSelected(const QPoint &point)
{
- if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0)
- return;
+ int row = point.x();
+ int column = point.y();
- setViewPorts();
-
- Abstract3DRenderer::handleResize();
-}
-
-void Surface3DRenderer::surfacePointSelected(int id)
-{
- int column = (id - 1) % m_sampleSpace.width();
- int row = (id - 1) / m_sampleSpace.width();
-
- if (row < 0 || column < 0 || m_dataArray.size() < row || m_dataArray.at(row)->size() < column)
- return;
-
- qreal value = qreal(m_dataArray.at(row)->at(column).y());
+ float value = m_dataArray.at(row)->at(column).y();
if (!m_selectionPointer)
m_selectionPointer = new SelectionPointer(m_drawer);
QVector3D pos;
- if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) {
- pos = m_sliceSurfaceObj->vertexAt(column, 0);
- pos *= QVector3D(m_surfaceScaleX, 1.0f, 0.0f);
- pos += QVector3D(m_surfaceOffsetX, 0.0f, 0.0f);
- m_selectionPointer->updateBoundingRect(m_sliceViewPort);
- m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment);
- } else if (m_cachedSelectionMode == QDataVis::SelectionModeSliceColumn) {
- pos = m_sliceSurfaceObj->vertexAt(row, 0);
- pos *= QVector3D(m_surfaceScaleZ, 1.0f, 0.0f);
- pos += QVector3D(-m_surfaceOffsetZ, 0.0f, 0.0f);
- m_selectionPointer->updateBoundingRect(m_sliceViewPort);
- m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment);
+ if (m_cachedIsSlicingActivated) {
+ if (m_cachedSelectionMode.testFlag(QDataVis::SelectionRow)) {
+ pos = m_sliceSurfaceObj->vertexAt(column, 0);
+ pos *= QVector3D(m_surfaceScaleX, 1.0f, 0.0f);
+ pos += QVector3D(m_surfaceOffsetX, 0.0f, 0.0f);
+ m_selectionPointer->updateBoundingRect(m_secondarySubViewport);
+ m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment);
+ } else if (m_cachedSelectionMode.testFlag(QDataVis::SelectionColumn)) {
+ pos = m_sliceSurfaceObj->vertexAt(row, 0);
+ pos *= QVector3D(m_surfaceScaleZ, 1.0f, 0.0f);
+ pos += QVector3D(-m_surfaceOffsetZ, 0.0f, 0.0f);
+ m_selectionPointer->updateBoundingRect(m_secondarySubViewport);
+ m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment);
+ }
} else {
pos = m_surfaceObj->vertexAt(column, row);
pos *= QVector3D(m_surfaceScaleX, 1.0f, m_surfaceScaleZ);;
pos += QVector3D(m_surfaceOffsetX, 0.0f, m_surfaceOffsetZ);
- m_selectionPointer->updateBoundingRect(m_mainViewPort);
+ m_selectionPointer->updateBoundingRect(m_primarySubViewport);
m_selectionPointer->updateSliceData(false, m_autoScaleAdjustment);
}
m_selectionPointer->setPosition(pos);
m_selectionPointer->setLabel(createSelectionLabel(value, column, row));
+ // TODO: Get pointer object from correct series once multiseries support implemented
+ m_selectionPointer->setPointerObject(m_visibleSeriesList.at(0).object());
+ m_selectionPointer->setHighlightColor(m_visibleSeriesList.at(0).singleHighlightColor());
m_selectionPointer->updateScene(m_cachedScene);
+}
- //Put the selection pointer flag active
- m_selectionActive = true;
+// Maps selection Id to surface point in data array
+QPoint Surface3DRenderer::selectionIdToSurfacePoint(uint id)
+{
+ int column = ((id - 1) % m_sampleSpace.width()) + m_sampleSpace.x();
+ int row = ((id - 1) / m_sampleSpace.width()) + m_sampleSpace.y();
+ return QPoint(row, column);
}
-QString Surface3DRenderer::createSelectionLabel(qreal value, int column, int row)
+QString Surface3DRenderer::createSelectionLabel(float value, int column, int row)
{
- QString labelText = itemLabelFormat();
+ // TODO: Get from correct series once multiple series supported
+ QString labelText = m_visibleSeriesList[0].itemLabelFormat();
static const QString xTitleTag(QStringLiteral("@xTitle"));
static const QString yTitleTag(QStringLiteral("@yTitle"));
static const QString zTitleTag(QStringLiteral("@zTitle"));
@@ -1879,16 +1977,10 @@ QString Surface3DRenderer::createSelectionLabel(qreal value, int column, int row
return labelText;
}
-void Surface3DRenderer::loadMeshFile()
-{
- // Do nothing, not yet supported by this renderer
- // TODO: To be used for overriding the selection ball mesh after technology preview
-}
-
void Surface3DRenderer::updateShadowQuality(QDataVis::ShadowQuality quality)
{
- qWarning() << "Shadows have been disabled for Q3DSurface in technology preview";
- m_cachedShadowQuality = QDataVis::ShadowQualityNone; //quality;
+ m_cachedShadowQuality = quality;
+
switch (quality) {
case QDataVis::ShadowQualityLow:
m_shadowQualityToShader = 33.3f;
@@ -1920,11 +2012,18 @@ void Surface3DRenderer::updateShadowQuality(QDataVis::ShadowQuality quality)
break;
}
+ handleShadowQualityChange();
+
#if !defined(QT_OPENGL_ES_2)
updateDepthBuffer();
#endif
}
+void Surface3DRenderer::updateTextures()
+{
+ // Do nothing, but required as it is pure virtual on parent
+}
+
void Surface3DRenderer::updateSlicingActive(bool isSlicing)
{
if (m_cachedIsSlicingActivated == isSlicing)
@@ -1932,50 +2031,58 @@ void Surface3DRenderer::updateSlicingActive(bool isSlicing)
m_cachedIsSlicingActivated = isSlicing;
- setViewPorts();
-
if (!m_cachedIsSlicingActivated)
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::setViewPorts()
-{
- // Update view ports
- if (m_cachedIsSlicingActivated) {
- m_mainViewPort = QRect(0,
- m_cachedBoundingRect.height()
- - (m_cachedBoundingRect.height() / subViewDivider),
- m_cachedBoundingRect.width() / subViewDivider,
- m_cachedBoundingRect.height() / subViewDivider);
- m_sliceViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height());
- if (m_selectionPointer)
- m_selectionPointer->updateBoundingRect(m_sliceViewPort);
- } else {
- m_mainViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height());
- m_sliceViewPort = QRect(0, 0, 0, 0);
- if (m_selectionPointer)
- m_selectionPointer->updateBoundingRect(m_mainViewPort);
- }
+ m_selectionDirty = true;
}
void Surface3DRenderer::loadLabelMesh()
{
if (m_labelObj)
delete m_labelObj;
- m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label"));
+ m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
m_labelObj->load();
}
void Surface3DRenderer::initShaders(const QString &vertexShader, const QString &fragmentShader)
{
+ // m_shader is used slice view surface only.
if (m_shader)
delete m_shader;
m_shader = new ShaderHelper(this, vertexShader, fragmentShader);
m_shader->initialize();
+
+ // draw the shader for the surface according to smooth status, shadow and uniform color
+ if (m_surfaceShader)
+ delete m_surfaceShader;
+#if !defined(QT_OPENGL_ES_2)
+ if (!m_cachedFlatShading) {
+ if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
+ m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentSurfaceShadowNoTex"));
+ } else {
+ m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragmentSurface"));
+ }
+ } else {
+ if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
+ m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceShadowFlat"),
+ QStringLiteral(":/shaders/fragmentSurfaceShadowFlat"));
+ } else {
+ m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
+ QStringLiteral(":/shaders/fragmentSurfaceFlat"));
+ }
+ }
+#else
+ m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragmentSurfaceES2"));
+#endif
+ m_surfaceShader->initialize();
}
void Surface3DRenderer::initBackgroundShaders(const QString &vertexShader,
@@ -1998,30 +2105,15 @@ void Surface3DRenderer::initSelectionShaders()
void Surface3DRenderer::initSurfaceShaders()
{
- if (m_surfaceShader)
- delete m_surfaceShader;
-
-#if !defined(QT_OPENGL_ES_2)
- if (m_cachedSmoothSurface) {
- m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurface"),
- QStringLiteral(":/shaders/fragmentSurface"));
- } else {
- m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
- QStringLiteral(":/shaders/fragmentSurfaceFlat"));
- }
-#else
- m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurface"),
- QStringLiteral(":/shaders/fragmentSurfaceES2"));
-#endif
- m_surfaceShader->initialize();
-
+ // Gridline shader
if (m_surfaceGridShader)
delete m_surfaceGridShader;
-
- m_surfaceGridShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceGrid"),
- QStringLiteral(":/shaders/fragmentSurfaceGrid"));
-
+ m_surfaceGridShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexPlainColor"),
+ QStringLiteral(":/shaders/fragmentPlainColor"));
m_surfaceGridShader->initialize();
+
+ // Triggers surface shader selection by shadow setting
+ handleShadowQualityChange();
}
void Surface3DRenderer::initLabelShaders(const QString &vertexShader, const QString &fragmentShader)
@@ -2035,7 +2127,6 @@ void Surface3DRenderer::initLabelShaders(const QString &vertexShader, const QStr
#if !defined(QT_OPENGL_ES_2)
void Surface3DRenderer::initDepthShader()
{
- // TODO: Implement a depth shader for surface after technology preview
if (m_depthShader)
delete m_depthShader;
m_depthShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexDepth"),
@@ -2050,52 +2141,33 @@ void Surface3DRenderer::updateDepthBuffer()
m_depthTexture = 0;
}
- if (m_mainViewPort.size().isEmpty())
+ if (m_primarySubViewport.size().isEmpty())
return;
if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) {
- m_depthTexture = m_textureHelper->createDepthTexture(m_mainViewPort.size(),
- m_depthFrameBuffer,
- m_shadowQualityMultiplier);
- if (!m_depthTexture) {
- switch (m_cachedShadowQuality) {
- case QDataVis::ShadowQualityHigh:
- qWarning("Creating high quality shadows failed. Changing to medium quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityMedium);
- updateShadowQuality(QDataVis::ShadowQualityMedium);
- break;
- case QDataVis::ShadowQualityMedium:
- qWarning("Creating medium quality shadows failed. Changing to low quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityLow);
- updateShadowQuality(QDataVis::ShadowQualityLow);
- break;
- case QDataVis::ShadowQualityLow:
- qWarning("Creating low quality shadows failed. Switching shadows off.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityNone);
- updateShadowQuality(QDataVis::ShadowQualityNone);
- break;
- case QDataVis::ShadowQualitySoftHigh:
- qWarning("Creating soft high quality shadows failed. Changing to soft medium quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualitySoftMedium);
- updateShadowQuality(QDataVis::ShadowQualitySoftMedium);
- break;
- case QDataVis::ShadowQualitySoftMedium:
- qWarning("Creating soft medium quality shadows failed. Changing to soft low quality.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualitySoftLow);
- updateShadowQuality(QDataVis::ShadowQualitySoftLow);
- break;
- case QDataVis::ShadowQualitySoftLow:
- qWarning("Creating soft low quality shadows failed. Switching shadows off.");
- (void)m_controller->setShadowQuality(QDataVis::ShadowQualityNone);
- updateShadowQuality(QDataVis::ShadowQualityNone);
- break;
- default:
- // You'll never get here
- break;
- }
- }
+ m_depthTexture = m_textureHelper->createDepthTextureFrameBuffer(m_primarySubViewport.size(),
+ m_depthFrameBuffer,
+ m_shadowQualityMultiplier);
+ m_textureHelper->fillDepthTexture(m_depthTexture, m_primarySubViewport.size(), m_shadowQualityMultiplier, 1.0f);
+ m_depthModelTexture = m_textureHelper->createDepthTexture(m_primarySubViewport.size(),
+ m_shadowQualityMultiplier);
+ if (!m_depthTexture || !m_depthModelTexture)
+ lowerShadowQuality();
}
}
#endif
+void Surface3DRenderer::generateUniformGradient(const QVector3D newColor)
+{
+ if (m_visibleSeriesList.size()) {
+ // TODO: move uniform gradient to render cache when multiseries support implemented QTRD-2657
+ QColor newQColor = Utils::colorFromVector(newColor);
+ m_uniformGradientTextureColor = newColor;
+ QLinearGradient newGradient;
+ newGradient.setColorAt(0.0, newQColor);
+ newGradient.setColorAt(1.0, newQColor);
+ fixGradientAndGenerateTexture(&newGradient, &m_uniformGradientTexture);
+ }
+}
+
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h
index c805e508..f70fde9b 100644
--- a/src/datavisualization/engine/surface3drenderer_p.h
+++ b/src/datavisualization/engine/surface3drenderer_p.h
@@ -33,7 +33,6 @@
#include <QtCore/QObject>
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QFont>
-#include <QLinearGradient>
#include <QWindow>
#include "datavisualizationglobal_p.h"
@@ -60,11 +59,9 @@ class QT_DATAVISUALIZATION_EXPORT Surface3DRenderer : public Abstract3DRenderer
Q_OBJECT
public:
- Surface3DController *m_controller;
-
// Visual parameters
QRect m_boundingRect;
- QDataVis::LabelStyle m_labelStyle;
+ bool m_labelBackground;
QFont m_font;
bool m_isGridEnabled;
@@ -72,8 +69,6 @@ private:
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,15 +98,16 @@ private:
SurfaceObject *m_surfaceObj;
SurfaceObject *m_sliceSurfaceObj;
GLuint m_depthTexture;
+ GLuint m_depthModelTexture;
GLuint m_depthFrameBuffer;
GLuint m_selectionFrameBuffer;
GLuint m_selectionDepthBuffer;
- GLuint m_gradientTexture;
GLuint m_selectionTexture;
GLuint m_selectionResultTexture;
GLfloat m_shadowQualityToShader;
- bool m_cachedSmoothSurface;
+ bool m_cachedFlatShading;
bool m_flatSupported;
+ bool m_cachedSurfaceVisible;
bool m_cachedSurfaceGridOn;
SelectionPointer *m_selectionPointer;
bool m_selectionActive;
@@ -124,36 +120,42 @@ private:
QRect m_sampleSpace;
GLint m_shadowQualityMultiplier;
QSizeF m_areaSize;
- uint m_cachedSelectionId;
- bool m_selectionModeChanged;
+ uint m_clickedPointId;
bool m_hasHeightAdjustmentChanged;
+ QPoint m_selectedPoint;
+ const QSurface3DSeries *m_selectedSeries;
+ GLuint m_uniformGradientTexture;
+ QVector3D m_uniformGradientTextureColor;
public:
explicit Surface3DRenderer(Surface3DController *controller);
~Surface3DRenderer();
- void updateDataModel(QSurfaceDataProxy *dataProxy);
+ void updateData();
+ void updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility);
+ void updateRows(const QVector<int> &rows);
+ void updateItem(const QVector<QPoint> &points);
void updateScene(Q3DScene *scene);
+ bool updateFlatStatus(bool enable);
+ void updateSurfaceGridStatus(bool enable);
+ void updateSlicingActive(bool isSlicing);
+ void updateSelectedPoint(const QPoint &position, const QSurface3DSeries *series);
+
void drawSlicedScene();
void render(GLuint defaultFboHandle = 0);
protected:
void initializeOpenGL();
- virtual void loadMeshFile();
-public slots:
- bool updateSmoothStatus(bool enable);
- void updateSurfaceGridStatus(bool enable);
- void updateSurfaceGradient(const QLinearGradient &gradient);
- void updateSlicingActive(bool isSlicing);
- void updateSelectionMode(QDataVis::SelectionMode mode);
+signals:
+ void pointClicked(QPoint position, QSurface3DSeries *series);
+ void flatShadingSupportedChanged(bool supported);
private:
- void setViewPorts();
- void updateSliceDataModel(int selectionId);
- virtual void updateShadowQuality(QDataVis::ShadowQuality quality);
- virtual void updateTextures();
- virtual void initShaders(const QString &vertexShader, const QString &fragmentShader);
+ void updateSliceDataModel(const QPoint &point);
+ void updateShadowQuality(QDataVis::ShadowQuality quality);
+ void updateTextures();
+ void initShaders(const QString &vertexShader, const QString &fragmentShader);
QRect calculateSampleRect(const QSurfaceDataArray &array);
void loadBackgroundMesh();
void loadGridLineMesh();
@@ -161,7 +163,6 @@ private:
void loadSurfaceObj();
void loadSliceSurfaceObj();
void drawScene(GLuint defaultFboHandle);
- void handleResize();
void calculateSceneScalingFactors();
void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader);
void initLabelShaders(const QString &vertexShader, const QString &fragmentShader);
@@ -172,11 +173,14 @@ private:
void updateSelectionTexture();
void idToRGBA(uint id, uchar *r, uchar *g, uchar *b, uchar *a);
void fillIdCorner(uchar *p, uchar r, uchar g, uchar b, uchar a, int stride);
- void surfacePointSelected(int id);
- QString createSelectionLabel(qreal value, int column, int row);
+ void surfacePointSelected(const QPoint &point);
+ QPoint selectionIdToSurfacePoint(uint id);
+ QString createSelectionLabel(float value, int column, int row);
#if !defined(QT_OPENGL_ES_2)
void updateDepthBuffer();
#endif
+ void emitSelectedPointChanged(QPoint position);
+ void generateUniformGradient(const QVector3D newColor);
Q_DISABLE_COPY(Surface3DRenderer)
};
diff --git a/src/datavisualization/engine/theme.cpp b/src/datavisualization/engine/theme.cpp
deleted file mode 100644
index 387540b1..00000000
--- a/src/datavisualization/engine/theme.cpp
+++ /dev/null
@@ -1,250 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use contact form at http://qt.digia.com
-**
-** This file is part of the QtDataVisualization module.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** contact form at http://qt.digia.com
-**
-****************************************************************************/
-
-#include "theme_p.h"
-
-#ifdef Q_OS_WIN
-#include <windows.h>
-#include <stdio.h>
-#endif
-
-QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-
-Theme::Theme()
- : m_baseColor(QColor(Qt::gray)),
- m_heightColor(QColor(Qt::black)),
- m_depthColor(QColor(Qt::black)),
- m_backgroundColor(QColor(Qt::gray)),
- m_windowColor(QColor(Qt::gray)),
- m_textColor(QColor(Qt::white)),
- m_textBackgroundColor(QColor(0x00, 0x00, 0x00, 0xa0)),
- m_gridLine(QColor(Qt::black)),
- m_highlightBarColor(QColor(Qt::red)),
- m_highlightRowColor(QColor(Qt::darkRed)),
- m_highlightColumnColor(QColor(Qt::darkMagenta)),
- m_surfaceGradient(QLinearGradient(2, 1024, 0, 0)),
- m_lightStrength(4.0f),
- m_ambientStrength(0.3f),
- m_highlightLightStrength(8.0f),
- m_uniformColor(true),
- m_labelBorders(false)
-{
- // Default values for surface gradient
-}
-
-Theme::~Theme()
-{
-}
-
-QDataVis::Theme Theme::theme()
-{
- return m_theme;
-}
-
-void Theme::useTheme(QDataVis::Theme theme)
-{
- m_theme = theme;
- switch (theme) {
- case QDataVis::ThemeQt: {
- m_baseColor = QColor(QRgb(0x80c342));
- //m_heightColor = QColor(QRgb(0x));
- //m_depthColor = QColor(QRgb(0x));
- m_backgroundColor = QColor(QRgb(0xffffff));
- m_windowColor = QColor(QRgb(0xffffff));
- m_textColor = QColor(QRgb(0x35322f));
- m_textBackgroundColor = QColor(0xff, 0xff, 0xff, 0x99);
- m_gridLine = QColor(QRgb(0xd7d6d5));
- m_highlightBarColor = QColor(QRgb(0x14aaff));
- m_highlightRowColor = QColor(QRgb(0x6400aa));
- m_highlightColumnColor = QColor(QRgb(0x6400aa));
- m_lightStrength = 5.0f;
- m_ambientStrength = 0.5f;
- m_highlightLightStrength = 5.0f;
- m_uniformColor = true;
- m_labelBorders = true;
- break;
- }
- case QDataVis::ThemePrimaryColors: {
- m_baseColor = QColor(QRgb(0xffe400));
- //m_heightColor = QColor(QRgb(0x));
- //m_depthColor = QColor(QRgb(0x));
- m_backgroundColor = QColor(QRgb(0xffffff));
- m_windowColor = QColor(QRgb(0xffffff));
- m_textColor = QColor(QRgb(0x000000));
- m_textBackgroundColor = QColor(0xff, 0xff, 0xff, 0x99);
- m_gridLine = QColor(QRgb(0xd7d6d5));
- m_highlightBarColor = QColor(QRgb(0x27beee));
- m_highlightRowColor = QColor(QRgb(0xee1414));
- m_highlightColumnColor = QColor(QRgb(0xee1414));
- m_lightStrength = 5.0f;
- m_ambientStrength = 0.5f;
- m_highlightLightStrength = 5.0f;
- m_uniformColor = true;
- m_labelBorders = false;
- break;
- }
- case QDataVis::ThemeDigia: {
- m_baseColor = QColor(QRgb(0xcccccc));
- //m_heightColor = QColor(QRgb(0x));
- //m_depthColor = QColor(QRgb(0x));
- m_backgroundColor = QColor(QRgb(0xffffff));
- m_windowColor = QColor(QRgb(0xffffff));
- m_textColor = QColor(QRgb(0x000000));
- m_textBackgroundColor = QColor(0xff, 0xff, 0xff, 0x80);
- m_gridLine = QColor(QRgb(0xd7d6d5));
- m_highlightBarColor = QColor(QRgb(0xfa0000));
- m_highlightRowColor = QColor(QRgb(0x555555));
- m_highlightColumnColor = QColor(QRgb(0x555555));
- m_lightStrength = 5.0f;
- m_ambientStrength = 0.5f;
- m_highlightLightStrength = 5.0f;
- m_uniformColor = false;
- m_labelBorders = false;
- break;
- }
- case QDataVis::ThemeStoneMoss: {
- m_baseColor = QColor(QRgb(0xbeb32b));
- //m_heightColor = QColor(QRgb(0x));
- //m_depthColor = QColor(QRgb(0x));
- m_backgroundColor = QColor(QRgb(0x4d4d4f));
- m_windowColor = QColor(QRgb(0x4d4d4f));
- m_textColor = QColor(QRgb(0xffffff));
- m_textBackgroundColor = QColor(0x4d, 0x4d, 0x4f, 0xcd);
- m_gridLine = QColor(QRgb(0x3e3e40));
- m_highlightBarColor = QColor(QRgb(0xfbf6d6));
- m_highlightRowColor = QColor(QRgb(0x442f20));
- m_highlightColumnColor = QColor(QRgb(0x442f20));
- m_lightStrength = 5.0f;
- m_ambientStrength = 0.5f;
- m_highlightLightStrength = 5.0f;
- m_uniformColor = true;
- m_labelBorders = true;
- break;
- }
- case QDataVis::ThemeArmyBlue: {
- m_baseColor = QColor(QRgb(0x495f76));
- //m_heightColor = QColor(QRgb(0x));
- //m_depthColor = QColor(QRgb(0x));
- m_backgroundColor = QColor(QRgb(0xd5d6d7));
- m_windowColor = QColor(QRgb(0xd5d6d7));
- m_textColor = QColor(QRgb(0x000000));
- m_textBackgroundColor = QColor(0xd5, 0xd6, 0xd7, 0xcd);
- m_gridLine = QColor(QRgb(0xaeadac));
- m_highlightBarColor = QColor(QRgb(0x2aa2f9));
- m_highlightRowColor = QColor(QRgb(0x103753));
- m_highlightColumnColor = QColor(QRgb(0x103753));
- m_lightStrength = 5.0f;
- m_ambientStrength = 0.5f;
- m_highlightLightStrength = 5.0f;
- m_uniformColor = false;
- m_labelBorders = false;
- break;
- }
- case QDataVis::ThemeRetro: {
- m_baseColor = QColor(QRgb(0x533b23));
- //m_heightColor = QColor(QRgb(0x));
- //m_depthColor = QColor(QRgb(0x));
- m_backgroundColor = QColor(QRgb(0xe9e2ce));
- m_windowColor = QColor(QRgb(0xe9e2ce));
- m_textColor = QColor(QRgb(0x000000));
- m_textBackgroundColor = QColor(0xe9, 0xe2, 0xce, 0xc0);
- m_gridLine = QColor(QRgb(0xd0c0b0));
- m_highlightBarColor = QColor(QRgb(0x8ea317));
- m_highlightRowColor = QColor(QRgb(0xc25708));
- m_highlightColumnColor = QColor(QRgb(0xc25708));
- m_lightStrength = 5.0f;
- m_ambientStrength = 0.5f;
- m_highlightLightStrength = 5.0f;
- m_uniformColor = false;
- m_labelBorders = false;
- break;
- }
- case QDataVis::ThemeEbony: {
- m_baseColor = QColor(QRgb(0xffffff));
- //m_heightColor = QColor(QRgb(0x));
- //m_depthColor = QColor(QRgb(0x));
- m_backgroundColor = QColor(QRgb(0x000000));
- m_windowColor = QColor(QRgb(0x000000));
- m_textColor = QColor(QRgb(0xaeadac));
- m_textBackgroundColor = QColor(0x00, 0x00, 0x00, 0xcd);
- m_gridLine = QColor(QRgb(0x35322f));
- m_highlightBarColor = QColor(QRgb(0xf5dc0d));
- m_highlightRowColor = QColor(QRgb(0xd72222));
- m_highlightColumnColor = QColor(QRgb(0xd72222));
- m_lightStrength = 5.0f;
- m_ambientStrength = 0.5f;
- m_highlightLightStrength = 5.0f;
- m_uniformColor = true;
- m_labelBorders = false;
- break;
- }
- case QDataVis::ThemeIsabelle: {
- m_baseColor = QColor(QRgb(0xf9d900));
- //m_heightColor = QColor(QRgb(0x));
- //m_depthColor = QColor(QRgb(0x));
- m_backgroundColor = QColor(QRgb(0x000000));
- m_windowColor = QColor(QRgb(0x000000));
- m_textColor = QColor(QRgb(0xaeadac));
- m_textBackgroundColor = QColor(0x00, 0x00, 0x00, 0xc0);
- m_gridLine = QColor(QRgb(0x35322f));
- m_highlightBarColor = QColor(QRgb(0xfff7cc));
- m_highlightRowColor = QColor(QRgb(0xde0a0a));
- m_highlightColumnColor = QColor(QRgb(0xde0a0a));
- m_lightStrength = 5.0f;
- m_ambientStrength = 0.5f;
- m_highlightLightStrength = 5.0f;
- m_uniformColor = true;
- m_labelBorders = false;
- break;
- }
- default:
- break;
- }
- if (m_uniformColor) {
- m_surfaceGradient.setColorAt(0.0, m_baseColor);
- } else {
- m_surfaceGradient.setColorAt(0.0, QColor(m_baseColor.redF() * 0.7,
- m_baseColor.greenF() * 0.7,
- m_baseColor.blueF() * 0.7));
- }
- m_surfaceGradient.setColorAt(1.0, m_baseColor);
-}
-
-void Theme::setFromTheme(Theme &theme)
-{
- m_theme = theme.m_theme;
- m_baseColor = theme.m_baseColor;
- m_heightColor = theme.m_heightColor;
- m_depthColor = theme.m_depthColor;
- m_backgroundColor = theme.m_backgroundColor;
- m_windowColor = theme.m_windowColor;
- m_textColor = theme.m_textColor;
- m_textBackgroundColor = theme.m_textBackgroundColor;
- m_gridLine = theme.m_gridLine;
- m_highlightBarColor = theme.m_highlightBarColor;
- m_highlightRowColor = theme.m_highlightRowColor;
- m_highlightColumnColor = theme.m_highlightColumnColor;
- m_surfaceGradient = theme.m_surfaceGradient;
- m_lightStrength = theme.m_lightStrength;
- m_ambientStrength = theme.m_ambientStrength;
- m_highlightLightStrength = theme.m_highlightLightStrength;
- m_uniformColor = theme.m_uniformColor;
- m_labelBorders = theme.m_labelBorders;
-}
-
-QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/engine/theme_p.h b/src/datavisualization/engine/theme_p.h
deleted file mode 100644
index ec689f63..00000000
--- a/src/datavisualization/engine/theme_p.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use contact form at http://qt.digia.com
-**
-** This file is part of the QtDataVisualization module.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** contact form at http://qt.digia.com
-**
-****************************************************************************/
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the QtDataVisualization API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-
-#ifndef THEME_P_H
-#define THEME_P_H
-
-#include "datavisualizationglobal_p.h"
-#include "q3dbars.h"
-#include <QLinearGradient>
-
-class QColor;
-
-QT_DATAVISUALIZATION_BEGIN_NAMESPACE
-
-class QT_DATAVISUALIZATION_EXPORT Theme
-{
-public:
- explicit Theme();
- ~Theme();
-
- void useTheme(QDataVis::Theme theme);
- QDataVis::Theme theme();
- void setFromTheme(Theme &theme);
-
-private:
- friend class Abstract3DController;
- friend class Abstract3DRenderer;
- friend class Bars3DRenderer;
- friend class Surface3DRenderer;
- friend class Surface3DController;
- friend class Scatter3DRenderer;
- friend class SelectionPointer;
- friend class Drawer;
-
- QDataVis::Theme m_theme;
- QColor m_baseColor;
- QColor m_heightColor;
- QColor m_depthColor;
- QColor m_backgroundColor;
- QColor m_windowColor;
- QColor m_textColor;
- QColor m_textBackgroundColor;
- QColor m_gridLine;
- QColor m_highlightBarColor;
- QColor m_highlightRowColor;
- QColor m_highlightColumnColor;
- QLinearGradient m_surfaceGradient;
- float m_lightStrength;
- float m_ambientStrength;
- float m_highlightLightStrength;
- bool m_uniformColor;
- bool m_labelBorders;
-};
-
-QT_DATAVISUALIZATION_END_NAMESPACE
-
-#endif