summaryrefslogtreecommitdiffstats
path: root/src/datavisualization/engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/datavisualization/engine')
-rw-r--r--src/datavisualization/engine/abstract3dcontroller.cpp563
-rw-r--r--src/datavisualization/engine/abstract3dcontroller_p.h141
-rw-r--r--src/datavisualization/engine/abstract3drenderer.cpp797
-rw-r--r--src/datavisualization/engine/abstract3drenderer_p.h123
-rw-r--r--src/datavisualization/engine/axisrendercache.cpp89
-rw-r--r--src/datavisualization/engine/axisrendercache_p.h81
-rw-r--r--src/datavisualization/engine/bars3dcontroller.cpp133
-rw-r--r--src/datavisualization/engine/bars3dcontroller_p.h23
-rw-r--r--src/datavisualization/engine/bars3drenderer.cpp2245
-rw-r--r--src/datavisualization/engine/bars3drenderer_p.h51
-rw-r--r--src/datavisualization/engine/barseriesrendercache.cpp42
-rw-r--r--src/datavisualization/engine/barseriesrendercache_p.h61
-rw-r--r--src/datavisualization/engine/drawer.cpp174
-rw-r--r--src/datavisualization/engine/drawer_p.h12
-rw-r--r--src/datavisualization/engine/engine.pri8
-rw-r--r--src/datavisualization/engine/engine.qrc5
-rw-r--r--src/datavisualization/engine/meshes/backgroundNoFloor.obj (renamed from src/datavisualization/engine/meshes/backgroundNegatives.obj)20
-rw-r--r--src/datavisualization/engine/q3dbars.cpp8
-rw-r--r--src/datavisualization/engine/q3dcamera.cpp23
-rw-r--r--src/datavisualization/engine/q3dlight.cpp4
-rw-r--r--src/datavisualization/engine/q3dobject.cpp3
-rw-r--r--src/datavisualization/engine/q3dscatter.cpp6
-rw-r--r--src/datavisualization/engine/q3dscene.cpp17
-rw-r--r--src/datavisualization/engine/q3dscene.h2
-rw-r--r--src/datavisualization/engine/q3dscene_p.h1
-rw-r--r--src/datavisualization/engine/q3dsurface.cpp6
-rw-r--r--src/datavisualization/engine/qabstract3dgraph.cpp355
-rw-r--r--src/datavisualization/engine/qabstract3dgraph.h65
-rw-r--r--src/datavisualization/engine/qabstract3dgraph_p.h5
-rw-r--r--src/datavisualization/engine/scatter3dcontroller.cpp85
-rw-r--r--src/datavisualization/engine/scatter3dcontroller_p.h13
-rw-r--r--src/datavisualization/engine/scatter3drenderer.cpp1924
-rw-r--r--src/datavisualization/engine/scatter3drenderer_p.h53
-rw-r--r--src/datavisualization/engine/scatterseriesrendercache.cpp50
-rw-r--r--src/datavisualization/engine/scatterseriesrendercache_p.h77
-rw-r--r--src/datavisualization/engine/selectionpointer.cpp37
-rw-r--r--src/datavisualization/engine/selectionpointer_p.h12
-rw-r--r--src/datavisualization/engine/seriesrendercache.cpp112
-rw-r--r--src/datavisualization/engine/seriesrendercache_p.h33
-rw-r--r--src/datavisualization/engine/shaders/colorOnY.frag6
-rw-r--r--src/datavisualization/engine/shaders/colorOnY_ES2.frag10
-rw-r--r--src/datavisualization/engine/shaders/default.frag8
-rw-r--r--src/datavisualization/engine/shaders/default.vert10
-rw-r--r--src/datavisualization/engine/shaders/default_ES2.frag12
-rw-r--r--src/datavisualization/engine/shaders/plainColor.frag5
-rw-r--r--src/datavisualization/engine/shaders/shadow.frag6
-rw-r--r--src/datavisualization/engine/shaders/shadow.vert8
-rw-r--r--src/datavisualization/engine/shaders/shadowNoTex.frag8
-rw-r--r--src/datavisualization/engine/shaders/shadowNoTexColorOnY.frag6
-rw-r--r--src/datavisualization/engine/shaders/surface.frag6
-rw-r--r--src/datavisualization/engine/shaders/surfaceFlat.frag6
-rw-r--r--src/datavisualization/engine/shaders/surfaceFlat.vert8
-rw-r--r--src/datavisualization/engine/shaders/surfaceShadowFlat.frag6
-rw-r--r--src/datavisualization/engine/shaders/surfaceShadowFlat.vert8
-rw-r--r--src/datavisualization/engine/shaders/surfaceShadowNoTex.frag6
-rw-r--r--src/datavisualization/engine/shaders/surface_ES2.frag10
-rw-r--r--src/datavisualization/engine/shaders/texture.frag37
-rw-r--r--src/datavisualization/engine/shaders/texture.vert28
-rw-r--r--src/datavisualization/engine/shaders/texture_ES2.frag40
-rw-r--r--src/datavisualization/engine/surface3dcontroller.cpp100
-rw-r--r--src/datavisualization/engine/surface3dcontroller_p.h8
-rw-r--r--src/datavisualization/engine/surface3drenderer.cpp1543
-rw-r--r--src/datavisualization/engine/surface3drenderer_p.h44
-rw-r--r--src/datavisualization/engine/surfaceseriesrendercache.cpp39
-rw-r--r--src/datavisualization/engine/surfaceseriesrendercache_p.h28
65 files changed, 6298 insertions, 3157 deletions
diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp
index ec18a850..8658d463 100644
--- a/src/datavisualization/engine/abstract3dcontroller.cpp
+++ b/src/datavisualization/engine/abstract3dcontroller.cpp
@@ -17,22 +17,16 @@
****************************************************************************/
#include "abstract3dcontroller_p.h"
-#include "camerahelper_p.h"
#include "qabstract3daxis_p.h"
-#include "qvalue3daxis.h"
-#include "qcategory3daxis.h"
+#include "qvalue3daxis_p.h"
#include "abstract3drenderer_p.h"
-#include "q3dcamera.h"
-#include "q3dlight.h"
-#include "qabstractdataproxy_p.h"
#include "qabstract3dinputhandler_p.h"
#include "qtouch3dinputhandler.h"
-#include "qabstract3dseries_p.h"
#include "thememanager_p.h"
#include "q3dtheme_p.h"
-#include "q3dscene_p.h"
-#include "q3dscene.h"
+#include "qcustom3ditem_p.h"
#include <QtCore/QThread>
+#include <QtGui/QOpenGLFramebufferObject>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -42,6 +36,9 @@ Abstract3DController::Abstract3DController(QRect initialViewport, Q3DScene *scen
m_themeManager(new ThemeManager(this)),
m_selectionMode(QAbstract3DGraph::SelectionItem),
m_shadowQuality(QAbstract3DGraph::ShadowQualityMedium),
+ m_useOrthoProjection(false),
+ m_aspectRatio(2.0f),
+ m_optimizationHints(QAbstract3DGraph::OptimizationDefault),
m_scene(scene),
m_activeInputHandler(0),
m_axisX(0),
@@ -49,9 +46,13 @@ Abstract3DController::Abstract3DController(QRect initialViewport, Q3DScene *scen
m_axisZ(0),
m_renderer(0),
m_isDataDirty(true),
- m_isSeriesVisibilityDirty(true),
+ m_isCustomDataDirty(true),
+ m_isCustomItemDirty(true),
m_isSeriesVisualsDirty(true),
- m_renderPending(false)
+ m_renderPending(false),
+ m_measureFps(false),
+ m_numFrames(0),
+ m_currentFps(0.0)
{
if (!m_scene)
m_scene = new Q3DScene;
@@ -84,6 +85,9 @@ Abstract3DController::~Abstract3DController()
destroyRenderer();
delete m_scene;
delete m_themeManager;
+ foreach (QCustom3DItem *item, m_customItems)
+ delete item;
+ m_customItems.clear();
}
void Abstract3DController::destroyRenderer()
@@ -142,7 +146,7 @@ void Abstract3DController::removeSeries(QAbstract3DSeries *series)
this, &Abstract3DController::handleSeriesVisibilityChanged);
series->d_ptr->setController(0);
m_isDataDirty = true;
- m_isSeriesVisibilityDirty = true;
+ m_isSeriesVisualsDirty = true;
emitNeedRender();
}
}
@@ -182,6 +186,46 @@ void Abstract3DController::synchDataToRenderer()
m_changeTracker.selectionModeChanged = false;
}
+ if (m_changeTracker.projectionChanged) {
+ m_renderer->m_useOrthoProjection = m_useOrthoProjection;
+ m_changeTracker.projectionChanged = false;
+ }
+
+ if (m_changeTracker.aspectRatioChanged) {
+ m_renderer->updateAspectRatio(m_aspectRatio);
+ m_changeTracker.aspectRatioChanged = false;
+ }
+
+ if (m_changeTracker.optimizationHintChanged) {
+ m_renderer->updateOptimizationHint(m_optimizationHints);
+ m_changeTracker.optimizationHintChanged = false;
+ }
+
+ if (m_changeTracker.axisXFormatterChanged) {
+ m_changeTracker.axisXFormatterChanged = false;
+ if (m_axisX->type() & QAbstract3DAxis::AxisTypeValue) {
+ QValue3DAxis *valueAxisX = static_cast<QValue3DAxis *>(m_axisX);
+ m_renderer->updateAxisFormatter(QAbstract3DAxis::AxisOrientationX,
+ valueAxisX->formatter());
+ }
+ }
+ if (m_changeTracker.axisYFormatterChanged) {
+ m_changeTracker.axisYFormatterChanged = false;
+ if (m_axisY->type() & QAbstract3DAxis::AxisTypeValue) {
+ QValue3DAxis *valueAxisY = static_cast<QValue3DAxis *>(m_axisY);
+ m_renderer->updateAxisFormatter(QAbstract3DAxis::AxisOrientationY,
+ valueAxisY->formatter());
+ }
+ }
+ if (m_changeTracker.axisZFormatterChanged) {
+ m_changeTracker.axisZFormatterChanged = false;
+ if (m_axisZ->type() & QAbstract3DAxis::AxisTypeValue) {
+ QValue3DAxis *valueAxisZ = static_cast<QValue3DAxis *>(m_axisZ);
+ m_renderer->updateAxisFormatter(QAbstract3DAxis::AxisOrientationZ,
+ valueAxisZ->formatter());
+ }
+ }
+
if (m_changeTracker.axisXTypeChanged) {
m_renderer->updateAxisType(QAbstract3DAxis::AxisOrientationX, m_axisX->type());
m_changeTracker.axisXTypeChanged = false;
@@ -325,9 +369,89 @@ void Abstract3DController::synchDataToRenderer()
}
}
- if (m_isSeriesVisibilityDirty || m_isSeriesVisualsDirty) {
- m_renderer->updateSeries(m_seriesList, m_isSeriesVisibilityDirty);
- m_isSeriesVisibilityDirty = false;
+ if (m_changeTracker.axisXReversedChanged) {
+ m_changeTracker.axisXReversedChanged = false;
+ if (m_axisX->type() & QAbstract3DAxis::AxisTypeValue) {
+ QValue3DAxis *valueAxisX = static_cast<QValue3DAxis *>(m_axisX);
+ m_renderer->updateAxisReversed(QAbstract3DAxis::AxisOrientationX,
+ valueAxisX->reversed());
+ }
+ }
+
+ if (m_changeTracker.axisYReversedChanged) {
+ m_changeTracker.axisYReversedChanged = false;
+ if (m_axisY->type() & QAbstract3DAxis::AxisTypeValue) {
+ QValue3DAxis *valueAxisY = static_cast<QValue3DAxis *>(m_axisY);
+ m_renderer->updateAxisReversed(QAbstract3DAxis::AxisOrientationY,
+ valueAxisY->reversed());
+ }
+ }
+
+ if (m_changeTracker.axisZReversedChanged) {
+ m_changeTracker.axisZReversedChanged = false;
+ if (m_axisZ->type() & QAbstract3DAxis::AxisTypeValue) {
+ QValue3DAxis *valueAxisZ = static_cast<QValue3DAxis *>(m_axisZ);
+ m_renderer->updateAxisReversed(QAbstract3DAxis::AxisOrientationZ,
+ valueAxisZ->reversed());
+ }
+ }
+
+ if (m_changeTracker.axisXLabelAutoRotationChanged) {
+ m_renderer->updateAxisLabelAutoRotation(QAbstract3DAxis::AxisOrientationX,
+ m_axisX->labelAutoRotation());
+ m_changeTracker.axisXLabelAutoRotationChanged = false;
+ }
+
+ if (m_changeTracker.axisYLabelAutoRotationChanged) {
+ m_renderer->updateAxisLabelAutoRotation(QAbstract3DAxis::AxisOrientationY,
+ m_axisY->labelAutoRotation());
+ m_changeTracker.axisYLabelAutoRotationChanged = false;
+ }
+
+ if (m_changeTracker.axisZLabelAutoRotationChanged) {
+ m_renderer->updateAxisLabelAutoRotation(QAbstract3DAxis::AxisOrientationZ,
+ m_axisZ->labelAutoRotation());
+ m_changeTracker.axisZLabelAutoRotationChanged = false;
+ }
+
+ if (m_changeTracker.axisXTitleVisibilityChanged) {
+ m_renderer->updateAxisTitleVisibility(QAbstract3DAxis::AxisOrientationX,
+ m_axisX->isTitleVisible());
+ m_changeTracker.axisXTitleVisibilityChanged = false;
+ }
+ if (m_changeTracker.axisYTitleVisibilityChanged) {
+ m_renderer->updateAxisTitleVisibility(QAbstract3DAxis::AxisOrientationY,
+ m_axisY->isTitleVisible());
+ m_changeTracker.axisYTitleVisibilityChanged = false;
+ }
+ if (m_changeTracker.axisZTitleVisibilityChanged) {
+ m_renderer->updateAxisTitleVisibility(QAbstract3DAxis::AxisOrientationZ,
+ m_axisZ->isTitleVisible());
+ m_changeTracker.axisZTitleVisibilityChanged = false;
+ }
+ if (m_changeTracker.axisXTitleFixedChanged) {
+ m_renderer->updateAxisTitleFixed(QAbstract3DAxis::AxisOrientationX,
+ m_axisX->isTitleFixed());
+ m_changeTracker.axisXTitleFixedChanged = false;
+ }
+ if (m_changeTracker.axisYTitleFixedChanged) {
+ m_renderer->updateAxisTitleFixed(QAbstract3DAxis::AxisOrientationY,
+ m_axisY->isTitleFixed());
+ m_changeTracker.axisYTitleFixedChanged = false;
+ }
+ if (m_changeTracker.axisZTitleFixedChanged) {
+ m_renderer->updateAxisTitleFixed(QAbstract3DAxis::AxisOrientationZ,
+ m_axisZ->isTitleFixed());
+ m_changeTracker.axisZTitleFixedChanged = false;
+ }
+
+ if (m_changedSeriesList.size()) {
+ m_renderer->modifiedSeriesList(m_changedSeriesList);
+ m_changedSeriesList.clear();
+ }
+
+ if (m_isSeriesVisualsDirty) {
+ m_renderer->updateSeries(m_seriesList);
m_isSeriesVisualsDirty = false;
}
@@ -337,6 +461,16 @@ void Abstract3DController::synchDataToRenderer()
m_renderer->updateData();
m_isDataDirty = false;
}
+
+ if (m_isCustomDataDirty) {
+ m_renderer->updateCustomData(m_customItems);
+ m_isCustomDataDirty = false;
+ }
+
+ if (m_isCustomItemDirty) {
+ m_renderer->updateCustomItems();
+ m_isCustomItemDirty = false;
+ }
}
void Abstract3DController::render(const GLuint defaultFboHandle)
@@ -347,12 +481,21 @@ void Abstract3DController::render(const GLuint defaultFboHandle)
if (!m_renderer)
return;
- m_renderer->render(defaultFboHandle);
+ if (m_measureFps) {
+ // Measure speed (as milliseconds per frame)
+ m_numFrames++;
+ int elapsed = m_frameTimer.elapsed();
+ if (elapsed >= 1000) {
+ m_currentFps = qreal(m_numFrames) * 1000.0 / qreal(elapsed);
+ emit currentFpsChanged(m_currentFps);
+ m_numFrames = 0;
+ m_frameTimer.restart();
+ }
+ // To get meaningful framerate, don't just do render on demand.
+ emitNeedRender();
+ }
-#ifdef DISPLAY_RENDER_SPEED
- // To get meaningful framerate, don't just do render on demand.
- emitNeedRender();
-#endif
+ m_renderer->render(defaultFboHandle);
}
void Abstract3DController::mouseDoubleClickEvent(QMouseEvent *event)
@@ -445,7 +588,8 @@ void Abstract3DController::handleThemeSingleHighlightColorChanged(const QColor &
markSeriesVisualsDirty();
}
-void Abstract3DController::handleThemeSingleHighlightGradientChanged(const QLinearGradient &gradient)
+void Abstract3DController::handleThemeSingleHighlightGradientChanged(
+ const QLinearGradient &gradient)
{
// Set value for series that have not explicitly set this value
foreach (QAbstract3DSeries *series, m_seriesList) {
@@ -503,7 +647,7 @@ void Abstract3DController::setAxisX(QAbstract3DAxis *axis)
}
}
-QAbstract3DAxis *Abstract3DController::axisX()
+QAbstract3DAxis *Abstract3DController::axisX() const
{
return m_axisX;
}
@@ -517,7 +661,7 @@ void Abstract3DController::setAxisY(QAbstract3DAxis *axis)
}
}
-QAbstract3DAxis *Abstract3DController::axisY()
+QAbstract3DAxis *Abstract3DController::axisY() const
{
return m_axisY;
}
@@ -531,7 +675,7 @@ void Abstract3DController::setAxisZ(QAbstract3DAxis *axis)
}
}
-QAbstract3DAxis *Abstract3DController::axisZ()
+QAbstract3DAxis *Abstract3DController::axisZ() const
{
return m_axisZ;
}
@@ -648,19 +792,6 @@ QList<QAbstract3DInputHandler *> Abstract3DController::inputHandlers() const
return m_inputHandlers;
}
-int Abstract3DController::zoomLevel()
-{
- return m_scene->activeCamera()->zoomLevel();
-}
-
-void Abstract3DController::setZoomLevel(int zoomLevel)
-{
- m_scene->activeCamera()->setZoomLevel(zoomLevel);
-
- m_changeTracker.zoomLevelChanged = true;
- emitNeedRender();
-}
-
void Abstract3DController::addTheme(Q3DTheme *theme)
{
m_themeManager->addTheme(theme);
@@ -675,12 +806,13 @@ void Abstract3DController::releaseTheme(Q3DTheme *theme)
if (oldTheme != m_themeManager->activeTheme())
emit activeThemeChanged(m_themeManager->activeTheme());
}
+
QList<Q3DTheme *> Abstract3DController::themes() const
{
return m_themeManager->themes();
}
-void Abstract3DController::setActiveTheme(Q3DTheme *theme)
+void Abstract3DController::setActiveTheme(Q3DTheme *theme, bool force)
{
if (theme != m_themeManager->activeTheme()) {
m_themeManager->setActiveTheme(theme);
@@ -689,7 +821,7 @@ void Abstract3DController::setActiveTheme(Q3DTheme *theme)
Q3DTheme *newActiveTheme = m_themeManager->activeTheme();
// Reset all attached series to the new theme
for (int i = 0; i < m_seriesList.size(); i++)
- m_seriesList.at(i)->d_ptr->resetToTheme(*newActiveTheme, i, true);
+ m_seriesList.at(i)->d_ptr->resetToTheme(*newActiveTheme, i, force);
markSeriesVisualsDirty();
emit activeThemeChanged(newActiveTheme);
}
@@ -717,6 +849,12 @@ QAbstract3DGraph::SelectionFlags Abstract3DController::selectionMode() const
void Abstract3DController::setShadowQuality(QAbstract3DGraph::ShadowQuality quality)
{
+ if (!m_useOrthoProjection)
+ doSetShadowQuality(quality);
+}
+
+void Abstract3DController::doSetShadowQuality(QAbstract3DGraph::ShadowQuality quality)
+{
if (quality != m_shadowQuality) {
m_shadowQuality = quality;
m_changeTracker.shadowQualityChanged = true;
@@ -730,6 +868,22 @@ QAbstract3DGraph::ShadowQuality Abstract3DController::shadowQuality() const
return m_shadowQuality;
}
+void Abstract3DController::setOptimizationHints(QAbstract3DGraph::OptimizationHints hints)
+{
+ if (hints != m_optimizationHints) {
+ m_optimizationHints = hints;
+ m_changeTracker.optimizationHintChanged = true;
+ m_isDataDirty = true;
+ emit optimizationHintsChanged(hints);
+ emitNeedRender();
+ }
+}
+
+QAbstract3DGraph::OptimizationHints Abstract3DController::optimizationHints() const
+{
+ return m_optimizationHints;
+}
+
bool Abstract3DController::shadowsSupported() const
{
#if defined(QT_OPENGL_ES_2)
@@ -747,7 +901,6 @@ bool Abstract3DController::isSlicingActive() const
void Abstract3DController::setSlicingActive(bool isSlicing)
{
m_scene->setSlicingActive(isSlicing);
- emitNeedRender();
}
Q3DScene *Abstract3DController::scene()
@@ -758,6 +911,8 @@ Q3DScene *Abstract3DController::scene()
void Abstract3DController::markDataDirty()
{
m_isDataDirty = true;
+
+ markSeriesItemLabelsDirty();
emitNeedRender();
}
@@ -767,6 +922,79 @@ void Abstract3DController::markSeriesVisualsDirty()
emitNeedRender();
}
+void Abstract3DController::requestRender(QOpenGLFramebufferObject *fbo)
+{
+ m_renderer->render(fbo->handle());
+}
+
+int Abstract3DController::addCustomItem(QCustom3DItem *item)
+{
+ if (!item)
+ return -1;
+
+ int index = m_customItems.indexOf(item);
+
+ if (index != -1)
+ return index;
+
+ item->setParent(this);
+ connect(item->d_ptr.data(), &QCustom3DItemPrivate::needUpdate,
+ this, &Abstract3DController::updateCustomItem);
+ m_customItems.append(item);
+ item->d_ptr->resetDirtyBits();
+ m_isCustomDataDirty = true;
+ emitNeedRender();
+ return m_customItems.count() - 1;
+}
+
+void Abstract3DController::deleteCustomItems()
+{
+ foreach (QCustom3DItem *item, m_customItems)
+ delete item;
+ m_customItems.clear();
+ m_isCustomDataDirty = true;
+ emitNeedRender();
+}
+
+void Abstract3DController::deleteCustomItem(QCustom3DItem *item)
+{
+ if (!item)
+ return;
+
+ m_customItems.removeOne(item);
+ delete item;
+ item = 0;
+ m_isCustomDataDirty = true;
+ emitNeedRender();
+}
+
+void Abstract3DController::deleteCustomItem(const QVector3D &position)
+{
+ // Get the item for the position
+ foreach (QCustom3DItem *item, m_customItems) {
+ if (item->position() == position)
+ deleteCustomItem(item);
+ }
+}
+
+void Abstract3DController::releaseCustomItem(QCustom3DItem *item)
+{
+ if (item && m_customItems.contains(item)) {
+ disconnect(item->d_ptr.data(), &QCustom3DItemPrivate::needUpdate,
+ this, &Abstract3DController::updateCustomItem);
+ m_customItems.removeOne(item);
+ item->setParent(0);
+ m_isCustomDataDirty = true;
+ emitNeedRender();
+ }
+}
+
+void Abstract3DController::updateCustomItem()
+{
+ m_isCustomItemDirty = true;
+ emitNeedRender();
+}
+
void Abstract3DController::handleAxisTitleChanged(const QString &title)
{
Q_UNUSED(title)
@@ -783,6 +1011,8 @@ void Abstract3DController::handleAxisTitleChangedBySender(QObject *sender)
m_changeTracker.axisZTitleChanged = true;
else
qWarning() << __FUNCTION__ << "invoked for invalid axis";
+
+ markSeriesItemLabelsDirty();
emitNeedRender();
}
@@ -801,6 +1031,8 @@ void Abstract3DController::handleAxisLabelsChangedBySender(QObject *sender)
m_changeTracker.axisZLabelsChanged = true;
else
qWarning() << __FUNCTION__ << "invoked for invalid axis";
+
+ markSeriesItemLabelsDirty();
emitNeedRender();
}
@@ -882,6 +1114,35 @@ void Abstract3DController::handleAxisLabelFormatChanged(const QString &format)
handleAxisLabelFormatChangedBySender(sender());
}
+void Abstract3DController::handleAxisReversedChanged(bool enable)
+{
+ Q_UNUSED(enable)
+ handleAxisReversedChangedBySender(sender());
+}
+
+void Abstract3DController::handleAxisFormatterDirty()
+{
+ handleAxisFormatterDirtyBySender(sender());
+}
+
+void Abstract3DController::handleAxisLabelAutoRotationChanged(float angle)
+{
+ Q_UNUSED(angle)
+ handleAxisLabelAutoRotationChangedBySender(sender());
+}
+
+void Abstract3DController::handleAxisTitleVisibilityChanged(bool visible)
+{
+ Q_UNUSED(visible)
+ handleAxisTitleVisibilityChangedBySender(sender());
+}
+
+void Abstract3DController::handleAxisTitleFixedChanged(bool fixed)
+{
+ Q_UNUSED(fixed)
+ handleAxisTitleFixedChangedBySender(sender());
+}
+
void Abstract3DController::handleInputViewChanged(QAbstract3DInputHandler::InputView view)
{
// When in automatic slicing mode, input view change to primary disables slice mode
@@ -890,15 +1151,12 @@ void Abstract3DController::handleInputViewChanged(QAbstract3DInputHandler::Input
setSlicingActive(false);
}
- m_changeTracker.inputViewChanged = true;
emitNeedRender();
}
void Abstract3DController::handleInputPositionChanged(const QPoint &position)
{
Q_UNUSED(position)
-
- m_changeTracker.inputPositionChanged = true;
emitNeedRender();
}
@@ -914,6 +1172,21 @@ void Abstract3DController::handleRequestShadowQuality(QAbstract3DGraph::ShadowQu
setShadowQuality(quality);
}
+void Abstract3DController::setMeasureFps(bool enable)
+{
+ if (m_measureFps != enable) {
+ m_measureFps = enable;
+ m_currentFps = 0.0;
+
+ if (enable) {
+ m_frameTimer.start();
+ m_numFrames = -1;
+ emitNeedRender();
+ }
+ emit measureFpsChanged(enable);
+ }
+}
+
void Abstract3DController::handleAxisLabelFormatChangedBySender(QObject *sender)
{
// Label format changing needs to dirty the data so that labels are reset.
@@ -932,15 +1205,104 @@ void Abstract3DController::handleAxisLabelFormatChangedBySender(QObject *sender)
emitNeedRender();
}
+void Abstract3DController::handleAxisReversedChangedBySender(QObject *sender)
+{
+ // Reversing change needs to dirty the data so item positions are recalculated
+ if (sender == m_axisX) {
+ m_isDataDirty = true;
+ m_changeTracker.axisXReversedChanged = true;
+ } else if (sender == m_axisY) {
+ m_isDataDirty = true;
+ m_changeTracker.axisYReversedChanged = true;
+ } else if (sender == m_axisZ) {
+ m_isDataDirty = true;
+ m_changeTracker.axisZReversedChanged = true;
+ } else {
+ qWarning() << __FUNCTION__ << "invoked for invalid axis";
+ }
+ emitNeedRender();
+}
+
+void Abstract3DController::handleAxisFormatterDirtyBySender(QObject *sender)
+{
+ // Sender is QValue3DAxisPrivate
+ QValue3DAxis *valueAxis = static_cast<QValue3DAxisPrivate *>(sender)->qptr();
+ if (valueAxis == m_axisX) {
+ m_isDataDirty = true;
+ m_changeTracker.axisXFormatterChanged = true;
+ } else if (valueAxis == m_axisY) {
+ m_isDataDirty = true;
+ m_changeTracker.axisYFormatterChanged = true;
+ } else if (valueAxis == m_axisZ) {
+ m_isDataDirty = true;
+ m_changeTracker.axisZFormatterChanged = true;
+ } else {
+ qWarning() << __FUNCTION__ << "invoked for invalid axis";
+ }
+ emitNeedRender();
+}
+
+void Abstract3DController::handleAxisLabelAutoRotationChangedBySender(QObject *sender)
+{
+ if (sender == m_axisX)
+ m_changeTracker.axisXLabelAutoRotationChanged = true;
+ else if (sender == m_axisY)
+ m_changeTracker.axisYLabelAutoRotationChanged = true;
+ else if (sender == m_axisZ)
+ m_changeTracker.axisZLabelAutoRotationChanged = true;
+ else
+ qWarning() << __FUNCTION__ << "invoked for invalid axis";
+
+ emitNeedRender();
+}
+
+void Abstract3DController::handleAxisTitleVisibilityChangedBySender(QObject *sender)
+{
+ if (sender == m_axisX)
+ m_changeTracker.axisXTitleVisibilityChanged = true;
+ else if (sender == m_axisY)
+ m_changeTracker.axisYTitleVisibilityChanged = true;
+ else if (sender == m_axisZ)
+ m_changeTracker.axisZTitleVisibilityChanged = true;
+ else
+ qWarning() << __FUNCTION__ << "invoked for invalid axis";
+
+ emitNeedRender();
+}
+
+void Abstract3DController::handleAxisTitleFixedChangedBySender(QObject *sender)
+{
+ if (sender == m_axisX)
+ m_changeTracker.axisXTitleFixedChanged = true;
+ else if (sender == m_axisY)
+ m_changeTracker.axisYTitleFixedChanged = true;
+ else if (sender == m_axisZ)
+ m_changeTracker.axisZTitleFixedChanged = true;
+ else
+ qWarning() << __FUNCTION__ << "invoked for invalid axis";
+
+ emitNeedRender();
+}
+
void Abstract3DController::handleSeriesVisibilityChangedBySender(QObject *sender)
{
- Q_UNUSED(sender)
+ QAbstract3DSeries *series = static_cast<QAbstract3DSeries *>(sender);
+ series->d_ptr->m_changeTracker.visibilityChanged = true;
m_isDataDirty = true;
- m_isSeriesVisibilityDirty = true;
+ m_isSeriesVisualsDirty = true;
+
+ adjustAxisRanges();
+
emitNeedRender();
}
+void Abstract3DController::markSeriesItemLabelsDirty()
+{
+ for (int i = 0; i < m_seriesList.size(); i++)
+ m_seriesList.at(i)->d_ptr->markItemLabelDirty();
+}
+
void Abstract3DController::setAxisHelper(QAbstract3DAxis::AxisOrientation orientation,
QAbstract3DAxis *axis, QAbstract3DAxis **axisPtr)
{
@@ -978,6 +1340,12 @@ void Abstract3DController::setAxisHelper(QAbstract3DAxis::AxisOrientation orient
this, &Abstract3DController::handleAxisRangeChanged);
QObject::connect(axis, &QAbstract3DAxis::autoAdjustRangeChanged,
this, &Abstract3DController::handleAxisAutoAdjustRangeChanged);
+ QObject::connect(axis, &QAbstract3DAxis::labelAutoRotationChanged,
+ this, &Abstract3DController::handleAxisLabelAutoRotationChanged);
+ QObject::connect(axis, &QAbstract3DAxis::titleVisibilityChanged,
+ this, &Abstract3DController::handleAxisTitleVisibilityChanged);
+ QObject::connect(axis, &QAbstract3DAxis::titleFixedChanged,
+ this, &Abstract3DController::handleAxisTitleFixedChanged);
if (orientation == QAbstract3DAxis::AxisOrientationX)
m_changeTracker.axisXTypeChanged = true;
@@ -991,6 +1359,9 @@ void Abstract3DController::setAxisHelper(QAbstract3DAxis::AxisOrientation orient
handleAxisRangeChangedBySender(axis);
handleAxisAutoAdjustRangeChangedInOrientation(axis->orientation(),
axis->isAutoAdjustRange());
+ handleAxisLabelAutoRotationChangedBySender(axis);
+ handleAxisTitleVisibilityChangedBySender(axis);
+ handleAxisTitleFixedChangedBySender(axis);
if (axis->type() & QAbstract3DAxis::AxisTypeValue) {
QValue3DAxis *valueAxis = static_cast<QValue3DAxis *>(axis);
@@ -1000,14 +1371,21 @@ void Abstract3DController::setAxisHelper(QAbstract3DAxis::AxisOrientation orient
this, &Abstract3DController::handleAxisSubSegmentCountChanged);
QObject::connect(valueAxis, &QValue3DAxis::labelFormatChanged,
this, &Abstract3DController::handleAxisLabelFormatChanged);
+ QObject::connect(valueAxis, &QValue3DAxis::reversedChanged,
+ this, &Abstract3DController::handleAxisReversedChanged);
+ QObject::connect(valueAxis->dptr(), &QValue3DAxisPrivate::formatterDirty,
+ this, &Abstract3DController::handleAxisFormatterDirty);
handleAxisSegmentCountChangedBySender(valueAxis);
handleAxisSubSegmentCountChangedBySender(valueAxis);
handleAxisLabelFormatChangedBySender(valueAxis);
+ handleAxisReversedChangedBySender(valueAxis);
+ handleAxisFormatterDirtyBySender(valueAxis->dptr());
}
}
-QAbstract3DAxis *Abstract3DController::createDefaultAxis(QAbstract3DAxis::AxisOrientation orientation)
+QAbstract3DAxis *Abstract3DController::createDefaultAxis(
+ QAbstract3DAxis::AxisOrientation orientation)
{
Q_UNUSED(orientation)
@@ -1047,4 +1425,97 @@ void Abstract3DController::emitNeedRender()
}
}
+void Abstract3DController::handlePendingClick()
+{
+ QAbstract3DGraph::ElementType type = m_renderer->clickedType();
+ emit elementSelected(type);
+}
+
+int Abstract3DController::selectedLabelIndex() const
+{
+ int index = m_renderer->m_selectedLabelIndex;
+ QAbstract3DAxis *axis = selectedAxis();
+ if (axis && axis->labels().count() <= index)
+ index = -1;
+ return index;
+}
+
+QAbstract3DAxis *Abstract3DController::selectedAxis() const
+{
+ QAbstract3DAxis *axis = 0;
+ QAbstract3DGraph::ElementType type = m_renderer->clickedType();
+ switch (type) {
+ case QAbstract3DGraph::ElementAxisXLabel:
+ axis = axisX();
+ break;
+ case QAbstract3DGraph::ElementAxisYLabel:
+ axis = axisY();
+ break;
+ case QAbstract3DGraph::ElementAxisZLabel:
+ axis = axisZ();
+ break;
+ default:
+ axis = 0;
+ break;
+ }
+
+ return axis;
+}
+
+int Abstract3DController::selectedCustomItemIndex() const
+{
+ int index = m_renderer->m_selectedCustomItemIndex;
+ if (m_customItems.count() <= index)
+ index = -1;
+ return index;
+}
+
+QCustom3DItem *Abstract3DController::selectedCustomItem() const
+{
+ QCustom3DItem *item = 0;
+ int index = selectedCustomItemIndex();
+ if (index >= 0)
+ item = m_customItems[index];
+ return item;
+}
+
+QAbstract3DGraph::ElementType Abstract3DController::selectedElement() const
+{
+ return m_renderer->clickedType();
+}
+
+void Abstract3DController::setOrthoProjection(bool enable)
+{
+ if (enable != m_useOrthoProjection) {
+ m_useOrthoProjection = enable;
+ m_changeTracker.projectionChanged = true;
+ emit orthoProjectionChanged(m_useOrthoProjection);
+ // If changed to ortho, disable shadows
+ if (m_useOrthoProjection)
+ doSetShadowQuality(QAbstract3DGraph::ShadowQualityNone);
+ emitNeedRender();
+ }
+}
+
+bool Abstract3DController::isOrthoProjection() const
+{
+ return m_useOrthoProjection;
+}
+
+void Abstract3DController::setAspectRatio(float ratio)
+{
+ if (m_aspectRatio != ratio) {
+ m_aspectRatio = ratio;
+ m_changeTracker.aspectRatioChanged = true;
+ emit aspectRatioChanged(m_aspectRatio);
+ m_isDataDirty = true;
+ emitNeedRender();
+ }
+}
+
+float Abstract3DController::aspectRatio()
+{
+ return m_aspectRatio;
+}
+
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/abstract3dcontroller_p.h b/src/datavisualization/engine/abstract3dcontroller_p.h
index 06be450e..0e4d1add 100644
--- a/src/datavisualization/engine/abstract3dcontroller_p.h
+++ b/src/datavisualization/engine/abstract3dcontroller_p.h
@@ -33,25 +33,25 @@
#include "qabstract3daxis.h"
#include "drawer_p.h"
#include "qabstract3dinputhandler.h"
-#include "qabstractdataproxy.h"
+#include "qabstract3dgraph.h"
#include "q3dscene_p.h"
+#include "qcustom3ditem.h"
#include <QtGui/QLinearGradient>
+#include <QtCore/QTime>
-class QFont;
+class QOpenGLFramebufferObject;
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
-class CameraHelper;
class Abstract3DRenderer;
class QAbstract3DSeries;
class ThemeManager;
struct Abstract3DChangeBitField {
- bool zoomLevelChanged : 1;
bool themeChanged : 1;
bool shadowQualityChanged : 1;
bool selectionModeChanged : 1;
- bool objFileChanged : 1;
+ bool optimizationHintChanged : 1;
bool axisXTypeChanged : 1;
bool axisYTypeChanged : 1;
bool axisZTypeChanged : 1;
@@ -73,15 +73,29 @@ struct Abstract3DChangeBitField {
bool axisXLabelFormatChanged : 1;
bool axisYLabelFormatChanged : 1;
bool axisZLabelFormatChanged : 1;
- bool inputViewChanged : 1;
- bool inputPositionChanged : 1;
+ bool axisXReversedChanged : 1;
+ bool axisYReversedChanged : 1;
+ bool axisZReversedChanged : 1;
+ bool axisXFormatterChanged : 1;
+ bool axisYFormatterChanged : 1;
+ bool axisZFormatterChanged : 1;
+ bool projectionChanged : 1;
+ bool axisXLabelAutoRotationChanged : 1;
+ bool axisYLabelAutoRotationChanged : 1;
+ bool axisZLabelAutoRotationChanged : 1;
+ bool aspectRatioChanged : 1;
+ bool axisXTitleVisibilityChanged : 1;
+ bool axisYTitleVisibilityChanged : 1;
+ bool axisZTitleVisibilityChanged : 1;
+ bool axisXTitleFixedChanged : 1;
+ bool axisYTitleFixedChanged : 1;
+ bool axisZTitleFixedChanged : 1;
Abstract3DChangeBitField() :
- zoomLevelChanged(true),
themeChanged(true),
shadowQualityChanged(true),
selectionModeChanged(true),
- objFileChanged(true),
+ optimizationHintChanged(true),
axisXTypeChanged(true),
axisYTypeChanged(true),
axisZTypeChanged(true),
@@ -102,7 +116,24 @@ struct Abstract3DChangeBitField {
axisZSubSegmentCountChanged(true),
axisXLabelFormatChanged(true),
axisYLabelFormatChanged(true),
- axisZLabelFormatChanged(true)
+ axisZLabelFormatChanged(true),
+ axisXReversedChanged(true),
+ axisYReversedChanged(true),
+ axisZReversedChanged(true),
+ axisXFormatterChanged(true),
+ axisYFormatterChanged(true),
+ axisZFormatterChanged(true),
+ projectionChanged(true),
+ axisXLabelAutoRotationChanged(true),
+ axisYLabelAutoRotationChanged(true),
+ axisZLabelAutoRotationChanged(true),
+ aspectRatioChanged(true),
+ axisXTitleVisibilityChanged(true),
+ axisYTitleVisibilityChanged(true),
+ axisZTitleVisibilityChanged(true),
+ axisXTitleFixedChanged(true),
+ axisYTitleFixedChanged(true),
+ axisZTitleFixedChanged(true)
{
}
};
@@ -119,28 +150,19 @@ public:
SelectionColumn
};
- enum MouseState {
- MouseNone = 0,
- MouseOnScene,
- MouseOnOverview,
- MouseOnZoom,
- MouseRotating,
- MouseOnPinch
- };
-
private:
Abstract3DChangeBitField m_changeTracker;
- GLfloat m_horizontalRotation;
- GLfloat m_verticalRotation;
ThemeManager *m_themeManager;
QAbstract3DGraph::SelectionFlags m_selectionMode;
QAbstract3DGraph::ShadowQuality m_shadowQuality;
+ bool m_useOrthoProjection;
+ float m_aspectRatio;
+ QAbstract3DGraph::OptimizationHints m_optimizationHints;
protected:
Q3DScene *m_scene;
QList<QAbstract3DInputHandler *> m_inputHandlers; // List of all added input handlers
QAbstract3DInputHandler *m_activeInputHandler;
- CameraHelper *m_cameraHelper;
// Active axes
QAbstract3DAxis *m_axisX;
QAbstract3DAxis *m_axisY;
@@ -149,12 +171,22 @@ protected:
QList<QAbstract3DAxis *> m_axes; // List of all added axes
Abstract3DRenderer *m_renderer;
bool m_isDataDirty;
- bool m_isSeriesVisibilityDirty;
+ bool m_isCustomDataDirty;
+ bool m_isCustomItemDirty;
bool m_isSeriesVisualsDirty;
bool m_renderPending;
QList<QAbstract3DSeries *> m_seriesList;
+ bool m_measureFps;
+ QTime m_frameTimer;
+ int m_numFrames;
+ qreal m_currentFps;
+
+ QVector<QAbstract3DSeries *> m_changedSeriesList;
+
+ QList<QCustom3DItem *> m_customItems;
+
explicit Abstract3DController(QRect initialViewport, Q3DScene *scene, QObject *parent = 0);
public:
@@ -173,11 +205,11 @@ public:
QList<QAbstract3DSeries *> seriesList();
virtual void setAxisX(QAbstract3DAxis *axis);
- virtual QAbstract3DAxis *axisX();
+ virtual QAbstract3DAxis *axisX() const;
virtual void setAxisY(QAbstract3DAxis *axis);
- virtual QAbstract3DAxis *axisY();
+ virtual QAbstract3DAxis *axisY() const;
virtual void setAxisZ(QAbstract3DAxis *axis);
- virtual QAbstract3DAxis *axisZ();
+ virtual QAbstract3DAxis *axisZ() const;
virtual void addAxis(QAbstract3DAxis *axis);
virtual void releaseAxis(QAbstract3DAxis *axis);
virtual QList<QAbstract3DAxis *> axes() const; // Omits default axes
@@ -188,12 +220,9 @@ public:
virtual QAbstract3DInputHandler *activeInputHandler();
virtual QList<QAbstract3DInputHandler *> inputHandlers() const;
- virtual int zoomLevel();
- virtual void setZoomLevel(int zoomLevel);
-
virtual void addTheme(Q3DTheme *theme);
virtual void releaseTheme(Q3DTheme *theme);
- virtual void setActiveTheme(Q3DTheme *theme);
+ virtual void setActiveTheme(Q3DTheme *theme, bool force = true);
virtual Q3DTheme *activeTheme() const;
virtual QList<Q3DTheme *> themes() const;
@@ -201,9 +230,13 @@ public:
virtual QAbstract3DGraph::SelectionFlags selectionMode() const;
virtual void setShadowQuality(QAbstract3DGraph::ShadowQuality quality);
+ virtual void doSetShadowQuality(QAbstract3DGraph::ShadowQuality quality);
virtual QAbstract3DGraph::ShadowQuality shadowQuality() const;
virtual bool shadowsSupported() const;
+ void setOptimizationHints(QAbstract3DGraph::OptimizationHints hints);
+ QAbstract3DGraph::OptimizationHints optimizationHints() const;
+
bool isSlicingActive() const;
void setSlicingActive(bool isSlicing);
@@ -212,6 +245,22 @@ public:
void markDataDirty();
void markSeriesVisualsDirty();
+ void requestRender(QOpenGLFramebufferObject *fbo);
+
+ int addCustomItem(QCustom3DItem *item);
+ void deleteCustomItems();
+ void deleteCustomItem(QCustom3DItem *item);
+ void deleteCustomItem(const QVector3D &position);
+ void releaseCustomItem(QCustom3DItem *item);
+
+ int selectedLabelIndex() const;
+ QAbstract3DAxis *selectedAxis() const;
+ int selectedCustomItemIndex() const;
+ QCustom3DItem *selectedCustomItem() const;
+
+ void setOrthoProjection(bool enable);
+ bool isOrthoProjection() const;
+
void emitNeedRender();
virtual void clearSelection() = 0;
@@ -231,8 +280,16 @@ public:
virtual void handleAxisAutoAdjustRangeChangedInOrientation(
QAbstract3DAxis::AxisOrientation orientation, bool autoAdjust) = 0;
virtual void handleAxisLabelFormatChangedBySender(QObject *sender);
+ virtual void handleAxisReversedChangedBySender(QObject *sender);
+ virtual void handleAxisFormatterDirtyBySender(QObject *sender);
+ virtual void handleAxisLabelAutoRotationChangedBySender(QObject *sender);
+ virtual void handleAxisTitleVisibilityChangedBySender(QObject *sender);
+ virtual void handleAxisTitleFixedChangedBySender(QObject *sender);
virtual void handleSeriesVisibilityChangedBySender(QObject *sender);
virtual void handlePendingClick() = 0;
+ virtual void adjustAxisRanges() = 0;
+
+ void markSeriesItemLabelsDirty();
public slots:
void handleAxisTitleChanged(const QString &title);
@@ -242,6 +299,11 @@ public slots:
void handleAxisSubSegmentCountChanged(int count);
void handleAxisAutoAdjustRangeChanged(bool autoAdjust);
void handleAxisLabelFormatChanged(const QString &format);
+ void handleAxisReversedChanged(bool enable);
+ void handleAxisFormatterDirty();
+ void handleAxisLabelAutoRotationChanged(float angle);
+ void handleAxisTitleVisibilityChanged(bool visible);
+ void handleAxisTitleFixedChanged(bool fixed);
void handleInputViewChanged(QAbstract3DInputHandler::InputView view);
void handleInputPositionChanged(const QPoint &position);
void handleSeriesVisibilityChanged(bool visible);
@@ -258,6 +320,17 @@ public slots:
// Renderer callback handlers
void handleRequestShadowQuality(QAbstract3DGraph::ShadowQuality quality);
+ void setMeasureFps(bool enable);
+ inline bool measureFps() const { return m_measureFps; }
+ inline qreal currentFps() const { return m_currentFps; }
+
+ QAbstract3DGraph::ElementType selectedElement() const;
+
+ void updateCustomItem();
+
+ void setAspectRatio(float ratio);
+ float aspectRatio();
+
signals:
void shadowQualityChanged(QAbstract3DGraph::ShadowQuality quality);
void activeInputHandlerChanged(QAbstract3DInputHandler *inputHandler);
@@ -267,6 +340,12 @@ signals:
void axisXChanged(QAbstract3DAxis *axis);
void axisYChanged(QAbstract3DAxis *axis);
void axisZChanged(QAbstract3DAxis *axis);
+ void elementSelected(QAbstract3DGraph::ElementType type);
+ void measureFpsChanged(bool enabled);
+ void currentFpsChanged(qreal fps);
+ void orthoProjectionChanged(bool enabled);
+ void aspectRatioChanged(float ratio);
+ void optimizationHintsChanged(QAbstract3DGraph::OptimizationHints hints);
protected:
virtual QAbstract3DAxis *createDefaultAxis(QAbstract3DAxis::AxisOrientation orientation);
@@ -278,7 +357,9 @@ private:
void setAxisHelper(QAbstract3DAxis::AxisOrientation orientation, QAbstract3DAxis *axis,
QAbstract3DAxis **axisPtr);
+ friend class AbstractDeclarative;
friend class Bars3DController;
+ friend class QAbstract3DGraphPrivate;
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp
index 3122cf76..5d97a6ca 100644
--- a/src/datavisualization/engine/abstract3drenderer.cpp
+++ b/src/datavisualization/engine/abstract3drenderer.cpp
@@ -17,15 +17,13 @@
****************************************************************************/
#include "abstract3drenderer_p.h"
-#include "qvalue3daxis.h"
#include "texturehelper_p.h"
-#include "utils_p.h"
-#include "q3dscene_p.h"
#include "q3dcamera_p.h"
-#include "q3dlight_p.h"
-#include "qabstract3dseries_p.h"
#include "q3dtheme_p.h"
-#include "objecthelper_p.h"
+#include "qvalue3daxisformatter_p.h"
+#include "shaderhelper_p.h"
+#include "qcustom3ditem_p.h"
+#include "qcustom3dlabel_p.h"
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -37,6 +35,7 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller)
m_cachedShadowQuality(QAbstract3DGraph::ShadowQualityMedium),
m_autoScaleAdjustment(1.0f),
m_cachedSelectionMode(QAbstract3DGraph::SelectionNone),
+ m_cachedOptimizationHint(QAbstract3DGraph::OptimizationDefault),
m_textureHelper(0),
m_cachedScene(new Q3DScene()),
m_selectionDirty(true),
@@ -45,12 +44,18 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller)
m_selectionLabelDirty(true),
m_clickPending(false),
m_clickedSeries(0),
- m_selectionLabelItem(0)
-#ifdef DISPLAY_RENDER_SPEED
- , m_isFirstFrame(true),
- m_numFrames(0)
-#endif
-
+ m_clickedType(QAbstract3DGraph::ElementNone),
+ m_selectionLabelItem(0),
+ m_visibleSeriesCount(0),
+ m_customItemShader(0),
+ m_useOrthoProjection(false),
+ m_xFlipped(false),
+ m_yFlipped(false),
+ m_zFlipped(false),
+ m_backgroundObj(0),
+ m_gridLineObj(0),
+ m_labelObj(0),
+ m_graphAspectRatio(2.0f)
{
QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Abstract3DRenderer::updateTextures);
QObject::connect(this, &Abstract3DRenderer::needRender, controller,
@@ -61,14 +66,30 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller)
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;
delete m_selectionLabelItem;
+ delete m_customItemShader;
+
+ foreach (SeriesRenderCache *cache, m_renderCacheList) {
+ cache->cleanup(m_textureHelper);
+ delete cache;
+ }
+ m_renderCacheList.clear();
+
+ foreach (CustomRenderItem *item, m_customRenderCache) {
+ GLuint texture = item->texture();
+ m_textureHelper->deleteTexture(&texture);
+ delete item;
+ }
+ m_customRenderCache.clear();
+
+ ObjectHelper::releaseObjectHelper(this, m_backgroundObj);
+ ObjectHelper::releaseObjectHelper(this, m_gridLineObj);
+ ObjectHelper::releaseObjectHelper(this, m_labelObj);
+
+ delete m_textureHelper;
}
void Abstract3DRenderer::initializeOpenGL()
@@ -95,23 +116,6 @@ void Abstract3DRenderer::initializeOpenGL()
void Abstract3DRenderer::render(const GLuint defaultFboHandle)
{
-#ifdef DISPLAY_RENDER_SPEED
- // For speed computation
- if (m_isFirstFrame) {
- m_lastFrameTime.start();
- m_isFirstFrame = false;
- }
-
- // Measure speed (as milliseconds per frame)
- m_numFrames++;
- if (m_lastFrameTime.elapsed() >= 1000) { // print only if last measurement was more than 1s ago
- qDebug() << float(m_lastFrameTime.elapsed()) / float(m_numFrames) << "ms/frame (="
- << float(m_numFrames) << "fps)";
- m_numFrames = 0;
- m_lastFrameTime.restart();
- }
-#endif
-
if (defaultFboHandle) {
glDepthMask(true);
glEnable(GL_DEPTH_TEST);
@@ -131,20 +135,12 @@ void Abstract3DRenderer::render(const GLuint defaultFboHandle)
m_viewport.width(),
m_viewport.height());
glEnable(GL_SCISSOR_TEST);
- QVector3D clearColor = Utils::vectorFromColor(m_cachedTheme->windowColor());
+ QVector4D clearColor = Utils::vectorFromColor(m_cachedTheme->windowColor());
glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_SCISSOR_TEST);
}
-QString Abstract3DRenderer::generateValueLabel(const QString &format, float value)
-{
- QString valueLabelFormat = format;
- Utils::ParamType valueParamType = Utils::findFormatParamType(valueLabelFormat);
- QByteArray valueFormatArray = valueLabelFormat.toUtf8();
- return Utils::formatLabel(valueFormatArray, valueParamType, value);
-}
-
void Abstract3DRenderer::updateSelectionState(SelectionState state)
{
m_selectionState = state;
@@ -163,6 +159,15 @@ void Abstract3DRenderer::initGradientShaders(const QString &vertexShader,
Q_UNUSED(fragmentShader)
}
+void Abstract3DRenderer::initCustomItemShaders(const QString &vertexShader,
+ const QString &fragmentShader)
+{
+ if (m_customItemShader)
+ delete m_customItemShader;
+ m_customItemShader = new ShaderHelper(this, vertexShader, fragmentShader);
+ m_customItemShader->initialize();
+}
+
void Abstract3DRenderer::updateTheme(Q3DTheme *theme)
{
// Synchronize the controller theme with renderer
@@ -229,6 +234,8 @@ void Abstract3DRenderer::reInitShaders()
QStringLiteral(":/shaders/fragmentShadowNoTex"));
initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"),
QStringLiteral(":/shaders/fragmentShadowNoTex"));
+ initCustomItemShaders(QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentShadow"));
} else {
initGradientShaders(QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragmentColorOnY"));
@@ -236,6 +243,8 @@ void Abstract3DRenderer::reInitShaders()
QStringLiteral(":/shaders/fragment"));
initBackgroundShaders(QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragment"));
+ initCustomItemShaders(QStringLiteral(":/shaders/vertexTexture"),
+ QStringLiteral(":/shaders/fragmentTexture"));
}
#else
initGradientShaders(QStringLiteral(":/shaders/vertex"),
@@ -244,6 +253,8 @@ void Abstract3DRenderer::reInitShaders()
QStringLiteral(":/shaders/fragmentES2"));
initBackgroundShaders(QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragmentES2"));
+ initCustomItemShaders(QStringLiteral(":/shaders/vertexTexture"),
+ QStringLiteral(":/shaders/fragmentTextureES2"));
#endif
}
@@ -266,18 +277,28 @@ void Abstract3DRenderer::updateSelectionMode(QAbstract3DGraph::SelectionFlags mo
m_selectionDirty = true;
}
+void Abstract3DRenderer::updateAspectRatio(float ratio)
+{
+ m_graphAspectRatio = ratio;
+ calculateZoomLevel();
+ m_cachedScene->activeCamera()->d_ptr->updateViewMatrix(m_autoScaleAdjustment);
+ foreach (SeriesRenderCache *cache, m_renderCacheList)
+ cache->setDataDirty(true);
+ updateCustomItemPositions();
+}
+
+void Abstract3DRenderer::updateOptimizationHint(QAbstract3DGraph::OptimizationHints hint)
+{
+ m_cachedOptimizationHint = hint;
+}
+
void Abstract3DRenderer::handleResize()
{
if (m_primarySubViewport.width() == 0 || m_primarySubViewport.height() == 0)
return;
- // Calculate zoom level based on aspect ratio
- GLfloat div;
- GLfloat zoomAdjustment;
- 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
+ // Recalculate zoom
+ calculateZoomLevel();
// Re-init selection buffer
initSelectionBuffer();
@@ -288,6 +309,18 @@ void Abstract3DRenderer::handleResize()
#endif
}
+void Abstract3DRenderer::calculateZoomLevel()
+{
+ // Calculate zoom level based on aspect ratio
+ GLfloat div;
+ GLfloat zoomAdjustment;
+ div = qMin(m_primarySubViewport.width(), m_primarySubViewport.height());
+ zoomAdjustment = 2.0f * defaultRatio
+ * ((m_primarySubViewport.width() / div)
+ / (m_primarySubViewport.height() / div)) / m_graphAspectRatio;
+ m_autoScaleAdjustment = qMin(zoomAdjustment, 1.0f); // clamp to 1.0f
+}
+
void Abstract3DRenderer::updateAxisType(QAbstract3DAxis::AxisOrientation orientation,
QAbstract3DAxis::AxisType type)
{
@@ -312,18 +345,25 @@ void Abstract3DRenderer::updateAxisRange(QAbstract3DAxis::AxisOrientation orient
AxisRenderCache &cache = axisCacheForOrientation(orientation);
cache.setMin(min);
cache.setMax(max);
+
+ foreach (SeriesRenderCache *cache, m_renderCacheList)
+ cache->setDataDirty(true);
+
+ updateCustomItemPositions();
}
void Abstract3DRenderer::updateAxisSegmentCount(QAbstract3DAxis::AxisOrientation orientation,
int count)
{
- axisCacheForOrientation(orientation).setSegmentCount(count);
+ AxisRenderCache &cache = axisCacheForOrientation(orientation);
+ cache.setSegmentCount(count);
}
void Abstract3DRenderer::updateAxisSubSegmentCount(QAbstract3DAxis::AxisOrientation orientation,
int count)
{
- axisCacheForOrientation(orientation).setSubSegmentCount(count);
+ AxisRenderCache &cache = axisCacheForOrientation(orientation);
+ cache.setSubSegmentCount(count);
}
void Abstract3DRenderer::updateAxisLabelFormat(QAbstract3DAxis::AxisOrientation orientation,
@@ -332,6 +372,67 @@ void Abstract3DRenderer::updateAxisLabelFormat(QAbstract3DAxis::AxisOrientation
axisCacheForOrientation(orientation).setLabelFormat(format);
}
+void Abstract3DRenderer::updateAxisReversed(QAbstract3DAxis::AxisOrientation orientation,
+ bool enable)
+{
+ axisCacheForOrientation(orientation).setReversed(enable);
+ foreach (SeriesRenderCache *cache, m_renderCacheList)
+ cache->setDataDirty(true);
+
+ updateCustomItemPositions();
+}
+
+void Abstract3DRenderer::updateAxisFormatter(QAbstract3DAxis::AxisOrientation orientation,
+ QValue3DAxisFormatter *formatter)
+{
+ AxisRenderCache &cache = axisCacheForOrientation(orientation);
+ if (cache.ctrlFormatter() != formatter) {
+ delete cache.formatter();
+ cache.setFormatter(formatter->createNewInstance());
+ cache.setCtrlFormatter(formatter);
+ }
+ formatter->d_ptr->populateCopy(*(cache.formatter()));
+ cache.markPositionsDirty();
+
+ foreach (SeriesRenderCache *cache, m_renderCacheList)
+ cache->setDataDirty(true);
+
+ updateCustomItemPositions();
+}
+
+void Abstract3DRenderer::updateAxisLabelAutoRotation(QAbstract3DAxis::AxisOrientation orientation,
+ float angle)
+{
+ AxisRenderCache &cache = axisCacheForOrientation(orientation);
+ if (cache.labelAutoRotation() != angle)
+ cache.setLabelAutoRotation(angle);
+}
+
+void Abstract3DRenderer::updateAxisTitleVisibility(QAbstract3DAxis::AxisOrientation orientation,
+ bool visible)
+{
+ AxisRenderCache &cache = axisCacheForOrientation(orientation);
+ if (cache.isTitleVisible() != visible)
+ cache.setTitleVisible(visible);
+}
+
+void Abstract3DRenderer::updateAxisTitleFixed(QAbstract3DAxis::AxisOrientation orientation,
+ bool fixed)
+{
+ AxisRenderCache &cache = axisCacheForOrientation(orientation);
+ if (cache.isTitleFixed() != fixed)
+ cache.setTitleFixed(fixed);
+}
+
+void Abstract3DRenderer::modifiedSeriesList(const QVector<QAbstract3DSeries *> &seriesList)
+{
+ foreach (QAbstract3DSeries *series, seriesList) {
+ SeriesRenderCache *cache = m_renderCacheList.value(series, 0);
+ if (cache)
+ cache->setDataDirty(true);
+ }
+}
+
void Abstract3DRenderer::fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh)
{
// Default implementation does nothing.
@@ -339,41 +440,84 @@ void Abstract3DRenderer::fixMeshFileName(QString &fileName, QAbstract3DSeries::M
Q_UNUSED(mesh)
}
-void Abstract3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList,
- bool updateVisibility)
+void Abstract3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList)
{
- int visibleCount = 0;
- if (updateVisibility) {
- int oldSize = m_visibleSeriesList.size();
- foreach (QAbstract3DSeries *current, seriesList) {
- if (current->isVisible())
- visibleCount++;
- }
+ foreach (SeriesRenderCache *cache, m_renderCacheList)
+ cache->setValid(false);
- // 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);
+ m_visibleSeriesCount = 0;
+ int seriesCount = seriesList.size();
+ for (int i = 0; i < seriesCount; i++) {
+ QAbstract3DSeries *series = seriesList.at(i);
+ SeriesRenderCache *cache = m_renderCacheList.value(series);
+ bool newSeries = false;
+ if (!cache) {
+ cache = createNewCache(series);
+ m_renderCacheList[series] = cache;
+ newSeries = true;
}
+ cache->setValid(true);
+ cache->populate(newSeries);
+ if (cache->isVisible())
+ m_visibleSeriesCount++;
+ }
+
+ // Remove non-valid objects from the cache list
+ foreach (SeriesRenderCache *cache, m_renderCacheList) {
+ if (!cache->isValid())
+ cleanCache(cache);
+ }
+}
+
+void Abstract3DRenderer::updateCustomData(const QList<QCustom3DItem *> &customItems)
+{
+ if (customItems.isEmpty() && m_customRenderCache.isEmpty())
+ return;
- if (visibleCount != oldSize)
- m_visibleSeriesList.resize(visibleCount);
+ foreach (CustomRenderItem *item, m_customRenderCache)
+ item->setValid(false);
- visibleCount = 0;
+ int itemCount = customItems.size();
+ // Check custom item list for items that are not yet in render item cache
+ for (int i = 0; i < itemCount; i++) {
+ QCustom3DItem *item = customItems.at(i);
+ CustomRenderItem *renderItem = m_customRenderCache.value(item);
+ if (!renderItem)
+ renderItem = addCustomItem(item);
+ renderItem->setValid(true);
+ renderItem->setIndex(i); // always update index, as it must match the custom item index
}
- foreach (QAbstract3DSeries *current, seriesList) {
- if (current->isVisible()) {
- // Item selection label may need update
- if (current->d_ptr->m_changeTracker.nameChanged
- || current->d_ptr->m_changeTracker.itemLabelFormatChanged) {
- m_selectionLabelDirty = true;
- }
- m_visibleSeriesList[visibleCount++].populate(current, this);
+
+ // Check render item cache and remove items that are not in customItems list anymore
+ foreach (CustomRenderItem *renderItem, m_customRenderCache) {
+ if (!renderItem->isValid()) {
+ m_customRenderCache.remove(renderItem->itemPointer());
+ GLuint texture = renderItem->texture();
+ m_textureHelper->deleteTexture(&texture);
+ delete renderItem;
}
}
}
+void Abstract3DRenderer::updateCustomItems()
+{
+ // Check all items
+ foreach (CustomRenderItem *item, m_customRenderCache)
+ updateCustomItem(item);
+}
+
+SeriesRenderCache *Abstract3DRenderer::createNewCache(QAbstract3DSeries *series)
+{
+ return new SeriesRenderCache(series, this);
+}
+
+void Abstract3DRenderer::cleanCache(SeriesRenderCache *cache)
+{
+ m_renderCacheList.remove(cache->series());
+ cache->cleanup(m_textureHelper);
+ delete cache;
+}
+
AxisRenderCache &Abstract3DRenderer::axisCacheForOrientation(
QAbstract3DAxis::AxisOrientation orientation)
{
@@ -428,26 +572,243 @@ void Abstract3DRenderer::lowerShadowQuality()
updateShadowQuality(newQuality);
}
-void Abstract3DRenderer::generateBaseColorTexture(const QColor &color, GLuint *texture)
+void Abstract3DRenderer::drawAxisTitleY(const QVector3D &sideLabelRotation,
+ const QVector3D &backLabelRotation,
+ const QVector3D &sideLabelTrans,
+ const QVector3D &backLabelTrans,
+ const QQuaternion &totalSideRotation,
+ const QQuaternion &totalBackRotation,
+ AbstractRenderItem &dummyItem,
+ const Q3DCamera *activeCamera,
+ float labelsMaxWidth,
+ const QMatrix4x4 &viewMatrix,
+ const QMatrix4x4 &projectionMatrix,
+ ShaderHelper *shader)
{
- if (*texture) {
- m_textureHelper->deleteTexture(texture);
- *texture = 0;
+ float scaleFactor = m_drawer->scaledFontSize() / m_axisCacheY.titleItem().size().height();
+ float titleOffset = 2.0f * (labelMargin + (labelsMaxWidth * scaleFactor));
+ float yRotation;
+ QVector3D titleTrans;
+ QQuaternion totalRotation;
+ if (m_xFlipped == m_zFlipped) {
+ yRotation = backLabelRotation.y();
+ titleTrans = backLabelTrans;
+ totalRotation = totalBackRotation;
+ } else {
+ yRotation = sideLabelRotation.y();
+ titleTrans = sideLabelTrans;
+ totalRotation = totalSideRotation;
+ }
+
+ QQuaternion offsetRotator = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, yRotation);
+ QVector3D titleOffsetVector =
+ offsetRotator.rotatedVector(QVector3D(-titleOffset, 0.0f, 0.0f));
+
+ QQuaternion titleRotation;
+ if (m_axisCacheY.isTitleFixed()) {
+ titleRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, yRotation)
+ * QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, 90.0f);
+ } else {
+ titleRotation = totalRotation
+ * QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, 90.0f);
}
+ dummyItem.setTranslation(titleTrans + titleOffsetVector);
+
+ m_drawer->drawLabel(dummyItem, m_axisCacheY.titleItem(), viewMatrix,
+ projectionMatrix, zeroVector, titleRotation, 0,
+ m_cachedSelectionMode, shader, m_labelObj, activeCamera,
+ true, true, Drawer::LabelMid, Qt::AlignBottom);
+}
+void Abstract3DRenderer::drawAxisTitleX(const QVector3D &labelRotation,
+ const QVector3D &labelTrans,
+ const QQuaternion &totalRotation,
+ AbstractRenderItem &dummyItem,
+ const Q3DCamera *activeCamera,
+ float labelsMaxWidth,
+ const QMatrix4x4 &viewMatrix,
+ const QMatrix4x4 &projectionMatrix,
+ ShaderHelper *shader)
+{
+ float scaleFactor = m_drawer->scaledFontSize() / m_axisCacheX.titleItem().size().height();
+ float titleOffset = 2.0f * (labelMargin + (labelsMaxWidth * scaleFactor));
+ float zRotation = 0.0f;
+ float yRotation = 0.0f;
+ float xRotation = -90.0f + labelRotation.z();
+ float offsetRotation = labelRotation.z();
+ float extraRotation = -90.0f;
+ Qt::AlignmentFlag alignment = Qt::AlignTop;
+ if (m_yFlipped) {
+ alignment = Qt::AlignBottom;
+ if (m_zFlipped) {
+ zRotation = 180.0f;
+ titleOffset = -titleOffset;
+ if (m_xFlipped) {
+ offsetRotation = -offsetRotation;
+ extraRotation = -extraRotation;
+ } else {
+ xRotation = -90.0f - labelRotation.z();
+ }
+ } else {
+ zRotation = 180.0f;
+ yRotation = 180.0f;
+ if (m_xFlipped) {
+ offsetRotation = -offsetRotation;
+ xRotation = -90.0f - labelRotation.z();
+ } else {
+ extraRotation = -extraRotation;
+ }
+ }
+ } else {
+ if (m_zFlipped) {
+ titleOffset = -titleOffset;
+ if (m_xFlipped) {
+ yRotation = 180.0f;
+ offsetRotation = -offsetRotation;
+ } else {
+ yRotation = 180.0f;
+ xRotation = -90.0f - labelRotation.z();
+ extraRotation = -extraRotation;
+ }
+ } else {
+ if (m_xFlipped) {
+ offsetRotation = -offsetRotation;
+ xRotation = -90.0f - labelRotation.z();
+ extraRotation = -extraRotation;
+ }
+ }
+ }
+
+ if (offsetRotation == 180.0f || offsetRotation == -180.0f)
+ offsetRotation = 0.0f;
+ QQuaternion offsetRotator = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, offsetRotation);
+ QVector3D titleOffsetVector =
+ offsetRotator.rotatedVector(QVector3D(0.0f, 0.0f, titleOffset));
+
+ QQuaternion titleRotation;
+ if (m_axisCacheX.isTitleFixed()) {
+ titleRotation = QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, zRotation)
+ * QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, yRotation)
+ * QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, xRotation);
+ } else {
+ titleRotation = totalRotation
+ * QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, extraRotation);
+ }
+ dummyItem.setTranslation(labelTrans + titleOffsetVector);
+
+ m_drawer->drawLabel(dummyItem, m_axisCacheX.titleItem(), viewMatrix,
+ projectionMatrix, zeroVector, titleRotation, 0,
+ m_cachedSelectionMode, shader, m_labelObj, activeCamera,
+ true, true, Drawer::LabelMid, alignment);
+}
+
+void Abstract3DRenderer::drawAxisTitleZ(const QVector3D &labelRotation,
+ const QVector3D &labelTrans,
+ const QQuaternion &totalRotation,
+ AbstractRenderItem &dummyItem,
+ const Q3DCamera *activeCamera,
+ float labelsMaxWidth,
+ const QMatrix4x4 &viewMatrix,
+ const QMatrix4x4 &projectionMatrix,
+ ShaderHelper *shader)
+{
+ float scaleFactor = m_drawer->scaledFontSize() / m_axisCacheZ.titleItem().size().height();
+ float titleOffset = 2.0f * (labelMargin + (labelsMaxWidth * scaleFactor));
+ float zRotation = labelRotation.z();
+ float yRotation = -90.0f;
+ float xRotation = -90.0f;
+ float extraRotation = 90.0f;
+ Qt::AlignmentFlag alignment = Qt::AlignTop;
+ if (m_yFlipped) {
+ alignment = Qt::AlignBottom;
+ xRotation = -xRotation;
+ if (m_zFlipped) {
+ if (m_xFlipped) {
+ titleOffset = -titleOffset;
+ zRotation = -zRotation;
+ extraRotation = -extraRotation;
+ } else {
+ zRotation = -zRotation;
+ yRotation = -yRotation;
+ }
+ } else {
+ if (m_xFlipped) {
+ titleOffset = -titleOffset;
+ } else {
+ extraRotation = -extraRotation;
+ yRotation = -yRotation;
+ }
+ }
+ } else {
+ if (m_zFlipped) {
+ zRotation = -zRotation;
+ if (m_xFlipped) {
+ titleOffset = -titleOffset;
+ } else {
+ extraRotation = -extraRotation;
+ yRotation = -yRotation;
+ }
+ } else {
+ if (m_xFlipped) {
+ titleOffset = -titleOffset;
+ extraRotation = -extraRotation;
+ } else {
+ yRotation = -yRotation;
+ }
+ }
+ }
+
+ float offsetRotation = zRotation;
+ if (offsetRotation == 180.0f || offsetRotation == -180.0f)
+ offsetRotation = 0.0f;
+ QQuaternion offsetRotator = QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, offsetRotation);
+ QVector3D titleOffsetVector =
+ offsetRotator.rotatedVector(QVector3D(titleOffset, 0.0f, 0.0f));
+
+ QQuaternion titleRotation;
+ if (m_axisCacheZ.isTitleFixed()) {
+ titleRotation = QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, zRotation)
+ * QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, yRotation)
+ * QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, xRotation);
+ } else {
+ titleRotation = totalRotation
+ * QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, extraRotation);
+ }
+ dummyItem.setTranslation(labelTrans + titleOffsetVector);
+
+ m_drawer->drawLabel(dummyItem, m_axisCacheZ.titleItem(), viewMatrix,
+ projectionMatrix, zeroVector, titleRotation, 0,
+ m_cachedSelectionMode, shader, m_labelObj, activeCamera,
+ true, true, Drawer::LabelMid, alignment);
+}
+
+void Abstract3DRenderer::loadGridLineMesh()
+{
+ ObjectHelper::resetObjectHelper(this, m_gridLineObj,
+ QStringLiteral(":/defaultMeshes/plane"));
+}
+
+void Abstract3DRenderer::loadLabelMesh()
+{
+ ObjectHelper::resetObjectHelper(this, m_labelObj,
+ QStringLiteral(":/defaultMeshes/plane"));
+}
+
+
+void Abstract3DRenderer::generateBaseColorTexture(const QColor &color, GLuint *texture)
+{
+ m_textureHelper->deleteTexture(texture);
*texture = m_textureHelper->createUniformTexture(color);
}
-void Abstract3DRenderer::fixGradientAndGenerateTexture(QLinearGradient *gradient, GLuint *gradientTexture)
+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;
- }
+ m_textureHelper->deleteTexture(gradientTexture);
*gradientTexture = m_textureHelper->createGradientTexture(*gradient);
}
@@ -471,4 +832,270 @@ QString &Abstract3DRenderer::selectionLabel()
return m_selectionLabel;
}
+QVector4D Abstract3DRenderer::indexToSelectionColor(GLint index)
+{
+ GLubyte idxRed = index & 0xff;
+ GLubyte idxGreen = (index & 0xff00) >> 8;
+ GLubyte idxBlue = (index & 0xff0000) >> 16;
+
+ return QVector4D(idxRed, idxGreen, idxBlue, 0);
+}
+
+CustomRenderItem *Abstract3DRenderer::addCustomItem(QCustom3DItem *item)
+{
+ CustomRenderItem *newItem = new CustomRenderItem();
+ newItem->setRenderer(this);
+ newItem->setItemPointer(item); // Store pointer for render item updates
+ newItem->setMesh(item->meshFile());
+ QVector3D scaling = item->scaling();
+ QImage textureImage = item->d_ptr->textureImage();
+ bool facingCamera = false;
+ if (item->d_ptr->m_isLabelItem) {
+ QCustom3DLabel *labelItem = static_cast<QCustom3DLabel *>(item);
+ float pointSize = labelItem->font().pointSizeF();
+ // Check do we have custom visuals or need to use theme
+ if (!labelItem->dptr()->m_customVisuals) {
+ // Recreate texture using theme
+ labelItem->dptr()->createTextureImage(m_cachedTheme->labelBackgroundColor(),
+ m_cachedTheme->labelTextColor(),
+ m_cachedTheme->isLabelBackgroundEnabled(),
+ m_cachedTheme->isLabelBorderEnabled());
+ pointSize = m_cachedTheme->font().pointSizeF();
+ textureImage = item->d_ptr->textureImage();
+ }
+ // Calculate scaling based on text (texture size), font size and asked scaling
+ float scaledFontSize = (0.05f + pointSize / 500.0f) / float(textureImage.height());
+ scaling.setX(scaling.x() * textureImage.width() * scaledFontSize);
+ scaling.setY(scaling.y() * textureImage.height() * scaledFontSize);
+ // Check if facing camera
+ facingCamera = labelItem->isFacingCamera();
+ }
+ newItem->setScaling(scaling);
+ newItem->setRotation(item->rotation());
+ newItem->setPosition(item->position());
+ newItem->setPositionAbsolute(item->isPositionAbsolute());
+ newItem->setBlendNeeded(textureImage.hasAlphaChannel());
+ GLuint texture = m_textureHelper->create2DTexture(textureImage, true, true, true);
+ newItem->setTexture(texture);
+ item->d_ptr->clearTextureImage();
+ QVector3D translation = convertPositionToTranslation(item->position(),
+ item->isPositionAbsolute());
+ newItem->setTranslation(translation);
+ newItem->setVisible(item->isVisible());
+ newItem->setShadowCasting(item->isShadowCasting());
+ newItem->setFacingCamera(facingCamera);
+ m_customRenderCache.insert(item, newItem);
+ return newItem;
+}
+
+void Abstract3DRenderer::updateCustomItem(CustomRenderItem *renderItem)
+{
+ QCustom3DItem *item = renderItem->itemPointer();
+ if (item->d_ptr->m_dirtyBits.meshDirty) {
+ renderItem->setMesh(item->meshFile());
+ item->d_ptr->m_dirtyBits.meshDirty = false;
+ }
+ if (item->d_ptr->m_dirtyBits.scalingDirty) {
+ QVector3D scaling = item->scaling();
+ // In case we have label item, we need to recreate texture for scaling adjustment
+ if (item->d_ptr->m_isLabelItem) {
+ QCustom3DLabel *labelItem = static_cast<QCustom3DLabel *>(item);
+ float pointSize = labelItem->font().pointSizeF();
+ // Check do we have custom visuals or need to use theme
+ if (labelItem->dptr()->m_customVisuals) {
+ // Recreate texture
+ labelItem->dptr()->createTextureImage();
+ } else {
+ // Recreate texture using theme
+ labelItem->dptr()->createTextureImage(m_cachedTheme->labelBackgroundColor(),
+ m_cachedTheme->labelTextColor(),
+ m_cachedTheme->isLabelBackgroundEnabled(),
+ m_cachedTheme->isLabelBorderEnabled());
+ pointSize = m_cachedTheme->font().pointSizeF();
+ }
+ QImage textureImage = item->d_ptr->textureImage();
+ // Calculate scaling based on text (texture size), font size and asked scaling
+ float scaledFontSize = (0.05f + pointSize / 500.0f) / float(textureImage.height());
+ scaling.setX(scaling.x() * textureImage.width() * scaledFontSize);
+ scaling.setY(scaling.y() * textureImage.height() * scaledFontSize);
+ item->d_ptr->clearTextureImage();
+ }
+ renderItem->setScaling(scaling);
+ item->d_ptr->m_dirtyBits.scalingDirty = false;
+ }
+ if (item->d_ptr->m_dirtyBits.rotationDirty) {
+ renderItem->setRotation(item->rotation());
+ item->d_ptr->m_dirtyBits.rotationDirty = false;
+ }
+ if (item->d_ptr->m_dirtyBits.textureDirty) {
+ QImage textureImage = item->d_ptr->textureImage();
+ if (item->d_ptr->m_isLabelItem) {
+ QCustom3DLabel *labelItem = static_cast<QCustom3DLabel *>(item);
+ // Check do we have custom visuals or need to use theme
+ if (!labelItem->dptr()->m_customVisuals) {
+ // Recreate texture using theme
+ labelItem->dptr()->createTextureImage(m_cachedTheme->labelBackgroundColor(),
+ m_cachedTheme->labelTextColor(),
+ m_cachedTheme->isLabelBackgroundEnabled(),
+ m_cachedTheme->isLabelBorderEnabled());
+ textureImage = item->d_ptr->textureImage();
+ }
+ }
+ renderItem->setBlendNeeded(textureImage.hasAlphaChannel());
+ GLuint oldTexture = renderItem->texture();
+ m_textureHelper->deleteTexture(&oldTexture);
+ GLuint texture = m_textureHelper->create2DTexture(textureImage, true, true, true);
+ renderItem->setTexture(texture);
+ item->d_ptr->clearTextureImage();
+ item->d_ptr->m_dirtyBits.textureDirty = false;
+ }
+ if (item->d_ptr->m_dirtyBits.positionDirty || item->d_ptr->m_dirtyBits.positionAbsoluteDirty) {
+ renderItem->setPosition(item->position());
+ renderItem->setPositionAbsolute(item->isPositionAbsolute());
+ QVector3D translation = convertPositionToTranslation(item->position(),
+ item->isPositionAbsolute());
+ renderItem->setTranslation(translation);
+ item->d_ptr->m_dirtyBits.positionDirty = false;
+ item->d_ptr->m_dirtyBits.positionAbsoluteDirty = false;
+ }
+ if (item->d_ptr->m_dirtyBits.visibleDirty) {
+ renderItem->setVisible(item->isVisible());
+ item->d_ptr->m_dirtyBits.visibleDirty = false;
+ }
+ if (item->d_ptr->m_dirtyBits.shadowCastingDirty) {
+ renderItem->setShadowCasting(item->isShadowCasting());
+ item->d_ptr->m_dirtyBits.shadowCastingDirty = false;
+ }
+ if (item->d_ptr->m_isLabelItem) {
+ QCustom3DLabel *labelItem = static_cast<QCustom3DLabel *>(item);
+ if (labelItem->dptr()->m_facingCameraDirty) {
+ renderItem->setFacingCamera(labelItem->isFacingCamera());
+ labelItem->dptr()->m_facingCameraDirty = false;
+ }
+ }
+}
+
+void Abstract3DRenderer::updateCustomItemPositions()
+{
+ foreach (CustomRenderItem *renderItem, m_customRenderCache) {
+ QVector3D translation = convertPositionToTranslation(renderItem->position(),
+ renderItem->isPositionAbsolute());
+ renderItem->setTranslation(translation);
+ }
+}
+
+void Abstract3DRenderer::drawCustomItems(RenderingState state,
+ ShaderHelper *shader,
+ const QMatrix4x4 &viewMatrix,
+ const QMatrix4x4 &projectionViewMatrix,
+ const QMatrix4x4 &depthProjectionViewMatrix,
+ GLuint depthTexture,
+ GLfloat shadowQuality)
+{
+ if (m_customRenderCache.isEmpty())
+ return;
+
+ if (RenderingNormal == state) {
+ shader->bind();
+ shader->setUniformValue(shader->lightP(), m_cachedScene->activeLight()->position());
+ shader->setUniformValue(shader->ambientS(), m_cachedTheme->ambientLightStrength());
+ shader->setUniformValue(shader->lightColor(),
+ Utils::vectorFromColor(m_cachedTheme->lightColor()));
+ shader->setUniformValue(shader->view(), viewMatrix);
+
+ glEnable(GL_TEXTURE_2D);
+ }
+
+ // Draw custom items
+ foreach (CustomRenderItem *item, m_customRenderCache) {
+ // Check that the render item is visible, and skip drawing if not
+ if (!item->isVisible())
+ continue;
+
+ // Check if the render item is in data coordinates and not within axis ranges, and skip drawing if it is
+ if (!item->isPositionAbsolute()
+ && (item->position().x() < m_axisCacheX.min()
+ || item->position().x() > m_axisCacheX.max()
+ || item->position().z() < m_axisCacheZ.min()
+ || item->position().z() > m_axisCacheZ.max()
+ || item->position().y() < m_axisCacheY.min()
+ || item->position().y() > m_axisCacheY.max())) {
+ continue;
+ }
+
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 itModelMatrix;
+ QMatrix4x4 MVPMatrix;
+
+ QQuaternion rotation = item->rotation();
+ // Check if the (label) item should be facing camera, and adjust rotation accordingly
+ if (item->isFacingCamera()) {
+ float camRotationX = m_cachedScene->activeCamera()->xRotation();
+ float camRotationY = m_cachedScene->activeCamera()->yRotation();
+ rotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, -camRotationX)
+ * QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, -camRotationY);
+ }
+
+ modelMatrix.translate(item->translation());
+ modelMatrix.rotate(rotation);
+ modelMatrix.scale(item->scaling());
+ itModelMatrix.rotate(rotation);
+ if (!item->isFacingCamera())
+ itModelMatrix.scale(item->scaling());
+ MVPMatrix = projectionViewMatrix * modelMatrix;
+
+ if (RenderingNormal == state) {
+ // Normal render
+ shader->setUniformValue(shader->model(), modelMatrix);
+ shader->setUniformValue(shader->MVP(), MVPMatrix);
+ shader->setUniformValue(shader->nModel(), itModelMatrix.inverted().transposed());
+
+ if (item->isBlendNeeded()) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_CULL_FACE);
+ } else {
+ glDisable(GL_BLEND);
+ glEnable(GL_CULL_FACE);
+ }
+
+#if !defined(QT_OPENGL_ES_2)
+ if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
+ // Set shadow shader bindings
+ shader->setUniformValue(shader->shadowQ(), shadowQuality);
+ shader->setUniformValue(shader->depth(), depthProjectionViewMatrix * modelMatrix);
+ shader->setUniformValue(shader->lightS(), m_cachedTheme->lightStrength() / 10.0f);
+ m_drawer->drawObject(shader, item->mesh(), item->texture(), depthTexture);
+ } else
+#else
+ Q_UNUSED(depthTexture)
+ Q_UNUSED(shadowQuality)
+#endif
+ {
+ // Set shadowless shader bindings
+ shader->setUniformValue(shader->lightS(), m_cachedTheme->lightStrength());
+ m_drawer->drawObject(shader, item->mesh(), item->texture());
+ }
+ } else if (RenderingSelection == state) {
+ // Selection render
+ shader->setUniformValue(shader->MVP(), MVPMatrix);
+ QVector4D itemColor = indexToSelectionColor(item->index());
+ itemColor.setW(customItemAlpha);
+ itemColor /= 255.0f;
+ shader->setUniformValue(shader->color(), itemColor);
+ m_drawer->drawObject(shader, item->mesh());
+ } else if (item->isShadowCasting()) {
+ // Depth render
+ shader->setUniformValue(shader->MVP(), depthProjectionViewMatrix * modelMatrix);
+ m_drawer->drawObject(shader, item->mesh());
+ }
+ }
+
+ if (RenderingNormal == state) {
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+ glEnable(GL_CULL_FACE);
+ }
+}
+
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h
index 4eb8426f..0dfc7367 100644
--- a/src/datavisualization/engine/abstract3drenderer_p.h
+++ b/src/datavisualization/engine/abstract3drenderer_p.h
@@ -29,18 +29,13 @@
#ifndef ABSTRACT3DRENDERER_P_H
#define ABSTRACT3DRENDERER_P_H
-//#define DISPLAY_RENDER_SPEED
-
#include <QtGui/QOpenGLFunctions>
-#ifdef DISPLAY_RENDER_SPEED
-#include <QtCore/QTime>
-#endif
#include "datavisualizationglobal_p.h"
#include "abstract3dcontroller_p.h"
#include "axisrendercache_p.h"
-#include "qabstractdataproxy.h"
#include "seriesrendercache_p.h"
+#include "customrenderitem_p.h"
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -60,18 +55,27 @@ protected:
SelectOnSlice
};
- QString generateValueLabel(const QString &format, float value);
+ enum RenderingState {
+ RenderingNormal = 0,
+ RenderingSelection,
+ RenderingDepth
+ };
public:
virtual ~Abstract3DRenderer();
virtual void updateData() = 0;
- virtual void updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility);
-
+ virtual void updateSeries(const QList<QAbstract3DSeries *> &seriesList);
+ virtual void updateCustomData(const QList<QCustom3DItem *> &customItems);
+ virtual void updateCustomItems();
+ virtual void updateCustomItemPositions();
+ virtual SeriesRenderCache *createNewCache(QAbstract3DSeries *series);
+ virtual void cleanCache(SeriesRenderCache *cache);
virtual void render(GLuint defaultFboHandle);
virtual void updateTheme(Q3DTheme *theme);
virtual void updateSelectionMode(QAbstract3DGraph::SelectionFlags newMode);
+ virtual void updateOptimizationHint(QAbstract3DGraph::OptimizationHints hint);
virtual void updateScene(Q3DScene *scene);
virtual void updateTextures() = 0;
virtual void initSelectionBuffer() = 0;
@@ -84,27 +88,64 @@ public:
virtual void updateShadowQuality(QAbstract3DGraph::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(QAbstract3DAxis::AxisOrientation orientation, QAbstract3DAxis::AxisType type);
- virtual void updateAxisTitle(QAbstract3DAxis::AxisOrientation orientation, const QString &title);
- virtual void updateAxisLabels(QAbstract3DAxis::AxisOrientation orientation, const QStringList &labels);
- virtual void updateAxisRange(QAbstract3DAxis::AxisOrientation orientation, float min, float max);
+ virtual void initBackgroundShaders(const QString &vertexShader,
+ const QString &fragmentShader) = 0;
+ virtual void initCustomItemShaders(const QString &vertexShader,
+ const QString &fragmentShader);
+ virtual void updateAxisType(QAbstract3DAxis::AxisOrientation orientation,
+ QAbstract3DAxis::AxisType type);
+ virtual void updateAxisTitle(QAbstract3DAxis::AxisOrientation orientation,
+ const QString &title);
+ virtual void updateAxisLabels(QAbstract3DAxis::AxisOrientation orientation,
+ const QStringList &labels);
+ virtual void updateAxisRange(QAbstract3DAxis::AxisOrientation orientation, float min,
+ float max);
virtual void updateAxisSegmentCount(QAbstract3DAxis::AxisOrientation orientation, int count);
- virtual void updateAxisSubSegmentCount(QAbstract3DAxis::AxisOrientation orientation, int count);
- virtual void updateAxisLabelFormat(QAbstract3DAxis::AxisOrientation orientation, const QString &format);
+ virtual void updateAxisSubSegmentCount(QAbstract3DAxis::AxisOrientation orientation,
+ int count);
+ virtual void updateAxisLabelFormat(QAbstract3DAxis::AxisOrientation orientation,
+ const QString &format);
+ virtual void updateAxisReversed(QAbstract3DAxis::AxisOrientation orientation,
+ bool enable);
+ virtual void updateAxisFormatter(QAbstract3DAxis::AxisOrientation orientation,
+ QValue3DAxisFormatter *formatter);
+ virtual void updateAxisLabelAutoRotation(QAbstract3DAxis::AxisOrientation orientation,
+ float angle);
+ virtual void updateAxisTitleVisibility(QAbstract3DAxis::AxisOrientation orientation,
+ bool visible);
+ virtual void updateAxisTitleFixed(QAbstract3DAxis::AxisOrientation orientation,
+ bool fixed);
+ virtual void modifiedSeriesList(const QVector<QAbstract3DSeries *> &seriesList);
virtual void fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh);
+
+ virtual CustomRenderItem *addCustomItem(QCustom3DItem *item);
+ virtual void updateCustomItem(CustomRenderItem *renderItem);
+
+ virtual void updateAspectRatio(float ratio);
+
+ virtual QVector3D convertPositionToTranslation(const QVector3D &position,
+ bool isAbsolute) = 0;
+
void generateBaseColorTexture(const QColor &color, GLuint *texture);
void fixGradientAndGenerateTexture(QLinearGradient *gradient, GLuint *gradientTexture);
inline bool isClickPending() { return m_clickPending; }
inline void clearClickPending() { m_clickPending = false; }
inline QAbstract3DSeries *clickedSeries() const { return m_clickedSeries; }
+ inline QAbstract3DGraph::ElementType clickedType() { return m_clickedType; }
LabelItem &selectionLabelItem();
void setSelectionLabel(const QString &label);
QString &selectionLabel();
+ void drawCustomItems(RenderingState state, ShaderHelper *shader,
+ const QMatrix4x4 &viewMatrix,
+ const QMatrix4x4 &projectionViewMatrix,
+ const QMatrix4x4 &depthProjectionViewMatrix,
+ GLuint depthTexture, GLfloat shadowQuality);
+ QVector4D indexToSelectionColor(GLint index);
+
signals:
void needRender(); // Emit this if something in renderer causes need for another render pass.
void requestShadowQuality(QAbstract3DGraph::ShadowQuality quality); // For automatic quality adjustments
@@ -124,6 +165,28 @@ protected:
void fixGradient(QLinearGradient *gradient, GLuint *gradientTexture);
+ void calculateZoomLevel();
+ void drawAxisTitleY(const QVector3D &sideLabelRotation, const QVector3D &backLabelRotation,
+ const QVector3D &sideLabelTrans, const QVector3D &backLabelTrans,
+ const QQuaternion &totalSideRotation, const QQuaternion &totalBackRotation,
+ AbstractRenderItem &dummyItem, const Q3DCamera *activeCamera,
+ float labelsMaxWidth,
+ const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionMatrix,
+ ShaderHelper *shader);
+ void drawAxisTitleX(const QVector3D &labelRotation, const QVector3D &labelTrans,
+ const QQuaternion &totalRotation, AbstractRenderItem &dummyItem,
+ const Q3DCamera *activeCamera, float labelsMaxWidth,
+ const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionMatrix,
+ ShaderHelper *shader);
+ void drawAxisTitleZ(const QVector3D &labelRotation, const QVector3D &labelTrans,
+ const QQuaternion &totalRotation, AbstractRenderItem &dummyItem,
+ const Q3DCamera *activeCamera, float labelsMaxWidth,
+ const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionMatrix,
+ ShaderHelper *shader);
+
+ void loadGridLineMesh();
+ void loadLabelMesh();
+
bool m_hasNegativeValues;
Q3DTheme *m_cachedTheme;
Drawer *m_drawer;
@@ -132,6 +195,7 @@ protected:
GLfloat m_autoScaleAdjustment;
QAbstract3DGraph::SelectionFlags m_cachedSelectionMode;
+ QAbstract3DGraph::OptimizationHints m_cachedOptimizationHint;
AxisRenderCache m_axisCacheX;
AxisRenderCache m_axisCacheY;
@@ -142,22 +206,37 @@ protected:
bool m_selectionDirty;
SelectionState m_selectionState;
QPoint m_inputPosition;
- QVector<SeriesRenderCache> m_visibleSeriesList;
+ QHash<QAbstract3DSeries *, SeriesRenderCache *> m_renderCacheList;
+ CustomRenderItemArray m_customRenderCache;
QRect m_primarySubViewport;
QRect m_secondarySubViewport;
float m_devicePixelRatio;
bool m_selectionLabelDirty;
bool m_clickPending;
QAbstract3DSeries *m_clickedSeries;
+ QAbstract3DGraph::ElementType m_clickedType;
+ int m_selectedLabelIndex;
+ int m_selectedCustomItemIndex;
QString m_selectionLabel;
LabelItem *m_selectionLabelItem;
+ int m_visibleSeriesCount;
-#ifdef DISPLAY_RENDER_SPEED
- bool m_isFirstFrame;
- QTime m_lastFrameTime;
- GLint m_numFrames;
-#endif
+ ShaderHelper *m_customItemShader;
+
+ bool m_useOrthoProjection;
+ bool m_xFlipped;
+ bool m_yFlipped;
+ bool m_zFlipped;
+
+ ObjectHelper *m_backgroundObj; // Shared reference
+ ObjectHelper *m_gridLineObj; // Shared reference
+ ObjectHelper *m_labelObj; // Shared reference
+
+ float m_graphAspectRatio;
+
+private:
+ friend class Abstract3DController;
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/axisrendercache.cpp b/src/datavisualization/engine/axisrendercache.cpp
index a107dd23..0b7a5c7a 100644
--- a/src/datavisualization/engine/axisrendercache.cpp
+++ b/src/datavisualization/engine/axisrendercache.cpp
@@ -18,7 +18,6 @@
#include "axisrendercache_p.h"
-#include <QtCore/qmath.h>
#include <QtGui/QFontMetrics>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -29,10 +28,17 @@ AxisRenderCache::AxisRenderCache()
m_max(10.0f),
m_segmentCount(5),
m_subSegmentCount(1),
+ m_reversed(false),
m_font(QFont(QStringLiteral("Arial"))),
+ m_formatter(0),
+ m_ctrlFormatter(0),
m_drawer(0),
- m_segmentStep(10.0f),
- m_subSegmentStep(10.0f)
+ m_positionsDirty(true),
+ m_translate(0.0f),
+ m_scale(1.0f),
+ m_labelAutoRotation(0.0f),
+ m_titleVisible(false),
+ m_titleFixed(false)
{
}
@@ -40,6 +46,8 @@ AxisRenderCache::~AxisRenderCache()
{
foreach (LabelItem *label, m_labelItems)
delete label;
+
+ delete m_formatter;
}
void AxisRenderCache::setDrawer(Drawer *drawer)
@@ -69,8 +77,6 @@ void AxisRenderCache::setType(QAbstract3DAxis::AxisType type)
foreach (LabelItem *label, m_labelItems)
delete label;
m_labelItems.clear();
- m_segmentStep = 10.0f;
- m_subSegmentStep = 10.0f;
}
void AxisRenderCache::setTitle(const QString &title)
@@ -110,28 +116,44 @@ void AxisRenderCache::setLabels(const QStringList &labels)
}
}
-void AxisRenderCache::setMin(float min)
-{
- m_min = min;
- updateSegmentStep();
-}
-
-void AxisRenderCache::setMax(float max)
+void AxisRenderCache::updateAllPositions()
{
- m_max = max;
- updateSegmentStep();
-}
-
-void AxisRenderCache::setSegmentCount(int count)
-{
- m_segmentCount = count;
- updateSegmentStep();
-}
+ // As long as grid and subgrid lines are drawn identically, we can further optimize
+ // by caching all grid and subgrid positions into a single vector.
+ // If subgrid lines are ever themed separately, this array will probably become obsolete.
+ if (m_formatter) {
+ int gridCount = m_formatter->gridPositions().size();
+ int subGridCount = m_formatter->subGridPositions().size();
+ int labelCount = m_formatter->labelPositions().size();
+ int fullSize = gridCount + subGridCount;
+
+ m_adjustedGridLinePositions.resize(fullSize);
+ m_adjustedLabelPositions.resize(labelCount);
+ int index = 0;
+ int grid = 0;
+ int label = 0;
+ float position = 0.0f;
+ for (; label < labelCount; label++) {
+ position = m_formatter->labelPositions().at(label);
+ if (m_reversed)
+ position = 1.0f - position;
+ m_adjustedLabelPositions[label] = position * m_scale + m_translate;
+ }
+ for (; grid < gridCount; grid++) {
+ position = m_formatter->gridPositions().at(grid);
+ if (m_reversed)
+ position = 1.0f - position;
+ m_adjustedGridLinePositions[index++] = position * m_scale + m_translate;
+ }
+ for (int subGrid = 0; subGrid < subGridCount; subGrid++) {
+ position = m_formatter->subGridPositions().at(subGrid);
+ if (m_reversed)
+ position = 1.0f - position;
+ m_adjustedGridLinePositions[index++] = position * m_scale + m_translate;
+ }
-void AxisRenderCache::setSubSegmentCount(int count)
-{
- m_subSegmentCount = count;
- updateSubSegmentStep();
+ m_positionsDirty = false;
+ }
}
void AxisRenderCache::updateTextures()
@@ -153,23 +175,6 @@ void AxisRenderCache::updateTextures()
}
}
-void AxisRenderCache::updateSegmentStep()
-{
- if (m_segmentCount > 0)
- m_segmentStep = qFabs((m_max - m_min) / m_segmentCount);
- else
- m_segmentStep = 0.0f; // Irrelevant
- updateSubSegmentStep();
-}
-
-void AxisRenderCache::updateSubSegmentStep()
-{
- if (m_subSegmentCount > 1)
- m_subSegmentStep = m_segmentStep / m_subSegmentCount;
- else
- m_subSegmentStep = m_segmentStep;
-}
-
int AxisRenderCache::maxLabelWidth(const QStringList &labels) const
{
int labelWidth = 0;
diff --git a/src/datavisualization/engine/axisrendercache_p.h b/src/datavisualization/engine/axisrendercache_p.h
index e1c51e7c..90321740 100644
--- a/src/datavisualization/engine/axisrendercache_p.h
+++ b/src/datavisualization/engine/axisrendercache_p.h
@@ -30,9 +30,8 @@
#define AXISRENDERCACHE_P_H
#include "datavisualizationglobal_p.h"
-#include "labelitem_p.h"
-#include "qabstract3daxis_p.h"
#include "drawer_p.h"
+#include <QtCore/QPointer>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -48,31 +47,70 @@ public:
void setType(QAbstract3DAxis::AxisType type);
inline QAbstract3DAxis::AxisType type() const { return m_type; }
void setTitle(const QString &title);
- inline const QString &title() { return m_title; }
+ inline const QString &title() const { return m_title; }
void setLabels(const QStringList &labels);
- inline const QStringList &labels() { return m_labels; }
- 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 const QStringList &labels() const { return m_labels; }
+ inline void setMin(float min) { m_min = min; }
+ inline float min() const { return m_min; }
+ inline void setMax(float max) { m_max = max; }
+ inline float max() const { return m_max; }
+ inline void setSegmentCount(int count) { m_segmentCount = count; m_positionsDirty = true; }
inline int segmentCount() const { return m_segmentCount; }
- void setSubSegmentCount(int count);
+ inline void setSubSegmentCount(int count) { m_subSegmentCount = count; m_positionsDirty = true; }
inline int subSegmentCount() const { return m_subSegmentCount; }
inline void setLabelFormat(const QString &format) { m_labelFormat = format; }
- inline const QString &labelFormat() { return m_labelFormat; }
+ inline const QString &labelFormat() const { return m_labelFormat; }
+ inline void setReversed(bool enable) { m_reversed = enable; m_positionsDirty = true; }
+ inline bool reversed() const { return m_reversed; }
+ inline void setFormatter(QValue3DAxisFormatter *formatter)
+ {
+ m_formatter = formatter; m_positionsDirty = true;
+ }
+ inline QValue3DAxisFormatter *formatter() const { return m_formatter; }
+ inline void setCtrlFormatter(QValue3DAxisFormatter *formatter)
+ {
+ m_ctrlFormatter = formatter;
+ }
+ inline QValue3DAxisFormatter *ctrlFormatter() const { return m_ctrlFormatter; }
inline LabelItem &titleItem() { return m_titleItem; }
inline QList<LabelItem *> &labelItems() { return m_labelItems; }
- inline GLfloat segmentStep() const { return m_segmentStep; }
- inline GLfloat subSegmentStep() const { return m_subSegmentStep; }
+ inline float gridLinePosition(int index) { return m_adjustedGridLinePositions.at(index); }
+ inline int gridLineCount() { return m_adjustedGridLinePositions.size(); }
+ inline float labelPosition(int index) { return m_adjustedLabelPositions.at(index); }
+ inline int labelCount() {
+ // Some value axis formatters may opt to not show all labels,
+ // so use positions array for determining count in that case.
+ if (m_type == QAbstract3DAxis::AxisTypeValue)
+ return m_adjustedLabelPositions.size();
+ else
+ return m_labels.size();
+ }
+ void updateAllPositions();
+ inline bool positionsDirty() const { return m_positionsDirty; }
+ inline void markPositionsDirty() { m_positionsDirty = true; }
+ inline void setTranslate(float translate) { m_translate = translate; m_positionsDirty = true; }
+ inline float translate() { return m_translate; }
+ inline void setScale(float scale) { m_scale = scale; m_positionsDirty = true; }
+ inline float scale() { return m_scale; }
+ inline float positionAt(float value)
+ {
+ if (m_reversed)
+ return (1.0f - m_formatter->positionAt(value)) * m_scale + m_translate;
+ else
+ return m_formatter->positionAt(value) * m_scale + m_translate;
+ }
+ inline float labelAutoRotation() const { return m_labelAutoRotation; }
+ inline void setLabelAutoRotation(float angle) { m_labelAutoRotation = angle; }
+ inline bool isTitleVisible() const { return m_titleVisible; }
+ inline void setTitleVisible(bool visible) { m_titleVisible = visible; }
+ inline bool isTitleFixed() const { return m_titleFixed; }
+ inline void setTitleFixed(bool fixed) { m_titleFixed = fixed; }
public slots:
void updateTextures();
private:
- void updateSegmentStep();
- void updateSubSegmentStep();
int maxLabelWidth(const QStringList &labels) const;
// Cached axis values
@@ -84,14 +122,23 @@ private:
int m_segmentCount;
int m_subSegmentCount;
QString m_labelFormat;
+ bool m_reversed;
QFont m_font;
+ QValue3DAxisFormatter *m_formatter;
+ QPointer<QValue3DAxisFormatter> m_ctrlFormatter;
// Renderer items
Drawer *m_drawer; // Not owned
LabelItem m_titleItem;
QList<LabelItem *> m_labelItems;
- GLfloat m_segmentStep;
- GLfloat m_subSegmentStep;
+ QVector<float> m_adjustedGridLinePositions;
+ QVector<float> m_adjustedLabelPositions;
+ bool m_positionsDirty;
+ float m_translate;
+ float m_scale;
+ float m_labelAutoRotation;
+ bool m_titleVisible;
+ bool m_titleFixed;
Q_DISABLE_COPY(AxisRenderCache)
};
diff --git a/src/datavisualization/engine/bars3dcontroller.cpp b/src/datavisualization/engine/bars3dcontroller.cpp
index 91240259..3a240c24 100644
--- a/src/datavisualization/engine/bars3dcontroller.cpp
+++ b/src/datavisualization/engine/bars3dcontroller.cpp
@@ -18,8 +18,6 @@
#include "bars3dcontroller_p.h"
#include "bars3drenderer_p.h"
-#include "camerahelper_p.h"
-#include "qabstract3daxis_p.h"
#include "qvalue3daxis_p.h"
#include "qcategory3daxis_p.h"
#include "qbardataproxy_p.h"
@@ -27,9 +25,6 @@
#include "thememanager_p.h"
#include "q3dtheme_p.h"
-#include <QtGui/QMatrix4x4>
-#include <QtCore/qmath.h>
-
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
Bars3DController::Bars3DController(QRect boundRect, Q3DScene *scene)
@@ -81,9 +76,28 @@ void Bars3DController::synchDataToRenderer()
series->d_ptr->m_changeTracker.meshChanged = true;
}
+ // If y range or reverse changed, scene needs to be updated to update camera limits
+ bool needSceneUpdate = false;
+ if (Abstract3DController::m_changeTracker.axisYRangeChanged
+ || Abstract3DController::m_changeTracker.axisYReversedChanged) {
+ needSceneUpdate = true;
+ }
+
Abstract3DController::synchDataToRenderer();
// Notify changes to renderer
+ if (m_changeTracker.rowsChanged) {
+ m_renderer->updateRows(m_changedRows);
+ m_changeTracker.rowsChanged = false;
+ m_changedRows.clear();
+ }
+
+ if (m_changeTracker.itemChanged) {
+ m_renderer->updateItems(m_changedItems);
+ m_changeTracker.itemChanged = false;
+ m_changedItems.clear();
+ }
+
if (m_changeTracker.multiSeriesScalingChanged) {
m_renderer->updateMultiSeriesScaling(m_isMultiSeriesUniform);
m_changeTracker.multiSeriesScalingChanged = false;
@@ -99,6 +113,13 @@ void Bars3DController::synchDataToRenderer()
m_renderer->updateSelectedBar(m_selectedBar, m_selectedBarSeries);
m_changeTracker.selectedBarChanged = false;
}
+
+ if (needSceneUpdate) {
+ // Since scene is updated before axis updates are handled,
+ // do another render pass for scene update
+ m_scene->d_ptr->m_sceneDirty = true;
+ emitNeedRender();
+ }
}
void Bars3DController::handleArrayReset()
@@ -107,7 +128,10 @@ void Bars3DController::handleArrayReset()
if (series->isVisible()) {
adjustAxisRanges();
m_isDataDirty = true;
+ series->d_ptr->markItemLabelDirty();
}
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
// Clear selection unless still valid
setSelectedBar(m_selectedBar, m_selectedBarSeries, false);
emitNeedRender();
@@ -122,19 +146,45 @@ void Bars3DController::handleRowsAdded(int startIndex, int count)
adjustAxisRanges();
m_isDataDirty = true;
}
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
emitNeedRender();
}
void Bars3DController::handleRowsChanged(int startIndex, int count)
{
- Q_UNUSED(startIndex)
- Q_UNUSED(count)
QBar3DSeries *series = static_cast<QBarDataProxy *>(sender())->series();
- if (series->isVisible()) {
- adjustAxisRanges();
- m_isDataDirty = true;
+ int oldChangeCount = m_changedRows.size();
+ if (!oldChangeCount)
+ m_changedRows.reserve(count);
+
+ for (int i = 0; i < count; i++) {
+ bool newItem = true;
+ int candidate = startIndex + i;
+ for (int j = 0; j < oldChangeCount; j++) {
+ const ChangeRow &oldChangeItem = m_changedRows.at(j);
+ if (oldChangeItem.row == candidate && series == oldChangeItem.series) {
+ newItem = false;
+ break;
+ }
+ }
+ if (newItem) {
+ ChangeRow newChangeItem = {series, candidate};
+ m_changedRows.append(newChangeItem);
+ if (series == m_selectedBarSeries && m_selectedBar.x() == candidate)
+ series->d_ptr->markItemLabelDirty();
+ }
+ }
+ if (count) {
+ m_changeTracker.rowsChanged = true;
+
+ if (series->isVisible())
+ adjustAxisRanges();
+
+ // Clear selection unless still valid (row length might have changed)
+ setSelectedBar(m_selectedBar, m_selectedBarSeries, false);
+ emitNeedRender();
}
- emitNeedRender();
}
void Bars3DController::handleRowsRemoved(int startIndex, int count)
@@ -160,6 +210,8 @@ void Bars3DController::handleRowsRemoved(int startIndex, int count)
adjustAxisRanges();
m_isDataDirty = true;
}
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
emitNeedRender();
}
@@ -182,20 +234,36 @@ void Bars3DController::handleRowsInserted(int startIndex, int count)
adjustAxisRanges();
m_isDataDirty = true;
}
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
emitNeedRender();
}
void Bars3DController::handleItemChanged(int rowIndex, int columnIndex)
{
- Q_UNUSED(rowIndex)
- Q_UNUSED(columnIndex)
QBar3DSeries *series = static_cast<QBarDataProxy *>(sender())->series();
- if (series->isVisible()) {
- adjustAxisRanges();
- m_isDataDirty = true;
+
+ bool newItem = true;
+ QPoint candidate(rowIndex, columnIndex);
+ foreach (ChangeItem item, m_changedItems) {
+ if (item.point == candidate && item.series == series) {
+ newItem = false;
+ break;
+ }
+ }
+
+ if (newItem) {
+ ChangeItem newItem = {series, candidate};
+ m_changedItems.append(newItem);
+ m_changeTracker.itemChanged = true;
+
+ if (series == m_selectedBarSeries && m_selectedBar == candidate)
+ series->d_ptr->markItemLabelDirty();
+ if (series->isVisible())
+ adjustAxisRanges();
+ emitNeedRender();
}
- emitNeedRender();
}
void Bars3DController::handleDataRowLabelsChanged()
@@ -238,8 +306,6 @@ void Bars3DController::handleSeriesVisibilityChangedBySender(QObject *sender)
{
Abstract3DController::handleSeriesVisibilityChangedBySender(sender);
- adjustAxisRanges();
-
// Visibility changes may require disabling slicing,
// so just reset selection to ensure everything is still valid.
setSelectedBar(m_selectedBar, m_selectedBarSeries, false);
@@ -253,6 +319,8 @@ void Bars3DController::handlePendingClick()
setSelectedBar(position, series, true);
+ Abstract3DController::handlePendingClick();
+
m_renderer->resetClickedStatus();
}
@@ -337,9 +405,6 @@ void Bars3DController::insertSeries(int index, QAbstract3DSeries *series)
Abstract3DController::insertSeries(index, series);
if (oldSize != m_seriesList.size()) {
- if (series->isVisible())
- adjustAxisRanges();
-
QBar3DSeries *barSeries = static_cast<QBar3DSeries *>(series);
if (!oldSize) {
m_primarySeries = barSeries;
@@ -460,7 +525,8 @@ void Bars3DController::setSelectedBar(const QPoint &position, QBar3DSeries *seri
adjustSelectionPosition(pos, series);
if (selectionMode().testFlag(QAbstract3DGraph::SelectionSlice)) {
- // If the selected bar is outside data window, or there is no visible selected bar, disable slicing
+ // 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()) {
@@ -518,7 +584,8 @@ void Bars3DController::adjustAxisRanges()
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));
+ const QBar3DSeries *barSeries =
+ static_cast<QBar3DSeries *>(m_seriesList.at(series));
if (barSeries->isVisible()) {
const QBarDataProxy *proxy = barSeries->dataProxy();
@@ -546,22 +613,24 @@ void Bars3DController::adjustAxisRanges()
}
// Call private implementations of setRange to avoid unsetting auto adjust flag
if (adjustZ)
- categoryAxisZ->dptr()->setRange(0.0f, float(maxRowCount));
+ categoryAxisZ->dptr()->setRange(0.0f, float(maxRowCount), true);
if (adjustX)
- categoryAxisX->dptr()->setRange(0.0f, float(maxColumnCount));
+ categoryAxisX->dptr()->setRange(0.0f, float(maxColumnCount), true);
}
// 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));
+ 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());
+ 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;
@@ -583,7 +652,7 @@ void Bars3DController::adjustAxisRanges()
minValue = 0.0f;
maxValue = 1.0f;
}
- valueAxis->dptr()->setRange(minValue, maxValue);
+ valueAxis->dptr()->setRange(minValue, maxValue, true);
}
}
}
diff --git a/src/datavisualization/engine/bars3dcontroller_p.h b/src/datavisualization/engine/bars3dcontroller_p.h
index 9ea59c89..4f0e1f20 100644
--- a/src/datavisualization/engine/bars3dcontroller_p.h
+++ b/src/datavisualization/engine/bars3dcontroller_p.h
@@ -38,16 +38,18 @@ class Bars3DRenderer;
class QBar3DSeries;
struct Bars3DChangeBitField {
- bool slicingActiveChanged : 1;
bool multiSeriesScalingChanged : 1;
bool barSpecsChanged : 1;
bool selectedBarChanged : 1;
+ bool rowsChanged : 1;
+ bool itemChanged : 1;
Bars3DChangeBitField() :
- slicingActiveChanged(true),
multiSeriesScalingChanged(true),
barSpecsChanged(true),
- selectedBarChanged(true)
+ selectedBarChanged(true),
+ rowsChanged(false),
+ itemChanged(false)
{
}
};
@@ -56,8 +58,20 @@ class QT_DATAVISUALIZATION_EXPORT Bars3DController : public Abstract3DController
{
Q_OBJECT
+public:
+ struct ChangeItem {
+ QBar3DSeries *series;
+ QPoint point;
+ };
+ struct ChangeRow {
+ QBar3DSeries *series;
+ int row;
+ };
+
private:
Bars3DChangeBitField m_changeTracker;
+ QVector<ChangeItem> m_changedItems;
+ QVector<ChangeRow> m_changedRows;
// Interaction
QPoint m_selectedBar; // Points to row & column in data window.
@@ -118,6 +132,7 @@ public:
virtual QList<QBar3DSeries *> barSeriesList();
virtual void handleAxisRangeChangedBySender(QObject *sender);
+ virtual void adjustAxisRanges();
public slots:
void handleArrayReset();
@@ -137,11 +152,9 @@ protected:
virtual QAbstract3DAxis *createDefaultAxis(QAbstract3DAxis::AxisOrientation orientation);
private:
- void adjustAxisRanges();
void adjustSelectionPosition(QPoint &pos, const QBar3DSeries *series);
Q_DISABLE_COPY(Bars3DController)
-
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp
index a7f9e2b3..3805e760 100644
--- a/src/datavisualization/engine/bars3drenderer.cpp
+++ b/src/datavisualization/engine/bars3drenderer.cpp
@@ -17,20 +17,12 @@
****************************************************************************/
#include "bars3drenderer_p.h"
-#include "bars3dcontroller_p.h"
#include "q3dcamera_p.h"
#include "shaderhelper_p.h"
-#include "objecthelper_p.h"
#include "texturehelper_p.h"
#include "utils_p.h"
-#include "drawer_p.h"
-#include "qbardataitem.h"
-#include "q3dlight.h"
-#include "qbar3dseries_p.h"
-
-#include <QtGui/QMatrix4x4>
-#include <QtGui/QMouseEvent>
-#include <QtCore/QThread>
+#include "barseriesrendercache_p.h"
+
#include <QtCore/qmath.h>
// You can verify that depth buffer drawing works correctly by uncommenting this.
@@ -39,9 +31,7 @@
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
-const GLfloat labelMargin = 0.05f;
const GLfloat gridLineWidth = 0.005f;
-
const bool sliceGridLabels = true;
Bars3DRenderer::Bars3DRenderer(Bars3DController *controller)
@@ -52,9 +42,6 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller)
m_selectedBar(0),
m_sliceCache(0),
m_sliceTitleItem(0),
- m_xFlipped(false),
- m_zFlipped(false),
- m_yFlipped(false),
m_updateLabels(false),
m_barShader(0),
m_barGradientShader(0),
@@ -62,9 +49,6 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller)
m_selectionShader(0),
m_backgroundShader(0),
m_labelShader(0),
- m_backgroundObj(0),
- m_gridLineObj(0),
- m_labelObj(0),
m_bgrTexture(0),
m_depthTexture(0),
m_selectionTexture(0),
@@ -74,7 +58,7 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller)
m_shadowQualityToShader(100.0f),
m_shadowQualityMultiplier(3),
m_heightNormalizer(1.0f),
- m_negativeBackgroundAdjustment(0.0f),
+ m_backgroundAdjustment(0.0f),
m_rowWidth(0),
m_columnDepth(0),
m_maxDimension(0),
@@ -83,18 +67,23 @@ Bars3DRenderer::Bars3DRenderer(Bars3DController *controller)
m_scaleFactor(0),
m_maxSceneSize(40.0f),
m_visualSelectedBarPos(Bars3DController::invalidSelectionPosition()),
- m_visualSelectedBarSeriesIndex(-1),
- m_hasHeightAdjustmentChanged(true),
+ m_resetCameraBaseOrientation(true),
m_selectedBarPos(Bars3DController::invalidSelectionPosition()),
- m_selectedBarSeries(0),
+ m_selectedSeriesCache(0),
m_noZeroInRange(false),
m_seriesScaleX(0.0f),
m_seriesScaleZ(0.0f),
m_seriesStep(0.0f),
m_seriesStart(0.0f),
m_clickedPosition(Bars3DController::invalidSelectionPosition()),
- m_keepSeriesUniform(false)
+ m_keepSeriesUniform(false),
+ m_haveUniformColorSeries(false),
+ m_haveGradientSeries(false),
+ m_zeroPosition(0.0f)
{
+ m_axisCacheY.setScale(2.0f);
+ m_axisCacheY.setTranslate(-1.0f);
+
initializeOpenGLFunctions();
initializeOpenGL();
}
@@ -114,9 +103,6 @@ Bars3DRenderer::~Bars3DRenderer()
delete m_depthShader;
delete m_selectionShader;
delete m_backgroundShader;
- delete m_backgroundObj;
- delete m_gridLineObj;
- delete m_labelObj;
delete m_labelShader;
}
@@ -148,23 +134,18 @@ void Bars3DRenderer::initializeOpenGL()
void Bars3DRenderer::updateData()
{
- 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;
- int updateSize = 0;
int dataRowCount = 0;
int maxDataRowCount = 0;
- if (m_renderingArrays.size() != seriesCount) {
- m_renderingArrays.resize(seriesCount);
- m_seriesScaleX = 1.0f / float(seriesCount);
- m_seriesStep = 1.0f / float(seriesCount);
- m_seriesStart = -((float(seriesCount) - 1.0f) / 2.0f) * m_seriesStep;
- }
+ m_seriesScaleX = 1.0f / float(m_visibleSeriesCount);
+ m_seriesStep = 1.0f / float(m_visibleSeriesCount);
+ m_seriesStart = -((float(m_visibleSeriesCount) - 1.0f) / 2.0f) * m_seriesStep;
if (m_keepSeriesUniform)
m_seriesScaleZ = m_seriesScaleX;
@@ -175,7 +156,6 @@ void Bars3DRenderer::updateData()
// Force update for selection related items
m_sliceCache = 0;
m_sliceTitleItem = 0;
- m_sliceSelection.clear();
m_cachedColumnCount = newColumns;
m_cachedRowCount = newRows;
@@ -187,88 +167,235 @@ void Bars3DRenderer::updateData()
calculateSceneScalingFactors();
}
- for (int series = 0; series < seriesCount; series++) {
- BarRenderItemArray &renderArray = m_renderingArrays[series];
- if (newRows != renderArray.size()
- || newColumns != renderArray.at(0).size()) {
- // Destroy old render items and reallocate new array
- renderArray.resize(newRows);
- for (int i = 0; i < newRows; i++)
- renderArray[i].resize(newColumns);
- }
+ m_zeroPosition = m_axisCacheY.formatter()->positionAt(0.0f);
+
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ BarSeriesRenderCache *cache = static_cast<BarSeriesRenderCache *>(baseCache);
+ if (cache->isVisible()) {
+ const QBar3DSeries *currentSeries = cache->series();
+ BarRenderItemArray &renderArray = cache->renderArray();
+ bool dimensionsChanged = false;
+ if (newRows != renderArray.size()
+ || newColumns != renderArray.at(0).size()) {
+ // Destroy old render items and reallocate new array
+ dimensionsChanged = true;
+ renderArray.resize(newRows);
+ for (int i = 0; i < newRows; i++)
+ renderArray[i].resize(newColumns);
+ cache->sliceArray().clear();
+ }
- // 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;
- BarRenderItemRow &renderRow = renderArray[i];
- if (dataRowIndex < dataRowCount) {
- const QBarDataRow *dataRow = dataProxy->rowAt(dataRowIndex);
- updateSize = qMin((dataRow->size() - minCol), renderRow.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;
- }
- }
- renderRow[j].setValue(value);
- renderRow[j].setHeight(heightValue / m_heightNormalizer);
- float angle = dataRow->at(dataColIndex).rotation();
- if (angle) {
- renderRow[j].setRotation(
- QQuaternion::fromAxisAndAngle(
- upVector, angle));
- } else {
- renderRow[j].setRotation(identityQuaternion);
- }
- dataColIndex++;
- }
+ if (cache->dataDirty() || dimensionsChanged) {
+ QBarDataProxy *dataProxy = currentSeries->dataProxy();
+ dataRowCount = dataProxy->rowCount();
+ if (maxDataRowCount < dataRowCount)
+ maxDataRowCount = qMin(dataRowCount, newRows);
+ int dataRowIndex = minRow;
+ for (int i = 0; i < newRows; i++) {
+ BarRenderItemRow &renderRow = renderArray[i];
+ const QBarDataRow *dataRow = 0;
+ if (dataRowIndex < dataRowCount)
+ dataRow = dataProxy->rowAt(dataRowIndex);
+ updateRenderRow(dataRow, renderRow);
+ dataRowIndex++;
}
+ cache->setDataDirty(false);
}
- for (; j < m_renderingArrays.at(series).at(i).size(); j++) {
- renderRow[j].setValue(0.0f);
- renderRow[j].setHeight(0.0f);
- renderRow[j].setRotation(identityQuaternion);
- }
- dataRowIndex++;
}
}
// Reset selected bar to update selection
- updateSelectedBar(m_selectedBarPos, m_selectedBarSeries);
+ updateSelectedBar(m_selectedBarPos,
+ m_selectedSeriesCache ? m_selectedSeriesCache->series() : 0);
+}
+
+void Bars3DRenderer::updateRenderRow(const QBarDataRow *dataRow, BarRenderItemRow &renderRow)
+{
+ int j = 0;
+ int renderRowSize = renderRow.size();
+ int startIndex = m_axisCacheX.min();
+
+ if (dataRow) {
+ int updateSize = qMin((dataRow->size() - startIndex), renderRowSize);
+ int dataColIndex = startIndex;
+ for (; j < updateSize ; j++) {
+ updateRenderItem(dataRow->at(dataColIndex), renderRow[j]);
+ dataColIndex++;
+ }
+ }
+ for (; j < renderRowSize; j++) {
+ renderRow[j].setValue(0.0f);
+ renderRow[j].setHeight(0.0f);
+ renderRow[j].setRotation(identityQuaternion);
+ }
+}
+
+void Bars3DRenderer::updateRenderItem(const QBarDataItem &dataItem, BarRenderItem &renderItem)
+{
+ float value = dataItem.value();
+ float heightValue = m_axisCacheY.formatter()->positionAt(value);
+ if (m_noZeroInRange) {
+ if (m_hasNegativeValues) {
+ heightValue = -1.0f + heightValue;
+ if (heightValue > 0.0f)
+ heightValue = 0.0f;
+ } else {
+ if (heightValue < 0.0f)
+ heightValue = 0.0f;
+ }
+ } else {
+ heightValue -= m_zeroPosition;
+ }
+ if (m_axisCacheY.reversed())
+ heightValue = -heightValue;
+
+ renderItem.setValue(value);
+ renderItem.setHeight(heightValue);
+
+ float angle = dataItem.rotation();
+ if (angle) {
+ renderItem.setRotation(
+ QQuaternion::fromAxisAndAngle(
+ upVector, angle));
+ } else {
+ renderItem.setRotation(identityQuaternion);
+ }
+}
+
+void Bars3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList)
+{
+ Abstract3DRenderer::updateSeries(seriesList);
+
+ bool noSelection = true;
+ int seriesCount = seriesList.size();
+ int visualIndex = 0;
+ m_haveUniformColorSeries = false;
+ m_haveGradientSeries = false;
+ for (int i = 0; i < seriesCount; i++) {
+ QBar3DSeries *barSeries = static_cast<QBar3DSeries *>(seriesList[i]);
+ BarSeriesRenderCache *cache =
+ static_cast<BarSeriesRenderCache *>(m_renderCacheList.value(barSeries));
+ if (barSeries->isVisible()) {
+ if (noSelection
+ && barSeries->selectedBar() != QBar3DSeries::invalidSelectionPosition()) {
+ if (selectionLabel() != cache->itemLabel())
+ m_selectionLabelDirty = true;
+ noSelection = false;
+ }
+ cache->setVisualIndex(visualIndex++);
+ if (cache->colorStyle() == Q3DTheme::ColorStyleUniform)
+ m_haveUniformColorSeries = true;
+ else
+ m_haveGradientSeries = true;
+ } else {
+ cache->setVisualIndex(-1);
+ }
+
+ }
+ if (noSelection) {
+ if (!selectionLabel().isEmpty())
+ m_selectionLabelDirty = true;
+ m_selectedSeriesCache = 0;
+ }
+}
+
+SeriesRenderCache *Bars3DRenderer::createNewCache(QAbstract3DSeries *series)
+{
+ return new BarSeriesRenderCache(series, this);
+}
+
+void Bars3DRenderer::updateRows(const QVector<Bars3DController::ChangeRow> &rows)
+{
+ int minRow = m_axisCacheZ.min();
+ int maxRow = m_axisCacheZ.max();
+ BarSeriesRenderCache *cache = 0;
+ const QBar3DSeries *prevSeries = 0;
+ const QBarDataArray *dataArray = 0;
+
+ foreach (Bars3DController::ChangeRow item, rows) {
+ const int row = item.row;
+ if (row < minRow || row > maxRow)
+ continue;
+ QBar3DSeries *currentSeries = item.series;
+ if (currentSeries != prevSeries) {
+ cache = static_cast<BarSeriesRenderCache *>(m_renderCacheList.value(currentSeries));
+ prevSeries = currentSeries;
+ dataArray = item.series->dataProxy()->array();
+ // Invisible series render caches are not updated, but instead just marked dirty, so that
+ // they can be completely recalculated when they are turned visible.
+ if (!cache->isVisible() && !cache->dataDirty())
+ cache->setDataDirty(true);
+ }
+ if (cache->isVisible()) {
+ updateRenderRow(dataArray->at(row), cache->renderArray()[row - minRow]);
+ if (m_cachedIsSlicingActivated
+ && cache == m_selectedSeriesCache
+ && m_selectedBarPos.x() == row) {
+ m_selectionDirty = true; // Need to update slice view
+ }
+ }
+ }
+}
+
+void Bars3DRenderer::updateItems(const QVector<Bars3DController::ChangeItem> &items)
+{
+ int minRow = m_axisCacheZ.min();
+ int maxRow = m_axisCacheZ.max();
+ int minCol = m_axisCacheX.min();
+ int maxCol = m_axisCacheX.max();
+ BarSeriesRenderCache *cache = 0;
+ const QBar3DSeries *prevSeries = 0;
+ const QBarDataArray *dataArray = 0;
+
+ foreach (Bars3DController::ChangeItem item, items) {
+ const int row = item.point.x();
+ const int col = item.point.y();
+ if (row < minRow || row > maxRow || col < minCol || col > maxCol)
+ continue;
+ QBar3DSeries *currentSeries = item.series;
+ if (currentSeries != prevSeries) {
+ cache = static_cast<BarSeriesRenderCache *>(m_renderCacheList.value(currentSeries));
+ prevSeries = currentSeries;
+ dataArray = item.series->dataProxy()->array();
+ // Invisible series render caches are not updated, but instead just marked dirty, so that
+ // they can be completely recalculated when they are turned visible.
+ if (!cache->isVisible() && !cache->dataDirty())
+ cache->setDataDirty(true);
+ }
+ if (cache->isVisible()) {
+ updateRenderItem(dataArray->at(row)->at(col),
+ cache->renderArray()[row - minRow][col - minCol]);
+ if (m_cachedIsSlicingActivated
+ && cache == m_selectedSeriesCache
+ && m_selectedBarPos == QPoint(row, col)) {
+ m_selectionDirty = true; // Need to update slice view
+ }
+ }
+ }
}
void Bars3DRenderer::updateScene(Q3DScene *scene)
{
- if (m_hasNegativeValues)
+ if (!m_noZeroInRange) {
scene->activeCamera()->d_ptr->setMinYRotation(-90.0);
- else
- scene->activeCamera()->d_ptr->setMinYRotation(0.0f);
+ scene->activeCamera()->d_ptr->setMaxYRotation(90.0);
+ } else {
+ if ((m_hasNegativeValues && !m_axisCacheY.reversed())
+ || (!m_hasNegativeValues && m_axisCacheY.reversed())) {
+ scene->activeCamera()->d_ptr->setMinYRotation(-90.0f);
+ scene->activeCamera()->d_ptr->setMaxYRotation(0.0);
+ } else {
+ scene->activeCamera()->d_ptr->setMinYRotation(0.0f);
+ scene->activeCamera()->d_ptr->setMaxYRotation(90.0);
+ }
+ }
- if (m_hasHeightAdjustmentChanged) {
+ if (m_resetCameraBaseOrientation) {
// Set initial camera position. Also update if height adjustment has changed.
scene->activeCamera()->d_ptr->setBaseOrientation(cameraDistanceVector,
zeroVector,
upVector);
- m_hasHeightAdjustmentChanged = false;
+ m_resetCameraBaseOrientation = false;
}
Abstract3DRenderer::updateScene(scene);
@@ -281,6 +408,9 @@ void Bars3DRenderer::render(GLuint defaultFboHandle)
// Handle GL state setup for FBO buffers and clearing of the render surface
Abstract3DRenderer::render(defaultFboHandle);
+ if (m_axisCacheY.positionsDirty())
+ m_axisCacheY.updateAllPositions();
+
drawScene(defaultFboHandle);
if (m_cachedIsSlicingActivated)
drawSlicedScene();
@@ -290,7 +420,7 @@ void Bars3DRenderer::drawSlicedScene()
{
GLfloat barPosX = 0;
QVector3D lightPos;
- QVector3D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor());
+ QVector4D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor());
static QQuaternion ninetyDegreeRotation = QQuaternion::fromAxisAndAngle(upVector, 90.0f);
// Specify viewport
@@ -301,8 +431,16 @@ void Bars3DRenderer::drawSlicedScene()
// Set up projection matrix
QMatrix4x4 projectionMatrix;
- projectionMatrix.perspective(35.0f, (GLfloat)m_secondarySubViewport.width()
- / (GLfloat)m_secondarySubViewport.height(), 0.1f, 100.0f);
+ GLfloat viewPortRatio = (GLfloat)m_primarySubViewport.width()
+ / (GLfloat)m_primarySubViewport.height();
+ if (m_useOrthoProjection) {
+ GLfloat orthoRatio = 2.0f / m_autoScaleAdjustment;
+ projectionMatrix.ortho(-viewPortRatio * orthoRatio, viewPortRatio * orthoRatio,
+ -orthoRatio, orthoRatio,
+ 0.0f, 100.0f);
+ } else {
+ projectionMatrix.perspective(35.0f, viewPortRatio, 0.1f, 100.0f);
+ }
// Set view matrix
QMatrix4x4 viewMatrix;
@@ -323,27 +461,37 @@ void Bars3DRenderer::drawSlicedScene()
bool itemMode = m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionItem);
GLfloat barPosYAdjustment = -0.8f; // Translate to -1.0 + 0.2 for row/column labels
+ GLfloat gridAdjustment = 1.0f + barPosYAdjustment - m_backgroundAdjustment;
GLfloat scaleFactor = 0.0f;
if (rowMode)
scaleFactor = (1.1f * m_rowWidth) / m_scaleFactor;
else
scaleFactor = (1.1f * m_columnDepth) / m_scaleFactor;
- GLfloat barLabelYPos = barPosYAdjustment - 0.4f - labelMargin; // 0.4 for labels
+ GLfloat barLabelYPos = barPosYAdjustment - labelMargin;
GLfloat zeroPosAdjustment = 0.0f;
- if (!m_noZeroInRange)
- zeroPosAdjustment = 2.0f * m_axisCacheY.min() / m_heightNormalizer;
- else if (m_hasNegativeValues)
- zeroPosAdjustment = -2.0f;
+ GLfloat directionMultiplier = 2.0f;
+ GLfloat directionBase = 0.0f;
+ if (m_axisCacheY.reversed()) {
+ directionMultiplier = -2.0f;
+ directionBase = -2.0f;
+ }
+ zeroPosAdjustment = directionBase +
+ directionMultiplier * m_axisCacheY.min() / m_heightNormalizer;
+ zeroPosAdjustment = qBound(-2.0f, zeroPosAdjustment, 0.0f);
// Draw grid lines
if (m_cachedTheme->isGridEnabled()) {
glDisable(GL_DEPTH_TEST);
+#if !(defined QT_OPENGL_ES_2)
ShaderHelper *lineShader = m_backgroundShader;
+#else
+ ShaderHelper *lineShader = m_selectionShader; // Plain color shader for GL_LINES
+#endif
// Bind line shader
lineShader->bind();
// Set unchanging shader bindings
- QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
+ QVector4D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
lineShader->setUniformValue(lineShader->lightP(), lightPos);
lineShader->setUniformValue(lineShader->view(), viewMatrix);
lineShader->setUniformValue(lineShader->color(), lineColor);
@@ -352,20 +500,18 @@ void Bars3DRenderer::drawSlicedScene()
lineShader->setUniformValue(lineShader->lightS(), 0.0f);
lineShader->setUniformValue(lineShader->lightColor(), lightColor);
- GLfloat gridStep = (2.0f * m_axisCacheY.subSegmentStep()) / m_heightNormalizer;
- GLfloat gridPos = barPosYAdjustment;
- int lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount();
- // Use the position of the bottom grid line as the base y position for bar labels
-
// Horizontal lines
if (m_axisCacheY.segmentCount() > 0) {
+ int gridLineCount = m_axisCacheY.gridLineCount();
+
QVector3D gridLineScale(scaleFactor, gridLineWidth, gridLineWidth);
bool noZero = true;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
+ GLfloat gridPos = m_axisCacheY.gridLinePosition(line) + gridAdjustment;
modelMatrix.translate(0.0f, gridPos, 0.0f);
modelMatrix.scale(gridLineScale);
itModelMatrix = modelMatrix;
@@ -378,14 +524,17 @@ void Bars3DRenderer::drawSlicedScene()
lineShader->setUniformValue(lineShader->MVP(), MVPMatrix);
// Draw the object
+#if !(defined QT_OPENGL_ES_2)
m_drawer->drawObject(lineShader, m_gridLineObj);
+#else
+ m_drawer->drawLine(lineShader);
+#endif
// Check if we have a line at zero position already
if (gridPos == (barPosYAdjustment + zeroPosAdjustment))
noZero = false;
-
- gridPos += gridStep;
}
+
// Draw a line at zero, if none exists
if (!m_noZeroInRange && noZero) {
QMatrix4x4 modelMatrix;
@@ -400,10 +549,15 @@ void Bars3DRenderer::drawSlicedScene()
itModelMatrix.inverted().transposed());
lineShader->setUniformValue(lineShader->MVP(), MVPMatrix);
lineShader->setUniformValue(lineShader->color(),
- Utils::vectorFromColor(m_cachedTheme->backgroundColor()));
+ Utils::vectorFromColor(
+ m_cachedTheme->labelTextColor()));
// Draw the object
+#if !(defined QT_OPENGL_ES_2)
m_drawer->drawObject(lineShader, m_gridLineObj);
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
}
@@ -417,24 +571,21 @@ void Bars3DRenderer::drawSlicedScene()
// Draw grid labels
int labelNbr = 0;
- int labelCount = m_axisCacheY.labels().size();
- gridStep = (2.0f * m_axisCacheY.segmentStep()) / m_heightNormalizer;
- gridPos = barPosYAdjustment;
- QVector3D backLabelRotation(0.0f, 0.0f, 0.0f);
+ int labelCount = m_axisCacheY.labelCount();
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);
+ GLfloat gridPos = m_axisCacheY.labelPosition(i) + gridAdjustment;
labelTrans.setY(gridPos);
m_dummyBarRenderItem.setTranslation(labelTrans);
m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix,
- projectionMatrix, zeroVector, backLabelRotation, 0,
+ projectionMatrix, zeroVector, identityQuaternion, 0,
m_cachedSelectionMode, m_labelShader, m_labelObj,
- activeCamera, true, true, Drawer::LabelMid, Qt::AlignRight);
+ activeCamera, true, true, Drawer::LabelMid, Qt::AlignLeft);
}
labelNbr++;
- gridPos += gridStep;
}
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
@@ -470,37 +621,40 @@ void Bars3DRenderer::drawSlicedScene()
ShaderHelper *barShader = m_barShader;
barShader->bind();
- int currentSeriesIndex = -1;
Q3DTheme::ColorStyle previousColorStyle = Q3DTheme::ColorStyleUniform;
Q3DTheme::ColorStyle colorStyle = Q3DTheme::ColorStyleUniform;
ObjectHelper *barObj = 0;
- QVector3D highlightColor;
- QVector3D baseColor;
+ QVector4D highlightColor;
+ QVector4D baseColor;
GLuint highlightGradientTexture = 0;
GLuint baseGradientTexture = 0;
- const SeriesRenderCache *currentSeries = 0;
bool colorStyleIsUniform = true;
+ int firstVisualIndex = m_renderCacheList.size();
+ QVector<BarRenderSliceItem> *firstVisualSliceArray = 0;
+ BarRenderSliceItem *selectedItem = 0;
+
+ QQuaternion seriesRotation;
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ if (baseCache->isVisible()
+ && (baseCache == m_selectedSeriesCache
+ || m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionMultiSeries))) {
+ BarSeriesRenderCache *cache = static_cast<BarSeriesRenderCache *>(baseCache);
+ QVector<BarRenderSliceItem> &sliceArray = cache->sliceArray();
+ int sliceCount = sliceArray.size();
+ if (firstVisualIndex > cache->visualIndex()) {
+ firstVisualIndex = cache->visualIndex();
+ firstVisualSliceArray = &sliceArray;
+ }
- int sliceItemCount = m_sliceSelection.size();
- for (int bar = 0; bar < sliceItemCount; bar++) {
- const BarRenderSliceItem &item = m_sliceSelection.at(bar);
- if (!item.value())
- continue;
-
- QQuaternion seriesRotation;
-
- if (item.seriesIndex() != currentSeriesIndex) {
- currentSeriesIndex = item.seriesIndex();
- currentSeries = &(m_visibleSeriesList.at(currentSeriesIndex));
- barObj = currentSeries->object();
- colorStyle = currentSeries->colorStyle();
+ barObj = cache->object();
+ colorStyle = cache->colorStyle();
colorStyleIsUniform = (colorStyle == Q3DTheme::ColorStyleUniform);
if (colorStyleIsUniform) {
- highlightColor = currentSeries->singleHighlightColor();
- baseColor = currentSeries->baseColor();
+ highlightColor = cache->singleHighlightColor();
+ baseColor = cache->baseColor();
} else {
- highlightGradientTexture = currentSeries->singleHighlightGradientTexture();
- baseGradientTexture = currentSeries->baseGradientTexture();
+ highlightGradientTexture = cache->singleHighlightGradientTexture();
+ baseGradientTexture = cache->baseGradientTexture();
}
// Rebind shader if it has changed
@@ -510,7 +664,6 @@ void Bars3DRenderer::drawSlicedScene()
else
barShader = m_barGradientShader;
barShader->bind();
-
}
if (!colorStyleIsUniform && (previousColorStyle != colorStyle)
@@ -519,76 +672,88 @@ void Bars3DRenderer::drawSlicedScene()
}
previousColorStyle = colorStyle;
- seriesRotation = currentSeries->meshRotation();
- }
+ seriesRotation = cache->meshRotation();
+ bool selectedSeries = (cache == m_selectedSeriesCache);
+
+ for (int bar = 0; bar < sliceCount; bar++) {
+ BarRenderSliceItem &item = cache->sliceArray()[bar];
+ if (selectedSeries && itemMode && sliceGridLabels
+ && m_visualSelectedBarPos.x() == item.position().x()
+ && m_visualSelectedBarPos.y() == item.position().y()) {
+ selectedItem = &item;
+ }
+ if (!item.value())
+ continue;
- if (item.height() < 0)
- glCullFace(GL_FRONT);
- else
- glCullFace(GL_BACK);
+ if (item.height() < 0)
+ glCullFace(GL_FRONT);
+ else
+ glCullFace(GL_BACK);
- QMatrix4x4 MVPMatrix;
- QMatrix4x4 modelMatrix;
- QMatrix4x4 itModelMatrix;
- QQuaternion barRotation = item.rotation();
- GLfloat barPosY = item.translation().y() + barPosYAdjustment - zeroPosAdjustment;
+ QMatrix4x4 MVPMatrix;
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 itModelMatrix;
+ QQuaternion barRotation = item.rotation();
+ GLfloat barPosY = item.translation().y() + barPosYAdjustment - zeroPosAdjustment;
+
+ if (rowMode) {
+ barPosX = item.translation().x();
+ } else {
+ barPosX = -(item.translation().z()); // flip z; frontmost bar to the left
+ barRotation *= ninetyDegreeRotation;
+ }
- if (rowMode) {
- barPosX = item.translation().x();
- } else {
- barPosX = -(item.translation().z()); // flip z; frontmost bar to the left
- barRotation *= ninetyDegreeRotation;
- }
+ modelMatrix.translate(barPosX, barPosY, 0.0f);
+ modelMatrixScaler.setY(item.height());
- modelMatrix.translate(barPosX, barPosY, 0.0f);
- modelMatrixScaler.setY(item.height());
+ if (!seriesRotation.isIdentity())
+ barRotation *= seriesRotation;
- if (!seriesRotation.isIdentity())
- barRotation *= seriesRotation;
+ if (!barRotation.isIdentity()) {
+ modelMatrix.rotate(barRotation);
+ itModelMatrix.rotate(barRotation);
+ }
- if (!barRotation.isIdentity()) {
- modelMatrix.rotate(barRotation);
- itModelMatrix.rotate(barRotation);
- }
+ modelMatrix.scale(modelMatrixScaler);
+ itModelMatrix.scale(modelMatrixScaler);
- modelMatrix.scale(modelMatrixScaler);
- itModelMatrix.scale(modelMatrixScaler);
+ MVPMatrix = projectionViewMatrix * modelMatrix;
- MVPMatrix = projectionViewMatrix * modelMatrix;
+ QVector4D barColor;
+ GLuint gradientTexture = 0;
- QVector3D barColor;
- GLuint gradientTexture = 0;
+ if (itemMode && m_visualSelectedBarPos.x() == item.position().x()
+ && m_visualSelectedBarPos.y() == item.position().y()) {
+ if (colorStyleIsUniform)
+ barColor = highlightColor;
+ else
+ gradientTexture = highlightGradientTexture;
+ } else {
+ if (colorStyleIsUniform)
+ barColor = baseColor;
+ else
+ gradientTexture = baseGradientTexture;
+ }
- if (itemMode && m_visualSelectedBarPos.x() == item.position().x()
- && m_visualSelectedBarPos.y() == item.position().y()) {
- if (colorStyleIsUniform)
- barColor = highlightColor;
- else
- gradientTexture = highlightGradientTexture;
- } else {
- if (colorStyleIsUniform)
- barColor = baseColor;
- else
- gradientTexture = baseGradientTexture;
- }
+ if (item.height() != 0) {
+ // Set shader bindings
+ 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));
+ }
- if (item.height() != 0) {
- // Set shader bindings
- 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(barShader,
+ barObj,
+ gradientTexture);
+ }
}
-
- // Draw the object
- m_drawer->drawObject(barShader,
- barObj,
- gradientTexture);
}
}
@@ -607,97 +772,111 @@ void Bars3DRenderer::drawSlicedScene()
// Draw labels for bars
QVector3D sliceValueRotation(0.0f, 0.0f, 90.0f);
QVector3D sliceLabelRotation(0.0f, 0.0f, -45.0f);
+ QQuaternion totalSliceValueRotation = Utils::calculateRotation(sliceValueRotation);
+ QQuaternion totalSliceLabelRotation = Utils::calculateRotation(sliceLabelRotation);
- int lastLabel = m_sliceCache->labelItems().size() - 1;
+ int labelCount = m_sliceCache->labelItems().size();
- for (int labelNo = 0; labelNo <= lastLabel; labelNo++) {
+ for (int labelNo = 0; labelNo < labelCount; labelNo++) {
// Get labels from first series only
- const BarRenderSliceItem &item = m_sliceSelection.at(labelNo);
+ const BarRenderSliceItem &item = firstVisualSliceArray->at(labelNo);
m_dummyBarRenderItem.setTranslation(QVector3D(item.translation().x(),
barLabelYPos,
item.translation().z()));
+
// Draw labels
m_drawer->drawLabel(m_dummyBarRenderItem, *m_sliceCache->labelItems().at(labelNo),
- viewMatrix, projectionMatrix, positionComp, sliceLabelRotation,
+ viewMatrix, projectionMatrix, positionComp, totalSliceLabelRotation,
0, m_cachedSelectionMode, m_labelShader,
m_labelObj, activeCamera, false, false, Drawer::LabelMid,
- Qt::AlignRight, true);
+ Qt::AlignmentFlag(Qt::AlignLeft | Qt::AlignTop), true);
}
- for (int col = 0; col < sliceItemCount; col++) {
- BarRenderSliceItem &item = m_sliceSelection[col];
-
- 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() || m_updateLabels) {
- item.setSliceLabel(generateValueLabel(m_axisCacheY.labelFormat(),
- item.value()));
- m_drawer->generateLabelItem(item.sliceLabelItem(), item.sliceLabel());
- m_updateLabels = false;
- }
- Qt::AlignmentFlag alignment = (item.height() < 0) ? Qt::AlignBottom : Qt::AlignTop;
- Drawer::LabelPosition labelPos = (item.height() < 0) ? Drawer::LabelBelow : Drawer::LabelOver;
- m_dummyBarRenderItem.setTranslation(QVector3D(item.translation().x(),
- barPosYAdjustment - zeroPosAdjustment
- + item.height(),
- item.translation().z()));
-
- m_drawer->drawLabel(m_dummyBarRenderItem, item.sliceLabelItem(), viewMatrix,
- projectionMatrix, zeroVector, sliceValueRotation,
- item.height(), m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera, false, false, labelPos,
- alignment, true);
- }
- } else {
- // Only draw value for selected item when grid labels are on
- 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() || m_updateLabels) {
- item.setSliceLabel(generateValueLabel(m_axisCacheY.labelFormat(),
- item.value()));
- m_drawer->generateLabelItem(item.sliceLabelItem(), item.sliceLabel());
- m_updateLabels = false;
+ if (!sliceGridLabels) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ if (baseCache->isVisible()) {
+ BarSeriesRenderCache *cache = static_cast<BarSeriesRenderCache *>(baseCache);
+ QVector<BarRenderSliceItem> &sliceArray = cache->sliceArray();
+ int sliceCount = sliceArray.size();
+ for (int col = 0; col < sliceCount; col++) {
+ BarRenderSliceItem &item = sliceArray[col];
+
+ // Draw values
+ if (item.height() != 0.0f || (!m_noZeroInRange && item.value() == 0.0f)) {
+ // Create label texture if we need it
+ if (item.sliceLabel().isNull() || m_updateLabels) {
+ QString valueLabelText = m_axisCacheY.formatter()->stringForValue(
+ qreal(item.value()), m_axisCacheY.labelFormat());
+ item.setSliceLabel(valueLabelText);
+ m_drawer->generateLabelItem(item.sliceLabelItem(), item.sliceLabel());
+ m_updateLabels = false;
+ }
+ Qt::AlignmentFlag alignment =
+ (item.height() > 0) ? Qt::AlignLeft : Qt::AlignRight;
+ Drawer::LabelPosition labelPos =
+ (item.height() < 0) ? Drawer::LabelBelow : Drawer::LabelOver;
+ m_dummyBarRenderItem.setTranslation(QVector3D(item.translation().x(),
+ barPosYAdjustment
+ - zeroPosAdjustment
+ + item.height(),
+ item.translation().z()));
+
+ m_drawer->drawLabel(m_dummyBarRenderItem, item.sliceLabelItem(), viewMatrix,
+ projectionMatrix, zeroVector, totalSliceValueRotation,
+ item.height(), m_cachedSelectionMode, m_labelShader,
+ m_labelObj, activeCamera, false, false, labelPos,
+ alignment, true);
+ }
}
- Qt::AlignmentFlag alignment = (item.height() < 0) ? Qt::AlignBottom : Qt::AlignTop;
- Drawer::LabelPosition labelPos = (item.height() < 0) ? Drawer::LabelBelow : Drawer::LabelOver;
- m_dummyBarRenderItem.setTranslation(QVector3D(item.translation().x(),
- barPosYAdjustment - zeroPosAdjustment
- + item.height(),
- item.translation().z()));
-
- m_drawer->drawLabel(m_dummyBarRenderItem, item.sliceLabelItem(), viewMatrix,
- projectionMatrix, zeroVector, sliceValueRotation,
- item.height(), m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera, false, false, labelPos,
- alignment, true);
}
}
+ } else if (selectedItem) {
+ // Only draw value for selected item when grid labels are on
+ // Create label texture if we need it
+ if (selectedItem->sliceLabel().isNull() || m_updateLabels) {
+ QString valueLabelText = m_axisCacheY.formatter()->stringForValue(
+ qreal(selectedItem->value()), m_axisCacheY.labelFormat());
+ selectedItem->setSliceLabel(valueLabelText);
+ m_drawer->generateLabelItem(selectedItem->sliceLabelItem(), selectedItem->sliceLabel());
+ m_updateLabels = false;
+ }
+ Qt::AlignmentFlag alignment = (selectedItem->height() > 0) ? Qt::AlignLeft : Qt::AlignRight;
+ Drawer::LabelPosition labelPos =
+ (selectedItem->height() < 0) ? Drawer::LabelBelow : Drawer::LabelOver;
+ m_dummyBarRenderItem.setTranslation(QVector3D(selectedItem->translation().x(),
+ barPosYAdjustment - zeroPosAdjustment
+ + selectedItem->height(),
+ selectedItem->translation().z()));
+
+ m_drawer->drawLabel(m_dummyBarRenderItem, selectedItem->sliceLabelItem(), viewMatrix,
+ projectionMatrix, zeroVector, totalSliceValueRotation,
+ selectedItem->height(), m_cachedSelectionMode, m_labelShader,
+ m_labelObj, activeCamera, false, false, labelPos,
+ alignment, true);
}
// 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,
- Qt::AlignCenter, true);
+ positionComp, identityQuaternion, 0, m_cachedSelectionMode,
+ m_labelShader, m_labelObj, activeCamera, false, false,
+ Drawer::LabelTop, Qt::AlignCenter, true);
}
m_drawer->drawLabel(*dummyItem, m_axisCacheX.titleItem(), viewMatrix, projectionMatrix,
- positionComp, zeroVector, 0, m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera, false, false, Drawer::LabelBottom,
- Qt::AlignCenter, true);
+ positionComp, identityQuaternion, 0, m_cachedSelectionMode,
+ m_labelShader, m_labelObj, activeCamera, false, false,
+ Drawer::LabelBottom, Qt::AlignCenter, true);
} else {
m_drawer->drawLabel(*dummyItem, m_axisCacheZ.titleItem(), viewMatrix, projectionMatrix,
- positionComp, zeroVector, 0, m_cachedSelectionMode, m_labelShader,
+ positionComp, identityQuaternion, 0, m_cachedSelectionMode,
+ m_labelShader,
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,
+ positionComp, identityQuaternion, 0, m_cachedSelectionMode,
+ m_labelShader,
m_labelObj, activeCamera, false, false, Drawer::LabelTop,
Qt::AlignCenter, true);
}
@@ -706,9 +885,9 @@ void Bars3DRenderer::drawSlicedScene()
QVector3D labelTrans = QVector3D(-scaleFactor - labelMargin, 0.2f, 0.0f); // y = 0.2 for row/column labels (see barPosYAdjustment)
m_dummyBarRenderItem.setTranslation(labelTrans);
m_drawer->drawLabel(m_dummyBarRenderItem, m_axisCacheY.titleItem(), viewMatrix,
- projectionMatrix, zeroVector, QVector3D(0.0f, 0.0f, 90.0f), 0,
+ projectionMatrix, zeroVector, totalSliceValueRotation, 0,
m_cachedSelectionMode, m_labelShader, m_labelObj, activeCamera,
- false, false, Drawer::LabelMid, Qt::AlignHCenter);
+ false, false, Drawer::LabelMid, Qt::AlignBottom);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
@@ -733,9 +912,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
GLfloat colPos = 0;
GLfloat rowPos = 0;
- QVector3D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor());
-
- int seriesCount = m_visibleSeriesList.size();
+ QVector4D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor());
const Q3DCamera *activeCamera = m_cachedScene->activeCamera();
@@ -748,7 +925,14 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
QMatrix4x4 projectionMatrix;
GLfloat viewPortRatio = (GLfloat)m_primarySubViewport.width()
/ (GLfloat)m_primarySubViewport.height();
- projectionMatrix.perspective(45.0f, viewPortRatio, 0.1f, 100.0f);
+ if (m_useOrthoProjection) {
+ GLfloat orthoRatio = 2.0f;
+ projectionMatrix.ortho(-viewPortRatio * orthoRatio, viewPortRatio * orthoRatio,
+ -orthoRatio, orthoRatio,
+ 0.0f, 100.0f);
+ } else {
+ projectionMatrix.perspective(45.0f, viewPortRatio, 0.1f, 100.0f);
+ }
// Get the view matrix
QMatrix4x4 viewMatrix = activeCamera->d_ptr->viewMatrix();
@@ -808,6 +992,11 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
bool rowMode = m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow);
+ GLfloat rowScaleFactor = m_rowWidth / m_scaleFactor;
+ GLfloat columnScaleFactor = m_columnDepth / m_scaleFactor;
+
+ BarRenderItem *selectedBar(0);
+
#if !defined(QT_OPENGL_ES_2)
if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
// Render scene into a depth texture for using with shadow mapping
@@ -837,72 +1026,80 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
// Draw bars to depth buffer
QVector3D shadowScaler(m_scaleX * m_seriesScaleX * 0.9f, 0.0f,
m_scaleZ * m_seriesScaleZ * 0.9f);
- float seriesPos = m_seriesStart;
- for (int series = 0; series < seriesCount; series++) {
- ObjectHelper *barObj = m_visibleSeriesList.at(series).object();
- QQuaternion seriesRotation(m_visibleSeriesList.at(series).meshRotation());
- 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;
- }
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ if (baseCache->isVisible()) {
+ BarSeriesRenderCache *cache = static_cast<BarSeriesRenderCache *>(baseCache);
+ float seriesPos = m_seriesStart + m_seriesStep * cache->visualIndex() + 0.5f;
+ ObjectHelper *barObj = cache->object();
+ QQuaternion seriesRotation(cache->meshRotation());
+ const BarRenderItemArray &renderArray = cache->renderArray();
+ for (int row = startRow; row != stopRow; row += stepRow) {
+ const BarRenderItemRow &renderRow = renderArray.at(row);
+ for (int bar = startBar; bar != stopBar; bar += stepBar) {
+ const BarRenderItem &item = renderRow.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;
+ }
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
- colPos = (bar + 0.5f + seriesPos) * (m_cachedBarSpacing.width());
- rowPos = (row + 0.5f) * (m_cachedBarSpacing.height());
+ colPos = (bar + 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() + shadowOffset,
- (m_columnDepth - rowPos) / m_scaleFactor);
- // Scale the bars down in X and Z to reduce self-shadowing issues
- shadowScaler.setY(item.height());
- if (!seriesRotation.isIdentity() || !item.rotation().isIdentity())
- modelMatrix.rotate(seriesRotation * item.rotation());
- 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());
+ if (!seriesRotation.isIdentity() || !item.rotation().isIdentity())
+ modelMatrix.rotate(seriesRotation * item.rotation());
+ 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, 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, barObj->elementBuf());
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, barObj->elementBuf());
- // Draw the triangles
- glDrawElements(GL_TRIANGLES, 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;
}
+ Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, viewMatrix,
+ projectionViewMatrix, depthProjectionViewMatrix,
+ m_depthTexture, m_shadowQualityToShader);
+
// Disable drawing to depth framebuffer (= enable drawing to screen)
glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle);
@@ -919,7 +1116,8 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
// Skip selection mode drawing if we're slicing or have no selection mode
if (!m_cachedIsSlicingActivated && m_cachedSelectionMode > QAbstract3DGraph::SelectionNone
- && m_selectionState == SelectOnScene && seriesCount > 0) {
+ && m_selectionState == SelectOnScene
+ && (m_visibleSeriesCount > 0 || !m_customRenderCache.isEmpty())) {
// Bind selection shader
m_selectionShader->bind();
@@ -933,71 +1131,65 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
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
- float seriesPos = m_seriesStart;
- for (int series = 0; series < seriesCount; series++) {
- ObjectHelper *barObj = m_visibleSeriesList.at(series).object();
- QQuaternion seriesRotation(m_visibleSeriesList.at(series).meshRotation());
- 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);
- if (!seriesRotation.isIdentity() || !item.rotation().isIdentity())
- modelMatrix.rotate(seriesRotation * item.rotation());
- modelMatrix.scale(QVector3D(m_scaleX * m_seriesScaleX,
- item.height(),
- m_scaleZ * m_seriesScaleZ));
-
- MVPMatrix = projectionViewMatrix * modelMatrix;
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ if (baseCache->isVisible()) {
+ BarSeriesRenderCache *cache = static_cast<BarSeriesRenderCache *>(baseCache);
+ float seriesPos = m_seriesStart + m_seriesStep * cache->visualIndex() + 0.5f;
+ ObjectHelper *barObj = cache->object();
+ QQuaternion seriesRotation(cache->meshRotation());
+ const BarRenderItemArray &renderArray = cache->renderArray();
+ for (int row = startRow; row != stopRow; row += stepRow) {
+ const BarRenderItemRow &renderRow = renderArray.at(row);
+ for (int bar = startBar; bar != stopBar; bar += stepBar) {
+ const BarRenderItem &item = renderRow.at(bar);
+ if (!item.value())
+ continue;
+
+ if (item.height() < 0)
+ glCullFace(GL_FRONT);
+ else
+ glCullFace(GL_BACK);
- QVector3D barColor = QVector3D(GLfloat(row) / 255.0f,
- GLfloat(bar) / 255.0f,
- GLfloat(series) / 255.0f);
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
- m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix);
- m_selectionShader->setUniformValue(m_selectionShader->color(), barColor);
+ colPos = (bar + seriesPos) * (m_cachedBarSpacing.width());
+ rowPos = (row + 0.5f) * (m_cachedBarSpacing.height());
- // 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);
+ modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor,
+ item.height(),
+ (m_columnDepth - rowPos) / m_scaleFactor);
+ if (!seriesRotation.isIdentity() || !item.rotation().isIdentity())
+ modelMatrix.rotate(seriesRotation * item.rotation());
+ modelMatrix.scale(QVector3D(m_scaleX * m_seriesScaleX,
+ item.height(),
+ m_scaleZ * m_seriesScaleZ));
- // Index buffer
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, barObj->elementBuf());
+ MVPMatrix = projectionViewMatrix * modelMatrix;
- // Draw the triangles
- glDrawElements(GL_TRIANGLES, barObj->indexCount(), GL_UNSIGNED_SHORT,
- (void *)0);
+ QVector4D barColor = QVector4D(GLfloat(row) / 255.0f,
+ GLfloat(bar) / 255.0f,
+ GLfloat(cache->visualIndex()) / 255.0f,
+ itemAlpha);
- // Free buffers
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
+ m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix);
+ m_selectionShader->setUniformValue(m_selectionShader->color(), barColor);
- glDisableVertexAttribArray(m_selectionShader->posAtt());
+ m_drawer->drawSelectionObject(m_selectionShader, barObj);
+ }
}
}
- seriesPos += m_seriesStep;
}
+ glCullFace(GL_BACK);
+ Abstract3DRenderer::drawCustomItems(RenderingSelection, m_selectionShader, viewMatrix,
+ projectionViewMatrix, depthProjectionViewMatrix,
+ m_depthTexture, m_shadowQualityToShader);
+ drawLabels(true, activeCamera, viewMatrix, projectionMatrix, rowScaleFactor,
+ columnScaleFactor);
glEnable(GL_DITHER);
// Read color under cursor
- QVector3D clickedColor = Utils::getSelection(m_inputPosition,
+ QVector4D clickedColor = Utils::getSelection(m_inputPosition,
m_viewport.height());
m_clickedPosition = selectionColorToArrayPosition(clickedColor);
m_clickedSeries = selectionColorToSeries(clickedColor);
@@ -1018,18 +1210,9 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
ShaderHelper *barShader = 0;
GLuint gradientTexture = 0;
Q3DTheme::ColorStyle previousColorStyle = Q3DTheme::ColorStyleUniform;
- bool haveUniformColorSeries = false;
- bool haveGradientSeries = false;
-
- 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) {
+ if (m_haveGradientSeries) {
m_barGradientShader->bind();
m_barGradientShader->setUniformValue(m_barGradientShader->lightP(), lightPos);
m_barGradientShader->setUniformValue(m_barGradientShader->view(), viewMatrix);
@@ -1039,7 +1222,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
m_barGradientShader->setUniformValue(m_barGradientShader->lightColor(), lightColor);
}
- if (haveUniformColorSeries) {
+ if (m_haveUniformColorSeries) {
m_barShader->bind();
m_barShader->setUniformValue(m_barShader->lightP(), lightPos);
m_barShader->setUniformValue(m_barShader->view(), viewMatrix);
@@ -1052,17 +1235,13 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
previousColorStyle = Q3DTheme::ColorStyleRangeGradient;
}
+ int sliceReserveAmount = 0;
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;
+ sliceReserveAmount = m_cachedColumnCount;
else
- reserveAmount = m_cachedRowCount;
- if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionMultiSeries))
- reserveAmount *= m_visibleSeriesList.size();
- m_sliceSelection.resize(reserveAmount);
+ sliceReserveAmount = m_cachedRowCount;
// Set slice cache, i.e. axis cache from where slice labels are taken
if (rowMode)
@@ -1073,259 +1252,253 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
}
// Draw bars
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(0.5f, 1.0f);
GLfloat adjustedLightStrength = m_cachedTheme->lightStrength() / 10.0f;
GLfloat adjustedHighlightStrength = m_cachedTheme->highlightLightStrength() / 10.0f;
bool barSelectionFound = false;
- BarRenderItem *selectedBar(0);
- QVector3D baseColor;
- QVector3D barColor;
+ QVector4D baseColor;
+ QVector4D barColor;
QVector3D modelScaler(m_scaleX * m_seriesScaleX, 0.0f, m_scaleZ * m_seriesScaleZ);
- bool somethingSelected = (m_visualSelectedBarPos != Bars3DController::invalidSelectionPosition());
- float seriesPos = m_seriesStart;
- for (int series = 0; series < seriesCount; series++) {
- const SeriesRenderCache &currentSeries = m_visibleSeriesList.at(series);
- QQuaternion seriesRotation(currentSeries.meshRotation());
- 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
- barShader = m_barGradientShader;
- barShader->bind();
- }
+ bool somethingSelected =
+ (m_visualSelectedBarPos != Bars3DController::invalidSelectionPosition());
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ if (baseCache->isVisible()) {
+ BarSeriesRenderCache *cache = static_cast<BarSeriesRenderCache *>(baseCache);
+ float seriesPos = m_seriesStart + m_seriesStep * cache->visualIndex() + 0.5f;
+ ObjectHelper *barObj = cache->object();
+ QQuaternion seriesRotation(cache->meshRotation());
+ Q3DTheme::ColorStyle colorStyle = cache->colorStyle();
+ BarRenderItemArray &renderArray = cache->renderArray();
+ bool colorStyleIsUniform = (colorStyle == Q3DTheme::ColorStyleUniform);
+ if (sliceReserveAmount)
+ cache->sliceArray().resize(sliceReserveAmount);
- if (colorStyleIsUniform) {
- baseColor = currentSeries.baseColor();
- } else if ((previousColorStyle != colorStyle)
- && (colorStyle == Q3DTheme::ColorStyleObjectGradient)) {
- m_barGradientShader->setUniformValue(m_barGradientShader->gradientHeight(), 0.5f);
- }
+ // Rebind shader if it has changed
+ if (colorStyleIsUniform != (previousColorStyle == Q3DTheme::ColorStyleUniform)) {
+ if (colorStyleIsUniform)
+ barShader = m_barShader;
+ else
+ barShader = m_barGradientShader;
+ barShader->bind();
+ }
- // Always use base color when no selection mode
- if (m_cachedSelectionMode == QAbstract3DGraph::SelectionNone) {
- if (colorStyleIsUniform)
- barColor = baseColor;
- else
- gradientTexture = currentSeries.baseGradientTexture();
- }
+ if (colorStyleIsUniform) {
+ baseColor = cache->baseColor();
+ } else if ((previousColorStyle != colorStyle)
+ && (colorStyle == Q3DTheme::ColorStyleObjectGradient)) {
+ m_barGradientShader->setUniformValue(m_barGradientShader->gradientHeight(), 0.5f);
+ }
- previousColorStyle = colorStyle;
- int sliceSeriesAdjust = 0;
- if (m_selectionDirty && m_cachedIsSlicingActivated) {
- int seriesMultiplier = 0;
- if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionMultiSeries))
- seriesMultiplier = series;
- if (rowMode)
- sliceSeriesAdjust = seriesMultiplier * m_cachedColumnCount;
- else
- sliceSeriesAdjust = seriesMultiplier * m_cachedRowCount;
- }
+ // Always use base color when no selection mode
+ if (m_cachedSelectionMode == QAbstract3DGraph::SelectionNone) {
+ if (colorStyleIsUniform)
+ barColor = baseColor;
+ else
+ gradientTexture = cache->baseGradientTexture();
+ }
- for (int row = startRow; row != stopRow; row += stepRow) {
- for (int bar = startBar; bar != stopBar; bar += stepBar) {
- BarRenderItem &item = m_renderingArrays[series][row][bar];
+ previousColorStyle = colorStyle;
- if (item.height() < 0)
- glCullFace(GL_FRONT);
- else
- glCullFace(GL_BACK);
+ for (int row = startRow; row != stopRow; row += stepRow) {
+ BarRenderItemRow &renderRow = renderArray[row];
+ for (int bar = startBar; bar != stopBar; bar += stepBar) {
+ BarRenderItem &item = renderRow[bar];
+ if (item.height() < 0)
+ glCullFace(GL_FRONT);
+ else
+ glCullFace(GL_BACK);
- QMatrix4x4 modelMatrix;
- QMatrix4x4 itModelMatrix;
- QMatrix4x4 MVPMatrix;
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 itModelMatrix;
+ 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);
- modelScaler.setY(item.height());
- if (!seriesRotation.isIdentity() || !item.rotation().isIdentity()) {
- QQuaternion totalRotation = seriesRotation * item.rotation();
- modelMatrix.rotate(totalRotation);
- itModelMatrix.rotate(totalRotation);
- }
- modelMatrix.scale(modelScaler);
- itModelMatrix.scale(modelScaler);
+ colPos = (bar + 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);
+ modelScaler.setY(item.height());
+ if (!seriesRotation.isIdentity() || !item.rotation().isIdentity()) {
+ QQuaternion totalRotation = seriesRotation * item.rotation();
+ modelMatrix.rotate(totalRotation);
+ itModelMatrix.rotate(totalRotation);
+ }
+ modelMatrix.scale(modelScaler);
+ itModelMatrix.scale(modelScaler);
#ifdef SHOW_DEPTH_TEXTURE_SCENE
- MVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ MVPMatrix = depthProjectionViewMatrix * modelMatrix;
#else
- MVPMatrix = projectionViewMatrix * modelMatrix;
+ MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
- GLfloat lightStrength = m_cachedTheme->lightStrength();
- GLfloat shadowLightStrength = adjustedLightStrength;
-
- if (m_cachedSelectionMode > QAbstract3DGraph::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 & QAbstract3DGraph::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].setItem(item);
+ GLfloat lightStrength = m_cachedTheme->lightStrength();
+ GLfloat shadowLightStrength = adjustedLightStrength;
+
+ if (m_cachedSelectionMode > QAbstract3DGraph::SelectionNone) {
+ Bars3DController::SelectionType selectionType =
+ Bars3DController::SelectionNone;
+ if (somethingSelected)
+ selectionType = isSelected(row, bar, cache);
+
+ switch (selectionType) {
+ case Bars3DController::SelectionItem: {
+ if (colorStyleIsUniform)
+ barColor = cache->singleHighlightColor();
else
- m_sliceSelection[sliceSeriesAdjust + row].setItem(item);
- }
- break;
- }
- 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].setItem(item);
+ gradientTexture = cache->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_selectedSeriesCache == cache) {
+ 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 & QAbstract3DGraph::SelectionColumn
+ && m_visibleSeriesCount > 1) {
+ translation.setZ((m_columnDepth
+ - ((row + seriesPos)
+ * (m_cachedBarSpacing.height())))
+ / m_scaleFactor);
+ }
+ item.setTranslation(translation);
+ item.setPosition(QPoint(row, bar));
+ if (rowMode)
+ cache->sliceArray()[bar].setItem(item);
+ else
+ cache->sliceArray()[row].setItem(item);
}
+ break;
}
- 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);
+ case Bars3DController::SelectionRow: {
+ // Current bar is on the same row as the selected bar
+ if (colorStyleIsUniform)
+ barColor = cache->multiHighlightColor();
+ else
+ gradientTexture = cache->multiHighlightGradientTexture();
+
+ lightStrength = m_cachedTheme->highlightLightStrength();
+ shadowLightStrength = adjustedHighlightStrength;
+ if (m_cachedIsSlicingActivated) {
+ item.setTranslation(modelMatrix.column(3).toVector3D());
+ item.setPosition(QPoint(row, bar));
+ if (m_selectionDirty) {
+ if (!m_sliceTitleItem && m_axisCacheZ.labelItems().size() > row)
+ m_sliceTitleItem = m_axisCacheZ.labelItems().at(row);
+ cache->sliceArray()[bar].setItem(item);
+ }
}
- 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].setItem(item);
+ break;
+ }
+ case Bars3DController::SelectionColumn: {
+ // Current bar is on the same column as the selected bar
+ if (colorStyleIsUniform)
+ barColor = cache->multiHighlightColor();
+ else
+ gradientTexture = cache->multiHighlightGradientTexture();
+
+ lightStrength = m_cachedTheme->highlightLightStrength();
+ shadowLightStrength = adjustedHighlightStrength;
+ if (m_cachedIsSlicingActivated) {
+ QVector3D translation = modelMatrix.column(3).toVector3D();
+ if (m_visibleSeriesCount > 1) {
+ translation.setZ((m_columnDepth
+ - ((row + seriesPos)
+ * (m_cachedBarSpacing.height())))
+ / m_scaleFactor);
+ }
+ item.setTranslation(translation);
+ item.setPosition(QPoint(row, bar));
+ if (m_selectionDirty) {
+ if (!m_sliceTitleItem && m_axisCacheX.labelItems().size() > bar)
+ m_sliceTitleItem = m_axisCacheX.labelItems().at(bar);
+ cache->sliceArray()[row].setItem(item);
+ }
}
+ break;
+ }
+ case Bars3DController::SelectionNone: {
+ // Current bar is not selected, nor on a row or column
+ if (colorStyleIsUniform)
+ barColor = baseColor;
+ else
+ gradientTexture = cache->baseGradientTexture();
+ break;
+ }
}
- break;
- }
- case Bars3DController::SelectionNone: {
- // Current bar is not selected, nor on a row or column
- if (colorStyleIsUniform)
- barColor = baseColor;
- else
- gradientTexture = currentSeries.baseGradientTexture();
- break;
- }
}
- }
- // 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);
- }
+ // 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 > QAbstract3DGraph::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);
- barShader->setUniformValue(barShader->lightColor(), lightColor);
-
- // Draw the object
- m_drawer->drawObject(barShader, barObj, gradientTexture, m_depthTexture);
- } else
+ if (m_cachedShadowQuality > QAbstract3DGraph::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);
+ barShader->setUniformValue(barShader->lightColor(), lightColor);
+
+ // Draw the object
+ m_drawer->drawObject(barShader, barObj, gradientTexture,
+ m_depthTexture);
+ } else
#else
- Q_UNUSED(shadowLightStrength);
+ Q_UNUSED(shadowLightStrength);
#endif
- {
- // Set shadowless shader bindings
- barShader->setUniformValue(barShader->lightS(), lightStrength);
+ {
+ // Set shadowless shader bindings
+ barShader->setUniformValue(barShader->lightS(), lightStrength);
- // Draw the object
- m_drawer->drawObject(barShader, barObj, gradientTexture);
+ // Draw the object
+ m_drawer->drawObject(barShader, barObj, gradientTexture);
+ }
}
}
}
}
- seriesPos += m_seriesStep;
}
- // Bind background shader
- m_backgroundShader->bind();
+ glDisable(GL_POLYGON_OFFSET_FILL);
// Reset culling
glCullFace(GL_BACK);
- // Draw background
- GLfloat rowScaleFactor = m_rowWidth / m_scaleFactor;
- GLfloat columnScaleFactor = m_columnDepth / m_scaleFactor;
+ // Bind background shader
+ m_backgroundShader->bind();
+ // Draw background
if (m_cachedTheme->isBackgroundEnabled() && m_backgroundObj) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
QVector3D backgroundScaler(rowScaleFactor, 1.0f, columnScaleFactor);
- 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.translate(0.0f, m_backgroundAdjustment, 0.0f);
+
modelMatrix.scale(backgroundScaler);
itModelMatrix.scale(backgroundScaler);
modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f);
@@ -1336,7 +1509,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
#else
MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
- QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme->backgroundColor());
+ QVector4D backgroundColor = Utils::vectorFromColor(m_cachedTheme->backgroundColor());
// Set shader bindings
m_backgroundShader->setUniformValue(m_backgroundShader->lightP(), lightPos);
@@ -1373,44 +1546,42 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
m_drawer->drawObject(m_backgroundShader, m_backgroundObj);
}
- // Draw floor for graph with negatives
- if (m_hasNegativeValues) {
- modelMatrix = QMatrix4x4();
- itModelMatrix = QMatrix4x4();
+ // Draw floor
+ modelMatrix = QMatrix4x4();
+ itModelMatrix = QMatrix4x4();
- modelMatrix.scale(backgroundScaler);
+ modelMatrix.scale(backgroundScaler);
- if (m_yFlipped)
- modelMatrix.rotate(90.0f, 1.0f, 0.0f, 0.0f);
- else
- modelMatrix.rotate(-90.0f, 1.0f, 0.0f, 0.0f);
+ 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;
+ itModelMatrix = modelMatrix;
#ifdef SHOW_DEPTH_TEXTURE_SCENE
- MVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ MVPMatrix = depthProjectionViewMatrix * modelMatrix;
#else
- MVPMatrix = projectionViewMatrix * modelMatrix;
+ 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);
+ // 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 > QAbstract3DGraph::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
+ if (m_cachedShadowQuality > QAbstract3DGraph::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);
- }
+ {
+ // Draw the object
+ m_drawer->drawObject(m_backgroundShader, m_gridLineObj);
}
}
@@ -1418,15 +1589,19 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
glDisable(GL_TEXTURE_2D);
// Draw grid lines
- if (m_cachedTheme->isGridEnabled() && m_heightNormalizer) {
+ if (m_cachedTheme->isGridEnabled()) {
+#if !(defined QT_OPENGL_ES_2)
ShaderHelper *lineShader = m_backgroundShader;
+#else
+ ShaderHelper *lineShader = m_selectionShader; // Plain color shader for GL_LINES
+#endif
QQuaternion lineRotation;
// Bind bar shader
lineShader->bind();
// Set unchanging shader bindings
- QVector3D barColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
+ QVector4D barColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
lineShader->setUniformValue(lineShader->lightP(), lightPos);
lineShader->setUniformValue(lineShader->view(), viewMatrix);
lineShader->setUniformValue(lineShader->color(), barColor);
@@ -1446,11 +1621,9 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
m_cachedTheme->lightStrength() / 2.5f);
}
- GLfloat yFloorLinePosition = 0.0f;
+ GLfloat yFloorLinePosition = gridLineOffset;
if (m_yFlipped)
- yFloorLinePosition -= gridLineOffset;
- else
- yFloorLinePosition += gridLineOffset;
+ yFloorLinePosition = -yFloorLinePosition;
QVector3D gridLineScaler(rowScaleFactor, gridLineWidth, gridLineWidth);
@@ -1488,15 +1661,19 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
// Floor lines: columns
+#if defined(QT_OPENGL_ES_2)
+ lineRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f);
+#endif
gridLineScaler = QVector3D(gridLineWidth, gridLineWidth, columnScaleFactor);
for (GLfloat bar = 0.0f; bar <= m_cachedColumnCount; bar++) {
QMatrix4x4 modelMatrix;
@@ -1526,40 +1703,31 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
if (m_axisCacheY.segmentCount() > 0) {
// Wall lines: back wall
- GLfloat heightStep = m_axisCacheY.subSegmentStep();
- GLfloat startLine = 0.0f;
- int segmentCount = m_axisCacheY.segmentCount() * m_axisCacheY.subSegmentCount();
+ int gridLineCount = m_axisCacheY.gridLineCount();
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 (int segment = 0; segment <= segmentCount; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
modelMatrix.translate(0.0f,
- 2.0f * lineHeight / m_heightNormalizer,
+ m_axisCacheY.gridLinePosition(line),
zWallLinePosition);
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
@@ -1583,13 +1751,13 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- lineHeight += heightStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
// Wall lines: side wall
@@ -1602,15 +1770,14 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
else
lineRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f);
- lineHeight = startLine;
gridLineScaler = QVector3D(gridLineWidth, gridLineWidth, columnScaleFactor);
- for (int segment = 0; segment <= segmentCount; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
modelMatrix.translate(xWallLinePosition,
- 2.0f * lineHeight / m_heightNormalizer,
+ m_axisCacheY.gridLinePosition(line),
0.0f);
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
@@ -1632,251 +1799,457 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- lineHeight += heightStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
}
}
- // Bind label shader
- m_labelShader->bind();
+ Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader, viewMatrix,
+ projectionViewMatrix, depthProjectionViewMatrix,
+ m_depthTexture, m_shadowQualityToShader);
+
+ drawLabels(false, activeCamera, viewMatrix, projectionMatrix, rowScaleFactor,
+ columnScaleFactor);
+
+ // Handle selected bar label generation
+ if (barSelectionFound) {
+ // Print value of selected bar
+ glDisable(GL_DEPTH_TEST);
+ // Draw the selection label
+ LabelItem &labelItem = selectionLabelItem();
+ if (m_selectedBar != selectedBar || m_updateLabels || !labelItem.textureId()
+ || m_selectionLabelDirty) {
+ QString labelText = selectionLabel();
+ if (labelText.isNull() || m_selectionLabelDirty) {
+ labelText = m_selectedSeriesCache->itemLabel();
+ setSelectionLabel(labelText);
+ m_selectionLabelDirty = false;
+ }
+ m_drawer->generateLabelItem(labelItem, labelText);
+ m_selectedBar = selectedBar;
+ }
+
+ Drawer::LabelPosition position =
+ m_selectedBar->height() >= 0 ? Drawer::LabelOver : Drawer::LabelBelow;
+
+ m_drawer->drawLabel(*selectedBar, labelItem, viewMatrix, projectionMatrix,
+ zeroVector, identityQuaternion, selectedBar->height(),
+ m_cachedSelectionMode, m_labelShader,
+ m_labelObj, activeCamera, true, false, position);
+
+ // Reset label update flag; they should have been updated when we get here
+ m_updateLabels = false;
+
+ glEnable(GL_DEPTH_TEST);
+ } else {
+ m_selectedBar = 0;
+ }
+
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+
+ // Release shader
+ glUseProgram(0);
+ m_selectionDirty = false;
+}
+
+void Bars3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCamera,
+ const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionMatrix,
+ GLfloat rowScaleFactor, GLfloat columnScaleFactor) {
+ ShaderHelper *shader = 0;
+ GLfloat alphaForValueSelection = labelValueAlpha / 255.0f;
+ GLfloat alphaForRowSelection = labelRowAlpha / 255.0f;
+ GLfloat alphaForColumnSelection = labelColumnAlpha / 255.0f;
+ if (drawSelection) {
+ shader = m_selectionShader;
+ // m_selectionShader is already bound
+ } else {
+ shader = m_labelShader;
+ shader->bind();
+
+ glEnable(GL_TEXTURE_2D);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
- glEnable(GL_TEXTURE_2D);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_POLYGON_OFFSET_FILL);
+ float labelAutoAngle = m_axisCacheY.labelAutoRotation();
+ float labelAngleFraction = labelAutoAngle / 90.0f;
+ float fractionCamY = activeCamera->yRotation() * labelAngleFraction;
+ float fractionCamX = activeCamera->xRotation() * labelAngleFraction;
+ float labelsMaxWidth = 0.0f;
+
+ int startIndex;
+ int endIndex;
+ int indexStep;
+
// Y Labels
- int labelNbr = 0;
- GLfloat heightStep = m_axisCacheY.segmentStep();
- GLfloat startLine = 0.0f;
- int labelCount = m_axisCacheY.labels().size();
- if (m_hasNegativeValues) {
- if (m_noZeroInRange)
- startLine = m_axisCacheY.min() - m_axisCacheY.max();
- else
- startLine = m_axisCacheY.min();
- }
- GLfloat labelPos = startLine;
+ int labelCount = m_axisCacheY.labelCount();
GLfloat labelMarginXTrans = labelMargin;
GLfloat labelMarginZTrans = labelMargin;
GLfloat labelXTrans = rowScaleFactor;
GLfloat labelZTrans = columnScaleFactor;
QVector3D backLabelRotation(0.0f, -90.0f, 0.0f);
QVector3D sideLabelRotation(0.0f, 0.0f, 0.0f);
- Qt::AlignmentFlag backAlignment = Qt::AlignLeft;
- Qt::AlignmentFlag sideAlignment = Qt::AlignLeft;
+ Qt::AlignmentFlag backAlignment = (m_xFlipped != m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight;
+ Qt::AlignmentFlag sideAlignment = (m_xFlipped == m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight;
+
if (!m_xFlipped) {
labelXTrans = -labelXTrans;
labelMarginXTrans = -labelMargin;
- backLabelRotation.setY(90.0f);
- sideAlignment = Qt::AlignRight;
}
if (m_zFlipped) {
labelZTrans = -labelZTrans;
labelMarginZTrans = -labelMargin;
- backAlignment = Qt::AlignRight;
- sideLabelRotation.setY(180.f);
}
+
+ if (labelAutoAngle == 0.0f) {
+ if (!m_xFlipped)
+ backLabelRotation.setY(90.0f);
+ if (m_zFlipped)
+ sideLabelRotation.setY(180.f);
+ } else {
+ // Orient side labels somewhat towards the camera
+ if (m_xFlipped) {
+ if (m_zFlipped)
+ sideLabelRotation.setY(180.0f + (2.0f * labelAutoAngle) - fractionCamX);
+ else
+ sideLabelRotation.setY(-fractionCamX);
+ backLabelRotation.setY(-90.0f + labelAutoAngle - fractionCamX);
+ } else {
+ if (m_zFlipped)
+ sideLabelRotation.setY(180.0f - (2.0f * labelAutoAngle) - fractionCamX);
+ else
+ sideLabelRotation.setY(-fractionCamX);
+ backLabelRotation.setY(90.0f - labelAutoAngle - fractionCamX);
+ }
+ }
+ sideLabelRotation.setX(-fractionCamY);
+ backLabelRotation.setX(-fractionCamY);
+
+ QQuaternion totalSideRotation = Utils::calculateRotation(sideLabelRotation);
+ QQuaternion totalBackRotation = Utils::calculateRotation(backLabelRotation);
+
QVector3D backLabelTrans = QVector3D(labelXTrans, 0.0f,
labelZTrans + labelMarginZTrans);
QVector3D sideLabelTrans = QVector3D(-labelXTrans - labelMarginXTrans,
0.0f, -labelZTrans);
- for (int i = 0; i < labelCount; i++) {
- if (m_axisCacheY.labelItems().size() > labelNbr) {
- backLabelTrans.setY(2.0f * labelPos / m_heightNormalizer);
- sideLabelTrans.setY(backLabelTrans.y());
-
- glPolygonOffset(GLfloat(i) / -10.0f, 1.0f);
+ if (m_yFlipped) {
+ startIndex = labelCount - 1;
+ endIndex = -1;
+ indexStep = -1;
+ } else {
+ startIndex = 0;
+ endIndex = labelCount;
+ indexStep = 1;
+ }
+ for (int i = startIndex; i != endIndex; i = i + indexStep) {
+ backLabelTrans.setY(m_axisCacheY.labelPosition(i));
+ sideLabelTrans.setY(backLabelTrans.y());
- const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr);
+ glPolygonOffset(GLfloat(i) / -10.0f, 1.0f);
- // Back wall
- m_dummyBarRenderItem.setTranslation(backLabelTrans);
- m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- zeroVector, backLabelRotation, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, activeCamera,
- true, true, Drawer::LabelMid, backAlignment);
+ const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(i);
- // Side wall
- m_dummyBarRenderItem.setTranslation(sideLabelTrans);
- m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- zeroVector, sideLabelRotation, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, activeCamera,
- true, true, Drawer::LabelMid, sideAlignment);
+ if (drawSelection) {
+ QVector4D labelColor = QVector4D(0.0f, 0.0f, i / 255.0f,
+ alphaForValueSelection);
+ shader->setUniformValue(shader->color(), labelColor);
}
- labelNbr++;
- labelPos += heightStep;
+
+ // Back wall
+ m_dummyBarRenderItem.setTranslation(backLabelTrans);
+ m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
+ zeroVector, totalBackRotation, 0, m_cachedSelectionMode,
+ shader, m_labelObj, activeCamera,
+ true, true, Drawer::LabelMid, backAlignment, false, drawSelection);
+
+ // Side wall
+ m_dummyBarRenderItem.setTranslation(sideLabelTrans);
+ m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
+ zeroVector, totalSideRotation, 0, m_cachedSelectionMode,
+ shader, m_labelObj, activeCamera,
+ true, true, Drawer::LabelMid, sideAlignment, false, drawSelection);
+
+ labelsMaxWidth = qMax(labelsMaxWidth, float(axisLabelItem.size().width()));
+ }
+
+ if (!drawSelection && m_axisCacheY.isTitleVisible()) {
+ sideLabelTrans.setY(m_backgroundAdjustment);
+ backLabelTrans.setY(m_backgroundAdjustment);
+ drawAxisTitleY(sideLabelRotation, backLabelRotation, sideLabelTrans, backLabelTrans,
+ totalSideRotation, totalBackRotation, m_dummyBarRenderItem, activeCamera,
+ labelsMaxWidth, viewMatrix, projectionMatrix, shader);
}
+ // Z labels
// Calculate the positions for row and column labels and store them
+ labelsMaxWidth = 0.0f;
+ labelAutoAngle = m_axisCacheZ.labelAutoRotation();
+ labelAngleFraction = labelAutoAngle / 90.0f;
+ fractionCamY = activeCamera->yRotation() * labelAngleFraction;
+ fractionCamX = activeCamera->xRotation() * labelAngleFraction;
GLfloat labelYAdjustment = 0.005f;
GLfloat scaledRowWidth = rowScaleFactor;
GLfloat scaledColumnDepth = columnScaleFactor;
GLfloat colPosValue = scaledRowWidth + labelMargin;
GLfloat rowPosValue = scaledColumnDepth + labelMargin;
- QVector3D labelRotation(-90.0f, 0.0f, 0.0f);
- if (m_zFlipped)
- labelRotation.setY(180.0f);
- if (m_yFlipped) {
+ GLfloat rowPos = 0.0f;
+ GLfloat colPos = 0.0f;
+ Qt::AlignmentFlag alignment = (m_xFlipped == m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight;
+ QVector3D labelRotation;
+
+ if (labelAutoAngle == 0.0f) {
+ labelRotation.setX(-90.0f);
if (m_zFlipped)
- labelRotation.setY(0.0f);
- else
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_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
- rowPos = (row + 0.5f) * m_cachedBarSpacing.height();
- if (m_xFlipped)
- colPos = -colPosValue;
+ if (m_yFlipped) {
+ if (m_zFlipped)
+ labelRotation.setY(0.0f);
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_axisCacheZ.labelItems().at(row);
-
- m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- zeroVector, labelRotation, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, activeCamera,
- true, true, Drawer::LabelMid, alignment, m_cachedIsSlicingActivated);
+ labelRotation.setY(180.0f);
+ labelRotation.setZ(180.0f);
+ }
+ } else {
+ if (m_zFlipped)
+ labelRotation.setY(180.0f);
+ if (m_yFlipped) {
+ if (m_zFlipped) {
+ if (m_xFlipped) {
+ labelRotation.setX(90.0f - (labelAutoAngle - fractionCamX)
+ * (-labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle + fractionCamY);
+ } else {
+ labelRotation.setX(90.0f + (labelAutoAngle + fractionCamX)
+ * (labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle - fractionCamY);
+ }
+ } else {
+ if (m_xFlipped) {
+ labelRotation.setX(90.0f + (labelAutoAngle - fractionCamX)
+ * -(labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle - fractionCamY);
+ } else {
+ labelRotation.setX(90.0f - (labelAutoAngle + fractionCamX)
+ * (labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle + fractionCamY);
+ }
+ }
+ } else {
+ if (m_zFlipped) {
+ if (m_xFlipped) {
+ labelRotation.setX(-90.0f + (labelAutoAngle - fractionCamX)
+ * (-labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle + fractionCamY);
+ } else {
+ labelRotation.setX(-90.0f - (labelAutoAngle + fractionCamX)
+ * (labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle - fractionCamY);
+ }
+ } else {
+ if (m_xFlipped) {
+ labelRotation.setX(-90.0f - (labelAutoAngle - fractionCamX)
+ * (-labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle - fractionCamY);
+ } else {
+ labelRotation.setX(-90.0f + (labelAutoAngle + fractionCamX)
+ * (labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle + fractionCamY);
+ }
+ }
}
}
- labelRotation = QVector3D(-90.0f, 90.0f, 0.0f);
- if (m_xFlipped)
- labelRotation.setY(-90.0f);
- if (m_yFlipped) {
+
+ QQuaternion totalRotation = Utils::calculateRotation(labelRotation);
+ labelCount = qMin(m_axisCacheZ.labelCount(), m_cachedRowCount);
+ if (m_zFlipped) {
+ startIndex = 0;
+ endIndex = labelCount;
+ indexStep = 1;
+ } else {
+ startIndex = labelCount - 1;
+ endIndex = -1;
+ indexStep = -1;
+ }
+ for (int row = startIndex; row != endIndex; row = row + indexStep) {
+ // 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
+ rowPos = (row + 0.5f) * m_cachedBarSpacing.height();
if (m_xFlipped)
- labelRotation.setY(90.0f);
+ colPos = -colPosValue;
else
- labelRotation.setY(-90.0f);
- labelRotation.setZ(180.0f);
- }
-
- alignment = m_zFlipped ? Qt::AlignRight : Qt::AlignLeft;
- 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
- colPos = (column + 0.5f) * m_cachedBarSpacing.width();
- if (m_zFlipped)
- rowPos = -rowPosValue;
- else
- rowPos = rowPosValue;
+ colPos = colPosValue;
- glPolygonOffset(GLfloat(column) / -10.0f, 1.0f);
+ glPolygonOffset(GLfloat(row) / -10.0f, 1.0f);
- QVector3D labelPos = QVector3D((colPos - m_rowWidth) / m_scaleFactor,
- labelYAdjustment, // raise a bit over background to avoid depth "glimmering"
- rowPos);
+ 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(column);
+ m_dummyBarRenderItem.setTranslation(labelPos);
+ const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(row);
- m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- zeroVector, labelRotation, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, activeCamera,
- true, true, Drawer::LabelMid, alignment);
+ if (drawSelection) {
+ QVector4D labelColor = QVector4D(row / 255.0f, 0.0f, 0.0f, alphaForRowSelection);
+ shader->setUniformValue(shader->color(), labelColor);
}
+
+ m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
+ zeroVector, totalRotation, 0, m_cachedSelectionMode,
+ shader, m_labelObj, activeCamera,
+ true, true, Drawer::LabelMid, alignment,
+ false, drawSelection);
+ labelsMaxWidth = qMax(labelsMaxWidth, float(axisLabelItem.size().width()));
}
- glDisable(GL_POLYGON_OFFSET_FILL);
+ if (!drawSelection && m_axisCacheZ.isTitleVisible()) {
+ QVector3D titleTrans(colPos, 0.0f, 0.0f);
+ drawAxisTitleZ(labelRotation, titleTrans, totalRotation, m_dummyBarRenderItem,
+ activeCamera, labelsMaxWidth, viewMatrix, projectionMatrix, shader);
+ }
- // Handle selected bar label generation
- if (barSelectionFound) {
- // Print value of selected bar
- glDisable(GL_DEPTH_TEST);
- // Draw the selection label
- LabelItem &labelItem = selectionLabelItem();
- if (m_selectedBar != selectedBar || m_updateLabels || !labelItem.textureId()
- || m_selectionLabelDirty) {
- QString labelText = selectionLabel();
- if (labelText.isNull() || m_selectionLabelDirty) {
- static const QString rowIndexTag(QStringLiteral("@rowIdx"));
- static const QString rowLabelTag(QStringLiteral("@rowLabel"));
- static const QString rowTitleTag(QStringLiteral("@rowTitle"));
- static const QString colIndexTag(QStringLiteral("@colIdx"));
- static const QString colLabelTag(QStringLiteral("@colLabel"));
- static const QString colTitleTag(QStringLiteral("@colTitle"));
- static const QString valueTitleTag(QStringLiteral("@valueTitle"));
- static const QString valueLabelTag(QStringLiteral("@valueLabel"));
- static const QString seriesNameTag(QStringLiteral("@seriesName"));
-
- // Custom format expects printf format specifier. There is no tag for it.
- 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_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_axisCacheX.title());
- labelText.replace(valueTitleTag, m_axisCacheY.title());
-
- if (labelText.contains(valueLabelTag)) {
- QString labelFormat = m_axisCacheY.labelFormat();
- if (labelFormat.isEmpty())
- labelFormat = Utils::defaultLabelFormat();
- QString valueLabelText = generateValueLabel(labelFormat, selectedBar->value());
- labelText.replace(valueLabelTag, valueLabelText);
+ // X labels
+ labelsMaxWidth = 0.0f;
+ labelAutoAngle = m_axisCacheX.labelAutoRotation();
+ labelAngleFraction = labelAutoAngle / 90.0f;
+ fractionCamY = activeCamera->yRotation() * labelAngleFraction;
+ fractionCamX = activeCamera->xRotation() * labelAngleFraction;
+ alignment = (m_xFlipped != m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight;
+ if (labelAutoAngle == 0.0f) {
+ labelRotation = QVector3D(-90.0f, 90.0f, 0.0f);
+ if (m_xFlipped)
+ labelRotation.setY(-90.0f);
+ if (m_yFlipped) {
+ if (m_xFlipped)
+ labelRotation.setY(90.0f);
+ else
+ labelRotation.setY(-90.0f);
+ labelRotation.setZ(180.0f);
+ }
+ } else {
+ if (m_xFlipped)
+ labelRotation.setY(-90.0f);
+ else
+ labelRotation.setY(90.0f);
+ if (m_yFlipped) {
+ if (m_zFlipped) {
+ if (m_xFlipped) {
+ labelRotation.setX(90.0f - (2.0f * labelAutoAngle - fractionCamX)
+ * (labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle - fractionCamY);
+ } else {
+ labelRotation.setX(90.0f - (2.0f * labelAutoAngle + fractionCamX)
+ * (labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle + fractionCamY);
+ }
+ } else {
+ if (m_xFlipped) {
+ labelRotation.setX(90.0f + fractionCamX
+ * -(labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle + fractionCamY);
+ } else {
+ labelRotation.setX(90.0f - fractionCamX
+ * (-labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle - fractionCamY);
+ }
+ }
+ } else {
+ if (m_zFlipped) {
+ if (m_xFlipped) {
+ labelRotation.setX(-90.0f + (2.0f * labelAutoAngle - fractionCamX)
+ * (labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle - fractionCamY);
+ } else {
+ labelRotation.setX(-90.0f + (2.0f * labelAutoAngle + fractionCamX)
+ * (labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle + fractionCamY);
+ }
+ } else {
+ if (m_xFlipped) {
+ labelRotation.setX(-90.0f - fractionCamX
+ * (-labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle + fractionCamY);
+ } else {
+ labelRotation.setX(-90.0f + fractionCamX
+ * -(labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle - fractionCamY);
}
-
- labelText.replace(seriesNameTag,
- m_visibleSeriesList[m_visualSelectedBarSeriesIndex].name());
-
- setSelectionLabel(labelText);
- m_selectionLabelDirty = false;
}
- m_drawer->generateLabelItem(labelItem, labelText);
- m_selectedBar = selectedBar;
}
+ }
- m_drawer->drawLabel(*selectedBar, labelItem, viewMatrix, projectionMatrix,
- zeroVector, zeroVector, selectedBar->height(),
- m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera, true, false);
-
- // Reset label update flag; they should have been updated when we get here
- m_updateLabels = false;
-
- glEnable(GL_DEPTH_TEST);
+ totalRotation = Utils::calculateRotation(labelRotation);
+ labelCount = qMin(m_axisCacheX.labelCount(), m_cachedColumnCount);
+ if (m_xFlipped) {
+ startIndex = labelCount - 1;
+ endIndex = -1;
+ indexStep = -1;
} else {
- m_selectedBar = 0;
+ startIndex = 0;
+ endIndex = labelCount;
+ indexStep = 1;
}
+ for (int column = startIndex; column != endIndex; column = column + indexStep) {
+ // 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
+ colPos = (column + 0.5f) * m_cachedBarSpacing.width();
+ if (m_zFlipped)
+ rowPos = -rowPosValue;
+ else
+ rowPos = rowPosValue;
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_BLEND);
+ glPolygonOffset(GLfloat(column) / -10.0f, 1.0f);
- // Release shader
- glUseProgram(0);
+ QVector3D labelPos = QVector3D((colPos - m_rowWidth) / m_scaleFactor,
+ labelYAdjustment, // raise a bit over background to avoid depth "glimmering"
+ rowPos);
- m_selectionDirty = false;
+ m_dummyBarRenderItem.setTranslation(labelPos);
+ const LabelItem &axisLabelItem = *m_axisCacheX.labelItems().at(column);
+
+ if (drawSelection) {
+ QVector4D labelColor = QVector4D(0.0f, column / 255.0f, 0.0f,
+ alphaForColumnSelection);
+ shader->setUniformValue(shader->color(), labelColor);
+ }
+
+ m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
+ zeroVector, totalRotation, 0, m_cachedSelectionMode,
+ shader, m_labelObj, activeCamera,
+ true, true, Drawer::LabelMid, alignment, false, drawSelection);
+ labelsMaxWidth = qMax(labelsMaxWidth, float(axisLabelItem.size().width()));
+ }
+
+ if (!drawSelection && m_axisCacheX.isTitleVisible()) {
+ QVector3D titleTrans(0.0f, 0.0f, rowPos);
+ drawAxisTitleX(labelRotation, titleTrans, totalRotation, m_dummyBarRenderItem,
+ activeCamera, labelsMaxWidth, viewMatrix, projectionMatrix, shader);
+ }
+
+#if 0 // Debug label
+ static LabelItem debugLabelItem;
+ QString debugLabelString(QStringLiteral("Flips: x:%1 y:%2 z:%3 xr:%4 yr:%5"));
+ QString finalDebugString = debugLabelString.arg(m_xFlipped).arg(m_yFlipped).arg(m_zFlipped)
+ .arg(activeCamera->xRotation()).arg(activeCamera->yRotation());
+ m_dummyBarRenderItem.setTranslation(QVector3D(m_xFlipped ? -1.5f : 1.5f,
+ m_yFlipped ? 1.5f : -1.5f,
+ m_zFlipped ? -1.5f : 1.5f));
+
+ m_drawer->generateLabelItem(debugLabelItem, finalDebugString);
+ m_drawer->drawLabel(m_dummyBarRenderItem, debugLabelItem, viewMatrix, projectionMatrix,
+ zeroVector, identityQuaternion, 0, m_cachedSelectionMode,
+ shader, m_labelObj, activeCamera,
+ true, false, Drawer::LabelMid, Qt::AlignHCenter, false, drawSelection);
+#endif
+ glDisable(GL_POLYGON_OFFSET_FILL);
}
void Bars3DRenderer::updateMultiSeriesScaling(bool uniform)
@@ -1884,7 +2257,7 @@ void Bars3DRenderer::updateMultiSeriesScaling(bool uniform)
m_keepSeriesUniform = uniform;
// Recalculate scale factors
- m_seriesScaleX = 1.0f / float(m_visibleSeriesList.size());
+ m_seriesScaleX = 1.0f / float(m_visibleSeriesCount);
if (m_keepSeriesUniform)
m_seriesScaleZ = m_seriesScaleX;
else
@@ -1920,46 +2293,41 @@ void Bars3DRenderer::updateAxisRange(QAbstract3DAxis::AxisOrientation orientatio
Abstract3DRenderer::updateAxisRange(orientation, min, max);
if (orientation == QAbstract3DAxis::AxisOrientationY) {
- calculateHeightAdjustment();
// Check if we have negative values
- if (min < 0 && !m_hasNegativeValues) {
+ if (min < 0)
m_hasNegativeValues = true;
- // Reload background
- loadBackgroundMesh();
- emit needRender();
- } else if (min >= 0 && m_hasNegativeValues) {
+ else if (min >= 0)
m_hasNegativeValues = false;
- // Reload background
- loadBackgroundMesh();
- emit needRender();
- }
+ calculateHeightAdjustment();
}
}
-void Bars3DRenderer::updateSelectedBar(const QPoint &position, const QBar3DSeries *series)
+void Bars3DRenderer::updateAxisReversed(QAbstract3DAxis::AxisOrientation orientation, bool enable)
+{
+ Abstract3DRenderer::updateAxisReversed(orientation, enable);
+ if (orientation == QAbstract3DAxis::AxisOrientationY)
+ calculateHeightAdjustment();
+}
+
+
+void Bars3DRenderer::updateSelectedBar(const QPoint &position, QBar3DSeries *series)
{
m_selectedBarPos = position;
- m_selectedBarSeries = series;
+ m_selectedSeriesCache = static_cast<BarSeriesRenderCache *>(m_renderCacheList.value(series, 0));
m_selectionDirty = true;
m_selectionLabelDirty = true;
- m_visualSelectedBarSeriesIndex = -1;
- if (m_renderingArrays.isEmpty()) {
+ if (!m_selectedSeriesCache
+ || !m_selectedSeriesCache->isVisible()
+ || m_selectedSeriesCache->renderArray().isEmpty()) {
m_visualSelectedBarPos = Bars3DController::invalidSelectionPosition();
return;
}
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;
- }
- }
+ int maxZ = m_selectedSeriesCache->renderArray().size() - 1;
+ int maxX = maxZ >= 0 ? m_selectedSeriesCache->renderArray().at(0).size() - 1 : -1;
if (m_selectedBarPos == Bars3DController::invalidSelectionPosition()
|| adjustedZ < 0 || adjustedZ > maxZ
@@ -2020,29 +2388,8 @@ void Bars3DRenderer::updateShadowQuality(QAbstract3DGraph::ShadowQuality quality
void Bars3DRenderer::loadBackgroundMesh()
{
- if (m_backgroundObj)
- delete m_backgroundObj;
- if (m_hasNegativeValues)
- m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/negativeBackground"));
- else
- m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/background"));
- m_backgroundObj->load();
-}
-
-void Bars3DRenderer::loadGridLineMesh()
-{
- if (m_gridLineObj)
- delete m_gridLineObj;
- m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
- m_gridLineObj->load();
-}
-
-void Bars3DRenderer::loadLabelMesh()
-{
- if (m_labelObj)
- delete m_labelObj;
- m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
- m_labelObj->load();
+ ObjectHelper::resetObjectHelper(this, m_backgroundObj,
+ QStringLiteral(":/defaultMeshes/backgroundNoFloor"));
}
void Bars3DRenderer::updateTextures()
@@ -2075,7 +2422,7 @@ void Bars3DRenderer::calculateSceneScalingFactors()
void Bars3DRenderer::calculateHeightAdjustment()
{
- GLfloat newAdjustment = 0.0f;
+ GLfloat newAdjustment = 1.0f;
GLfloat maxAbs = qFabs(m_axisCacheY.max());
if (m_axisCacheY.max() < 0.0f) {
@@ -2086,7 +2433,8 @@ void Bars3DRenderer::calculateHeightAdjustment()
}
// Height fractions are used in gradient calculations and are therefore doubled
- if (m_axisCacheY.max() < 0.0f || m_axisCacheY.min() > 0.0f) {
+ // Note that if max or min is exactly zero, we still consider it outside the range
+ if (m_axisCacheY.max() <= 0.0f || m_axisCacheY.min() >= 0.0f) {
m_noZeroInRange = true;
m_gradientFraction = 2.0f;
} else {
@@ -2095,22 +2443,24 @@ void Bars3DRenderer::calculateHeightAdjustment()
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;
+ // Calculate translation adjustment for background floor
+ newAdjustment = (qBound(0.0f, (maxAbs / m_heightNormalizer), 1.0f) - 0.5f) * 2.0f;
+ if (m_axisCacheY.reversed())
+ newAdjustment = -newAdjustment;
- if (newAdjustment != m_negativeBackgroundAdjustment) {
- m_hasHeightAdjustmentChanged = true;
- m_negativeBackgroundAdjustment = newAdjustment;
+ if (newAdjustment != m_backgroundAdjustment) {
+ m_backgroundAdjustment = newAdjustment;
+ m_axisCacheY.setTranslate(m_backgroundAdjustment - 1.0f);
}
}
-Bars3DController::SelectionType Bars3DRenderer::isSelected(int row, int bar, int seriesIndex)
+Bars3DController::SelectionType Bars3DRenderer::isSelected(int row, int bar,
+ const BarSeriesRenderCache *cache)
{
Bars3DController::SelectionType isSelectedType = Bars3DController::SelectionNone;
if ((m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionMultiSeries)
- && m_visualSelectedBarSeriesIndex >= 0)
- || seriesIndex == m_visualSelectedBarSeriesIndex) {
+ && m_selectedSeriesCache) || cache == m_selectedSeriesCache) {
if (row == m_visualSelectedBarPos.x() && bar == m_visualSelectedBarPos.y()
&& (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionItem))) {
isSelectedType = Bars3DController::SelectionItem;
@@ -2126,24 +2476,68 @@ Bars3DController::SelectionType Bars3DRenderer::isSelected(int row, int bar, int
return isSelectedType;
}
-QPoint Bars3DRenderer::selectionColorToArrayPosition(const QVector3D &selectionColor)
+QPoint Bars3DRenderer::selectionColorToArrayPosition(const QVector4D &selectionColor)
{
- QPoint position;
- if (selectionColor == selectionSkipColor) {
- position = Bars3DController::invalidSelectionPosition();
- } else {
+ QPoint position = Bars3DController::invalidSelectionPosition();
+ m_clickedType = QAbstract3DGraph::ElementNone;
+ m_selectedLabelIndex = -1;
+ m_selectedCustomItemIndex = -1;
+ if (selectionColor.w() == itemAlpha) {
+ // Normal selection item
position = QPoint(int(selectionColor.x() + int(m_axisCacheZ.min())),
int(selectionColor.y()) + int(m_axisCacheX.min()));
+ // Pass item clicked info to input handler
+ m_clickedType = QAbstract3DGraph::ElementSeries;
+ } else if (selectionColor.w() == labelRowAlpha) {
+ // Row selection
+ if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow)) {
+ // Use column from previous selection in case we have row + column mode
+ GLint previousCol = qMax(0, m_selectedBarPos.y()); // Use 0 if previous is invalid
+ position = QPoint(int(selectionColor.x() + int(m_axisCacheZ.min())), previousCol);
+ }
+ m_selectedLabelIndex = selectionColor.x();
+ // Pass label clicked info to input handler
+ m_clickedType = QAbstract3DGraph::ElementAxisZLabel;
+ } else if (selectionColor.w() == labelColumnAlpha) {
+ // Column selection
+ if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionColumn)) {
+ // Use row from previous selection in case we have row + column mode
+ GLint previousRow = qMax(0, m_selectedBarPos.x()); // Use 0 if previous is invalid
+ position = QPoint(previousRow, int(selectionColor.y()) + int(m_axisCacheX.min()));
+ }
+ m_selectedLabelIndex = selectionColor.y();
+ // Pass label clicked info to input handler
+ m_clickedType = QAbstract3DGraph::ElementAxisXLabel;
+ } else if (selectionColor.w() == labelValueAlpha) {
+ // Value selection
+ position = Bars3DController::invalidSelectionPosition();
+ m_selectedLabelIndex = selectionColor.z();
+ // Pass label clicked info to input handler
+ m_clickedType = QAbstract3DGraph::ElementAxisYLabel;
+ } else if (selectionColor.w() == customItemAlpha) {
+ // Custom item selection
+ position = Bars3DController::invalidSelectionPosition();
+ m_selectedCustomItemIndex = int(selectionColor.x())
+ + (int(selectionColor.y()) << 8)
+ + (int(selectionColor.z()) << 16);
+ m_clickedType = QAbstract3DGraph::ElementCustomItem;
}
return position;
}
-QBar3DSeries *Bars3DRenderer::selectionColorToSeries(const QVector3D &selectionColor)
+QBar3DSeries *Bars3DRenderer::selectionColorToSeries(const QVector4D &selectionColor)
{
- if (selectionColor == selectionSkipColor)
+ if (selectionColor == selectionSkipColor) {
return 0;
- else
- return static_cast<QBar3DSeries *>(m_visibleSeriesList.at(int(selectionColor.z())).series());
+ } else {
+ int seriesIndexFromColor(selectionColor.z());
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ BarSeriesRenderCache *cache = static_cast<BarSeriesRenderCache *>(baseCache);
+ if (cache->visualIndex() == seriesIndexFromColor)
+ return cache->series();
+ }
+ }
+ return 0;
}
void Bars3DRenderer::updateSlicingActive(bool isSlicing)
@@ -2190,10 +2584,7 @@ void Bars3DRenderer::initSelectionShader()
void Bars3DRenderer::initSelectionBuffer()
{
- if (m_selectionTexture) {
- m_textureHelper->deleteTexture(&m_selectionTexture);
- m_selectionTexture = 0;
- }
+ m_textureHelper->deleteTexture(&m_selectionTexture);
if (m_cachedIsSlicingActivated || m_primarySubViewport.size().isEmpty())
return;
@@ -2215,10 +2606,7 @@ void Bars3DRenderer::initDepthShader()
void Bars3DRenderer::updateDepthBuffer()
{
- if (m_depthTexture) {
- m_textureHelper->deleteTexture(&m_depthTexture);
- m_depthTexture = 0;
- }
+ m_textureHelper->deleteTexture(&m_depthTexture);
if (m_primarySubViewport.size().isEmpty())
return;
@@ -2250,4 +2638,29 @@ void Bars3DRenderer::initLabelShaders(const QString &vertexShader, const QString
m_labelShader->initialize();
}
+QVector3D Bars3DRenderer::convertPositionToTranslation(const QVector3D &position, bool isAbsolute)
+{
+ float xTrans = 0.0f;
+ float yTrans = 0.0f;
+ float zTrans = 0.0f;
+ if (!isAbsolute) {
+ // Convert row and column to translation on graph
+ xTrans = (((position.x() + 0.5f) * m_cachedBarSpacing.width()) - m_rowWidth)
+ / m_scaleFactor;
+ zTrans = (m_columnDepth - ((position.z() + 0.5f) * m_cachedBarSpacing.height()))
+ / m_scaleFactor;
+ yTrans = m_axisCacheY.positionAt(position.y());
+ } else {
+ xTrans = position.x() * m_scaleX;
+ yTrans = position.y() + m_backgroundAdjustment;
+ zTrans = position.z() * m_scaleZ;
+ }
+ return QVector3D(xTrans, yTrans, zTrans);
+}
+
+void Bars3DRenderer::updateAspectRatio(float ratio)
+{
+ Q_UNUSED(ratio)
+}
+
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/bars3drenderer_p.h b/src/datavisualization/engine/bars3drenderer_p.h
index 37ac2b76..3a0ab3b8 100644
--- a/src/datavisualization/engine/bars3drenderer_p.h
+++ b/src/datavisualization/engine/bars3drenderer_p.h
@@ -32,19 +32,17 @@
#include "datavisualizationglobal_p.h"
#include "bars3dcontroller_p.h"
#include "abstract3drenderer_p.h"
-#include "qbardataproxy.h"
#include "barrenderitem_p.h"
class QPoint;
class QSizeF;
-class QOpenGLShaderProgram;
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
class ShaderHelper;
-class ObjectHelper;
class LabelItem;
class Q3DScene;
+class BarSeriesRenderCache;
class QT_DATAVISUALIZATION_EXPORT Bars3DRenderer : public Abstract3DRenderer
{
@@ -60,12 +58,8 @@ private:
// Internal state
BarRenderItem *m_selectedBar; // points to renderitem array
- QVector<BarRenderSliceItem> m_sliceSelection;
AxisRenderCache *m_sliceCache; // not owned
const LabelItem *m_sliceTitleItem; // not owned
- bool m_xFlipped;
- bool m_zFlipped;
- bool m_yFlipped;
bool m_updateLabels;
ShaderHelper *m_barShader;
ShaderHelper *m_barGradientShader;
@@ -73,9 +67,6 @@ private:
ShaderHelper *m_selectionShader;
ShaderHelper *m_backgroundShader;
ShaderHelper *m_labelShader;
- ObjectHelper *m_backgroundObj;
- ObjectHelper *m_gridLineObj;
- ObjectHelper *m_labelObj;
GLuint m_bgrTexture;
GLuint m_depthTexture;
GLuint m_selectionTexture;
@@ -86,7 +77,7 @@ private:
GLint m_shadowQualityMultiplier;
GLfloat m_heightNormalizer;
GLfloat m_gradientFraction;
- GLfloat m_negativeBackgroundAdjustment;
+ GLfloat m_backgroundAdjustment;
GLfloat m_rowWidth;
GLfloat m_columnDepth;
GLfloat m_maxDimension;
@@ -95,12 +86,10 @@ private:
GLfloat m_scaleFactor;
GLfloat m_maxSceneSize;
QPoint m_visualSelectedBarPos;
- int m_visualSelectedBarSeriesIndex;
- bool m_hasHeightAdjustmentChanged;
+ bool m_resetCameraBaseOrientation;
QPoint m_selectedBarPos;
- const QBar3DSeries *m_selectedBarSeries;
+ BarSeriesRenderCache *m_selectedSeriesCache;
BarRenderItem m_dummyBarRenderItem;
- QVector<BarRenderItemArray> m_renderingArrays;
bool m_noZeroInRange;
float m_seriesScaleX;
float m_seriesScaleZ;
@@ -108,15 +97,26 @@ private:
float m_seriesStart;
QPoint m_clickedPosition;
bool m_keepSeriesUniform;
+ bool m_haveUniformColorSeries;
+ bool m_haveGradientSeries;
+ float m_zeroPosition;
public:
explicit Bars3DRenderer(Bars3DController *controller);
~Bars3DRenderer();
void updateData();
+ void updateSeries(const QList<QAbstract3DSeries *> &seriesList);
+ SeriesRenderCache *createNewCache(QAbstract3DSeries *series);
+ void updateRows(const QVector<Bars3DController::ChangeRow> &rows);
+ void updateItems(const QVector<Bars3DController::ChangeItem> &items);
void updateScene(Q3DScene *scene);
void render(GLuint defaultFboHandle = 0);
+ QVector3D convertPositionToTranslation(const QVector3D &position, bool isAbsolute);
+
+ void updateAspectRatio(float ratio);
+
protected:
virtual void initializeOpenGL();
@@ -126,13 +126,15 @@ public slots:
const QSizeF &spacing = QSizeF(1.0, 1.0),
bool relative = true);
void updateSlicingActive(bool isSlicing);
- void updateSelectedBar(const QPoint &position, const QBar3DSeries *series);
+ void updateSelectedBar(const QPoint &position, QBar3DSeries *series);
inline QPoint clickedPosition() const { return m_clickedPosition; }
void resetClickedStatus();
// Overloaded from abstract renderer
virtual void updateAxisRange(QAbstract3DAxis::AxisOrientation orientation, float min,
float max);
+ virtual void updateAxisReversed(QAbstract3DAxis::AxisOrientation orientation,
+ bool enable);
private:
virtual void initShaders(const QString &vertexShader, const QString &fragmentShader);
@@ -143,10 +145,11 @@ private:
void drawSlicedScene();
void drawScene(GLuint defaultFboHandle);
+ void drawLabels(bool drawSelection, const Q3DCamera *activeCamera,
+ const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionMatrix,
+ GLfloat rowScaleFactor, GLfloat columnScaleFactor);
void loadBackgroundMesh();
- void loadGridLineMesh();
- void loadLabelMesh();
void initSelectionShader();
void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader);
void initLabelShaders(const QString &vertexShader, const QString &fragmentShader);
@@ -157,13 +160,15 @@ private:
#endif
void calculateSceneScalingFactors();
void calculateHeightAdjustment();
- Abstract3DController::SelectionType isSelected(int row, int bar, int seriesIndex);
- QPoint selectionColorToArrayPosition(const QVector3D &selectionColor);
- QBar3DSeries *selectionColorToSeries(const QVector3D &selectionColor);
+ Abstract3DController::SelectionType isSelected(int row, int bar,
+ const BarSeriesRenderCache *cache);
+ QPoint selectionColorToArrayPosition(const QVector4D &selectionColor);
+ QBar3DSeries *selectionColorToSeries(const QVector4D &selectionColor);
- Q_DISABLE_COPY(Bars3DRenderer)
+ inline void updateRenderRow(const QBarDataRow *dataRow, BarRenderItemRow &renderRow);
+ inline void updateRenderItem(const QBarDataItem &dataItem, BarRenderItem &renderItem);
- friend class BarRenderItem;
+ Q_DISABLE_COPY(Bars3DRenderer)
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/barseriesrendercache.cpp b/src/datavisualization/engine/barseriesrendercache.cpp
new file mode 100644
index 00000000..95da3680
--- /dev/null
+++ b/src/datavisualization/engine/barseriesrendercache.cpp
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 "barseriesrendercache_p.h"
+
+QT_BEGIN_NAMESPACE_DATAVISUALIZATION
+
+BarSeriesRenderCache::BarSeriesRenderCache(QAbstract3DSeries *series,
+ Abstract3DRenderer *renderer)
+ : SeriesRenderCache(series, renderer),
+ m_visualIndex(-1)
+{
+}
+
+BarSeriesRenderCache::~BarSeriesRenderCache()
+{
+}
+
+void BarSeriesRenderCache::cleanup(TextureHelper *texHelper)
+{
+ m_renderArray.clear();
+ m_sliceArray.clear();
+
+ SeriesRenderCache::cleanup(texHelper);
+}
+
+QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/barseriesrendercache_p.h b/src/datavisualization/engine/barseriesrendercache_p.h
new file mode 100644
index 00000000..4e169300
--- /dev/null
+++ b/src/datavisualization/engine/barseriesrendercache_p.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 BARSERIESRENDERCACHE_P_H
+#define BARSERIESRENDERCACHE_P_H
+
+#include "datavisualizationglobal_p.h"
+#include "seriesrendercache_p.h"
+#include "qbar3dseries_p.h"
+#include "barrenderitem_p.h"
+
+QT_BEGIN_NAMESPACE_DATAVISUALIZATION
+
+class BarSeriesRenderCache : public SeriesRenderCache
+{
+public:
+ BarSeriesRenderCache(QAbstract3DSeries *series, Abstract3DRenderer *renderer);
+ virtual ~BarSeriesRenderCache();
+
+ void cleanup(TextureHelper *texHelper);
+
+ inline BarRenderItemArray &renderArray() { return m_renderArray; }
+ inline QBar3DSeries *series() const { return static_cast<QBar3DSeries *>(m_series); }
+ inline QVector<BarRenderSliceItem> &sliceArray() { return m_sliceArray; }
+ inline void setVisualIndex(int index) { m_visualIndex = index; }
+ inline int visualIndex() {return m_visualIndex; }
+
+protected:
+ BarRenderItemArray m_renderArray;
+ QVector<BarRenderSliceItem> m_sliceArray;
+ int m_visualIndex; // order of the series is relevant
+};
+
+QT_END_NAMESPACE_DATAVISUALIZATION
+
+#endif
diff --git a/src/datavisualization/engine/drawer.cpp b/src/datavisualization/engine/drawer.cpp
index 55a2c2a5..b8726840 100644
--- a/src/datavisualization/engine/drawer.cpp
+++ b/src/datavisualization/engine/drawer.cpp
@@ -18,13 +18,11 @@
#include "drawer_p.h"
#include "shaderhelper_p.h"
-#include "objecthelper_p.h"
-#include "abstractobjecthelper_p.h"
#include "surfaceobject_p.h"
-#include "q3dcamera.h"
#include "utils_p.h"
#include "texturehelper_p.h"
#include "abstract3drenderer_p.h"
+#include "scatterpointbufferhelper_p.h"
#include <QtGui/QMatrix4x4>
#include <QtCore/qmath.h>
@@ -45,18 +43,28 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
// Vertex array buffer for point
const GLfloat point_data[] = {0.0f, 0.0f, 0.0f};
+// Vertex array buffer for line
+const GLfloat line_data[] = {
+ -1.0f, 0.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f,
+};
+
Drawer::Drawer(Q3DTheme *theme)
: m_theme(theme),
m_textureHelper(0),
- m_pointbuffer(0)
+ m_pointbuffer(0),
+ m_linebuffer(0),
+ m_scaledFontSize(0.0f)
{
}
Drawer::~Drawer()
{
delete m_textureHelper;
- if (QOpenGLContext::currentContext())
+ if (QOpenGLContext::currentContext()) {
glDeleteBuffers(1, &m_pointbuffer);
+ glDeleteBuffers(1, &m_linebuffer);
+ }
}
void Drawer::initializeOpenGL()
@@ -70,6 +78,7 @@ void Drawer::initializeOpenGL()
void Drawer::setTheme(Q3DTheme *theme)
{
m_theme = theme;
+ m_scaledFontSize = 0.05f + m_theme->font().pointSizeF() / 500.0f;
emit drawerChanged();
}
@@ -140,6 +149,18 @@ void Drawer::drawObject(ShaderHelper *shader, AbstractObjectHelper *object, GLui
}
}
+void Drawer::drawSelectionObject(ShaderHelper *shader, AbstractObjectHelper *object)
+{
+ glEnableVertexAttribArray(shader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, object->vertexBuf());
+ glVertexAttribPointer(shader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object->elementBuf());
+ glDrawElements(GL_TRIANGLES, object->indexCount(), GL_UNSIGNED_SHORT, (void *)0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glDisableVertexAttribArray(shader->posAtt());
+}
+
void Drawer::drawSurfaceGrid(ShaderHelper *shader, SurfaceObject *object)
{
// 1st attribute buffer : vertices
@@ -162,6 +183,8 @@ void Drawer::drawSurfaceGrid(ShaderHelper *shader, SurfaceObject *object)
void Drawer::drawPoint(ShaderHelper *shader)
{
+ // Draw a single point
+
// Generate vertex buffer for point if it does not exist
if (!m_pointbuffer) {
glGenBuffers(1, &m_pointbuffer);
@@ -183,13 +206,55 @@ void Drawer::drawPoint(ShaderHelper *shader)
glDisableVertexAttribArray(shader->posAtt());
}
+void Drawer::drawPoints(ShaderHelper *shader, ScatterPointBufferHelper *object)
+{
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(shader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, object->pointBuf());
+ glVertexAttribPointer(shader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
+
+ // Draw the points
+ glDrawArrays(GL_POINTS, 0, object->indexCount());
+
+ // Free buffers
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDisableVertexAttribArray(shader->posAtt());
+}
+
+void Drawer::drawLine(ShaderHelper *shader)
+{
+ // Draw a single line
+
+ // Generate vertex buffer for line if it does not exist
+ if (!m_linebuffer) {
+ glGenBuffers(1, &m_linebuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, m_linebuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(line_data), line_data, GL_STATIC_DRAW);
+ }
+
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(shader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, m_linebuffer);
+ glVertexAttribPointer(shader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
+
+ // Draw the line
+ glDrawArrays(GL_LINES, 0, 2);
+
+ // 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,
+ const QVector3D &positionComp, const QQuaternion &rotation,
GLfloat itemHeight, QAbstract3DGraph::SelectionFlags mode,
ShaderHelper *shader, ObjectHelper *object,
const Q3DCamera *camera, bool useDepth, bool rotateAlong,
- LabelPosition position, Qt::AlignmentFlag alignment, bool isSlicing)
+ LabelPosition position, Qt::AlignmentFlag alignment, bool isSlicing,
+ bool isSelecting)
{
// Draw label
if (!labelItem.textureId())
@@ -246,68 +311,20 @@ void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelIte
}
// Calculate scale factor to get uniform font size
- GLfloat scaledFontSize = 0.05f + m_theme->font().pointSizeF() / 500.0f;
- GLfloat scaleFactor = scaledFontSize / (GLfloat)textureSize.height();
+ GLfloat scaleFactor = m_scaledFontSize / (GLfloat)textureSize.height();
// Apply alignment
- GLfloat xAlignment = 0.0f;
- GLfloat yAlignment = 0.0f;
- GLfloat zAlignment = 0.0f;
- GLfloat sinRotY = qFabs(qSin(qDegreesToRadians(rotation.y())));
- GLfloat cosRotY = qFabs(qCos(qDegreesToRadians(rotation.y())));
- GLfloat sinRotZ = 0.0f;
- GLfloat cosRotZ = 0.0f;
- if (rotation.z()) {
- sinRotZ = qFabs(qSin(qDegreesToRadians(rotation.z())));
- cosRotZ = qFabs(qCos(qDegreesToRadians(rotation.z())));
- }
- switch (alignment) {
- case Qt::AlignLeft: {
- if (rotation.z() && rotation.z() != 180.0f && !rotation.y()) {
- xAlignment = ((-(GLfloat)textureSize.width() * scaleFactor) * cosRotZ
- - ((GLfloat)textureSize.height() * scaleFactor) * sinRotZ) / 2.0f;
- yAlignment = (((GLfloat)textureSize.width() * scaleFactor) * sinRotZ
- + ((GLfloat)textureSize.height() * scaleFactor) * cosRotZ) / 2.0f;
- } else {
- xAlignment = (-(GLfloat)textureSize.width() * scaleFactor) * cosRotY;
- zAlignment = ((GLfloat)textureSize.width() * scaleFactor) * sinRotY;
- }
- break;
- }
- case Qt::AlignRight: {
- if (rotation.z() && rotation.z() != 180.0f && !rotation.y()) {
- xAlignment = (((GLfloat)textureSize.width() * scaleFactor) * cosRotZ
- + ((GLfloat)textureSize.height() * scaleFactor) * sinRotZ) / 2.0f;
- yAlignment = (((GLfloat)textureSize.width() * scaleFactor) * sinRotZ
- + ((GLfloat)textureSize.height() * scaleFactor) * cosRotZ) / 2.0f;
- } else {
- xAlignment = ((GLfloat)textureSize.width() * scaleFactor) * cosRotY;
- zAlignment = (-(GLfloat)textureSize.width() * scaleFactor) * sinRotY;
- }
- break;
- }
- case Qt::AlignTop: {
- yAlignment = ((GLfloat)textureSize.width() * scaleFactor) * cosRotY;
- break;
- }
- case Qt::AlignBottom: {
- yAlignment = (-(GLfloat)textureSize.width() * scaleFactor) * cosRotY;
- break;
- }
- case Qt::AlignHCenter: {
- xAlignment = (-(GLfloat)textureSize.width() * scaleFactor) * cosRotZ
- - ((GLfloat)textureSize.height() * scaleFactor) * sinRotZ;
- break;
- }
- case Qt::AlignVCenter: {
- yAlignment = ((GLfloat)textureSize.width() * scaleFactor) * cosRotZ
- + ((GLfloat)textureSize.height() * scaleFactor) * sinRotZ;
- break;
- }
- default: {
- break;
- }
- }
+ QVector3D anchorPoint;
+
+ if (alignment & Qt::AlignLeft)
+ anchorPoint.setX(float(textureSize.width()) * scaleFactor);
+ else if (alignment & Qt::AlignRight)
+ anchorPoint.setX(float(-textureSize.width()) * scaleFactor);
+
+ if (alignment & Qt::AlignTop)
+ anchorPoint.setY(float(-textureSize.height()) * scaleFactor);
+ else if (alignment & Qt::AlignBottom)
+ anchorPoint.setY(float(textureSize.height()) * scaleFactor);
if (position < LabelBottom) {
xPosition = item.translation().x();
@@ -318,15 +335,9 @@ void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelIte
}
// Position label
- modelMatrix.translate(xPosition + xAlignment, yPosition + yAlignment, zPosition + zAlignment);
+ modelMatrix.translate(xPosition, yPosition, zPosition);
// Rotate
- 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) {
float yComp = float(qRadiansToDegrees(qTan(positionComp.y() / cameraDistance)));
// Apply negative camera rotations to keep labels facing camera
@@ -334,20 +345,27 @@ void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelIte
float camRotationY = camera->yRotation();
modelMatrix.rotate(-camRotationX, 0.0f, 1.0f, 0.0f);
modelMatrix.rotate(-camRotationY - yComp, 1.0f, 0.0f, 0.0f);
+ } else {
+ modelMatrix.rotate(rotation);
}
+ modelMatrix.translate(anchorPoint);
// Scale label based on text size
modelMatrix.scale(QVector3D((GLfloat)textureSize.width() * scaleFactor,
- scaledFontSize,
+ m_scaledFontSize,
0.0f));
MVPMatrix = projectionmatrix * viewmatrix * modelMatrix;
- // Set shader bindings
shader->setUniformValue(shader->MVP(), MVPMatrix);
- // Draw the object
- drawObject(shader, object, labelItem.textureId());
+ if (isSelecting) {
+ // Draw the selection object
+ drawSelectionObject(shader, object);
+ } else {
+ // Draw the object
+ drawObject(shader, object, labelItem.textureId());
+ }
}
void Drawer::generateSelectionLabelTexture(Abstract3DRenderer *renderer)
diff --git a/src/datavisualization/engine/drawer_p.h b/src/datavisualization/engine/drawer_p.h
index 8e98aa3a..ffcea315 100644
--- a/src/datavisualization/engine/drawer_p.h
+++ b/src/datavisualization/engine/drawer_p.h
@@ -44,6 +44,7 @@ class SurfaceObject;
class TextureHelper;
class Q3DCamera;
class Abstract3DRenderer;
+class ScatterPointBufferHelper;
class Drawer : public QObject, public QOpenGLFunctions
{
@@ -71,18 +72,23 @@ public:
void setTheme(Q3DTheme *theme);
Q3DTheme *theme() const;
QFont font() const;
+ inline GLfloat scaledFontSize() const { return m_scaledFontSize; }
void drawObject(ShaderHelper *shader, AbstractObjectHelper *object, GLuint textureId = 0,
GLuint depthTextureId = 0);
+ void drawSelectionObject(ShaderHelper *shader, AbstractObjectHelper *object);
void drawSurfaceGrid(ShaderHelper *shader, SurfaceObject *object);
void drawPoint(ShaderHelper *shader);
+ void drawPoints(ShaderHelper *shader, ScatterPointBufferHelper *object);
+ void drawLine(ShaderHelper *shader);
void drawLabel(const AbstractRenderItem &item, const LabelItem &labelItem,
const QMatrix4x4 &viewmatrix, const QMatrix4x4 &projectionmatrix,
- const QVector3D &positionComp, const QVector3D &rotation, GLfloat itemHeight,
+ const QVector3D &positionComp, const QQuaternion &rotation, GLfloat itemHeight,
QAbstract3DGraph::SelectionFlags mode, ShaderHelper *shader, ObjectHelper *object,
const Q3DCamera *camera, bool useDepth = false, bool rotateAlong = false,
LabelPosition position = LabelOver,
- Qt::AlignmentFlag alignment = Qt::AlignCenter, bool isSlicing = false);
+ Qt::AlignmentFlag alignment = Qt::AlignCenter, bool isSlicing = false,
+ bool isSelecting = false);
void generateSelectionLabelTexture(Abstract3DRenderer *item);
void generateLabelItem(LabelItem &item, const QString &text, int widestLabel = 0);
@@ -94,6 +100,8 @@ private:
Q3DTheme *m_theme;
TextureHelper *m_textureHelper;
GLuint m_pointbuffer;
+ GLuint m_linebuffer;
+ GLfloat m_scaledFontSize;
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/engine.pri b/src/datavisualization/engine/engine.pri
index 9c2e71e4..96fa7fa9 100644
--- a/src/datavisualization/engine/engine.pri
+++ b/src/datavisualization/engine/engine.pri
@@ -26,7 +26,9 @@ HEADERS += $$PWD/qabstract3dgraph_p.h \
$$PWD/q3dobject.h \
$$PWD/q3dobject_p.h \
$$PWD/q3dscene_p.h \
- $$PWD/surfaceseriesrendercache_p.h
+ $$PWD/surfaceseriesrendercache_p.h \
+ $$PWD/barseriesrendercache_p.h \
+ $$PWD/scatterseriesrendercache_p.h
SOURCES += $$PWD/qabstract3dgraph.cpp \
$$PWD/q3dbars.cpp \
@@ -48,7 +50,9 @@ SOURCES += $$PWD/qabstract3dgraph.cpp \
$$PWD/q3dlight.cpp \
$$PWD/q3dobject.cpp \
$$PWD/q3dscene.cpp \
- $$PWD/surfaceseriesrendercache.cpp
+ $$PWD/surfaceseriesrendercache.cpp \
+ $$PWD/barseriesrendercache.cpp \
+ $$PWD/scatterseriesrendercache.cpp
RESOURCES += engine/engine.qrc
diff --git a/src/datavisualization/engine/engine.qrc b/src/datavisualization/engine/engine.qrc
index 18cba7fe..673b6ee0 100644
--- a/src/datavisualization/engine/engine.qrc
+++ b/src/datavisualization/engine/engine.qrc
@@ -24,7 +24,7 @@
<file alias="bevelbarSmoothFull">meshes/barFilledSmooth.obj</file>
<file alias="barFull">meshes/cubeFilledFlat.obj</file>
<file alias="barSmoothFull">meshes/cubeFilledSmooth.obj</file>
- <file alias="negativeBackground">meshes/backgroundNegatives.obj</file>
+ <file alias="backgroundNoFloor">meshes/backgroundNoFloor.obj</file>
<file alias="minimal">meshes/minimalFlat.obj</file>
<file alias="minimalSmooth">meshes/minimalSmooth.obj</file>
<file alias="arrow">meshes/arrowFlat.obj</file>
@@ -54,5 +54,8 @@
<file alias="fragmentSurfaceShadowNoTex">shaders/surfaceShadowNoTex.frag</file>
<file alias="fragmentSurfaceShadowFlat">shaders/surfaceShadowFlat.frag</file>
<file alias="vertexSurfaceShadowFlat">shaders/surfaceShadowFlat.vert</file>
+ <file alias="fragmentTexture">shaders/texture.frag</file>
+ <file alias="fragmentTextureES2">shaders/texture_ES2.frag</file>
+ <file alias="vertexTexture">shaders/texture.vert</file>
</qresource>
</RCC>
diff --git a/src/datavisualization/engine/meshes/backgroundNegatives.obj b/src/datavisualization/engine/meshes/backgroundNoFloor.obj
index 76c7c1d8..0b94617f 100644
--- a/src/datavisualization/engine/meshes/backgroundNegatives.obj
+++ b/src/datavisualization/engine/meshes/backgroundNoFloor.obj
@@ -1,18 +1,18 @@
# 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 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
+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.000000
+vt 0.500000 0.000000
+vt 0.500000 1.000000
+vt 1.000000 0.000000
+vt 1.000000 1.000000
+vt 0.000000 1.000000
vn 0.000000 -0.000000 -1.000000
vn 1.000000 0.000000 0.000000
s off
diff --git a/src/datavisualization/engine/q3dbars.cpp b/src/datavisualization/engine/q3dbars.cpp
index 7b37715f..a903d831 100644
--- a/src/datavisualization/engine/q3dbars.cpp
+++ b/src/datavisualization/engine/q3dbars.cpp
@@ -16,13 +16,7 @@
**
****************************************************************************/
-#include "q3dbars.h"
#include "q3dbars_p.h"
-#include "bars3dcontroller_p.h"
-#include "qvalue3daxis.h"
-#include "qcategory3daxis.h"
-#include "q3dcamera.h"
-#include "qbar3dseries_p.h"
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -30,7 +24,7 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
* \class Q3DBars
* \inmodule QtDataVisualization
* \brief The Q3DBars class provides methods for rendering 3D bar graphs.
- * \since Qt Data Visualization 1.0
+ * \since QtDataVisualization 1.0
*
* This class enables developers to render bar graphs in 3D and to view them by rotating the scene
* freely. Rotation is done by holding down the right mouse button and moving the mouse. Zooming
diff --git a/src/datavisualization/engine/q3dcamera.cpp b/src/datavisualization/engine/q3dcamera.cpp
index 50f2e319..9866a34e 100644
--- a/src/datavisualization/engine/q3dcamera.cpp
+++ b/src/datavisualization/engine/q3dcamera.cpp
@@ -16,10 +16,7 @@
**
****************************************************************************/
-#include "q3dcamera.h"
#include "q3dcamera_p.h"
-#include "q3dscene.h"
-#include "q3dobject.h"
#include "utils_p.h"
#include <QtCore/qmath.h>
@@ -30,7 +27,7 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
* \class Q3DCamera
* \inmodule QtDataVisualization
* \brief Representation of a camera in 3D space.
- * \since Qt Data Visualization 1.0
+ * \since QtDataVisualization 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 rotating the camera around the origin
@@ -85,7 +82,7 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
* data visualization. The type offers simple methods for rotating the camera around the origin
* and setting zoom level.
*
- * For Camera3D enums, see \l Q3DCamera::CameraPreset
+ * For Camera3D enums, see \l{Q3DCamera::CameraPreset}.
*/
/*!
@@ -208,10 +205,12 @@ float Q3DCamera::xRotation() const {
void Q3DCamera::setXRotation(float rotation)
{
- if (d_ptr->m_wrapXRotation)
+ if (d_ptr->m_wrapXRotation) {
rotation = Utils::wrapValue(rotation, d_ptr->m_minXRotation, d_ptr->m_maxXRotation);
- else
- rotation = qBound(float(d_ptr->m_minXRotation), float(rotation), float(d_ptr->m_maxXRotation));
+ } else {
+ rotation = qBound(float(d_ptr->m_minXRotation), float(rotation),
+ float(d_ptr->m_maxXRotation));
+ }
if (d_ptr->m_xRotation != rotation) {
d_ptr->setXRotation(rotation);
@@ -235,10 +234,12 @@ float Q3DCamera::yRotation() const {
void Q3DCamera::setYRotation(float rotation)
{
- if (d_ptr->m_wrapYRotation)
+ if (d_ptr->m_wrapYRotation) {
rotation = Utils::wrapValue(rotation, d_ptr->m_minYRotation, d_ptr->m_maxYRotation);
- else
- rotation = qBound(float(d_ptr->m_minYRotation), float(rotation), float(d_ptr->m_maxYRotation));
+ } else {
+ rotation = qBound(float(d_ptr->m_minYRotation), float(rotation),
+ float(d_ptr->m_maxYRotation));
+ }
if (d_ptr->m_yRotation != rotation) {
d_ptr->setYRotation(rotation);
diff --git a/src/datavisualization/engine/q3dlight.cpp b/src/datavisualization/engine/q3dlight.cpp
index 8ac9e3a0..03f094cb 100644
--- a/src/datavisualization/engine/q3dlight.cpp
+++ b/src/datavisualization/engine/q3dlight.cpp
@@ -16,8 +16,6 @@
**
****************************************************************************/
-#include "q3dlight.h"
-#include "q3dscene.h"
#include "q3dlight_p.h"
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -26,7 +24,7 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
* \class Q3DLight
* \inmodule QtDataVisualization
* \brief Representation of a light source in 3D space.
- * \since Qt Data Visualization 1.0
+ * \since QtDataVisualization 1.0
*
* Q3DLight represents a monochrome non variable light source in 3D space.
*/
diff --git a/src/datavisualization/engine/q3dobject.cpp b/src/datavisualization/engine/q3dobject.cpp
index 05edf287..56edb098 100644
--- a/src/datavisualization/engine/q3dobject.cpp
+++ b/src/datavisualization/engine/q3dobject.cpp
@@ -16,7 +16,6 @@
**
****************************************************************************/
-#include "q3dobject.h"
#include "q3dobject_p.h"
#include "q3dscene_p.h"
@@ -26,7 +25,7 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
\class Q3DObject
\inmodule QtDataVisualization
\brief Simple baseclass for all the objects in the 3D scene.
- \since Qt Data Visualization 1.0
+ \since QtDataVisualization 1.0
Q3DObject is a baseclass that contains only position information for an object in 3D scene.
The object is considered to be a single point in the coordinate space without dimensions.
diff --git a/src/datavisualization/engine/q3dscatter.cpp b/src/datavisualization/engine/q3dscatter.cpp
index 7c7809f3..40bd5021 100644
--- a/src/datavisualization/engine/q3dscatter.cpp
+++ b/src/datavisualization/engine/q3dscatter.cpp
@@ -18,10 +18,6 @@
#include "q3dscatter.h"
#include "q3dscatter_p.h"
-#include "scatter3dcontroller_p.h"
-#include "qvalue3daxis.h"
-#include "q3dcamera.h"
-#include "qscatter3dseries_p.h"
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -29,7 +25,7 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
* \class Q3DScatter
* \inmodule QtDataVisualization
* \brief The Q3DScatter class provides methods for rendering 3D scatter graphs.
- * \since Qt Data Visualization 1.0
+ * \since QtDataVisualization 1.0
*
* This class enables developers to render scatter graphs in 3D and to view them by rotating the scene
* freely. Rotation is done by holding down the right mouse button and moving the mouse. Zooming
diff --git a/src/datavisualization/engine/q3dscene.cpp b/src/datavisualization/engine/q3dscene.cpp
index be64b928..9464bc8d 100644
--- a/src/datavisualization/engine/q3dscene.cpp
+++ b/src/datavisualization/engine/q3dscene.cpp
@@ -16,22 +16,17 @@
**
****************************************************************************/
-#include "datavisualizationglobal_p.h"
-
-#include "q3dscene.h"
#include "q3dscene_p.h"
#include "q3dcamera_p.h"
#include "q3dlight_p.h"
-#include <QtCore/qmath.h>
-
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
/*!
* \class Q3DScene
* \inmodule QtDataVisualization
* \brief Q3DScene class provides description of the 3D scene being visualized.
- * \since Qt Data Visualization 1.0
+ * \since QtDataVisualization 1.0
*
* The 3D scene contains a single active camera and a single active light source.
* Visualized data is assumed to be at a fixed location.
@@ -260,8 +255,12 @@ void Q3DScene::setSecondarySubViewport(const QRect &secondarySubViewport)
*
* 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().
+ * graph tries to select a data item, axis label, or a custom item at the given \a point within
+ * the primary viewport.
+ * After the rendering pass the property is returned to its default state of
+ * invalidSelectionPoint().
+ *
+ * \sa QAbstract3DGraph::selectedElement
*/
void Q3DScene::setSelectionQueryPosition(const QPoint &point)
{
@@ -411,6 +410,7 @@ void Q3DScene::setActiveLight(Q3DLight *light)
d_ptr->m_sceneDirty = true;
emit activeLightChanged(light);
+ emit d_ptr->needRender();
}
}
@@ -554,7 +554,6 @@ void Q3DScenePrivate::setWindowSize(const QSize &size)
m_windowSize = size;
updateGLViewport();
m_changeTracker.windowSizeChanged = true;
- m_sceneDirty = true;
emit needRender();
}
}
diff --git a/src/datavisualization/engine/q3dscene.h b/src/datavisualization/engine/q3dscene.h
index d663744e..1699b125 100644
--- a/src/datavisualization/engine/q3dscene.h
+++ b/src/datavisualization/engine/q3dscene.h
@@ -93,7 +93,9 @@ private:
friend class AbstractDeclarative;
friend class QAbstract3DGraph;
+ friend class QAbstract3DGraphPrivate;
friend class Abstract3DController;
+ friend class Bars3DController;
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 bc6a7223..2c69e5e0 100644
--- a/src/datavisualization/engine/q3dscene_p.h
+++ b/src/datavisualization/engine/q3dscene_p.h
@@ -36,7 +36,6 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
class Q3DCamera;
class Q3DLight;
-class Q3DScene;
struct Q3DSceneChangeBitField {
bool viewportChanged : 1;
diff --git a/src/datavisualization/engine/q3dsurface.cpp b/src/datavisualization/engine/q3dsurface.cpp
index 7724cb24..162b7a67 100644
--- a/src/datavisualization/engine/q3dsurface.cpp
+++ b/src/datavisualization/engine/q3dsurface.cpp
@@ -18,10 +18,6 @@
#include "q3dsurface.h"
#include "q3dsurface_p.h"
-#include "qvalue3daxis.h"
-#include "qsurfacedataproxy.h"
-#include "q3dcamera.h"
-#include "qsurface3dseries_p.h"
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -29,7 +25,7 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
* \class Q3DSurface
* \inmodule QtDataVisualization
* \brief The Q3DSurface class provides methods for rendering 3D surface plots.
- * \since Qt Data Visualization 1.0
+ * \since QtDataVisualization 1.0
*
* This class enables developers to render 3D surface plots and to view them by rotating the scene
* freely. The visual properties of the surface such as draw mode and shading can be controlled
diff --git a/src/datavisualization/engine/qabstract3dgraph.cpp b/src/datavisualization/engine/qabstract3dgraph.cpp
index bde5b585..dabec744 100644
--- a/src/datavisualization/engine/qabstract3dgraph.cpp
+++ b/src/datavisualization/engine/qabstract3dgraph.cpp
@@ -27,6 +27,8 @@
#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLPaintDevice>
#include <QtGui/QPainter>
+#include <QtGui/QOpenGLFramebufferObject>
+#include <QtGui/QOffscreenSurface>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -34,7 +36,7 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
* \class QAbstract3DGraph
* \inmodule QtDataVisualization
* \brief The QAbstract3DGraph class provides a window and render loop for graphs.
- * \since Qt Data Visualization 1.0
+ * \since QtDataVisualization 1.0
*
* This class subclasses a QWindow and provides render loop for graphs inheriting it.
*
@@ -118,6 +120,38 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
*/
/*!
+ \enum QAbstract3DGraph::ElementType
+ \since QtDataVisualization 1.1
+
+ Type of an element in the graph.
+
+ \value ElementNone
+ No defined element.
+ \value ElementSeries
+ A series (i.e. an item in a series).
+ \value ElementAxisXLabel
+ X axis label.
+ \value ElementAxisYLabel
+ Y axis label.
+ \value ElementAxisZLabel
+ Z axis label.
+ \value ElementCustomItem
+ Custom item.
+*/
+
+/*!
+ \enum QAbstract3DGraph::OptimizationHint
+ \since Qt Data Visualization 1.1
+
+ The optimization hint for rendering.
+
+ \value OptimizationDefault
+ Provides the full feature set at a reasonable performance.
+ \value OptimizationStatic
+ Beta level feature. Optimizes the rendering of static data sets at the expense of some features.
+*/
+
+/*!
* \internal
*/
QAbstract3DGraph::QAbstract3DGraph(QAbstract3DGraphPrivate *d, const QSurfaceFormat *format,
@@ -126,6 +160,7 @@ QAbstract3DGraph::QAbstract3DGraph(QAbstract3DGraphPrivate *d, const QSurfaceFor
d_ptr(d)
{
qRegisterMetaType<QAbstract3DGraph::ShadowQuality>("QAbstract3DGraph::ShadowQuality");
+ qRegisterMetaType<QAbstract3DGraph::ElementType>("QAbstract3DGraph::ElementType");
// Default to frameless window, as typically graphs are not toplevel
setFlags(flags() | Qt::FramelessWindowHint);
@@ -164,7 +199,8 @@ QAbstract3DGraph::QAbstract3DGraph(QAbstract3DGraphPrivate *d, const QSurfaceFor
#if !defined(QT_OPENGL_ES_2)
// If we have real OpenGL, GLSL version must be 1.2 or over. Quit if not.
- QStringList splitversionstr = QString::fromLatin1((const char *)shaderVersion).split(QChar::fromLatin1(' '));
+ QStringList splitversionstr =
+ QString::fromLatin1((const char *)shaderVersion).split(QChar::fromLatin1(' '));
if (splitversionstr[0].toFloat() < 1.2)
qFatal("GLSL version must be 1.20 or higher. Try installing latest display drivers.");
#else
@@ -342,7 +378,8 @@ bool QAbstract3DGraph::shadowsSupported() const
/*!
* \property QAbstract3DGraph::scene
*
- * This property contains the read only Q3DScene that can be used to access, for example, a camera object.
+ * This property contains the read only Q3DScene that can be used to access, for example, a camera
+ * object.
*/
Q3DScene *QAbstract3DGraph::scene() const
{
@@ -358,6 +395,257 @@ void QAbstract3DGraph::clearSelection()
}
/*!
+ * Adds a QCustom3DItem \a item to the graph. Graph takes ownership of the added item.
+ *
+ * \return index to the added item if add was successful, -1 if trying to add a null item, and
+ * index of the item if trying to add an already added item.
+ *
+ * \sa removeCustomItems(), removeCustomItem(), removeCustomItemAt()
+ *
+ * \since QtDataVisualization 1.1
+ */
+int QAbstract3DGraph::addCustomItem(QCustom3DItem *item)
+{
+ return d_ptr->m_visualController->addCustomItem(item);
+}
+
+/*!
+ * Removes all custom items. Deletes the resources allocated to them.
+ *
+ * \since QtDataVisualization 1.1
+ */
+void QAbstract3DGraph::removeCustomItems()
+{
+ d_ptr->m_visualController->deleteCustomItems();
+}
+
+/*!
+ * Removes the custom \a {item}. Deletes the resources allocated to it.
+ *
+ * \since QtDataVisualization 1.1
+ */
+void QAbstract3DGraph::removeCustomItem(QCustom3DItem *item)
+{
+ d_ptr->m_visualController->deleteCustomItem(item);
+}
+
+/*!
+ * Removes all custom items at \a {position}. Deletes the resources allocated to them.
+ *
+ * \since QtDataVisualization 1.1
+ */
+void QAbstract3DGraph::removeCustomItemAt(const QVector3D &position)
+{
+ d_ptr->m_visualController->deleteCustomItem(position);
+}
+
+/*!
+ * Gets ownership of given \a item back and removes the \a item from the graph.
+ *
+ * \since QtDataVisualization 1.1
+ *
+ * \note If the same item is added back to the graph, the texture or the texture file needs to be
+ * re-set.
+ *
+ * \sa QCustom3DItem::setTextureImage(), QCustom3DItem::setTextureFile()
+ */
+void QAbstract3DGraph::releaseCustomItem(QCustom3DItem *item)
+{
+ return d_ptr->m_visualController->releaseCustomItem(item);
+}
+
+/*!
+ * Can be used to query the index of the selected label after receiving \c selectedElementChanged
+ * signal with any label type. Selection is valid until the next \c selectedElementChanged signal.
+ *
+ * \return index of the selected label, or -1.
+ *
+ * \since QtDataVisualization 1.1
+ *
+ * \sa selectedElement
+ */
+int QAbstract3DGraph::selectedLabelIndex() const
+{
+ return d_ptr->m_visualController->selectedLabelIndex();
+}
+
+/*!
+ * Can be used to get the selected axis after receiving \c selectedElementChanged signal with any label
+ * type. Selection is valid until the next \c selectedElementChanged signal.
+ *
+ * \return pointer to the selected axis, or null.
+ *
+ * \since QtDataVisualization 1.1
+ *
+ * \sa selectedElement
+ */
+QAbstract3DAxis *QAbstract3DGraph::selectedAxis() const
+{
+ return d_ptr->m_visualController->selectedAxis();
+}
+
+/*!
+ * Can be used to query the index of the selected custom item after receiving \c selectedElementChanged
+ * signal with QAbstract3DGraph::ElementCustomItem type. Selection is valid until the next
+ * \c selectedElementChanged signal.
+ *
+ * \return index of the selected custom item, or -1.
+ *
+ * \since QtDataVisualization 1.1
+ *
+ * \sa selectedElement
+ */
+int QAbstract3DGraph::selectedCustomItemIndex() const
+{
+ return d_ptr->m_visualController->selectedCustomItemIndex();
+}
+
+/*!
+ * Can be used to get the selected custom item after receiving \c selectedElementChanged signal with
+ * QAbstract3DGraph::ElementCustomItem type. Ownership of the item remains with the graph.
+ * Selection is valid until the next \c selectedElementChanged signal.
+ *
+ * \return pointer to the selected custom item, or null.
+ *
+ * \since QtDataVisualization 1.1
+ *
+ * \sa selectedElement
+ */
+QCustom3DItem *QAbstract3DGraph::selectedCustomItem() const
+{
+ return d_ptr->m_visualController->selectedCustomItem();
+}
+
+/*!
+ * \property QAbstract3DGraph::selectedElement
+ *
+ * Can be used to query the selected element type.
+ * Type is valid until the next \c selectedElementChanged signal.
+ *
+ * \c selectedElementChanged signal is emitted when a selection is made in the graph.
+ *
+ * Signal can be used for example for implementing custom input handlers, as demonstrated in this
+ * \l {Axis Range Dragging With Labels Example}{example}.
+ *
+ * \sa selectedLabelIndex(), selectedAxis(), selectedCustomItemIndex(), selectedCustomItem(),
+ * Q3DBars::selectedSeries(), Q3DScatter::selectedSeries(), Q3DSurface::selectedSeries(),
+ * Q3DScene::setSelectionQueryPosition()
+ *
+ * \since QtDataVisualization 1.1
+ */
+QAbstract3DGraph::ElementType QAbstract3DGraph::selectedElement() const
+{
+ return d_ptr->m_visualController->selectedElement();
+}
+
+/*!
+ * Renders current frame to an image of \a imageSize. Default size is the window size. Image is
+ * rendered with antialiasing level given in \a msaaSamples. Default level is \c{0}.
+ *
+ * \since QtDataVisualization 1.1
+ *
+ * \return rendered image.
+ */
+QImage QAbstract3DGraph::renderToImage(int msaaSamples, const QSize &imageSize)
+{
+ QSize renderSize = imageSize;
+ if (renderSize.isEmpty())
+ renderSize = size();
+ return d_ptr->renderToImage(msaaSamples, renderSize);
+}
+
+/*!
+ * \property QAbstract3DGraph::measureFps
+ * \since QtDataVisualization 1.1
+ *
+ * If \c {true}, the rendering is done continuously instead of on demand, and currentFps property
+ * is updated. Defaults to \c{false}.
+ *
+ * \sa currentFps
+ */
+void QAbstract3DGraph::setMeasureFps(bool enable)
+{
+ d_ptr->m_visualController->setMeasureFps(enable);
+}
+
+bool QAbstract3DGraph::measureFps() const
+{
+ return d_ptr->m_visualController->measureFps();
+}
+
+/*!
+ * \property QAbstract3DGraph::currentFps
+ * \since QtDataVisualization 1.1
+ *
+ * When fps measuring is enabled, the results for the last second are stored in this read-only
+ * property. It takes at least a second before this value updates after measurement is activated.
+ *
+ * \sa measureFps
+ */
+qreal QAbstract3DGraph::currentFps() const
+{
+ return d_ptr->m_visualController->currentFps();
+}
+
+/*!
+ * \property QAbstract3DGraph::orthoProjection
+ * \since QtDataVisualization 1.1
+ *
+ * If \c {true}, orthographic projection will be used for displaying the graph. Defaults to \c{false}.
+ * \note Shadows will be disabled when set to \c{true}.
+ */
+void QAbstract3DGraph::setOrthoProjection(bool enable)
+{
+ d_ptr->m_visualController->setOrthoProjection(enable);
+}
+
+bool QAbstract3DGraph::isOrthoProjection() const
+{
+ return d_ptr->m_visualController->isOrthoProjection();
+}
+
+/*!
+ * \property QAbstract3DGraph::aspectRatio
+ * \since QtDataVisualization 1.1
+ *
+ * Aspect ratio of the graph data. This is the ratio of data scaling between horizontal and
+ * vertical axes. Defaults to \c{2.0}.
+ *
+ * \note Has no effect on Q3DBars.
+ */
+void QAbstract3DGraph::setAspectRatio(qreal ratio)
+{
+ d_ptr->m_visualController->setAspectRatio(float(ratio));
+}
+
+qreal QAbstract3DGraph::aspectRatio() const
+{
+ return d_ptr->m_visualController->aspectRatio();
+}
+
+/*!
+ * \property QAbstract3DGraph::optimizationHints
+ *
+ * Defines if the rendering optimization is default or static. Default mode provides the full feature set at
+ * reasonable performance. Static is a beta level feature and currently supports only a subset of the
+ * features on the Scatter graph. Missing features are object gradient for mesh objects, both gradients
+ * for points, and diffuse and specular color on rotations. At this point static is intended just for
+ * introducing a new feature. It optimizes graph rendering and is ideal for large non-changing data
+ * sets. It is slower with dynamic data changes and item rotations. Selection is not optimized, so using it
+ * with massive data sets is not advisable.
+ * Defaults to \c{OptimizationDefault}.
+ */
+void QAbstract3DGraph::setOptimizationHints(OptimizationHints hints)
+{
+ d_ptr->m_visualController->setOptimizationHints(hints);
+}
+
+QAbstract3DGraph::OptimizationHints QAbstract3DGraph::optimizationHints() const
+{
+ return d_ptr->m_visualController->optimizationHints();
+}
+
+/*!
* \internal
*/
bool QAbstract3DGraph::event(QEvent *event)
@@ -453,12 +741,17 @@ QAbstract3DGraphPrivate::QAbstract3DGraphPrivate(QAbstract3DGraph *q)
q_ptr(q),
m_updatePending(false),
m_visualController(0),
- m_devicePixelRatio(1.f)
+ m_devicePixelRatio(1.f),
+ m_offscreenSurface(0)
{
}
QAbstract3DGraphPrivate::~QAbstract3DGraphPrivate()
{
+ if (m_offscreenSurface) {
+ m_offscreenSurface->destroy();
+ delete m_offscreenSurface;
+ }
if (m_context)
m_context->makeCurrent(q_ptr);
@@ -477,6 +770,11 @@ void QAbstract3DGraphPrivate::setVisualController(Abstract3DController *controll
&QAbstract3DGraph::selectionModeChanged);
QObject::connect(m_visualController, &Abstract3DController::shadowQualityChanged, q_ptr,
&QAbstract3DGraph::shadowQualityChanged);
+ QObject::connect(m_visualController, &Abstract3DController::optimizationHintsChanged, q_ptr,
+ &QAbstract3DGraph::optimizationHintsChanged);
+ QObject::connect(m_visualController, &Abstract3DController::elementSelected, q_ptr,
+ &QAbstract3DGraph::selectedElementChanged);
+
QObject::connect(m_visualController, &Abstract3DController::needRender, this,
&QAbstract3DGraphPrivate::renderLater);
@@ -486,6 +784,17 @@ void QAbstract3DGraphPrivate::setVisualController(Abstract3DController *controll
&QAbstract3DGraphPrivate::handleAxisYChanged);
QObject::connect(m_visualController, &Abstract3DController::axisZChanged, this,
&QAbstract3DGraphPrivate::handleAxisZChanged);
+
+ QObject::connect(m_visualController, &Abstract3DController::measureFpsChanged, q_ptr,
+ &QAbstract3DGraph::measureFpsChanged);
+ QObject::connect(m_visualController, &Abstract3DController::currentFpsChanged, q_ptr,
+ &QAbstract3DGraph::currentFpsChanged);
+
+ QObject::connect(m_visualController, &Abstract3DController::orthoProjectionChanged, q_ptr,
+ &QAbstract3DGraph::orthoProjectionChanged);
+
+ QObject::connect(m_visualController, &Abstract3DController::aspectRatioChanged, q_ptr,
+ &QAbstract3DGraph::aspectRatioChanged);
}
void QAbstract3DGraphPrivate::handleDevicePixelRatioChange()
@@ -526,4 +835,42 @@ void QAbstract3DGraphPrivate::renderNow()
m_context->swapBuffers(q_ptr);
}
+QImage QAbstract3DGraphPrivate::renderToImage(int msaaSamples, const QSize &imageSize)
+{
+ QImage image;
+ QOpenGLFramebufferObject *fbo;
+ QOpenGLFramebufferObjectFormat fboFormat;
+ if (!m_offscreenSurface) {
+ // Create an offscreen surface for rendering to images without rendering on screen
+ m_offscreenSurface = new QOffscreenSurface(q_ptr->screen());
+ m_offscreenSurface->setFormat(q_ptr->requestedFormat());
+ m_offscreenSurface->create();
+ }
+ // Render the wanted frame offscreen
+ m_context->makeCurrent(m_offscreenSurface);
+ fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ fboFormat.setInternalTextureFormat(GL_RGB);
+ fboFormat.setSamples(msaaSamples);
+ fbo = new QOpenGLFramebufferObject(imageSize, fboFormat);
+ if (fbo->isValid()) {
+ QRect originalViewport = m_visualController->m_scene->viewport();
+ m_visualController->m_scene->d_ptr->setWindowSize(imageSize);
+ m_visualController->m_scene->d_ptr->setViewport(QRect(0, 0,
+ imageSize.width(),
+ imageSize.height()));
+ m_visualController->synchDataToRenderer();
+ fbo->bind();
+ m_context->swapBuffers(m_offscreenSurface);
+ m_visualController->requestRender(fbo);
+ image = fbo->toImage();
+ fbo->release();
+ m_visualController->m_scene->d_ptr->setWindowSize(originalViewport.size());
+ m_visualController->m_scene->d_ptr->setViewport(originalViewport);
+ }
+ delete fbo;
+ m_context->makeCurrent(q_ptr);
+
+ return image;
+}
+
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/qabstract3dgraph.h b/src/datavisualization/engine/qabstract3dgraph.h
index 18eda7df..59f61aae 100644
--- a/src/datavisualization/engine/qabstract3dgraph.h
+++ b/src/datavisualization/engine/qabstract3dgraph.h
@@ -29,20 +29,31 @@
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
class QAbstract3DGraphPrivate;
+class QCustom3DItem;
+class QAbstract3DAxis;
class QT_DATAVISUALIZATION_EXPORT QAbstract3DGraph : public QWindow, protected QOpenGLFunctions
{
Q_OBJECT
Q_ENUMS(ShadowQuality)
+ Q_ENUMS(ElementType)
Q_FLAGS(SelectionFlag SelectionFlags)
+ Q_FLAGS(OptimizationHint OptimizationHints)
Q_PROPERTY(QAbstract3DInputHandler* activeInputHandler READ activeInputHandler WRITE setActiveInputHandler NOTIFY activeInputHandlerChanged)
Q_PROPERTY(Q3DTheme* activeTheme READ activeTheme WRITE setActiveTheme NOTIFY activeThemeChanged)
Q_PROPERTY(SelectionFlags selectionMode READ selectionMode WRITE setSelectionMode NOTIFY selectionModeChanged)
Q_PROPERTY(ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality NOTIFY shadowQualityChanged)
Q_PROPERTY(Q3DScene* scene READ scene)
+ Q_PROPERTY(bool measureFps READ measureFps WRITE setMeasureFps NOTIFY measureFpsChanged)
+ Q_PROPERTY(qreal currentFps READ currentFps NOTIFY currentFpsChanged)
+ Q_PROPERTY(bool orthoProjection READ isOrthoProjection WRITE setOrthoProjection NOTIFY orthoProjectionChanged)
+ Q_PROPERTY(ElementType selectedElement READ selectedElement NOTIFY selectedElementChanged)
+ Q_PROPERTY(qreal aspectRatio READ aspectRatio WRITE setAspectRatio NOTIFY aspectRatioChanged)
+ Q_PROPERTY(OptimizationHints optimizationHints READ optimizationHints WRITE setOptimizationHints NOTIFY optimizationHintsChanged)
protected:
- explicit QAbstract3DGraph(QAbstract3DGraphPrivate *d, const QSurfaceFormat *format, QWindow *parent = 0);
+ explicit QAbstract3DGraph(QAbstract3DGraphPrivate *d, const QSurfaceFormat *format,
+ QWindow *parent = 0);
public:
enum SelectionFlag {
@@ -69,6 +80,21 @@ public:
ShadowQualitySoftHigh
};
+ enum ElementType {
+ ElementNone = 0,
+ ElementSeries,
+ ElementAxisXLabel,
+ ElementAxisYLabel,
+ ElementAxisZLabel,
+ ElementCustomItem
+ };
+
+ enum OptimizationHint {
+ OptimizationDefault = 0,
+ OptimizationStatic = 1
+ };
+ Q_DECLARE_FLAGS(OptimizationHints, OptimizationHint)
+
public:
virtual ~QAbstract3DGraph();
@@ -95,6 +121,35 @@ public:
void clearSelection();
+ int addCustomItem(QCustom3DItem *item);
+ void removeCustomItems();
+ void removeCustomItem(QCustom3DItem *item);
+ void removeCustomItemAt(const QVector3D &position);
+ void releaseCustomItem(QCustom3DItem *item);
+
+ int selectedLabelIndex() const;
+ QAbstract3DAxis *selectedAxis() const;
+
+ int selectedCustomItemIndex() const;
+ QCustom3DItem *selectedCustomItem() const;
+
+ QImage renderToImage(int msaaSamples = 0, const QSize &imageSize = QSize());
+
+ void setMeasureFps(bool enable);
+ bool measureFps() const;
+ qreal currentFps() const;
+
+ void setOrthoProjection(bool enable);
+ bool isOrthoProjection() const;
+
+ ElementType selectedElement() const;
+
+ void setAspectRatio(qreal ratio);
+ qreal aspectRatio() const;
+
+ void setOptimizationHints(OptimizationHints hints);
+ OptimizationHints optimizationHints() const;
+
protected:
bool event(QEvent *event);
void resizeEvent(QResizeEvent *event);
@@ -107,12 +162,17 @@ protected:
void mouseMoveEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
-
signals:
void activeInputHandlerChanged(QAbstract3DInputHandler *inputHandler);
void activeThemeChanged(Q3DTheme *theme);
void selectionModeChanged(QAbstract3DGraph::SelectionFlags mode);
void shadowQualityChanged(QAbstract3DGraph::ShadowQuality quality);
+ void selectedElementChanged(QAbstract3DGraph::ElementType type);
+ void measureFpsChanged(bool enabled);
+ void currentFpsChanged(qreal fps);
+ void orthoProjectionChanged(bool enabled);
+ void aspectRatioChanged(qreal ratio);
+ void optimizationHintsChanged(QAbstract3DGraph::OptimizationHints hints);
private:
Q_DISABLE_COPY(QAbstract3DGraph)
@@ -123,6 +183,7 @@ private:
friend class Q3DSurface;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstract3DGraph::SelectionFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstract3DGraph::OptimizationHints)
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/qabstract3dgraph_p.h b/src/datavisualization/engine/qabstract3dgraph_p.h
index d28495ab..a8b0965a 100644
--- a/src/datavisualization/engine/qabstract3dgraph_p.h
+++ b/src/datavisualization/engine/qabstract3dgraph_p.h
@@ -32,7 +32,7 @@
#include "datavisualizationglobal_p.h"
class QOpenGLContext;
-class QOpenGLPaintDevice;
+class QOffscreenSurface;
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -52,6 +52,8 @@ public:
void render();
+ QImage renderToImage(int msaaSamples, const QSize &imageSize);
+
public slots:
void renderLater();
void renderNow();
@@ -67,6 +69,7 @@ public:
QOpenGLContext *m_context;
Abstract3DController *m_visualController;
float m_devicePixelRatio;
+ QOffscreenSurface *m_offscreenSurface;
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/scatter3dcontroller.cpp b/src/datavisualization/engine/scatter3dcontroller.cpp
index 54292ac0..da40fc85 100644
--- a/src/datavisualization/engine/scatter3dcontroller.cpp
+++ b/src/datavisualization/engine/scatter3dcontroller.cpp
@@ -18,15 +18,10 @@
#include "scatter3dcontroller_p.h"
#include "scatter3drenderer_p.h"
-#include "camerahelper_p.h"
-#include "qabstract3daxis_p.h"
#include "qvalue3daxis_p.h"
#include "qscatterdataproxy_p.h"
#include "qscatter3dseries_p.h"
-#include <QtGui/QMatrix4x4>
-#include <QtCore/qmath.h>
-
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
static const int insertRemoveRecordReserveSize = 31;
@@ -71,6 +66,12 @@ void Scatter3DController::synchDataToRenderer()
Abstract3DController::synchDataToRenderer();
// Notify changes to renderer
+ if (m_changeTracker.itemChanged) {
+ m_renderer->updateItems(m_changedItems);
+ m_changeTracker.itemChanged = false;
+ m_changedItems.clear();
+ }
+
if (m_changeTracker.selectedItemChanged) {
m_renderer->updateSelectedItem(m_selectedItem, m_selectedItemSeries);
m_changeTracker.selectedItemChanged = false;
@@ -83,9 +84,6 @@ void Scatter3DController::addSeries(QAbstract3DSeries *series)
Abstract3DController::addSeries(series);
- if (series->isVisible())
- adjustValueAxisRange();
-
QScatter3DSeries *scatterSeries = static_cast<QScatter3DSeries *>(series);
if (scatterSeries->selectedItem() != invalidSelectionIndex())
setSelectedItem(scatterSeries->selectedItem(), scatterSeries);
@@ -101,7 +99,7 @@ void Scatter3DController::removeSeries(QAbstract3DSeries *series)
setSelectedItem(invalidSelectionIndex(), 0);
if (wasVisible)
- adjustValueAxisRange();
+ adjustAxisRanges();
}
QList<QScatter3DSeries *> Scatter3DController::scatterSeriesList()
@@ -121,10 +119,13 @@ void Scatter3DController::handleArrayReset()
{
QScatter3DSeries *series = static_cast<QScatterDataProxy *>(sender())->series();
if (series->isVisible()) {
- adjustValueAxisRange();
+ adjustAxisRanges();
m_isDataDirty = true;
}
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
setSelectedItem(m_selectedItem, m_selectedItemSeries);
+ series->d_ptr->markItemLabelDirty();
emitNeedRender();
}
@@ -134,22 +135,45 @@ void Scatter3DController::handleItemsAdded(int startIndex, int count)
Q_UNUSED(count)
QScatter3DSeries *series = static_cast<QScatterDataProxy *>(sender())->series();
if (series->isVisible()) {
- adjustValueAxisRange();
+ adjustAxisRanges();
m_isDataDirty = true;
}
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
emitNeedRender();
}
void Scatter3DController::handleItemsChanged(int startIndex, int count)
{
- Q_UNUSED(startIndex)
- Q_UNUSED(count)
QScatter3DSeries *series = static_cast<QScatterDataProxy *>(sender())->series();
- if (series->isVisible()) {
- adjustValueAxisRange();
- m_isDataDirty = true;
+ int oldChangeCount = m_changedItems.size();
+ if (!oldChangeCount)
+ m_changedItems.reserve(count);
+
+ for (int i = 0; i < count; i++) {
+ bool newItem = true;
+ int candidate = startIndex + i;
+ for (int j = 0; j < oldChangeCount; j++) {
+ const ChangeItem &oldChangeItem = m_changedItems.at(j);
+ if (oldChangeItem.index == candidate && series == oldChangeItem.series) {
+ newItem = false;
+ break;
+ }
+ }
+ if (newItem) {
+ ChangeItem newChangeItem = {series, candidate};
+ m_changedItems.append(newChangeItem);
+ if (series == m_selectedItemSeries && m_selectedItem == candidate)
+ series->d_ptr->markItemLabelDirty();
+ }
+ }
+
+ if (count) {
+ m_changeTracker.itemChanged = true;
+ if (series->isVisible())
+ adjustAxisRanges();
+ emitNeedRender();
}
- emitNeedRender();
}
void Scatter3DController::handleItemsRemoved(int startIndex, int count)
@@ -171,9 +195,11 @@ void Scatter3DController::handleItemsRemoved(int startIndex, int count)
}
if (series->isVisible()) {
- adjustValueAxisRange();
+ adjustAxisRanges();
m_isDataDirty = true;
}
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
if (m_recordInsertsAndRemoves) {
InsertRemoveRecord record(false, startIndex, count, series);
@@ -198,9 +224,11 @@ void Scatter3DController::handleItemsInserted(int startIndex, int count)
}
if (series->isVisible()) {
- adjustValueAxisRange();
+ adjustAxisRanges();
m_isDataDirty = true;
}
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
if (m_recordInsertsAndRemoves) {
InsertRemoveRecord record(true, startIndex, count, series);
@@ -229,7 +257,7 @@ void Scatter3DController::handleAxisAutoAdjustRangeChangedInOrientation(
{
Q_UNUSED(orientation)
Q_UNUSED(autoAdjust)
- adjustValueAxisRange();
+ adjustAxisRanges();
}
void Scatter3DController::handleAxisRangeChangedBySender(QObject *sender)
@@ -240,13 +268,6 @@ void Scatter3DController::handleAxisRangeChangedBySender(QObject *sender)
setSelectedItem(m_selectedItem, m_selectedItemSeries);
}
-void Scatter3DController::handleSeriesVisibilityChangedBySender(QObject *sender)
-{
- Abstract3DController::handleSeriesVisibilityChangedBySender(sender);
-
- adjustValueAxisRange();
-}
-
void Scatter3DController::handlePendingClick()
{
int index = m_renderer->clickedIndex();
@@ -274,6 +295,8 @@ void Scatter3DController::handlePendingClick()
setSelectedItem(index, series);
+ Abstract3DController::handlePendingClick();
+
m_renderer->resetClickedStatus();
}
@@ -329,7 +352,7 @@ void Scatter3DController::clearSelection()
setSelectedItem(invalidSelectionIndex(), 0);
}
-void Scatter3DController::adjustValueAxisRange()
+void Scatter3DController::adjustAxisRanges()
{
QValue3DAxis *valueAxisX = static_cast<QValue3DAxis *>(m_axisX);
QValue3DAxis *valueAxisY = static_cast<QValue3DAxis *>(m_axisY);
@@ -407,7 +430,7 @@ void Scatter3DController::adjustValueAxisRange()
adjustment = defaultAdjustment;
}
}
- valueAxisX->dptr()->setRange(minValueX - adjustment, maxValueX + adjustment);
+ valueAxisX->dptr()->setRange(minValueX - adjustment, maxValueX + adjustment, true);
}
if (adjustY) {
// If all points at same coordinate, need to default to some valid range
@@ -415,7 +438,7 @@ void Scatter3DController::adjustValueAxisRange()
float adjustment = 0.0f;
if (minValueY == maxValueY)
adjustment = defaultAdjustment;
- valueAxisY->dptr()->setRange(minValueY - adjustment, maxValueY + adjustment);
+ valueAxisY->dptr()->setRange(minValueY - adjustment, maxValueY + adjustment, true);
}
if (adjustZ) {
// If all points at same coordinate, need to default to some valid range
@@ -434,7 +457,7 @@ void Scatter3DController::adjustValueAxisRange()
adjustment = defaultAdjustment;
}
}
- valueAxisZ->dptr()->setRange(minValueZ - adjustment, maxValueZ + adjustment);
+ valueAxisZ->dptr()->setRange(minValueZ - adjustment, maxValueZ + adjustment, true);
}
}
}
diff --git a/src/datavisualization/engine/scatter3dcontroller_p.h b/src/datavisualization/engine/scatter3dcontroller_p.h
index 53d24549..db5a95f5 100644
--- a/src/datavisualization/engine/scatter3dcontroller_p.h
+++ b/src/datavisualization/engine/scatter3dcontroller_p.h
@@ -40,9 +40,11 @@ class QScatter3DSeries;
struct Scatter3DChangeBitField {
bool selectedItemChanged : 1;
+ bool itemChanged : 1;
Scatter3DChangeBitField() :
- selectedItemChanged(true)
+ selectedItemChanged(true),
+ itemChanged(false)
{
}
};
@@ -51,8 +53,14 @@ class QT_DATAVISUALIZATION_EXPORT Scatter3DController : public Abstract3DControl
{
Q_OBJECT
+public:
+ struct ChangeItem {
+ QScatter3DSeries *series;
+ int index;
+ };
private:
Scatter3DChangeBitField m_changeTracker;
+ QVector<ChangeItem> m_changedItems;
// Rendering
Scatter3DRenderer *m_renderer;
@@ -108,8 +116,8 @@ public:
virtual void handleAxisAutoAdjustRangeChangedInOrientation(
QAbstract3DAxis::AxisOrientation orientation, bool autoAdjust);
virtual void handleAxisRangeChangedBySender(QObject *sender);
- virtual void handleSeriesVisibilityChangedBySender(QObject *sender);
virtual void handlePendingClick();
+ virtual void adjustAxisRanges();
public slots:
void handleArrayReset();
@@ -125,7 +133,6 @@ protected:
virtual void startRecordingRemovesAndInserts();
private:
- void adjustValueAxisRange();
Q_DISABLE_COPY(Scatter3DController)
};
diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp
index de1a769a..21d86d03 100644
--- a/src/datavisualization/engine/scatter3drenderer.cpp
+++ b/src/datavisualization/engine/scatter3drenderer.cpp
@@ -17,25 +17,16 @@
****************************************************************************/
#include "scatter3drenderer_p.h"
-#include "scatter3dcontroller_p.h"
-#include "q3dcamera.h"
#include "q3dcamera_p.h"
#include "shaderhelper_p.h"
-#include "objecthelper_p.h"
#include "texturehelper_p.h"
#include "utils_p.h"
-#include "q3dlight.h"
-#include "qscatter3dseries_p.h"
+#include "scatterseriesrendercache_p.h"
+#include "scatterobjectbufferhelper_p.h"
+#include "scatterpointbufferhelper_p.h"
-#include <QtGui/QMatrix4x4>
-#include <QtGui/QMouseEvent>
-#include <QtCore/QThread>
#include <QtCore/qmath.h>
-// Commenting this draws the shadow map with perspective projection. Otherwise it's drawn in
-// orthographic projection.
-//#define USE_WIDER_SHADOWS
-
// You can verify that depth buffer drawing works correctly by uncommenting this.
// You should see the scene from where the light is
//#define SHOW_DEPTH_TEXTURE_SCENE
@@ -44,20 +35,14 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
//#define USE_UNIFORM_SCALING // Scale x and z uniformly, or based on autoscaled values
-const GLfloat aspectRatio = 2.0f; // Forced ratio of x and z to y. Dynamic will make it look odd.
-const GLfloat labelMargin = 0.05f;
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;
Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller)
: Abstract3DRenderer(controller),
m_selectedItem(0),
- m_xFlipped(false),
- m_zFlipped(false),
- m_yFlipped(false),
m_updateLabels(false),
m_dotShader(0),
m_dotGradientShader(0),
@@ -68,9 +53,6 @@ Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller)
m_selectionShader(0),
m_backgroundShader(0),
m_labelShader(0),
- m_backgroundObj(0),
- m_gridLineObj(0),
- m_labelObj(0),
m_bgrTexture(0),
m_depthTexture(0),
m_selectionTexture(0),
@@ -82,16 +64,22 @@ Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller)
m_heightNormalizer(1.0f),
m_scaleFactor(0),
m_selectedItemIndex(Scatter3DController::invalidSelectionIndex()),
- m_selectedItemTotalIndex(Scatter3DController::invalidSelectionIndex()),
- m_selectedItemSeriesIndex(Scatter3DController::invalidSelectionIndex()),
- m_selectedSeries(0),
+ m_selectedSeriesCache(0),
+ m_oldSelectedSeriesCache(0),
m_areaSize(QSizeF(0.0, 0.0)),
m_dotSizeScale(1.0f),
m_hasHeightAdjustmentChanged(true),
- m_backgroundMargin(defaultMargin),
+ m_backgroundMargin(defaultMaxSize),
m_maxItemSize(0.0f),
- m_clickedIndex(Scatter3DController::invalidSelectionIndex())
+ m_clickedIndex(Scatter3DController::invalidSelectionIndex()),
+ m_havePointSeries(false),
+ m_haveMeshSeries(false),
+ m_haveUniformColorMeshSeries(false),
+ m_haveGradientMeshSeries(false)
{
+ m_axisCacheY.setScale(2.0f);
+ m_axisCacheY.setTranslate(-1.0f);
+
initializeOpenGLFunctions();
initializeOpenGL();
}
@@ -111,9 +99,6 @@ Scatter3DRenderer::~Scatter3DRenderer()
delete m_selectionShader;
delete m_backgroundShader;
delete m_labelShader;
- delete m_backgroundObj;
- delete m_gridLineObj;
- delete m_labelObj;
}
void Scatter3DRenderer::initializeOpenGL()
@@ -135,8 +120,10 @@ void Scatter3DRenderer::initializeOpenGL()
// Init selection shader
initSelectionShader();
+#if !defined(QT_OPENGL_ES_2)
// Load grid line mesh
loadGridLineMesh();
+#endif
// Load label mesh
loadLabelMesh();
@@ -151,78 +138,153 @@ void Scatter3DRenderer::initializeOpenGL()
loadBackgroundMesh();
}
-void Scatter3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList,
- bool updateVisibility)
+void Scatter3DRenderer::updateData()
{
- Abstract3DRenderer::updateSeries(seriesList, updateVisibility);
+ calculateSceneScalingFactors();
+ int totalDataSize = 0;
- int seriesCount = m_visibleSeriesList.size();
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ ScatterSeriesRenderCache *cache = static_cast<ScatterSeriesRenderCache *>(baseCache);
+ if (cache->isVisible() && cache->dataDirty()) {
+ const QScatter3DSeries *currentSeries = cache->series();
+ ScatterRenderItemArray &renderArray = cache->renderArray();
+ QScatterDataProxy *dataProxy = currentSeries->dataProxy();
+ const QScatterDataArray &dataArray = *dataProxy->array();
+ int dataSize = dataArray.size();
+ totalDataSize += dataSize;
+ if (dataSize != renderArray.size())
+ renderArray.resize(dataSize);
+
+ for (int i = 0; i < dataSize; i++)
+ updateRenderItem(dataArray.at(i), renderArray[i]);
+ cache->setDataDirty(false);
+ }
+ }
+
+ if (totalDataSize) {
+ m_dotSizeScale = GLfloat(qBound(defaultMinSize, 2.0f / float(qSqrt(qreal(totalDataSize))),
+ defaultMaxSize));
+ }
+
+ if (m_cachedOptimizationHint.testFlag(QAbstract3DGraph::OptimizationStatic)) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ ScatterSeriesRenderCache *cache = static_cast<ScatterSeriesRenderCache *>(baseCache);
+ if (cache->isVisible()) {
+ ScatterRenderItemArray &renderArray = cache->renderArray();
+ const int renderArraySize = renderArray.size();
+
+ if (cache->mesh() == QAbstract3DSeries::MeshPoint) {
+ ScatterPointBufferHelper *points = cache->bufferPoints();
+ if (!points) {
+ points = new ScatterPointBufferHelper();
+ cache->setBufferPoints(points);
+ }
+ points->load(cache);
+ } else {
+ ScatterObjectBufferHelper *object = cache->bufferObject();
+ if (!object) {
+ object = new ScatterObjectBufferHelper();
+ cache->setBufferObject(object);
+ }
+ if (renderArraySize != cache->oldArraySize()
+ || cache->object()->objectFile() != cache->oldMeshFileName()) {
+ object->fullLoad(cache, m_dotSizeScale);
+ cache->setOldArraySize(renderArraySize);
+ cache->setOldMeshFileName(cache->object()->objectFile());
+ } else {
+ object->update(cache, m_dotSizeScale);
+ }
+ }
+ }
+ }
+ }
+
+ updateSelectedItem(m_selectedItemIndex,
+ m_selectedSeriesCache ? m_selectedSeriesCache->series() : 0);
+}
+
+void Scatter3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList)
+{
+ Abstract3DRenderer::updateSeries(seriesList);
+
+ int seriesCount = seriesList.size();
float maxItemSize = 0.0f;
float itemSize = 0.0f;
+ bool noSelection = true;
- if (m_cachedItemSize.size() != seriesCount)
- m_cachedItemSize.resize(seriesCount);
+ m_havePointSeries = false;
+ m_haveMeshSeries = false;
+ m_haveUniformColorMeshSeries = false;
+ m_haveGradientMeshSeries = false;
- for (int series = 0; series < seriesCount; series++) {
- itemSize = static_cast<QScatter3DSeries *>(m_visibleSeriesList.at(series).series())->itemSize();
- if (maxItemSize < itemSize)
- maxItemSize = itemSize;
- if (m_cachedItemSize.at(series) != itemSize)
- m_cachedItemSize[series] = itemSize;
+ for (int i = 0; i < seriesCount; i++) {
+ QScatter3DSeries *scatterSeries = static_cast<QScatter3DSeries *>(seriesList[i]);
+ if (scatterSeries->isVisible()) {
+ ScatterSeriesRenderCache *cache =
+ static_cast<ScatterSeriesRenderCache *>(m_renderCacheList.value(scatterSeries));
+ itemSize = scatterSeries->itemSize();
+ if (maxItemSize < itemSize)
+ maxItemSize = itemSize;
+ if (cache->itemSize() != itemSize)
+ cache->setItemSize(itemSize);
+ if (noSelection
+ && scatterSeries->selectedItem() != QScatter3DSeries::invalidSelectionIndex()) {
+ if (m_selectionLabel != cache->itemLabel())
+ m_selectionLabelDirty = true;
+ noSelection = false;
+ }
+
+ if (cache->mesh() == QAbstract3DSeries::MeshPoint) {
+ m_havePointSeries = true;
+ } else {
+ m_haveMeshSeries = true;
+ if (cache->colorStyle() == Q3DTheme::ColorStyleUniform)
+ m_haveUniformColorMeshSeries = true;
+ else
+ m_haveGradientMeshSeries = true;
+ }
+ }
}
- m_backgroundMargin = defaultMargin;
m_maxItemSize = maxItemSize;
if (maxItemSize > defaultMaxSize)
- m_backgroundMargin += maxItemSize / itemScaler;
+ m_backgroundMargin = maxItemSize / itemScaler;
+ else
+ m_backgroundMargin = defaultMaxSize;
+
+ if (noSelection) {
+ if (!selectionLabel().isEmpty())
+ m_selectionLabelDirty = true;
+ m_selectedSeriesCache = 0;
+ }
}
-void Scatter3DRenderer::updateData()
+SeriesRenderCache *Scatter3DRenderer::createNewCache(QAbstract3DSeries *series)
{
- int seriesCount = m_visibleSeriesList.size();
- calculateSceneScalingFactors();
- 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());
- int totalDataSize = 0;
+ return new ScatterSeriesRenderCache(series, this);
+}
- 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();
- ScatterRenderItem &renderItem = m_renderingArrays[series][i];
- if ((dotPos.x() >= minX && dotPos.x() <= maxX )
- && (dotPos.y() >= minY && dotPos.y() <= maxY)
- && (dotPos.z() >= minZ && dotPos.z() <= maxZ)) {
- renderItem.setPosition(dotPos);
- renderItem.setVisible(true);
- if (!dataArray.at(i).rotation().isIdentity())
- renderItem.setRotation(dataArray.at(i).rotation().normalized());
- else
- renderItem.setRotation(identityQuaternion);
- calculateTranslation(renderItem);
- } else {
- renderItem.setVisible(false);
- }
+void Scatter3DRenderer::updateItems(const QVector<Scatter3DController::ChangeItem> &items)
+{
+ ScatterSeriesRenderCache *cache = 0;
+ const QScatter3DSeries *prevSeries = 0;
+ const QScatterDataArray *dataArray = 0;
+
+ foreach (Scatter3DController::ChangeItem item, items) {
+ QScatter3DSeries *currentSeries = item.series;
+ if (currentSeries != prevSeries) {
+ cache = static_cast<ScatterSeriesRenderCache *>(m_renderCacheList.value(currentSeries));
+ prevSeries = currentSeries;
+ dataArray = item.series->dataProxy()->array();
+ // Invisible series render caches are not updated, but instead just marked dirty, so that
+ // they can be completely recalculated when they are turned visible.
+ if (!cache->isVisible() && !cache->dataDirty())
+ cache->setDataDirty(true);
+ }
+ if (cache->isVisible()) {
+ const int index = item.index;
+ updateRenderItem(dataArray->at(index), cache->renderArray()[index]);
}
}
- m_dotSizeScale = GLfloat(qBound(defaultMinSize, 2.0f / float(qSqrt(qreal(totalDataSize))),
- defaultMaxSize));
-
- updateSelectedItem(m_selectedItemIndex, m_selectedSeries);
}
void Scatter3DRenderer::updateScene(Q3DScene *scene)
@@ -231,7 +293,8 @@ void Scatter3DRenderer::updateScene(Q3DScene *scene)
if (m_hasHeightAdjustmentChanged) {
// Set initial camera position. Also update if height adjustment has changed.
- scene->activeCamera()->d_ptr->setBaseOrientation(cameraDistanceVector, zeroVector, upVector);
+ scene->activeCamera()->d_ptr->setBaseOrientation(cameraDistanceVector, zeroVector,
+ upVector);
m_hasHeightAdjustmentChanged = false;
}
@@ -249,6 +312,13 @@ void Scatter3DRenderer::render(GLuint defaultFboHandle)
// Handle GL state setup for FBO buffers and clearing of the render surface
Abstract3DRenderer::render(defaultFboHandle);
+ if (m_axisCacheX.positionsDirty())
+ m_axisCacheX.updateAllPositions();
+ if (m_axisCacheY.positionsDirty())
+ m_axisCacheY.updateAllPositions();
+ if (m_axisCacheZ.positionsDirty())
+ m_axisCacheZ.updateAllPositions();
+
// Draw dots scene
drawScene(defaultFboHandle);
}
@@ -258,9 +328,13 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
GLfloat backgroundRotation = 0;
GLfloat selectedItemSize = 0.0f;
+ // Get the optimization flag
+ const bool optimizationDefault =
+ !m_cachedOptimizationHint.testFlag(QAbstract3DGraph::OptimizationStatic);
+
const Q3DCamera *activeCamera = m_cachedScene->activeCamera();
- QVector3D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor());
+ QVector4D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor());
// Specify viewport
glViewport(m_primarySubViewport.x(),
@@ -272,14 +346,19 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
QMatrix4x4 projectionMatrix;
GLfloat viewPortRatio = (GLfloat)m_primarySubViewport.width()
/ (GLfloat)m_primarySubViewport.height();
- projectionMatrix.perspective(45.0f, viewPortRatio, 0.1f, 100.0f);
+ if (m_useOrthoProjection) {
+ GLfloat orthoRatio = 2.0f;
+ projectionMatrix.ortho(-viewPortRatio * orthoRatio, viewPortRatio * orthoRatio,
+ -orthoRatio, orthoRatio,
+ 0.0f, 100.0f);
+ } else {
+ projectionMatrix.perspective(45.0f, viewPortRatio, 0.1f, 100.0f);
+ }
// Calculate view matrix
QMatrix4x4 viewMatrix = activeCamera->d_ptr->viewMatrix();
QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix;
- int seriesCount = m_visibleSeriesList.size();
-
// Calculate label flipping
if (viewMatrix.row(0).x() > 0)
m_zFlipped = false;
@@ -314,25 +393,8 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
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) {
+ if (m_havePointSeries) {
glEnable(GL_POINT_SMOOTH);
glEnable(GL_PROGRAM_POINT_SIZE);
}
@@ -360,77 +422,107 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
zeroVector, 0.0f, 2.5f / m_autoScaleAdjustment);
depthViewMatrix.lookAt(depthLightPos, zeroVector, upVector);
// Set the depth projection matrix
-#ifndef USE_WIDER_SHADOWS
- // Use this for perspective shadows
depthProjectionMatrix.perspective(15.0f, viewPortRatio, 3.0f, 100.0f);
-#else
- // Use these for orthographic shadows
- GLfloat testAspectRatio = viewPortRatio;
- depthProjectionMatrix.ortho(-testAspectRatio * 2.0f, testAspectRatio * 2.0f,
- -m_heightNormalizer * 2.0f, m_heightNormalizer * 2.0f,
- 0.0f, 100.0f);
-#endif
depthProjectionViewMatrix = depthProjectionMatrix * depthViewMatrix;
// Draw dots to depth buffer
- for (int series = 0; series < seriesCount; series++) {
- ObjectHelper *dotObj = m_visibleSeriesList.at(series).object();
- QQuaternion seriesRotation = m_visibleSeriesList.at(series).meshRotation();
- bool drawingPoints = (m_visibleSeriesList.at(series).mesh() == QAbstract3DSeries::MeshPoint);
-
- float itemSize = m_cachedItemSize.at(series) / 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);
-
- for (int dot = 0; dot < m_renderingArrays.at(series).size(); dot++) {
- const ScatterRenderItem &item = m_renderingArrays.at(series).at(dot);
- if (!item.isVisible())
- continue;
-
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
-
- modelMatrix.translate(item.translation());
- if (!drawingPoints) {
- if (!seriesRotation.isIdentity() || !item.rotation().isIdentity())
- modelMatrix.rotate(seriesRotation * item.rotation());
- modelMatrix.scale(modelScaler);
- }
-
- MVPMatrix = depthProjectionViewMatrix * modelMatrix;
-
- m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix);
-
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ if (baseCache->isVisible()) {
+ ScatterSeriesRenderCache *cache =
+ static_cast<ScatterSeriesRenderCache *>(baseCache);
+ ObjectHelper *dotObj = cache->object();
+ QQuaternion seriesRotation(cache->meshRotation());
+ const ScatterRenderItemArray &renderArray = cache->renderArray();
+ const int renderArraySize = renderArray.size();
+ bool drawingPoints = (cache->mesh() == QAbstract3DSeries::MeshPoint);
+ float itemSize = cache->itemSize() / itemScaler;
+ if (itemSize == 0.0f)
+ itemSize = m_dotSizeScale;
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);
-
- // Index buffer
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dotObj->elementBuf());
-
- // Draw the triangles
- glDrawElements(GL_TRIANGLES, dotObj->indexCount(), GL_UNSIGNED_SHORT,
- (void *)0);
-
- // Free buffers
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
- glDisableVertexAttribArray(m_depthShader->posAtt());
+ // Scale points based on shadow quality for shadows, not by zoom level
+ glPointSize(itemSize * 100.0f * m_shadowQualityMultiplier);
+ }
+ QVector3D modelScaler(itemSize, itemSize, itemSize);
+
+ int loopCount = 1;
+ if (optimizationDefault)
+ loopCount = renderArraySize;
+ for (int dot = 0; dot < loopCount; dot++) {
+ const ScatterRenderItem &item = renderArray.at(dot);
+ if (!item.isVisible() && optimizationDefault)
+ continue;
+
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+
+ if (optimizationDefault) {
+ modelMatrix.translate(item.translation());
+ if (!drawingPoints) {
+ if (!seriesRotation.isIdentity() || !item.rotation().isIdentity())
+ modelMatrix.rotate(seriesRotation * item.rotation());
+ modelMatrix.scale(modelScaler);
+ }
+ }
+
+ MVPMatrix = depthProjectionViewMatrix * modelMatrix;
+
+ m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix);
+
+ if (drawingPoints) {
+ if (optimizationDefault)
+ m_drawer->drawPoint(m_depthShader);
+ else
+ m_drawer->drawPoints(m_depthShader, cache->bufferPoints());
+ } else {
+ if (optimizationDefault) {
+ // 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);
+
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dotObj->elementBuf());
+
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, dotObj->indexCount(), GL_UNSIGNED_SHORT,
+ (void *)0);
+
+ // Free buffers
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDisableVertexAttribArray(m_depthShader->posAtt());
+ } else {
+ ScatterObjectBufferHelper *object = cache->bufferObject();
+ // 1st attribute buffer : vertices
+ glEnableVertexAttribArray(m_depthShader->posAtt());
+ glBindBuffer(GL_ARRAY_BUFFER, object->vertexBuf());
+ glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0,
+ (void *)0);
+
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object->elementBuf());
+
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, object->indexCount(),
+ object->indicesType(), (void *)0);
+
+ // Free buffers
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDisableVertexAttribArray(m_depthShader->posAtt());
+ }
+ }
}
}
}
+ Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, viewMatrix,
+ projectionViewMatrix, depthProjectionViewMatrix,
+ m_depthTexture, m_shadowQualityToShader);
+
// Disable drawing to framebuffer (= enable drawing to screen)
glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle);
@@ -446,14 +538,14 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
ShaderHelper *pointSelectionShader = m_selectionShader;
#else
- Q_UNUSED(havePointSeries);
ShaderHelper *pointSelectionShader = m_pointShader;
#endif
ShaderHelper *selectionShader = m_selectionShader;
// Skip selection mode drawing if we have no selection mode
if (m_cachedSelectionMode > QAbstract3DGraph::SelectionNone
- && SelectOnScene == m_selectionState && seriesCount > 0) {
+ && SelectOnScene == m_selectionState
+ && (m_visibleSeriesCount > 0 || !m_customRenderCache.isEmpty())) {
// Draw dots to selection buffer
glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer);
glViewport(0, 0,
@@ -465,94 +557,80 @@ 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 = 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();
- QQuaternion seriesRotation = m_visibleSeriesList.at(series).meshRotation();
- bool drawingPoints = (m_visibleSeriesList.at(series).mesh() == QAbstract3DSeries::MeshPoint);
-
- float itemSize = m_cachedItemSize.at(series) / itemScaler;
- if (itemSize == 0.0f)
- itemSize = m_dotSizeScale;
+ bool previousDrawingPoints = false;
+ int totalIndex = 0;
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ if (baseCache->isVisible()) {
+ ScatterSeriesRenderCache *cache =
+ static_cast<ScatterSeriesRenderCache *>(baseCache);
+ ObjectHelper *dotObj = cache->object();
+ QQuaternion seriesRotation(cache->meshRotation());
+ const ScatterRenderItemArray &renderArray = cache->renderArray();
+ const int renderArraySize = renderArray.size();
+ bool drawingPoints = (cache->mesh() == QAbstract3DSeries::MeshPoint);
+ float itemSize = cache->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 selection shader if it has changed
- if (drawingPoints != previousDrawingPoints) {
- previousDrawingPoints = drawingPoints;
if (drawingPoints)
- selectionShader = pointSelectionShader;
- else
- selectionShader = m_selectionShader;
-
- selectionShader->bind();
- }
- arraySize = m_renderingArrays.at(series).size();
- totalArraySize += arraySize;
-
- if (totalArraySize > 0xfffffe) // Max possible different selection colors, 0xffffff being skipColor
- qFatal("Too many objects");
-
- for (int dot = 0; dot < arraySize; dot++) {
- const ScatterRenderItem &item = m_renderingArrays.at(series).at(dot);
- if (!item.isVisible())
- continue;
+ glPointSize(itemSize * activeCamera->zoomLevel()); // Scale points based on zoom
+#endif
+ QVector3D modelScaler(itemSize, itemSize, itemSize);
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
+ // Rebind selection shader if it has changed
+ if (!totalIndex || drawingPoints != previousDrawingPoints) {
+ previousDrawingPoints = drawingPoints;
+ if (drawingPoints)
+ selectionShader = pointSelectionShader;
+ else
+ selectionShader = m_selectionShader;
- modelMatrix.translate(item.translation());
- if (!drawingPoints) {
- if (!seriesRotation.isIdentity() || !item.rotation().isIdentity())
- modelMatrix.rotate(seriesRotation * item.rotation());
- modelMatrix.scale(modelScaler);
+ selectionShader->bind();
}
-
- MVPMatrix = projectionViewMatrix * modelMatrix;
-
- QVector3D dotColor = indexToSelectionColor(dotNo);
- dotColor /= 255.0f;
-
- selectionShader->setUniformValue(selectionShader->MVP(), MVPMatrix);
- selectionShader->setUniformValue(selectionShader->color(), dotColor);
-
- 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);
-
- // Index buffer
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dotObj->elementBuf());
-
- // Draw the triangles
- glDrawElements(GL_TRIANGLES, dotObj->indexCount(), GL_UNSIGNED_SHORT,
- (void *)0);
-
- // Free buffers
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
- glDisableVertexAttribArray(selectionShader->posAtt());
+ cache->setSelectionIndexOffset(totalIndex);
+ for (int dot = 0; dot < renderArraySize; dot++) {
+ const ScatterRenderItem &item = renderArray.at(dot);
+ if (!item.isVisible()) {
+ totalIndex++;
+ continue;
+ }
+
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+
+ modelMatrix.translate(item.translation());
+ if (!drawingPoints) {
+ if (!seriesRotation.isIdentity() || !item.rotation().isIdentity())
+ modelMatrix.rotate(seriesRotation * item.rotation());
+ modelMatrix.scale(modelScaler);
+ }
+
+ MVPMatrix = projectionViewMatrix * modelMatrix;
+
+ QVector4D dotColor = indexToSelectionColor(totalIndex++);
+ dotColor /= 255.0f;
+
+ selectionShader->setUniformValue(selectionShader->MVP(), MVPMatrix);
+ selectionShader->setUniformValue(selectionShader->color(), dotColor);
+
+ if (drawingPoints)
+ m_drawer->drawPoint(selectionShader);
+ else
+ m_drawer->drawSelectionObject(selectionShader, dotObj);
}
- dotNo++;
}
}
+
+ Abstract3DRenderer::drawCustomItems(RenderingSelection, m_selectionShader, viewMatrix,
+ projectionViewMatrix, depthProjectionViewMatrix,
+ m_depthTexture, m_shadowQualityToShader);
+
+ drawLabels(true, activeCamera, viewMatrix, projectionMatrix);
+
glEnable(GL_DITHER);
// Read color under cursor
- QVector3D clickedColor = Utils::getSelection(m_inputPosition,
+ QVector4D clickedColor = Utils::getSelection(m_inputPosition,
m_viewport.height());
selectionColorToSeriesAndIndex(clickedColor, m_clickedIndex, m_clickedSeries);
@@ -571,15 +649,14 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
GLuint gradientTexture = 0;
bool dotSelectionFound = false;
ScatterRenderItem *selectedItem(0);
- int dotNo = 0;
- QVector3D baseColor;
- QVector3D dotColor;
+ QVector4D baseColor;
+ QVector4D dotColor;
bool previousDrawingPoints = false;
Q3DTheme::ColorStyle previousMeshColorStyle = Q3DTheme::ColorStyleUniform;
- if (haveMeshSeries) {
+ if (m_haveMeshSeries) {
// Set unchanging shader bindings
- if (haveGradientMeshSeries) {
+ if (m_haveGradientMeshSeries) {
m_dotGradientShader->bind();
m_dotGradientShader->setUniformValue(m_dotGradientShader->lightP(), lightPos);
m_dotGradientShader->setUniformValue(m_dotGradientShader->view(), viewMatrix);
@@ -587,7 +664,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
m_cachedTheme->ambientLightStrength());
m_dotGradientShader->setUniformValue(m_dotGradientShader->lightColor(), lightColor);
}
- if (haveUniformColorMeshSeries) {
+ if (m_haveUniformColorMeshSeries) {
m_dotShader->bind();
m_dotShader->setUniformValue(m_dotShader->lightP(), lightPos);
m_dotShader->setUniformValue(m_dotShader->view(), viewMatrix);
@@ -607,152 +684,281 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
dotShader->bind();
}
- for (int series = 0; series < seriesCount; series++) {
- const SeriesRenderCache &currentSeries = m_visibleSeriesList.at(series);
- QQuaternion seriesRotation = currentSeries.meshRotation();
- ObjectHelper *dotObj = currentSeries.object();
- bool drawingPoints = (currentSeries.mesh() == QAbstract3DSeries::MeshPoint);
- Q3DTheme::ColorStyle colorStyle = currentSeries.colorStyle();
- bool colorStyleIsUniform = (colorStyle == Q3DTheme::ColorStyleUniform);
- bool useColor = colorStyleIsUniform || drawingPoints;
-
- float itemSize = m_cachedItemSize.at(series) / itemScaler;
- if (itemSize == 0.0f)
- itemSize = m_dotSizeScale;
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ if (baseCache->isVisible()) {
+ ScatterSeriesRenderCache *cache =
+ static_cast<ScatterSeriesRenderCache *>(baseCache);
+ ObjectHelper *dotObj = cache->object();
+ QQuaternion seriesRotation(cache->meshRotation());
+ ScatterRenderItemArray &renderArray = cache->renderArray();
+ const int renderArraySize = renderArray.size();
+ bool selectedSeries = m_cachedSelectionMode > QAbstract3DGraph::SelectionNone
+ && (m_selectedSeriesCache == cache);
+ bool drawingPoints = (cache->mesh() == QAbstract3DSeries::MeshPoint);
+ Q3DTheme::ColorStyle colorStyle = cache->colorStyle();
+ bool colorStyleIsUniform = (colorStyle == Q3DTheme::ColorStyleUniform);
+ bool useColor = colorStyleIsUniform || drawingPoints;
+ bool rangeGradientPoints = drawingPoints
+ && (colorStyle == Q3DTheme::ColorStyleRangeGradient);
+ float itemSize = cache->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
+ 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;
+ 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();
}
- dotShader->bind();
- }
- 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);
+ 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 dot is of uniform color according to its Y-coordinate
+ m_dotGradientShader->setUniformValue(m_dotGradientShader->gradientHeight(),
+ 0.0f);
+ }
}
- }
- if (!drawingPoints)
- previousMeshColorStyle = colorStyle;
+ if (!drawingPoints)
+ previousMeshColorStyle = colorStyle;
- if (useColor) {
- baseColor = currentSeries.baseColor();
- dotColor = baseColor;
- }
+ if (useColor) {
+ baseColor = cache->baseColor();
+ dotColor = baseColor;
+ }
+ int loopCount = 1;
+ if (optimizationDefault)
+ loopCount = renderArraySize;
+ for (int i = 0; i < loopCount; i++) {
+ ScatterRenderItem &item = renderArray[i];
+ if (!item.isVisible() && optimizationDefault)
+ continue;
- int seriesSize = m_renderingArrays.at(series).size();
- for (int dot = 0; dot < seriesSize; dot++) {
- ScatterRenderItem &item = m_renderingArrays[series][dot];
- if (!item.isVisible())
- continue;
-
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
- QMatrix4x4 itModelMatrix;
-
- modelMatrix.translate(item.translation());
- if (!drawingPoints) {
- if (!seriesRotation.isIdentity() || !item.rotation().isIdentity()) {
- QQuaternion totalRotation = seriesRotation * item.rotation();
- modelMatrix.rotate(totalRotation);
- itModelMatrix.rotate(totalRotation);
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+ QMatrix4x4 itModelMatrix;
+
+ if (optimizationDefault) {
+ modelMatrix.translate(item.translation());
+ if (!drawingPoints) {
+ if (!seriesRotation.isIdentity() || !item.rotation().isIdentity()) {
+ QQuaternion totalRotation = seriesRotation * item.rotation();
+ modelMatrix.rotate(totalRotation);
+ itModelMatrix.rotate(totalRotation);
+ }
+ modelMatrix.scale(modelScaler);
+ itModelMatrix.scale(modelScaler);
+ }
}
- modelMatrix.scale(modelScaler);
- itModelMatrix.scale(modelScaler);
- }
#ifdef SHOW_DEPTH_TEXTURE_SCENE
- MVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ MVPMatrix = depthProjectionViewMatrix * modelMatrix;
#else
- MVPMatrix = projectionViewMatrix * modelMatrix;
+ MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
- if (useColor)
- dotColor = baseColor;
- else
- gradientTexture = currentSeries.baseGradientTexture();
+ if (useColor) {
+ if (rangeGradientPoints) {
+ // Drawing points with range gradient
+ // Get color from gradient based on items y position converted to percent
+ int position = int(item.translation().y() * 50.0f) + 50;
+ dotColor = Utils::vectorFromColor(
+ cache->gradientImage().pixel(0, position));
+ } else {
+ dotColor = baseColor;
+ }
+ } else {
+ gradientTexture = cache->baseGradientTexture();
+ }
+
+ GLfloat lightStrength = m_cachedTheme->lightStrength();
+ if (optimizationDefault && selectedSeries && (m_selectedItemIndex == i)) {
+ if (useColor)
+ dotColor = cache->singleHighlightColor();
+ else
+ gradientTexture = cache->singleHighlightGradientTexture();
+ lightStrength = m_cachedTheme->highlightLightStrength();
+ // Insert data to ScatterRenderItem
+ // We don't have ownership, so don't delete the previous one
+ selectedItem = &item;
+ dotSelectionFound = true;
+ // Save selected item size (adjusted with font size) for selection label
+ // positioning
+ selectedItemSize = itemSize + (m_cachedTheme->font().pointSizeF() / 500.0f);
+ }
+
+ 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.translation().y() + 1.0f) / 2.0f);
+ }
+#if !defined(QT_OPENGL_ES_2)
+ if (m_cachedShadowQuality > QAbstract3DGraph::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
+ if (optimizationDefault) {
+ m_drawer->drawObject(dotShader, dotObj, gradientTexture,
+ m_depthTexture);
+ } else {
+ m_drawer->drawObject(dotShader, cache->bufferObject(), gradientTexture,
+ m_depthTexture);
+ }
+ } else {
+ // Draw the object
+ if (optimizationDefault)
+ m_drawer->drawPoint(dotShader);
+ else
+ m_drawer->drawPoints(dotShader, cache->bufferPoints());
+ }
+ } else
+#endif
+ {
+ if (!drawingPoints) {
+ // Set shadowless shader bindings
+ dotShader->setUniformValue(dotShader->lightS(), lightStrength);
+ // Draw the object
+ if (optimizationDefault)
+ m_drawer->drawObject(dotShader, dotObj, gradientTexture);
+ else
+ m_drawer->drawObject(dotShader, cache->bufferObject(), gradientTexture);
+ } else {
+ // Draw the object
+ if (optimizationDefault)
+ m_drawer->drawPoint(dotShader);
+ else
+ m_drawer->drawPoints(dotShader, cache->bufferPoints());
+ }
+ }
+ }
+
+ // Draw the selected item on static optimization
+ if (!optimizationDefault && selectedSeries
+ && m_selectedItemIndex != Scatter3DController::invalidSelectionIndex()) {
+ ScatterRenderItem &item = renderArray[m_selectedItemIndex];
+ ObjectHelper *dotObj = cache->object();
+
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 itModelMatrix;
+
+ modelMatrix.translate(item.translation());
+ if (!drawingPoints) {
+ if (!seriesRotation.isIdentity() || !item.rotation().isIdentity()) {
+ QQuaternion totalRotation = seriesRotation * item.rotation();
+ modelMatrix.rotate(totalRotation);
+ itModelMatrix.rotate(totalRotation);
+ }
+ modelMatrix.scale(modelScaler);
+ itModelMatrix.scale(modelScaler);
+ }
+
+ QMatrix4x4 MVPMatrix;
+#ifdef SHOW_DEPTH_TEXTURE_SCENE
+ MVPMatrix = depthProjectionViewMatrix * modelMatrix;
+#else
+ MVPMatrix = projectionViewMatrix * modelMatrix;
+#endif
- GLfloat lightStrength = m_cachedTheme->lightStrength();
- if (m_cachedSelectionMode > QAbstract3DGraph::SelectionNone
- && (m_selectedItemTotalIndex == dotNo)) {
if (useColor)
- dotColor = currentSeries.singleHighlightColor();
+ dotColor = cache->singleHighlightColor();
else
- gradientTexture = currentSeries.singleHighlightGradientTexture();
- lightStrength = m_cachedTheme->highlightLightStrength();
- // Insert data to ScatterRenderItem. We have no ownership, don't delete the previous one
+ gradientTexture = cache->singleHighlightGradientTexture();
+ GLfloat lightStrength = m_cachedTheme->highlightLightStrength();
+ // Save the reference to the item to be used on label drawing
selectedItem = &item;
dotSelectionFound = true;
- // Save selected item size (adjusted with font size) for selection label positioning
+ // Save selected item size (adjusted with font size) for selection label
+ // positioning
selectedItemSize = itemSize + (m_cachedTheme->font().pointSizeF() / 500.0f);
- }
- 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.translation().y() + 1.0f) / 2.0f);
- }
-#if !defined(QT_OPENGL_ES_2)
- if (m_cachedShadowQuality > QAbstract3DGraph::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);
+ // Set shader bindings
+ dotShader->setUniformValue(dotShader->model(), modelMatrix);
+ dotShader->setUniformValue(dotShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ }
- // Draw the object
- m_drawer->drawObject(dotShader, dotObj, gradientTexture, m_depthTexture);
- } else {
- // Draw the object
- m_drawer->drawPoint(dotShader);
+ dotShader->setUniformValue(dotShader->MVP(), MVPMatrix);
+ if (useColor) {
+ dotShader->setUniformValue(dotShader->color(), dotColor);
+ } else if (colorStyle == Q3DTheme::ColorStyleRangeGradient) {
+ dotShader->setUniformValue(dotShader->gradientMin(),
+ (item.translation().y() + 1.0f) / 2.0f);
}
- } else
-#endif
- {
+
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);
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(-0.5f, 1.0f);
+ }
+
+#if !defined(QT_OPENGL_ES_2)
+ if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
+ if (!drawingPoints) {
+ // Set shadow shader bindings
+ QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ dotShader->setUniformValue(dotShader->depth(), depthMVPMatrix);
+ dotShader->setUniformValue(dotShader->lightS(), lightStrength / 10.0f);
+
+ // Draw the object
+ m_drawer->drawObject(dotShader, dotObj, gradientTexture, m_depthTexture);
+ } else {
+ // Draw the object
+ m_drawer->drawPoint(dotShader);
+ }
+ } else
+#endif
+ {
+ 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);
+ }
}
+
+ if (!drawingPoints)
+ glDisable(GL_POLYGON_OFFSET_FILL);
}
- dotNo++;
}
}
#if !defined(QT_OPENGL_ES_2)
- if (havePointSeries) {
+ if (m_havePointSeries) {
glDisable(GL_POINT_SMOOTH);
glDisable(GL_PROGRAM_POINT_SIZE);
}
@@ -770,17 +976,19 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
QMatrix4x4 itModelMatrix;
#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z
- GLfloat xScale = (aspectRatio * m_backgroundMargin * m_areaSize.width()) / m_scaleFactor;
- GLfloat zScale = (aspectRatio * m_backgroundMargin * m_areaSize.height()) / m_scaleFactor;
+ GLfloat xScale = (m_graphAspectRatio * m_areaSize.width()) / m_scaleFactor
+ + m_backgroundMargin;
+ GLfloat zScale = (m_graphAspectRatio * m_areaSize.height()) / m_scaleFactor
+ + m_backgroundMargin;
if (m_maxItemSize > xScale)
xScale = m_maxItemSize;
if (m_maxItemSize > zScale)
zScale = m_maxItemSize;
- QVector3D bgScale(xScale, m_backgroundMargin, zScale);
+ QVector3D bgScale(xScale, 1.0f + m_backgroundMargin, zScale);
#else // ..and this if we want uniform scaling based on largest dimension
- QVector3D bgScale((aspectRatio * m_backgroundMargin),
- m_backgroundMargin,
- (aspectRatio * m_backgroundMargin));
+ QVector3D bgScale((m_graphAspectRatio + m_backgroundMargin),
+ 1.0f + m_backgroundMargin,
+ (m_graphAspectRatio + m_backgroundMargin));
#endif
modelMatrix.scale(bgScale);
// If we're viewing from below, background object must be flipped
@@ -797,7 +1005,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
#else
MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
- QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme->backgroundColor());
+ QVector4D backgroundColor = Utils::vectorFromColor(m_cachedTheme->backgroundColor());
// Set shader bindings
m_backgroundShader->setUniformValue(m_backgroundShader->lightP(), lightPos);
@@ -839,22 +1047,18 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
glDisable(GL_TEXTURE_2D);
// Draw grid lines
-#ifdef USE_UNIFORM_SCALING
- AxisRenderCache *axisCacheMax;
- if (m_axisCacheZ.max() > m_axisCacheX.max())
- axisCacheMax = &m_axisCacheZ;
- else
- axisCacheMax = &m_axisCacheX;
-#endif
-
- if (m_cachedTheme->isGridEnabled() && m_heightNormalizer) {
+ if (m_cachedTheme->isGridEnabled()) {
+#if !(defined QT_OPENGL_ES_2)
ShaderHelper *lineShader = m_backgroundShader;
+#else
+ ShaderHelper *lineShader = m_selectionShader; // Plain color shader for GL_LINES
+#endif
// Bind line shader
lineShader->bind();
// Set unchanging shader bindings
- QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
+ QVector4D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
lineShader->setUniformValue(lineShader->lightP(), lightPos);
lineShader->setUniformValue(lineShader->view(), viewMatrix);
lineShader->setUniformValue(lineShader->color(), lineColor);
@@ -887,39 +1091,33 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
else
lineXRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, -90.0f);
- GLfloat yFloorLinePosition = -m_backgroundMargin + gridLineOffset;
+ GLfloat yFloorLinePosition = -1.0f - 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() - m_translationOffset.z()); // Start line
- int lastSegment = m_axisCacheZ.subSegmentCount() * m_axisCacheZ.segmentCount();
-#else
- GLfloat lineStep = aspectRatio * axisCacheMax->subSegmentStep();
- GLfloat linePos = -aspectRatio * m_scaleFactor; // Start line
- int lastSegment = axisCacheMax->subSegmentCount() * axisCacheMax->segmentCount();
-#endif
+ int gridLineCount = m_axisCacheZ.gridLineCount();
#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z
- GLfloat xScale = (aspectRatio * m_backgroundMargin * m_areaSize.width()) / m_scaleFactor;
+ GLfloat xScale = (m_graphAspectRatio * m_areaSize.width()) / m_scaleFactor
+ + m_backgroundMargin;
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 * m_backgroundMargin),
+ QVector3D gridLineScaler((m_graphAspectRatio + m_backgroundMargin),
gridLineWidth, gridLineWidth);
#endif
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(0.0f, yFloorLinePosition, linePos / m_scaleFactor);
+ modelMatrix.translate(0.0f, yFloorLinePosition,
+ m_axisCacheZ.gridLinePosition(line));
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
@@ -942,42 +1140,45 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- linePos -= lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
// Side wall lines
- gridLineScaler = QVector3D(gridLineWidth, m_backgroundMargin, gridLineWidth);
+ gridLineScaler = QVector3D(gridLineWidth, 1.0f + m_backgroundMargin, gridLineWidth);
#ifndef USE_UNIFORM_SCALING
- GLfloat lineXTrans = (aspectRatio * m_backgroundMargin * m_areaSize.width())
- / m_scaleFactor - gridLineOffset;
+ GLfloat lineXTrans = (m_graphAspectRatio * m_areaSize.width())
+ / m_scaleFactor - gridLineOffset + m_backgroundMargin;
if (m_maxItemSize > lineXTrans)
lineXTrans = m_maxItemSize - gridLineOffset;
- linePos = -aspectRatio * (m_axisCacheZ.min() - m_translationOffset.z()); // Start line
#else
- GLfloat lineXTrans = aspectRatio * m_backgroundMargin - gridLineOffset;
- linePos = -aspectRatio * m_scaleFactor; // Start line
+ GLfloat lineXTrans = m_graphAspectRatio + m_backgroundMargin - gridLineOffset;
#endif
if (!m_xFlipped)
lineXTrans = -lineXTrans;
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(lineXTrans, 0.0f, linePos / m_scaleFactor);
+ modelMatrix.translate(lineXTrans, 0.0f, m_axisCacheZ.gridLinePosition(line));
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
+#if !defined(QT_OPENGL_ES_2)
modelMatrix.rotate(lineYRotation);
itModelMatrix.rotate(lineYRotation);
+#else
+ modelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f);
+ itModelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f);
+#endif
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -994,41 +1195,42 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- linePos -= lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
}
// Columns (= X)
if (m_axisCacheX.segmentCount() > 0) {
+#if defined(QT_OPENGL_ES_2)
+ lineXRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f);
+#endif
// Floor lines
+ int gridLineCount = m_axisCacheX.gridLineCount();
+
#ifndef USE_UNIFORM_SCALING
- GLfloat lineStep = aspectRatio * m_axisCacheX.subSegmentStep();
- GLfloat linePos = aspectRatio * (m_axisCacheX.min() - m_translationOffset.x());
- int lastSegment = m_axisCacheX.subSegmentCount() * m_axisCacheX.segmentCount();
- GLfloat zScale = (aspectRatio * m_backgroundMargin * m_areaSize.height()) / m_scaleFactor;
+ GLfloat zScale = (m_graphAspectRatio * m_areaSize.height()) / m_scaleFactor
+ + m_backgroundMargin;
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 * m_backgroundMargin);
+ m_graphAspectRatio + m_backgroundMargin);
#endif
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(linePos / m_scaleFactor, yFloorLinePosition, 0.0f);
+ modelMatrix.translate(m_axisCacheX.gridLinePosition(line), yFloorLinePosition,
+ 0.0f);
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
@@ -1051,45 +1253,48 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- linePos += lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
// Back wall lines
#ifndef USE_UNIFORM_SCALING
- GLfloat lineZTrans = (aspectRatio * m_backgroundMargin * m_areaSize.height())
- / m_scaleFactor - gridLineOffset;
+ GLfloat lineZTrans = (m_graphAspectRatio * m_areaSize.height())
+ / m_scaleFactor - gridLineOffset + m_backgroundMargin;
if (m_maxItemSize > lineZTrans)
lineZTrans = m_maxItemSize - gridLineOffset;
- linePos = aspectRatio * (m_axisCacheX.min() - m_translationOffset.x());
#else
- GLfloat lineZTrans = aspectRatio * m_backgroundMargin - gridLineOffset;
- linePos = -aspectRatio * m_scaleFactor;
+ GLfloat lineZTrans = m_graphAspectRatio + m_backgroundMargin - gridLineOffset;
#endif
if (!m_zFlipped)
lineZTrans = -lineZTrans;
- gridLineScaler = QVector3D(gridLineWidth, m_backgroundMargin, gridLineWidth);
+ gridLineScaler = QVector3D(gridLineWidth, 1.0f + m_backgroundMargin, gridLineWidth);
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(linePos / m_scaleFactor, 0.0f, lineZTrans);
+ modelMatrix.translate(m_axisCacheX.gridLinePosition(line), 0.0f, lineZTrans);
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
+#if !defined(QT_OPENGL_ES_2)
if (m_zFlipped) {
modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
itModelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
}
+#else
+ modelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f);
+ itModelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f);
+#endif
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -1106,46 +1311,45 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- linePos += lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
}
// Horizontal wall lines
if (m_axisCacheY.segmentCount() > 0) {
// Back wall
- GLfloat lineStep = m_axisCacheY.subSegmentStep();
- GLfloat linePos = m_axisCacheY.min() - m_translationOffset.y();
- int lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount();
+ int gridLineCount = m_axisCacheY.gridLineCount();
#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z
- GLfloat lineZTrans = (aspectRatio * m_backgroundMargin * m_areaSize.height())
- / m_scaleFactor - gridLineOffset;
+ GLfloat lineZTrans = (m_graphAspectRatio * m_areaSize.height())
+ / m_scaleFactor - gridLineOffset + m_backgroundMargin;
if (m_maxItemSize > lineZTrans)
lineZTrans = m_maxItemSize - gridLineOffset;
- GLfloat xScale = (aspectRatio * m_backgroundMargin * m_areaSize.width()) / m_scaleFactor;
+ GLfloat xScale = (m_graphAspectRatio * m_areaSize.width()) / m_scaleFactor
+ + m_backgroundMargin;
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 * m_backgroundMargin - gridLineOffset;
- QVector3D gridLineScaler((aspectRatio * m_backgroundMargin),
+ GLfloat lineZTrans = m_graphAspectRatio + m_backgroundMargin - gridLineOffset;
+ QVector3D gridLineScaler((m_graphAspectRatio + m_backgroundMargin),
gridLineWidth, gridLineWidth);
#endif
if (!m_zFlipped)
lineZTrans = -lineZTrans;
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(0.0f, linePos / m_heightNormalizer, lineZTrans);
+ modelMatrix.translate(0.0f, m_axisCacheY.gridLinePosition(line), lineZTrans);
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
@@ -1170,42 +1374,40 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- linePos += lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
// Side wall
- 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 * m_backgroundMargin * m_areaSize.width())
- / m_scaleFactor - gridLineOffset;
+ GLfloat lineXTrans = (m_graphAspectRatio * m_areaSize.width())
+ / m_scaleFactor - gridLineOffset + m_backgroundMargin;
if (m_maxItemSize > lineXTrans)
lineXTrans = m_maxItemSize - gridLineOffset;
- GLfloat zScale = (aspectRatio * m_backgroundMargin * m_areaSize.height())
- / m_scaleFactor;
+ GLfloat zScale = (m_graphAspectRatio * m_areaSize.height())
+ / m_scaleFactor + m_backgroundMargin;
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 * m_backgroundMargin - gridLineOffset;
+ GLfloat lineXTrans = m_graphAspectRatio + m_backgroundMargin - gridLineOffset;
gridLineScaler = QVector3D(gridLineWidth, gridLineWidth,
- aspectRatio * m_backgroundMargin);
+ m_graphAspectRatio + m_backgroundMargin);
#endif
if (!m_xFlipped)
lineXTrans = -lineXTrans;
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(lineXTrans, linePos / m_heightNormalizer, 0.0f);
+ modelMatrix.translate(lineXTrans, m_axisCacheY.gridLinePosition(line), 0.0f);
modelMatrix.scale(gridLineScaler);
itModelMatrix.scale(gridLineScaler);
@@ -1228,328 +1430,478 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- linePos += lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
+ }
+ }
+ }
+
+ Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader, viewMatrix,
+ projectionViewMatrix, depthProjectionViewMatrix,
+ m_depthTexture, m_shadowQualityToShader);
+
+ drawLabels(false, activeCamera, viewMatrix, projectionMatrix);
+
+ // Handle selection clearing and selection label drawing
+ if (!dotSelectionFound) {
+ // We have no ownership, don't delete. Just NULL the pointer.
+ m_selectedItem = NULL;
+ } else {
+ glDisable(GL_DEPTH_TEST);
+ // Draw the selection label
+ LabelItem &labelItem = selectionLabelItem();
+ if (m_selectedItem != selectedItem || m_updateLabels
+ || !labelItem.textureId() || m_selectionLabelDirty) {
+ QString labelText = selectionLabel();
+ if (labelText.isNull() || m_selectionLabelDirty) {
+ labelText = m_selectedSeriesCache->itemLabel();
+ setSelectionLabel(labelText);
+ m_selectionLabelDirty = false;
}
+ m_drawer->generateLabelItem(labelItem, labelText);
+ m_selectedItem = selectedItem;
}
+
+ m_drawer->drawLabel(*selectedItem, labelItem, viewMatrix, projectionMatrix,
+ zeroVector, identityQuaternion, selectedItemSize, m_cachedSelectionMode,
+ m_labelShader, m_labelObj, activeCamera, true, false,
+ Drawer::LabelOver);
+
+ // Reset label update flag; they should have been updated when we get here
+ m_updateLabels = false;
+ glEnable(GL_DEPTH_TEST);
}
- // Draw axis labels
- // Bind label shader
- m_labelShader->bind();
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+
+ // Release shader
+ glUseProgram(0);
+
+ m_selectionDirty = false;
+}
+
+void Scatter3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCamera,
+ const QMatrix4x4 &viewMatrix,
+ const QMatrix4x4 &projectionMatrix) {
+ ShaderHelper *shader = 0;
+ GLfloat alphaForValueSelection = labelValueAlpha / 255.0f;
+ GLfloat alphaForRowSelection = labelRowAlpha / 255.0f;
+ GLfloat alphaForColumnSelection = labelColumnAlpha / 255.0f;
+ if (drawSelection) {
+ shader = m_selectionShader;
+ // m_selectionShader is already bound
+ } else {
+ shader = m_labelShader;
+ shader->bind();
+
+ glEnable(GL_TEXTURE_2D);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
- glEnable(GL_TEXTURE_2D);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_POLYGON_OFFSET_FILL);
+ float labelAutoAngle = m_axisCacheZ.labelAutoRotation();
+ float labelAngleFraction = labelAutoAngle / 90.0f;
+ float fractionCamY = activeCamera->yRotation() * labelAngleFraction;
+ float fractionCamX = activeCamera->xRotation() * labelAngleFraction;
+ float labelsMaxWidth = 0.0f;
+
+ int startIndex;
+ int endIndex;
+ int indexStep;
+
// Z Labels
if (m_axisCacheZ.segmentCount() > 0) {
+ int labelCount = m_axisCacheZ.labelCount();
#ifndef USE_UNIFORM_SCALING
- GLfloat posStep = aspectRatio * m_axisCacheZ.segmentStep();
- GLfloat labelPos = -aspectRatio * (m_axisCacheZ.min() - m_translationOffset.z());
- int lastSegment = m_axisCacheZ.segmentCount();
- GLfloat labelXTrans = (aspectRatio * m_backgroundMargin * m_areaSize.width())
- / m_scaleFactor + labelMargin;
+ GLfloat labelXTrans = (m_graphAspectRatio * m_areaSize.width())
+ / m_scaleFactor + labelMargin + m_backgroundMargin;
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 * m_backgroundMargin + labelMargin;
+ GLfloat labelXTrans = m_graphAspectRatio + m_backgroundMargin + labelMargin;
#endif
- int labelNbr = 0;
- GLfloat labelYTrans = -m_backgroundMargin;
- GLfloat rotLabelX = -90.0f;
- GLfloat rotLabelY = 0.0f;
- GLfloat rotLabelZ = 0.0f;
- Qt::AlignmentFlag alignment = Qt::AlignRight;
- if (m_zFlipped)
- rotLabelY = 180.0f;
- if (m_xFlipped) {
+ GLfloat labelYTrans = -1.0f - m_backgroundMargin;
+ Qt::AlignmentFlag alignment = (m_xFlipped == m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight;
+ QVector3D labelRotation;
+ if (m_xFlipped)
labelXTrans = -labelXTrans;
- alignment = Qt::AlignLeft;
- }
- if (m_yFlipped) {
- rotLabelZ += 180.0f;
- rotLabelY += 180.0f;
+ if (m_yFlipped)
labelYTrans = -labelYTrans;
+ if (labelAutoAngle == 0.0f) {
+ labelRotation.setX(-90.0f);
+ if (m_zFlipped)
+ labelRotation.setY(180.0f);
+ if (m_yFlipped) {
+ if (m_zFlipped)
+ labelRotation.setY(0.0f);
+ else
+ labelRotation.setY(180.0f);
+ labelRotation.setZ(180.0f);
+ }
+ } else {
+ if (m_zFlipped)
+ labelRotation.setY(180.0f);
+ if (m_yFlipped) {
+ if (m_zFlipped) {
+ if (m_xFlipped) {
+ labelRotation.setX(90.0f - (labelAutoAngle - fractionCamX)
+ * (-labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle + fractionCamY);
+ } else {
+ labelRotation.setX(90.0f + (labelAutoAngle + fractionCamX)
+ * (labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle - fractionCamY);
+ }
+ } else {
+ if (m_xFlipped) {
+ labelRotation.setX(90.0f + (labelAutoAngle - fractionCamX)
+ * -(labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle - fractionCamY);
+ } else {
+ labelRotation.setX(90.0f - (labelAutoAngle + fractionCamX)
+ * (labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle + fractionCamY);
+ }
+ }
+ } else {
+ if (m_zFlipped) {
+ if (m_xFlipped) {
+ labelRotation.setX(-90.0f + (labelAutoAngle - fractionCamX)
+ * (-labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle + fractionCamY);
+ } else {
+ labelRotation.setX(-90.0f - (labelAutoAngle + fractionCamX)
+ * (labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle - fractionCamY);
+ }
+ } else {
+ if (m_xFlipped) {
+ labelRotation.setX(-90.0f - (labelAutoAngle - fractionCamX)
+ * (-labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle - fractionCamY);
+ } else {
+ labelRotation.setX(-90.0f + (labelAutoAngle + fractionCamX)
+ * (labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle + fractionCamY);
+ }
+ }
+ }
}
- QVector3D labelRotateVector(rotLabelX, rotLabelY, rotLabelZ);
+ QQuaternion totalRotation = Utils::calculateRotation(labelRotation);
QVector3D labelTrans = QVector3D(labelXTrans, labelYTrans, 0.0f);
- for (int segment = 0; segment <= lastSegment; segment++) {
-#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z
- if (m_axisCacheZ.labelItems().size() > labelNbr) {
-#else // ..and this if we want uniform scaling based on largest dimension
- if (axisCacheMax->labelItems().size() > labelNbr) {
-#endif
- labelTrans.setZ(labelPos / m_scaleFactor);
+ if (m_zFlipped) {
+ startIndex = 0;
+ endIndex = labelCount;
+ indexStep = 1;
+ } else {
+ startIndex = labelCount - 1;
+ endIndex = -1;
+ indexStep = -1;
+ }
+ for (int label = startIndex; label != endIndex; label = label + indexStep) {
+ labelTrans.setZ(m_axisCacheZ.labelPosition(label));
- glPolygonOffset(GLfloat(segment) / -10.0f, 1.0f);
+ glPolygonOffset(GLfloat(label) / -10.0f, 1.0f);
- // Draw the label here
- m_dummyRenderItem.setTranslation(labelTrans);
-#ifndef USE_UNIFORM_SCALING
- const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(labelNbr);
-#else
- const LabelItem &axisLabelItem = *axisCacheMax->labelItems().at(labelNbr);
-#endif
+ // Draw the label here
+ m_dummyRenderItem.setTranslation(labelTrans);
+ const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(label);
- m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- zeroVector, labelRotateVector, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, activeCamera, true, true,
- Drawer::LabelMid, alignment);
+ if (drawSelection) {
+ QVector4D labelColor = QVector4D(label / 255.0f, 0.0f, 0.0f,
+ alphaForRowSelection);
+ shader->setUniformValue(shader->color(), labelColor);
}
- labelNbr++;
- labelPos -= posStep;
+
+ m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
+ zeroVector, totalRotation, 0, m_cachedSelectionMode,
+ shader, m_labelObj, activeCamera, true, true,
+ Drawer::LabelMid, alignment, false, drawSelection);
+ labelsMaxWidth = qMax(labelsMaxWidth, float(axisLabelItem.size().width()));
+ }
+ if (!drawSelection && m_axisCacheZ.isTitleVisible()) {
+ labelTrans.setZ(0.0f);
+ drawAxisTitleZ(labelRotation, labelTrans, totalRotation, m_dummyRenderItem,
+ activeCamera, labelsMaxWidth, viewMatrix, projectionMatrix, shader);
}
}
+
// X Labels
if (m_axisCacheX.segmentCount() > 0) {
+ labelsMaxWidth = 0.0f;
+ labelAutoAngle = m_axisCacheX.labelAutoRotation();
+ labelAngleFraction = labelAutoAngle / 90.0f;
+ fractionCamY = activeCamera->yRotation() * labelAngleFraction;
+ fractionCamX = activeCamera->xRotation() * labelAngleFraction;
+ int labelCount = m_axisCacheX.labelCount();
#ifndef USE_UNIFORM_SCALING
- GLfloat posStep = aspectRatio * m_axisCacheX.segmentStep();
- GLfloat labelPos = aspectRatio * (m_axisCacheX.min() - m_translationOffset.x());
- int lastSegment = m_axisCacheX.segmentCount();
- GLfloat labelZTrans = (aspectRatio * m_backgroundMargin * m_areaSize.height())
- / m_scaleFactor + labelMargin;
+ GLfloat labelZTrans = (m_graphAspectRatio * m_areaSize.height())
+ / m_scaleFactor + labelMargin + m_backgroundMargin;
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 * m_backgroundMargin + labelMargin;
+ GLfloat labelZTrans = m_graphAspectRatio + m_backgroundMargin + labelMargin;
#endif
- int labelNbr = 0;
- GLfloat labelYTrans = -m_backgroundMargin;
- GLfloat rotLabelX = -90.0f;
- GLfloat rotLabelY = 90.0f;
- GLfloat rotLabelZ = 0.0f;
- Qt::AlignmentFlag alignment = Qt::AlignLeft;
- if (m_xFlipped)
- rotLabelY = -90.0f;
- if (m_zFlipped) {
+ GLfloat labelYTrans = -1.0f - m_backgroundMargin;
+ Qt::AlignmentFlag alignment = (m_xFlipped != m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight;
+ QVector3D labelRotation;
+ if (m_zFlipped)
labelZTrans = -labelZTrans;
- alignment = Qt::AlignRight;
- }
- if (m_yFlipped) {
- rotLabelZ += 180.0f;
- rotLabelY += 180.0f;
+ if (m_yFlipped)
labelYTrans = -labelYTrans;
+ if (labelAutoAngle == 0.0f) {
+ labelRotation = QVector3D(-90.0f, 90.0f, 0.0f);
+ if (m_xFlipped)
+ labelRotation.setY(-90.0f);
+ if (m_yFlipped) {
+ if (m_xFlipped)
+ labelRotation.setY(90.0f);
+ else
+ labelRotation.setY(-90.0f);
+ labelRotation.setZ(180.0f);
+ }
+ } else {
+ if (m_xFlipped)
+ labelRotation.setY(-90.0f);
+ else
+ labelRotation.setY(90.0f);
+ if (m_yFlipped) {
+ if (m_zFlipped) {
+ if (m_xFlipped) {
+ labelRotation.setX(90.0f - (2.0f * labelAutoAngle - fractionCamX)
+ * (labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle - fractionCamY);
+ } else {
+ labelRotation.setX(90.0f - (2.0f * labelAutoAngle + fractionCamX)
+ * (labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle + fractionCamY);
+ }
+ } else {
+ if (m_xFlipped) {
+ labelRotation.setX(90.0f + fractionCamX
+ * -(labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle + fractionCamY);
+ } else {
+ labelRotation.setX(90.0f - fractionCamX
+ * (-labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle - fractionCamY);
+ }
+ }
+ } else {
+ if (m_zFlipped) {
+ if (m_xFlipped) {
+ labelRotation.setX(-90.0f + (2.0f * labelAutoAngle - fractionCamX)
+ * (labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle - fractionCamY);
+ } else {
+ labelRotation.setX(-90.0f + (2.0f * labelAutoAngle + fractionCamX)
+ * (labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle + fractionCamY);
+ }
+ } else {
+ if (m_xFlipped) {
+ labelRotation.setX(-90.0f - fractionCamX
+ * (-labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle + fractionCamY);
+ } else {
+ labelRotation.setX(-90.0f + fractionCamX
+ * -(labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle - fractionCamY);
+ }
+ }
+ }
}
- QVector3D labelRotateVector(rotLabelX, rotLabelY, rotLabelZ);
+
+ QQuaternion totalRotation = Utils::calculateRotation(labelRotation);
QVector3D labelTrans = QVector3D(0.0f, labelYTrans, labelZTrans);
- for (int segment = 0; segment <= lastSegment; segment++) {
-#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z
- if (m_axisCacheX.labelItems().size() > labelNbr) {
-#else // ..and this if we want uniform scaling based on largest dimension
- if (axisCacheMax->labelItems().size() > labelNbr) {
-#endif
- labelTrans.setX(labelPos / m_scaleFactor);
+ if (m_xFlipped) {
+ startIndex = labelCount - 1;
+ endIndex = -1;
+ indexStep = -1;
+ } else {
+ startIndex = 0;
+ endIndex = labelCount;
+ indexStep = 1;
+ }
+ for (int label = startIndex; label != endIndex; label = label + indexStep) {
+ labelTrans.setX(m_axisCacheX.labelPosition(label));
- glPolygonOffset(GLfloat(segment) / -10.0f, 1.0f);
+ glPolygonOffset(GLfloat(label) / -10.0f, 1.0f);
- // Draw the label here
- m_dummyRenderItem.setTranslation(labelTrans);
-#ifndef USE_UNIFORM_SCALING
- const LabelItem &axisLabelItem = *m_axisCacheX.labelItems().at(labelNbr);
-#else
- const LabelItem &axisLabelItem = *axisCacheMax->labelItems().at(labelNbr);
-#endif
+ // Draw the label here
+ m_dummyRenderItem.setTranslation(labelTrans);
+ const LabelItem &axisLabelItem = *m_axisCacheX.labelItems().at(label);
- m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- zeroVector, labelRotateVector, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, activeCamera, true, true,
- Drawer::LabelMid, alignment);
+ if (drawSelection) {
+ QVector4D labelColor = QVector4D(0.0f, label / 255.0f, 0.0f,
+ alphaForColumnSelection);
+ shader->setUniformValue(shader->color(), labelColor);
}
- labelNbr++;
- labelPos += posStep;
+
+ m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
+ zeroVector, totalRotation, 0, m_cachedSelectionMode,
+ shader, m_labelObj, activeCamera, true, true,
+ Drawer::LabelMid, alignment, false, drawSelection);
+ labelsMaxWidth = qMax(labelsMaxWidth, float(axisLabelItem.size().width()));
+ }
+ if (!drawSelection && m_axisCacheX.isTitleVisible()) {
+ labelTrans.setX(0.0f);
+ drawAxisTitleX(labelRotation, labelTrans, totalRotation, m_dummyRenderItem,
+ activeCamera, labelsMaxWidth, viewMatrix, projectionMatrix, shader);
}
}
+
// Y Labels
if (m_axisCacheY.segmentCount() > 0) {
- GLfloat posStep = m_axisCacheY.segmentStep();
- GLfloat labelPos = m_axisCacheY.min() - m_translationOffset.y();
- int labelNbr = 0;
+ labelsMaxWidth = 0.0f;
+ labelAutoAngle = m_axisCacheY.labelAutoRotation();
+ labelAngleFraction = labelAutoAngle / 90.0f;
+ fractionCamY = activeCamera->yRotation() * labelAngleFraction;
+ fractionCamX = activeCamera->xRotation() * labelAngleFraction;
+ int labelCount = m_axisCacheY.labelCount();
#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z
- GLfloat labelXTrans = (aspectRatio * m_backgroundMargin * m_areaSize.width())
- / m_scaleFactor;
- GLfloat labelZTrans = (aspectRatio * m_backgroundMargin * m_areaSize.height())
- / m_scaleFactor;
+ GLfloat labelXTrans = (m_graphAspectRatio* m_areaSize.width())
+ / m_scaleFactor + m_backgroundMargin;
+ GLfloat labelZTrans = (m_graphAspectRatio * m_areaSize.height())
+ / m_scaleFactor + m_backgroundMargin;
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 * m_backgroundMargin;
+ GLfloat labelXTrans = m_graphAspectRatio + m_backgroundMargin;
GLfloat labelZTrans = labelXTrans;
#endif
- // Back wall init
+ // Back & side wall
GLfloat labelMarginXTrans = labelMargin;
GLfloat labelMarginZTrans = labelMargin;
- GLfloat rotLabelX = 0.0f;
- GLfloat rotLabelY = -90.0f;
- GLfloat rotLabelZ = 0.0f;
- Qt::AlignmentFlag alignmentBack = Qt::AlignLeft;
+ QVector3D backLabelRotation(0.0f, -90.0f, 0.0f);
+ QVector3D sideLabelRotation(0.0f, 0.0f, 0.0f);
+ Qt::AlignmentFlag backAlignment =
+ (m_xFlipped != m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight;
+ Qt::AlignmentFlag sideAlignment =
+ (m_xFlipped == m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight;
if (!m_xFlipped) {
labelXTrans = -labelXTrans;
labelMarginXTrans = -labelMargin;
- rotLabelY = 90.0f;
}
if (m_zFlipped) {
labelZTrans = -labelZTrans;
labelMarginZTrans = -labelMargin;
- alignmentBack = Qt::AlignRight;
}
- QVector3D labelRotateVectorBack(rotLabelX, rotLabelY, rotLabelZ);
- QVector3D labelTransBack = QVector3D(labelXTrans, 0.0f, labelZTrans + labelMarginZTrans);
+ if (labelAutoAngle == 0.0f) {
+ if (!m_xFlipped)
+ backLabelRotation.setY(90.0f);
+ if (m_zFlipped)
+ sideLabelRotation.setY(180.f);
+ } else {
+ // Orient side labels somewhat towards the camera
+ if (m_xFlipped) {
+ if (m_zFlipped)
+ sideLabelRotation.setY(180.0f + (2.0f * labelAutoAngle) - fractionCamX);
+ else
+ sideLabelRotation.setY(-fractionCamX);
+ backLabelRotation.setY(-90.0f + labelAutoAngle - fractionCamX);
+ } else {
+ if (m_zFlipped)
+ sideLabelRotation.setY(180.0f - (2.0f * labelAutoAngle) - fractionCamX);
+ else
+ sideLabelRotation.setY(-fractionCamX);
+ backLabelRotation.setY(90.0f - labelAutoAngle - fractionCamX);
+ }
+ }
+ sideLabelRotation.setX(-fractionCamY);
+ backLabelRotation.setX(-fractionCamY);
- // Side wall init
- Qt::AlignmentFlag alignmentSide = Qt::AlignLeft;
- if (m_xFlipped)
- alignmentSide = Qt::AlignLeft;
- else
- alignmentSide = Qt::AlignRight;
- if (m_zFlipped)
- rotLabelY = 180.0f;
- else
- rotLabelY = 0.0f;
+ QQuaternion totalSideRotation = Utils::calculateRotation(sideLabelRotation);
+ QQuaternion totalBackRotation = Utils::calculateRotation(backLabelRotation);
- QVector3D labelRotateVectorSide(rotLabelX, rotLabelY, rotLabelZ);
+ QVector3D labelTransBack = QVector3D(labelXTrans, 0.0f, labelZTrans + labelMarginZTrans);
QVector3D labelTransSide(-labelXTrans - labelMarginXTrans, 0.0f, -labelZTrans);
- for (int segment = 0; segment <= m_axisCacheY.segmentCount(); segment++) {
- if (m_axisCacheY.labelItems().size() > labelNbr) {
- 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);
- m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- zeroVector, labelRotateVectorBack, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, activeCamera, true, true,
- Drawer::LabelMid, alignmentBack);
-
- // Side wall
- labelTransSide.setY(labelYTrans);
- m_dummyRenderItem.setTranslation(labelTransSide);
- m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- zeroVector, labelRotateVectorSide, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, activeCamera, true, true,
- Drawer::LabelMid, alignmentSide);
- }
- labelNbr++;
- labelPos += posStep;
+ if (m_yFlipped) {
+ startIndex = labelCount - 1;
+ endIndex = -1;
+ indexStep = -1;
+ } else {
+ startIndex = 0;
+ endIndex = labelCount;
+ indexStep = 1;
}
- }
- glDisable(GL_POLYGON_OFFSET_FILL);
+ for (int label = startIndex; label != endIndex; label = label + indexStep) {
+ const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(label);
+ const GLfloat labelYTrans = m_axisCacheY.labelPosition(label);
- // Handle selection clearing and selection label drawing
- if (!dotSelectionFound) {
- // We have no ownership, don't delete. Just NULL the pointer.
- m_selectedItem = NULL;
- } else {
- glDisable(GL_DEPTH_TEST);
- // Draw the selection label
- LabelItem &labelItem = selectionLabelItem();
- if (m_selectedItem != selectedItem || m_updateLabels
- || !labelItem.textureId() || m_selectionLabelDirty) {
- QString labelText = selectionLabel();
- if (labelText.isNull() || m_selectionLabelDirty) {
- static const QString xTitleTag(QStringLiteral("@xTitle"));
- static const QString yTitleTag(QStringLiteral("@yTitle"));
- static const QString zTitleTag(QStringLiteral("@zTitle"));
- static const QString xLabelTag(QStringLiteral("@xLabel"));
- static const QString yLabelTag(QStringLiteral("@yLabel"));
- static const QString zLabelTag(QStringLiteral("@zLabel"));
- static const QString seriesNameTag(QStringLiteral("@seriesName"));
-
- labelText = m_visibleSeriesList[m_selectedItemSeriesIndex].itemLabelFormat();
-
- labelText.replace(xTitleTag, m_axisCacheX.title());
- labelText.replace(yTitleTag, m_axisCacheY.title());
- labelText.replace(zTitleTag, m_axisCacheZ.title());
-
- if (labelText.contains(xLabelTag)) {
- QString labelFormat = m_axisCacheX.labelFormat();
- if (labelFormat.isEmpty())
- labelFormat = Utils::defaultLabelFormat();
- QString valueLabelText = generateValueLabel(labelFormat,
- selectedItem->position().x());
- labelText.replace(xLabelTag, valueLabelText);
- }
- if (labelText.contains(yLabelTag)) {
- QString labelFormat = m_axisCacheY.labelFormat();
- if (labelFormat.isEmpty())
- labelFormat = Utils::defaultLabelFormat();
- QString valueLabelText = generateValueLabel(labelFormat,
- selectedItem->position().y());
- labelText.replace(yLabelTag, valueLabelText);
- }
- if (labelText.contains(zLabelTag)) {
- QString labelFormat = m_axisCacheZ.labelFormat();
- if (labelFormat.isEmpty())
- labelFormat = Utils::defaultLabelFormat();
- QString valueLabelText = generateValueLabel(labelFormat,
- selectedItem->position().z());
- labelText.replace(zLabelTag, valueLabelText);
- }
- labelText.replace(seriesNameTag, m_visibleSeriesList[m_selectedItemSeriesIndex].name());
+ glPolygonOffset(GLfloat(label) / -10.0f, 1.0f);
- setSelectionLabel(labelText);
- m_selectionLabelDirty = false;
+ if (drawSelection) {
+ QVector4D labelColor = QVector4D(0.0f, 0.0f, label / 255.0f,
+ alphaForValueSelection);
+ shader->setUniformValue(shader->color(), labelColor);
}
- m_drawer->generateLabelItem(labelItem, labelText);
- m_selectedItem = selectedItem;
- }
- m_drawer->drawLabel(*selectedItem, labelItem, viewMatrix, projectionMatrix,
- zeroVector, zeroVector, selectedItemSize, m_cachedSelectionMode,
- m_labelShader, m_labelObj, activeCamera, true, false,
- Drawer::LabelOver);
+ // Back wall
+ labelTransBack.setY(labelYTrans);
+ m_dummyRenderItem.setTranslation(labelTransBack);
+ m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
+ zeroVector, totalBackRotation, 0, m_cachedSelectionMode,
+ shader, m_labelObj, activeCamera, true, true,
+ Drawer::LabelMid, backAlignment, false, drawSelection);
- // Reset label update flag; they should have been updated when we get here
- m_updateLabels = false;
- glEnable(GL_DEPTH_TEST);
+ // Side wall
+ labelTransSide.setY(labelYTrans);
+ m_dummyRenderItem.setTranslation(labelTransSide);
+ m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
+ zeroVector, totalSideRotation, 0, m_cachedSelectionMode,
+ shader, m_labelObj, activeCamera, true, true,
+ Drawer::LabelMid, sideAlignment, false, drawSelection);
+ labelsMaxWidth = qMax(labelsMaxWidth, float(axisLabelItem.size().width()));
+ }
+ if (!drawSelection && m_axisCacheY.isTitleVisible()) {
+ labelTransSide.setY(0.0f);
+ labelTransBack.setY(0.0f);
+ drawAxisTitleY(sideLabelRotation, backLabelRotation, labelTransSide, labelTransBack,
+ totalSideRotation, totalBackRotation, m_dummyRenderItem, activeCamera,
+ labelsMaxWidth, viewMatrix, projectionMatrix,
+ shader);
+ }
}
-
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_BLEND);
-
- // Release shader
- glUseProgram(0);
-
- m_selectionDirty = false;
+ glDisable(GL_POLYGON_OFFSET_FILL);
}
-void Scatter3DRenderer::updateSelectedItem(int index, const QScatter3DSeries *series)
+void Scatter3DRenderer::updateSelectedItem(int index, QScatter3DSeries *series)
{
m_selectionDirty = true;
m_selectionLabelDirty = true;
- m_selectedSeries = series;
+ m_selectedSeriesCache =
+ static_cast<ScatterSeriesRenderCache *>(m_renderCacheList.value(series, 0));
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;
+ if (m_cachedOptimizationHint.testFlag(QAbstract3DGraph::OptimizationStatic)
+ && m_oldSelectedSeriesCache
+ && m_oldSelectedSeriesCache->mesh() == QAbstract3DSeries::MeshPoint) {
+ m_oldSelectedSeriesCache->bufferPoints()->popPoint();
+ m_oldSelectedSeriesCache = 0;
+ }
+
+ if (m_selectedSeriesCache) {
+ const ScatterRenderItemArray &renderArray = m_selectedSeriesCache->renderArray();
+ if (index < renderArray.size() && index >= 0) {
+ m_selectedItemIndex = index;
+
+ if (m_cachedOptimizationHint.testFlag(QAbstract3DGraph::OptimizationStatic)
+ && m_selectedSeriesCache->mesh() == QAbstract3DSeries::MeshPoint) {
+ m_selectedSeriesCache->bufferPoints()->pushPoint(m_selectedItemIndex);
+ m_oldSelectedSeriesCache = m_selectedSeriesCache;
}
- totalIndex += m_renderingArrays.at(i).size();
}
}
}
@@ -1598,26 +1950,8 @@ void Scatter3DRenderer::updateShadowQuality(QAbstract3DGraph::ShadowQuality qual
void Scatter3DRenderer::loadBackgroundMesh()
{
- if (m_backgroundObj)
- delete m_backgroundObj;
- m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/background"));
- m_backgroundObj->load();
-}
-
-void Scatter3DRenderer::loadGridLineMesh()
-{
- if (m_gridLineObj)
- delete m_gridLineObj;
- m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
- m_gridLineObj->load();
-}
-
-void Scatter3DRenderer::loadLabelMesh()
-{
- if (m_labelObj)
- delete m_labelObj;
- m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
- m_labelObj->load();
+ ObjectHelper::resetObjectHelper(this, m_backgroundObj,
+ QStringLiteral(":/defaultMeshes/background"));
}
void Scatter3DRenderer::updateTextures()
@@ -1640,11 +1974,10 @@ void Scatter3DRenderer::fixMeshFileName(QString &fileName, QAbstract3DSeries::Me
void Scatter3DRenderer::calculateTranslation(ScatterRenderItem &item)
{
// We need to normalize translations
- 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;
+ const QVector3D &pos = item.position();
+ float xTrans = m_axisCacheX.positionAt(pos.x());
+ float yTrans = m_axisCacheY.positionAt(pos.y());
+ float zTrans = m_axisCacheZ.positionAt(pos.z());
item.setTranslation(QVector3D(xTrans, yTrans, zTrans));
}
@@ -1655,10 +1988,16 @@ void Scatter3DRenderer::calculateSceneScalingFactors()
m_areaSize.setWidth((m_axisCacheX.max() - m_axisCacheX.min()) / 2.0f);
m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height());
- // 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);
+#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z
+ float factorScaler = 2.0f * m_graphAspectRatio / m_scaleFactor;
+ m_axisCacheX.setScale(factorScaler * m_areaSize.width());
+ m_axisCacheZ.setScale(-factorScaler * m_areaSize.height());
+#else // ..and this if we want uniform scaling based on largest dimension
+ m_axisCacheX.setScale(2.0f * m_graphAspectRatio);
+ m_axisCacheZ.setScale(-m_axisCacheX.scale());
+#endif
+ m_axisCacheX.setTranslate(-m_axisCacheX.scale() / 2.0f);
+ m_axisCacheZ.setTranslate(-m_axisCacheZ.scale() / 2.0f);
}
void Scatter3DRenderer::initShaders(const QString &vertexShader, const QString &fragmentShader)
@@ -1689,10 +2028,7 @@ void Scatter3DRenderer::initSelectionShader()
void Scatter3DRenderer::initSelectionBuffer()
{
- if (m_selectionTexture) {
- m_textureHelper->deleteTexture(&m_selectionTexture);
- m_selectionTexture = 0;
- }
+ m_textureHelper->deleteTexture(&m_selectionTexture);
if (m_primarySubViewport.size().isEmpty())
return;
@@ -1714,10 +2050,7 @@ void Scatter3DRenderer::initDepthShader()
void Scatter3DRenderer::updateDepthBuffer()
{
- if (m_depthTexture) {
- m_textureHelper->deleteTexture(&m_depthTexture);
- m_depthTexture = 0;
- }
+ m_textureHelper->deleteTexture(&m_depthTexture);
if (m_primarySubViewport.size().isEmpty())
return;
@@ -1758,30 +2091,54 @@ void Scatter3DRenderer::initLabelShaders(const QString &vertexShader, const QStr
m_labelShader->initialize();
}
-QVector3D Scatter3DRenderer::indexToSelectionColor(GLint index)
-{
- GLubyte dotIdxRed = index & 0xff;
- GLubyte dotIdxGreen = (index & 0xff00) >> 8;
- GLubyte dotIdxBlue = (index & 0xff0000) >> 16;
-
- return QVector3D(dotIdxRed, dotIdxGreen, dotIdxBlue);
-}
-
-void Scatter3DRenderer::selectionColorToSeriesAndIndex(const QVector3D &color,
+void Scatter3DRenderer::selectionColorToSeriesAndIndex(const QVector4D &color,
int &index,
QAbstract3DSeries *&series)
{
+ m_clickedType = QAbstract3DGraph::ElementNone;
+ m_selectedLabelIndex = -1;
+ m_selectedCustomItemIndex = -1;
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 = 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();
+ if (color.w() == labelRowAlpha) {
+ // Row selection
+ index = Scatter3DController::invalidSelectionIndex();
+ m_selectedLabelIndex = color.x();
+ m_clickedType = QAbstract3DGraph::ElementAxisZLabel;
+ } else if (color.w() == labelColumnAlpha) {
+ // Column selection
+ index = Scatter3DController::invalidSelectionIndex();
+ m_selectedLabelIndex = color.y();
+ m_clickedType = QAbstract3DGraph::ElementAxisXLabel;
+ } else if (color.w() == labelValueAlpha) {
+ // Value selection
+ index = Scatter3DController::invalidSelectionIndex();
+ m_selectedLabelIndex = color.z();
+ m_clickedType = QAbstract3DGraph::ElementAxisYLabel;
+ } else if (color.w() == customItemAlpha) {
+ // Custom item selection
+ index = Scatter3DController::invalidSelectionIndex();
+ m_selectedCustomItemIndex = int(color.x())
+ + (int(color.y()) << 8)
+ + (int(color.z()) << 16);
+ m_clickedType = QAbstract3DGraph::ElementCustomItem;
+ } else {
+ int totalIndex = int(color.x())
+ + (int(color.y()) << 8)
+ + (int(color.z()) << 16);
+ // Find the series and adjust the index accordingly
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ if (baseCache->isVisible()) {
+ ScatterSeriesRenderCache *cache =
+ static_cast<ScatterSeriesRenderCache *>(baseCache);
+ int offset = cache->selectionIndexOffset();
+ if (totalIndex >= offset
+ && totalIndex < (offset + cache->renderArray().size())) {
+ index = totalIndex - offset;
+ series = cache->series();
+ m_clickedType = QAbstract3DGraph::ElementSeries;
+ return;
+ }
+ }
}
}
}
@@ -1791,4 +2148,41 @@ void Scatter3DRenderer::selectionColorToSeriesAndIndex(const QVector3D &color,
series = 0;
}
+void Scatter3DRenderer::updateRenderItem(const QScatterDataItem &dataItem,
+ ScatterRenderItem &renderItem)
+{
+ QVector3D dotPos = dataItem.position();
+ if ((dotPos.x() >= m_axisCacheX.min() && dotPos.x() <= m_axisCacheX.max() )
+ && (dotPos.y() >= m_axisCacheY.min() && dotPos.y() <= m_axisCacheY.max())
+ && (dotPos.z() >= m_axisCacheZ.min() && dotPos.z() <= m_axisCacheZ.max())) {
+ renderItem.setPosition(dotPos);
+ renderItem.setVisible(true);
+ if (!dataItem.rotation().isIdentity())
+ renderItem.setRotation(dataItem.rotation().normalized());
+ else
+ renderItem.setRotation(identityQuaternion);
+ calculateTranslation(renderItem);
+ } else {
+ renderItem.setVisible(false);
+ }
+}
+
+QVector3D Scatter3DRenderer::convertPositionToTranslation(const QVector3D &position,
+ bool isAbsolute)
+{
+ float xTrans = 0.0f;
+ float yTrans = 0.0f;
+ float zTrans = 0.0f;
+ if (!isAbsolute) {
+ xTrans = m_axisCacheX.positionAt(position.x());
+ yTrans = m_axisCacheY.positionAt(position.y());
+ zTrans = m_axisCacheZ.positionAt(position.z());
+ } else {
+ xTrans = position.x() * m_axisCacheX.scale() / 2.0f;
+ yTrans = position.y();
+ zTrans = position.z() * m_axisCacheZ.scale() / 2.0f;
+ }
+ return QVector3D(xTrans, yTrans, zTrans);
+}
+
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/scatter3drenderer_p.h b/src/datavisualization/engine/scatter3drenderer_p.h
index 5591a362..7f213179 100644
--- a/src/datavisualization/engine/scatter3drenderer_p.h
+++ b/src/datavisualization/engine/scatter3drenderer_p.h
@@ -32,20 +32,16 @@
#include "datavisualizationglobal_p.h"
#include "scatter3dcontroller_p.h"
#include "abstract3drenderer_p.h"
-#include "qscatterdataproxy.h"
#include "scatterrenderitem_p.h"
-class QPoint;
class QSizeF;
-class QOpenGLShaderProgram;
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
class ShaderHelper;
-class ObjectHelper;
-class LabelItem;
class Q3DScene;
-class QAbstractAxisPrivate;
+class ScatterSeriesRenderCache;
+class QScatterDataItem;
class QT_DATAVISUALIZATION_EXPORT Scatter3DRenderer : public Abstract3DRenderer
{
@@ -54,9 +50,6 @@ class QT_DATAVISUALIZATION_EXPORT Scatter3DRenderer : public Abstract3DRenderer
private:
// Internal state
ScatterRenderItem *m_selectedItem; // points to renderitem array
- bool m_xFlipped;
- bool m_zFlipped;
- bool m_yFlipped;
bool m_updateLabels;
ShaderHelper *m_dotShader;
ShaderHelper *m_dotGradientShader;
@@ -67,9 +60,6 @@ private:
ShaderHelper *m_selectionShader;
ShaderHelper *m_backgroundShader;
ShaderHelper *m_labelShader;
- ObjectHelper *m_backgroundObj;
- ObjectHelper *m_gridLineObj;
- ObjectHelper *m_labelObj;
GLuint m_bgrTexture;
GLuint m_depthTexture;
GLuint m_selectionTexture;
@@ -81,33 +71,40 @@ private:
GLfloat m_heightNormalizer;
GLfloat m_scaleFactor;
int m_selectedItemIndex;
- int m_selectedItemTotalIndex;
- int m_selectedItemSeriesIndex;
- const QScatter3DSeries *m_selectedSeries;
+ ScatterSeriesRenderCache *m_selectedSeriesCache;
+ ScatterSeriesRenderCache *m_oldSelectedSeriesCache;
QSizeF m_areaSize;
GLfloat m_dotSizeScale;
- QVector3D m_translationOffset;
bool m_hasHeightAdjustmentChanged;
ScatterRenderItem m_dummyRenderItem;
- QVector<ScatterRenderItemArray> m_renderingArrays;
GLfloat m_backgroundMargin;
GLfloat m_maxItemSize;
- QVector<float> m_cachedItemSize;
int m_clickedIndex;
+ bool m_havePointSeries;
+ bool m_haveMeshSeries;
+ bool m_haveUniformColorMeshSeries;
+ bool m_haveGradientMeshSeries;
public:
explicit Scatter3DRenderer(Scatter3DController *controller);
~Scatter3DRenderer();
- void updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility);
void updateData();
+ void updateSeries(const QList<QAbstract3DSeries *> &seriesList);
+ SeriesRenderCache *createNewCache(QAbstract3DSeries *series);
+ void updateItems(const QVector<Scatter3DController::ChangeItem> &items);
void updateScene(Q3DScene *scene);
+ QVector3D convertPositionToTranslation(const QVector3D &position, bool isAbsolute);
+
inline int clickedIndex() const { return m_clickedIndex; }
void resetClickedStatus();
void render(GLuint defaultFboHandle);
+public slots:
+ void updateSelectedItem(int index, QScatter3DSeries *series);
+
protected:
virtual void initializeOpenGL();
@@ -119,10 +116,10 @@ private:
virtual void fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh);
void drawScene(GLuint defaultFboHandle);
+ void drawLabels(bool drawSelection, const Q3DCamera *activeCamera,
+ const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionMatrix);
void loadBackgroundMesh();
- void loadGridLineMesh();
- void loadLabelMesh();
void initSelectionShader();
void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader);
void initLabelShaders(const QString &vertexShader, const QString &fragmentShader);
@@ -136,17 +133,11 @@ private:
void calculateTranslation(ScatterRenderItem &item);
void calculateSceneScalingFactors();
- Q_DISABLE_COPY(Scatter3DRenderer)
-
- friend class ScatterRenderItem;
-
-public slots:
- void updateSelectedItem(int index, const QScatter3DSeries *series);
-
-private:
- QVector3D indexToSelectionColor(GLint index);
- void selectionColorToSeriesAndIndex(const QVector3D &color, int &index,
+ void selectionColorToSeriesAndIndex(const QVector4D &color, int &index,
QAbstract3DSeries *&series);
+ inline void updateRenderItem(const QScatterDataItem &dataItem, ScatterRenderItem &renderItem);
+
+ Q_DISABLE_COPY(Scatter3DRenderer)
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/scatterseriesrendercache.cpp b/src/datavisualization/engine/scatterseriesrendercache.cpp
new file mode 100644
index 00000000..e8888d19
--- /dev/null
+++ b/src/datavisualization/engine/scatterseriesrendercache.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 "scatterseriesrendercache_p.h"
+#include "scatterobjectbufferhelper_p.h"
+#include "scatterpointbufferhelper_p.h"
+
+QT_BEGIN_NAMESPACE_DATAVISUALIZATION
+
+ScatterSeriesRenderCache::ScatterSeriesRenderCache(QAbstract3DSeries *series,
+ Abstract3DRenderer *renderer)
+ : SeriesRenderCache(series, renderer),
+ m_itemSize(0.0f),
+ m_selectionIndexOffset(0),
+ m_oldRenderArraySize(0),
+ m_oldMeshFileName(QString()),
+ m_scatterBufferObj(0),
+ m_scatterBufferPoints(0)
+{
+}
+
+ScatterSeriesRenderCache::~ScatterSeriesRenderCache()
+{
+ delete m_scatterBufferObj;
+ delete m_scatterBufferPoints;
+}
+
+void ScatterSeriesRenderCache::cleanup(TextureHelper *texHelper)
+{
+ m_renderArray.clear();
+
+ SeriesRenderCache::cleanup(texHelper);
+}
+
+QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/scatterseriesrendercache_p.h b/src/datavisualization/engine/scatterseriesrendercache_p.h
new file mode 100644
index 00000000..490e21fb
--- /dev/null
+++ b/src/datavisualization/engine/scatterseriesrendercache_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 SCATTERSERIESRENDERCACHE_P_H
+#define SCATTERSERIESRENDERCACHE_P_H
+
+#include "datavisualizationglobal_p.h"
+#include "seriesrendercache_p.h"
+#include "qscatter3dseries_p.h"
+#include "scatterrenderitem_p.h"
+
+QT_BEGIN_NAMESPACE_DATAVISUALIZATION
+
+class ScatterObjectBufferHelper;
+class ScatterPointBufferHelper;
+
+class ScatterSeriesRenderCache : public SeriesRenderCache
+{
+public:
+ ScatterSeriesRenderCache(QAbstract3DSeries *series, Abstract3DRenderer *renderer);
+ virtual ~ScatterSeriesRenderCache();
+
+ void cleanup(TextureHelper *texHelper);
+
+ inline ScatterRenderItemArray &renderArray() { return m_renderArray; }
+ inline QScatter3DSeries *series() const { return static_cast<QScatter3DSeries *>(m_series); }
+ inline void setItemSize(float size) { m_itemSize = size; }
+ inline float itemSize() const { return m_itemSize; }
+ inline void setSelectionIndexOffset(int offset) { m_selectionIndexOffset = offset; }
+ inline int selectionIndexOffset() const { return m_selectionIndexOffset; }
+ inline int oldArraySize() const { return m_oldRenderArraySize; }
+ inline void setOldArraySize(int size) { m_oldRenderArraySize = size; }
+ inline const QString &oldMeshFileName() const { return m_oldMeshFileName; }
+ inline void setOldMeshFileName(const QString &meshFileName) { m_oldMeshFileName = meshFileName; }
+ inline void setBufferObject(ScatterObjectBufferHelper *object) { m_scatterBufferObj = object; }
+ inline ScatterObjectBufferHelper *bufferObject() const { return m_scatterBufferObj; }
+ inline void setBufferPoints(ScatterPointBufferHelper *object) { m_scatterBufferPoints = object; }
+ inline ScatterPointBufferHelper *bufferPoints() const { return m_scatterBufferPoints; }
+
+protected:
+ ScatterRenderItemArray m_renderArray;
+ float m_itemSize;
+ int m_selectionIndexOffset; // Temporarily cached value for selection color calculations
+ int m_oldRenderArraySize; // Used to detect if full buffer change needed
+ QString m_oldMeshFileName; // Used to detect if full buffer change needed
+ ScatterObjectBufferHelper *m_scatterBufferObj;
+ ScatterPointBufferHelper *m_scatterBufferPoints;
+};
+
+QT_END_NAMESPACE_DATAVISUALIZATION
+
+#endif
diff --git a/src/datavisualization/engine/selectionpointer.cpp b/src/datavisualization/engine/selectionpointer.cpp
index d4e635bc..183d3f8e 100644
--- a/src/datavisualization/engine/selectionpointer.cpp
+++ b/src/datavisualization/engine/selectionpointer.cpp
@@ -17,16 +17,11 @@
****************************************************************************/
#include "selectionpointer_p.h"
-#include "surface3dcontroller_p.h"
#include "shaderhelper_p.h"
#include "objecthelper_p.h"
#include "texturehelper_p.h"
#include "q3dcamera_p.h"
-#include "drawer_p.h"
#include "utils_p.h"
-#include "q3dlight.h"
-
-#include <QtGui/QMatrix4x4>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -54,7 +49,6 @@ SelectionPointer::~SelectionPointer()
{
delete m_labelShader;
delete m_pointShader;
- delete m_labelObj;
delete m_textureHelper;
}
@@ -66,7 +60,6 @@ void SelectionPointer::initializeOpenGL()
m_drawer->initializeOpenGL();
initShaders();
- loadLabelMesh();
}
void SelectionPointer::updateScene(Q3DScene *scene)
@@ -74,7 +67,7 @@ void SelectionPointer::updateScene(Q3DScene *scene)
m_cachedScene = scene;
}
-void SelectionPointer::render(GLuint defaultFboHandle)
+void SelectionPointer::render(GLuint defaultFboHandle, bool useOrtho)
{
Q_UNUSED(defaultFboHandle)
@@ -89,17 +82,22 @@ void SelectionPointer::render(GLuint defaultFboHandle)
// Get view matrix
QMatrix4x4 viewMatrix;
QMatrix4x4 projectionMatrix;
+ GLfloat viewPortRatio = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height();
if (m_cachedIsSlicingActivated) {
- GLfloat aspect = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height();
GLfloat sliceUnitsScaled = sliceUnits / m_autoScaleAdjustment;
viewMatrix.lookAt(QVector3D(0.0f, 0.0f, 1.0f), zeroVector, upVector);
- projectionMatrix.ortho(-sliceUnitsScaled * aspect, sliceUnitsScaled * aspect,
+ projectionMatrix.ortho(-sliceUnitsScaled * viewPortRatio, sliceUnitsScaled * viewPortRatio,
-sliceUnitsScaled, sliceUnitsScaled,
-1.0f, 4.0f);
+ } else if (useOrtho) {
+ viewMatrix = camera->d_ptr->viewMatrix();
+ GLfloat orthoRatio = 2.0f;
+ projectionMatrix.ortho(-viewPortRatio * orthoRatio, viewPortRatio * orthoRatio,
+ -orthoRatio, orthoRatio,
+ 0.0f, 100.0f);
} else {
viewMatrix = camera->d_ptr->viewMatrix();
- projectionMatrix.perspective(45.0f, (GLfloat)m_mainViewPort.width()
- / (GLfloat)m_mainViewPort.height(), 0.1f, 100.0f);
+ projectionMatrix.perspective(45.0f, viewPortRatio, 0.1f, 100.0f);
}
// Calculate scale factor to get uniform font size
@@ -209,7 +207,7 @@ void SelectionPointer::updateSliceData(bool sliceActivated, GLfloat autoScaleAdj
m_autoScaleAdjustment = autoScaleAdjustment;
}
-void SelectionPointer::setHighlightColor(const QVector3D &colorVector)
+void SelectionPointer::setHighlightColor(const QVector4D &colorVector)
{
m_highlightColor = colorVector;
}
@@ -230,6 +228,11 @@ void SelectionPointer::setPointerObject(ObjectHelper *object)
m_pointObj = object;
}
+void SelectionPointer::setLabelObject(ObjectHelper *object)
+{
+ m_labelObj = object;
+}
+
void SelectionPointer::handleDrawerChange()
{
m_cachedTheme = m_drawer->theme();
@@ -264,12 +267,4 @@ void SelectionPointer::initShaders()
}
-void SelectionPointer::loadLabelMesh()
-{
- if (m_labelObj)
- delete m_labelObj;
- m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
- m_labelObj->load();
-}
-
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/selectionpointer_p.h b/src/datavisualization/engine/selectionpointer_p.h
index 1eac22be..7dc28024 100644
--- a/src/datavisualization/engine/selectionpointer_p.h
+++ b/src/datavisualization/engine/selectionpointer_p.h
@@ -29,7 +29,6 @@
#ifndef SELECTIONPOINTER_P_H
#define SELECTIONPOINTER_P_H
-#include "q3dscene.h"
#include "datavisualizationglobal_p.h"
#include "surface3dcontroller_p.h"
@@ -37,7 +36,6 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
class ShaderHelper;
class ObjectHelper;
-class SurfaceObject;
class TextureHelper;
class Drawer;
@@ -49,26 +47,26 @@ public:
explicit SelectionPointer(Drawer *drawer);
~SelectionPointer();
- void render(GLuint defaultFboHandle = 0);
+ void render(GLuint defaultFboHandle = 0, bool useOrtho = false);
void setPosition(const QVector3D &position);
void setLabel(const QString &label);
void setPointerObject(ObjectHelper *object);
+ void setLabelObject(ObjectHelper *object);
void handleDrawerChange();
void updateBoundingRect(const QRect &rect);
void updateScene(Q3DScene *scene);
void updateSliceData(bool sliceActivated, GLfloat autoScaleAdjustment);
- void setHighlightColor(const QVector3D &colorVector);
+ void setHighlightColor(const QVector4D &colorVector);
void setRotation(const QQuaternion &rotation);
private:
void initializeOpenGL();
void initShaders();
- void loadLabelMesh();
private:
ShaderHelper *m_labelShader;
ShaderHelper *m_pointShader;
- ObjectHelper *m_labelObj;
+ ObjectHelper *m_labelObj; // Not owned
ObjectHelper *m_pointObj; // Not owned
TextureHelper *m_textureHelper;
Q3DTheme *m_cachedTheme;
@@ -81,7 +79,7 @@ private:
QString m_label;
bool m_cachedIsSlicingActivated;
GLfloat m_autoScaleAdjustment;
- QVector3D m_highlightColor;
+ QVector4D m_highlightColor;
QQuaternion m_rotation;
};
diff --git a/src/datavisualization/engine/seriesrendercache.cpp b/src/datavisualization/engine/seriesrendercache.cpp
index 896b3b28..dc4b9db3 100644
--- a/src/datavisualization/engine/seriesrendercache.cpp
+++ b/src/datavisualization/engine/seriesrendercache.cpp
@@ -17,7 +17,6 @@
****************************************************************************/
#include "seriesrendercache_p.h"
-#include "objecthelper_p.h"
#include "abstract3drenderer_p.h"
#include "texturehelper_p.h"
#include "utils_p.h"
@@ -26,14 +25,19 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
const QString smoothString(QStringLiteral("Smooth"));
-SeriesRenderCache::SeriesRenderCache()
- : m_series(0),
+SeriesRenderCache::SeriesRenderCache(QAbstract3DSeries *series, Abstract3DRenderer *renderer)
+ : m_series(series),
m_object(0),
m_mesh(QAbstract3DSeries::MeshCube),
m_baseUniformTexture(0),
m_baseGradientTexture(0),
+ m_gradientImage(0),
m_singleHighlightGradientTexture(0),
- m_multiHighlightGradientTexture(0)
+ m_multiHighlightGradientTexture(0),
+ m_valid(false),
+ m_visible(false),
+ m_renderer(renderer),
+ m_objectDirty(true)
{
}
@@ -41,27 +45,13 @@ SeriesRenderCache::~SeriesRenderCache()
{
}
-void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer *renderer)
+void SeriesRenderCache::populate(bool newSeries)
{
- Q_ASSERT(series);
+ QAbstract3DSeriesChangeBitField &changeTracker = m_series->d_ptr->m_changeTracker;
- 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
+ if (newSeries || changeTracker.meshChanged || changeTracker.meshSmoothChanged
|| changeTracker.userDefinedMeshChanged) {
- m_mesh = series->mesh();
+ m_mesh = m_series->mesh();
changeTracker.meshChanged = false;
changeTracker.meshSmoothChanged = false;
changeTracker.userDefinedMeshChanged = false;
@@ -71,7 +61,7 @@ void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer *
// Compose mesh filename
if (m_mesh == QAbstract3DSeries::MeshUserDefined) {
// Always use the supplied mesh directly
- meshFileName = series->userDefinedMesh();
+ meshFileName = m_series->userDefinedMesh();
} else {
switch (m_mesh) {
case QAbstract3DSeries::MeshBar:
@@ -111,24 +101,18 @@ void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer *
break;
}
- if (series->isMeshSmooth() && m_mesh != QAbstract3DSeries::MeshPoint)
+ if (m_series->isMeshSmooth() && m_mesh != QAbstract3DSeries::MeshPoint)
meshFileName += smoothString;
// Give renderer an opportunity to customize the mesh
- renderer->fixMeshFileName(meshFileName, m_mesh);
+ m_renderer->fixMeshFileName(meshFileName, m_mesh);
}
- delete m_object;
- if (meshFileName.isEmpty()) {
- m_object = 0;
- } else {
- m_object = new ObjectHelper(meshFileName);
- m_object->load();
- }
+ ObjectHelper::resetObjectHelper(m_renderer, m_object, meshFileName);
}
- if (seriesChanged || changeTracker.meshRotationChanged) {
- m_meshRotation = series->meshRotation().normalized();
+ if (newSeries || changeTracker.meshRotationChanged) {
+ m_meshRotation = m_series->meshRotation().normalized();
if (m_series->type() == QAbstract3DSeries::SeriesTypeBar
&& (m_meshRotation.x() || m_meshRotation.z())) {
m_meshRotation = identityQuaternion;
@@ -136,55 +120,73 @@ void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer *
changeTracker.meshRotationChanged = false;
}
- if (seriesChanged || changeTracker.colorStyleChanged) {
- m_colorStyle = series->colorStyle();
+ if (newSeries || changeTracker.colorStyleChanged) {
+ m_colorStyle = m_series->colorStyle();
changeTracker.colorStyleChanged = false;
}
- if (seriesChanged || changeTracker.baseColorChanged) {
- m_baseColor = Utils::vectorFromColor(series->baseColor());
+ if (newSeries || changeTracker.baseColorChanged) {
+ m_baseColor = Utils::vectorFromColor(m_series->baseColor());
if (m_series->type() == QAbstract3DSeries::SeriesTypeSurface)
- renderer->generateBaseColorTexture(series->baseColor(), &m_baseUniformTexture);
+ m_renderer->generateBaseColorTexture(m_series->baseColor(), &m_baseUniformTexture);
changeTracker.baseColorChanged = false;
}
- if (seriesChanged || changeTracker.baseGradientChanged) {
- QLinearGradient gradient = series->baseGradient();
- renderer->fixGradientAndGenerateTexture(&gradient, &m_baseGradientTexture);
+ if (newSeries || changeTracker.baseGradientChanged) {
+ QLinearGradient gradient = m_series->baseGradient();
+ m_gradientImage = Utils::getGradientImage(gradient);
+ m_renderer->fixGradientAndGenerateTexture(&gradient, &m_baseGradientTexture);
changeTracker.baseGradientChanged = false;
}
- if (seriesChanged || changeTracker.singleHighlightColorChanged) {
- m_singleHighlightColor = Utils::vectorFromColor(series->singleHighlightColor());
+ if (newSeries || changeTracker.singleHighlightColorChanged) {
+ m_singleHighlightColor = Utils::vectorFromColor(m_series->singleHighlightColor());
changeTracker.singleHighlightColorChanged = false;
}
- if (seriesChanged || changeTracker.singleHighlightGradientChanged) {
- QLinearGradient gradient = series->singleHighlightGradient();
- renderer->fixGradientAndGenerateTexture(&gradient, &m_singleHighlightGradientTexture);
+ if (newSeries || changeTracker.singleHighlightGradientChanged) {
+ QLinearGradient gradient = m_series->singleHighlightGradient();
+ m_renderer->fixGradientAndGenerateTexture(&gradient, &m_singleHighlightGradientTexture);
changeTracker.singleHighlightGradientChanged = false;
}
- if (seriesChanged || changeTracker.multiHighlightColorChanged) {
- m_multiHighlightColor = Utils::vectorFromColor(series->multiHighlightColor());
+ if (newSeries || changeTracker.multiHighlightColorChanged) {
+ m_multiHighlightColor = Utils::vectorFromColor(m_series->multiHighlightColor());
changeTracker.multiHighlightColorChanged = false;
}
- if (seriesChanged || changeTracker.multiHighlightGradientChanged) {
- QLinearGradient gradient = series->multiHighlightGradient();
- renderer->fixGradientAndGenerateTexture(&gradient, &m_multiHighlightGradientTexture);
+ if (newSeries || changeTracker.multiHighlightGradientChanged) {
+ QLinearGradient gradient = m_series->multiHighlightGradient();
+ m_renderer->fixGradientAndGenerateTexture(&gradient, &m_multiHighlightGradientTexture);
changeTracker.multiHighlightGradientChanged = false;
}
- if (seriesChanged || changeTracker.nameChanged) {
- m_name = series->name();
+ if (newSeries || changeTracker.nameChanged) {
+ m_name = m_series->name();
changeTracker.nameChanged = false;
}
+
+ if (newSeries || changeTracker.itemLabelChanged
+ || changeTracker.itemLabelVisibilityChanged) {
+ changeTracker.itemLabelChanged = false;
+ changeTracker.itemLabelVisibilityChanged = false;
+ // series->itemLabel() call resolves the item label and emits the changed signal
+ // if it is dirty, so we need to call it even if m_itemLabel is eventually set
+ // to an empty string.
+ m_itemLabel = m_series->itemLabel();
+ if (!m_series->isItemLabelVisible())
+ m_itemLabel = QString();
+ }
+
+ if (newSeries || changeTracker.visibilityChanged) {
+ m_visible = m_series->isVisible();
+ changeTracker.visibilityChanged = false;
+ }
}
void SeriesRenderCache::cleanup(TextureHelper *texHelper)
{
- delete m_object;
+ ObjectHelper::releaseObjectHelper(m_renderer, m_object);
if (QOpenGLContext::currentContext()) {
texHelper->deleteTexture(&m_baseUniformTexture);
texHelper->deleteTexture(&m_baseGradientTexture);
diff --git a/src/datavisualization/engine/seriesrendercache_p.h b/src/datavisualization/engine/seriesrendercache_p.h
index 77e050b0..96b61b87 100644
--- a/src/datavisualization/engine/seriesrendercache_p.h
+++ b/src/datavisualization/engine/seriesrendercache_p.h
@@ -41,48 +41,59 @@ class TextureHelper;
class SeriesRenderCache
{
public:
- SeriesRenderCache();
+ SeriesRenderCache(QAbstract3DSeries *series, Abstract3DRenderer *renderer);
virtual ~SeriesRenderCache();
- void populate(QAbstract3DSeries *series, Abstract3DRenderer *renderer);
+ virtual void populate(bool newSeries);
virtual 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 const QQuaternion &meshRotation() const { return m_meshRotation; }
inline void setMeshRotation(const QQuaternion &rotation) { m_meshRotation = rotation; }
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 QVector4D &baseColor() const { return m_baseColor; }
inline const GLuint &baseUniformTexture() const { return m_baseUniformTexture; }
inline const GLuint &baseGradientTexture() const { return m_baseGradientTexture; }
- inline const QVector3D &singleHighlightColor() const { return m_singleHighlightColor; }
+ inline const QImage &gradientImage() const { return m_gradientImage; }
+ inline const QVector4D &singleHighlightColor() const { return m_singleHighlightColor; }
inline const GLuint &singleHighlightGradientTexture() const { return m_singleHighlightGradientTexture; }
- inline const QVector3D &multiHighlightColor() const { return m_multiHighlightColor; }
+ inline const QVector4D &multiHighlightColor() const { return m_multiHighlightColor; }
inline const GLuint &multiHighlightGradientTexture() const { return m_multiHighlightGradientTexture; }
inline const QString &name() const { return m_name; }
+ inline const QString &itemLabel() const { return m_itemLabel; }
+ inline void setValid(bool valid) { m_valid = valid; }
+ inline bool isValid() const { return m_valid; }
+ inline bool isVisible() const { return m_visible; }
+ inline void setDataDirty(bool state) { m_objectDirty = state; }
+ inline bool dataDirty() const { return m_objectDirty; }
protected:
QAbstract3DSeries *m_series;
- QString m_itemLabelFormat;
- ObjectHelper *m_object;
+ ObjectHelper *m_object; // Shared reference
QAbstract3DSeries::Mesh m_mesh;
QQuaternion m_meshRotation;
Q3DTheme::ColorStyle m_colorStyle;
- QVector3D m_baseColor;
+ QVector4D m_baseColor;
GLuint m_baseUniformTexture;
GLuint m_baseGradientTexture;
- QVector3D m_singleHighlightColor;
+ QImage m_gradientImage;
+ QVector4D m_singleHighlightColor;
GLuint m_singleHighlightGradientTexture;
- QVector3D m_multiHighlightColor;
+ QVector4D m_multiHighlightColor;
GLuint m_multiHighlightGradientTexture;
QString m_name;
+ QString m_itemLabel;
+ bool m_valid;
+ bool m_visible;
+ Abstract3DRenderer *m_renderer;
+ bool m_objectDirty;
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/shaders/colorOnY.frag b/src/datavisualization/engine/shaders/colorOnY.frag
index 8c610cd7..7a5eb46b 100644
--- a/src/datavisualization/engine/shaders/colorOnY.frag
+++ b/src/datavisualization/engine/shaders/colorOnY.frag
@@ -6,7 +6,7 @@ uniform highp float ambientStrength;
uniform sampler2D textureSampler;
uniform highp float gradMin;
uniform highp float gradHeight;
-uniform highp vec3 lightColor;
+uniform highp vec4 lightColor;
varying highp vec3 position_wrld;
varying highp vec3 normal_cmr;
@@ -17,8 +17,8 @@ varying highp vec2 coords_mdl;
void main() {
highp vec2 gradientUV = vec2(0.0, gradMin + ((coords_mdl.y + 1.0) * gradHeight));
highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz;
- highp vec3 materialAmbientColor = lightColor * ambientStrength * materialDiffuseColor;
- highp vec3 materialSpecularColor = lightColor;
+ highp vec3 materialAmbientColor = lightColor.rgb * ambientStrength * materialDiffuseColor;
+ highp vec3 materialSpecularColor = lightColor.rgb;
highp float distance = length(lightPosition_wrld - position_wrld);
highp vec3 n = normalize(normal_cmr);
diff --git a/src/datavisualization/engine/shaders/colorOnY_ES2.frag b/src/datavisualization/engine/shaders/colorOnY_ES2.frag
index 5b553562..4352de05 100644
--- a/src/datavisualization/engine/shaders/colorOnY_ES2.frag
+++ b/src/datavisualization/engine/shaders/colorOnY_ES2.frag
@@ -1,11 +1,11 @@
-uniform highp vec3 lightPosition_wrld;
uniform highp float lightStrength;
uniform highp float ambientStrength;
uniform sampler2D textureSampler;
uniform highp float gradMin;
uniform highp float gradHeight;
-uniform highp vec3 lightColor;
+uniform highp vec4 lightColor;
+varying highp vec3 lightPosition_wrld_frag;
varying highp vec3 position_wrld;
varying highp vec3 normal_cmr;
varying highp vec3 eyeDirection_cmr;
@@ -15,10 +15,10 @@ varying highp vec2 coords_mdl;
void main() {
highp vec2 gradientUV = vec2(0.0, gradMin + ((coords_mdl.y + 1.0) * gradHeight));
highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz;
- highp vec3 materialAmbientColor = lightColor * ambientStrength * materialDiffuseColor;
- highp vec3 materialSpecularColor = lightColor;
+ highp vec3 materialAmbientColor = lightColor.rgb * ambientStrength * materialDiffuseColor;
+ highp vec3 materialSpecularColor = lightColor.rgb;
- highp float distance = length(lightPosition_wrld - position_wrld);
+ highp float distance = length(lightPosition_wrld_frag - position_wrld);
highp vec3 n = normalize(normal_cmr);
highp vec3 l = normalize(lightDirection_cmr);
highp float cosTheta = dot(n, l);
diff --git a/src/datavisualization/engine/shaders/default.frag b/src/datavisualization/engine/shaders/default.frag
index ca6fefb9..d16055a3 100644
--- a/src/datavisualization/engine/shaders/default.frag
+++ b/src/datavisualization/engine/shaders/default.frag
@@ -8,15 +8,15 @@ varying highp vec3 eyeDirection_cmr;
varying highp vec3 lightDirection_cmr;
uniform highp vec3 lightPosition_wrld;
-uniform highp vec3 color_mdl;
+uniform highp vec4 color_mdl;
uniform highp float lightStrength;
uniform highp float ambientStrength;
-uniform highp vec3 lightColor;
+uniform highp vec4 lightColor;
void main() {
highp vec3 materialDiffuseColor = color_mdl.rgb;
- highp vec3 materialAmbientColor = lightColor * ambientStrength * materialDiffuseColor;
- highp vec3 materialSpecularColor = lightColor;
+ highp vec3 materialAmbientColor = lightColor.rgb * ambientStrength * materialDiffuseColor;
+ highp vec3 materialSpecularColor = lightColor.rgb;
highp float distance = length(lightPosition_wrld - position_wrld);
diff --git a/src/datavisualization/engine/shaders/default.vert b/src/datavisualization/engine/shaders/default.vert
index efb40862..b454913b 100644
--- a/src/datavisualization/engine/shaders/default.vert
+++ b/src/datavisualization/engine/shaders/default.vert
@@ -8,6 +8,7 @@ uniform highp mat4 M;
uniform highp mat4 itM;
uniform highp vec3 lightPosition_wrld;
+varying highp vec3 lightPosition_wrld_frag;
varying highp vec3 position_wrld;
varying highp vec3 normal_cmr;
varying highp vec3 eyeDirection_cmr;
@@ -17,10 +18,11 @@ 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;
+ position_wrld = vec4(M * vec4(vertexPosition_mdl, 1.0)).xyz;
+ vec3 vertexPosition_cmr = vec4(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;
+ vec3 lightPosition_cmr = vec4(V * vec4(lightPosition_wrld, 1.0)).xyz;
lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr;
- normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz;
+ normal_cmr = vec4(V * itM * vec4(vertexNormal_mdl, 0.0)).xyz;
+ lightPosition_wrld_frag = lightPosition_wrld;
}
diff --git a/src/datavisualization/engine/shaders/default_ES2.frag b/src/datavisualization/engine/shaders/default_ES2.frag
index bc5c18b6..73d66d5b 100644
--- a/src/datavisualization/engine/shaders/default_ES2.frag
+++ b/src/datavisualization/engine/shaders/default_ES2.frag
@@ -4,19 +4,19 @@ varying highp vec3 position_wrld;
varying highp vec3 normal_cmr;
varying highp vec3 eyeDirection_cmr;
varying highp vec3 lightDirection_cmr;
+varying highp vec3 lightPosition_wrld_frag;
-uniform highp vec3 lightPosition_wrld;
-uniform highp vec3 color_mdl;
+uniform highp vec4 color_mdl;
uniform highp float lightStrength;
uniform highp float ambientStrength;
-uniform highp vec3 lightColor;
+uniform highp vec4 lightColor;
void main() {
highp vec3 materialDiffuseColor = color_mdl.rgb;
- highp vec3 materialAmbientColor = lightColor * ambientStrength * materialDiffuseColor;
- highp vec3 materialSpecularColor = lightColor;
+ highp vec3 materialAmbientColor = lightColor.rgb * ambientStrength * materialDiffuseColor;
+ highp vec3 materialSpecularColor = lightColor.rgb;
- highp float distance = length(lightPosition_wrld - position_wrld);
+ highp float distance = length(lightPosition_wrld_frag - position_wrld);
highp vec3 n = normalize(normal_cmr);
highp vec3 l = normalize(lightDirection_cmr);
diff --git a/src/datavisualization/engine/shaders/plainColor.frag b/src/datavisualization/engine/shaders/plainColor.frag
index 099c87a1..da9ee060 100644
--- a/src/datavisualization/engine/shaders/plainColor.frag
+++ b/src/datavisualization/engine/shaders/plainColor.frag
@@ -1,7 +1,6 @@
-uniform highp vec3 color_mdl;
+uniform highp vec4 color_mdl;
void main() {
- gl_FragColor.rgb = color_mdl;
- gl_FragColor.a = 1.0;
+ gl_FragColor = color_mdl;
}
diff --git a/src/datavisualization/engine/shaders/shadow.frag b/src/datavisualization/engine/shaders/shadow.frag
index e2286dc5..237e9780 100644
--- a/src/datavisualization/engine/shaders/shadow.frag
+++ b/src/datavisualization/engine/shaders/shadow.frag
@@ -5,7 +5,7 @@ uniform highp float ambientStrength;
uniform highp float shadowQuality;
uniform highp sampler2D textureSampler;
uniform highp sampler2DShadow shadowMap;
-uniform highp vec3 lightColor;
+uniform highp vec4 lightColor;
varying highp vec4 shadowCoord;
varying highp vec2 UV;
@@ -33,8 +33,8 @@ highp vec2 poissonDisk[16] = vec2[16](vec2(-0.94201624, -0.39906216),
void main() {
highp vec3 materialDiffuseColor = texture2D(textureSampler, UV).rgb;
- highp vec3 materialAmbientColor = lightColor * ambientStrength * materialDiffuseColor;
- highp vec3 materialSpecularColor = lightColor * 0.2;
+ highp vec3 materialAmbientColor = lightColor.rgb * ambientStrength * materialDiffuseColor;
+ highp vec3 materialSpecularColor = lightColor.rgb * 0.2;
highp vec3 n = normalize(normal_cmr);
highp vec3 l = normalize(lightDirection_cmr);
diff --git a/src/datavisualization/engine/shaders/shadow.vert b/src/datavisualization/engine/shaders/shadow.vert
index e29a8a30..0adcd43c 100644
--- a/src/datavisualization/engine/shaders/shadow.vert
+++ b/src/datavisualization/engine/shaders/shadow.vert
@@ -28,10 +28,10 @@ void main() {
gl_Position = MVP * vec4(vertexPosition_mdl, 1.0);
coords_mdl = vertexPosition_mdl.xy;
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;
+ position_wrld = vec4(M * vec4(vertexPosition_mdl, 1.0)).xyz;
+ vec3 vertexPosition_cmr = vec4(V * M * vec4(vertexPosition_mdl, 1.0)).xyz;
eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr;
- lightDirection_cmr = (V * vec4(lightPosition_wrld, 0.0)).xyz;
- normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz;
+ lightDirection_cmr = vec4(V * vec4(lightPosition_wrld, 0.0)).xyz;
+ normal_cmr = vec4(V * itM * vec4(vertexNormal_mdl, 0.0)).xyz;
UV = vertexUV;
}
diff --git a/src/datavisualization/engine/shaders/shadowNoTex.frag b/src/datavisualization/engine/shaders/shadowNoTex.frag
index d54efea9..b2e7adfc 100644
--- a/src/datavisualization/engine/shaders/shadowNoTex.frag
+++ b/src/datavisualization/engine/shaders/shadowNoTex.frag
@@ -3,9 +3,9 @@
uniform highp float lightStrength;
uniform highp float ambientStrength;
uniform highp float shadowQuality;
-uniform highp vec3 color_mdl;
+uniform highp vec4 color_mdl;
uniform highp sampler2DShadow shadowMap;
-uniform highp vec3 lightColor;
+uniform highp vec4 lightColor;
varying highp vec4 shadowCoord;
varying highp vec3 position_wrld;
@@ -32,8 +32,8 @@ highp vec2 poissonDisk[16] = vec2[16](vec2(-0.94201624, -0.39906216),
void main() {
highp vec3 materialDiffuseColor = color_mdl.rgb;
- highp vec3 materialAmbientColor = lightColor * ambientStrength * materialDiffuseColor;
- highp vec3 materialSpecularColor = lightColor;
+ highp vec3 materialAmbientColor = lightColor.rgb * ambientStrength * materialDiffuseColor;
+ highp vec3 materialSpecularColor = lightColor.rgb;
highp vec3 n = normalize(normal_cmr);
highp vec3 l = normalize(lightDirection_cmr);
diff --git a/src/datavisualization/engine/shaders/shadowNoTexColorOnY.frag b/src/datavisualization/engine/shaders/shadowNoTexColorOnY.frag
index e986a52a..73b84138 100644
--- a/src/datavisualization/engine/shaders/shadowNoTexColorOnY.frag
+++ b/src/datavisualization/engine/shaders/shadowNoTexColorOnY.frag
@@ -7,7 +7,7 @@ uniform highp sampler2DShadow shadowMap;
uniform sampler2D textureSampler;
uniform highp float gradMin;
uniform highp float gradHeight;
-uniform highp vec3 lightColor;
+uniform highp vec4 lightColor;
varying highp vec4 shadowCoord;
varying highp vec3 position_wrld;
@@ -36,8 +36,8 @@ highp vec2 poissonDisk[16] = vec2[16](vec2(-0.94201624, -0.39906216),
void main() {
highp vec2 gradientUV = vec2(0.0, gradMin + ((coords_mdl.y + 1.0) * gradHeight));
highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz;
- highp vec3 materialAmbientColor = lightColor * ambientStrength * materialDiffuseColor;
- highp vec3 materialSpecularColor = lightColor;
+ highp vec3 materialAmbientColor = lightColor.rgb * ambientStrength * materialDiffuseColor;
+ highp vec3 materialSpecularColor = lightColor.rgb;
highp vec3 n = normalize(normal_cmr);
highp vec3 l = normalize(lightDirection_cmr);
diff --git a/src/datavisualization/engine/shaders/surface.frag b/src/datavisualization/engine/shaders/surface.frag
index b5205d2d..f17dd73e 100644
--- a/src/datavisualization/engine/shaders/surface.frag
+++ b/src/datavisualization/engine/shaders/surface.frag
@@ -10,13 +10,13 @@ uniform sampler2D textureSampler;
uniform highp vec3 lightPosition_wrld;
uniform highp float lightStrength;
uniform highp float ambientStrength;
-uniform highp vec3 lightColor;
+uniform highp vec4 lightColor;
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 = lightColor * ambientStrength * materialDiffuseColor;
- highp vec3 materialSpecularColor = lightColor;
+ highp vec3 materialAmbientColor = lightColor.rgb * ambientStrength * materialDiffuseColor;
+ highp vec3 materialSpecularColor = lightColor.rgb;
highp float distance = length(lightPosition_wrld - position_wrld);
diff --git a/src/datavisualization/engine/shaders/surfaceFlat.frag b/src/datavisualization/engine/shaders/surfaceFlat.frag
index 7eaa917f..748fb3dd 100644
--- a/src/datavisualization/engine/shaders/surfaceFlat.frag
+++ b/src/datavisualization/engine/shaders/surfaceFlat.frag
@@ -12,13 +12,13 @@ uniform sampler2D textureSampler;
uniform highp vec3 lightPosition_wrld;
uniform highp float lightStrength;
uniform highp float ambientStrength;
-uniform highp vec3 lightColor;
+uniform highp vec4 lightColor;
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 = lightColor * ambientStrength * materialDiffuseColor;
- highp vec3 materialSpecularColor = lightColor;
+ highp vec3 materialAmbientColor = lightColor.rgb * ambientStrength * materialDiffuseColor;
+ highp vec3 materialSpecularColor = lightColor.rgb;
highp float distance = length(lightPosition_wrld - position_wrld);
diff --git a/src/datavisualization/engine/shaders/surfaceFlat.vert b/src/datavisualization/engine/shaders/surfaceFlat.vert
index 0d39f6bc..102bea78 100644
--- a/src/datavisualization/engine/shaders/surfaceFlat.vert
+++ b/src/datavisualization/engine/shaders/surfaceFlat.vert
@@ -20,10 +20,10 @@ varying highp vec3 coords_mdl;
void main() {
gl_Position = MVP * vec4(vertexPosition_mdl, 1.0);
coords_mdl = vertexPosition_mdl;
- position_wrld = (M * vec4(vertexPosition_mdl, 1.0)).xyz;
- vec3 vertexPosition_cmr = (V * M * vec4(vertexPosition_mdl, 1.0)).xyz;
+ position_wrld = vec4(M * vec4(vertexPosition_mdl, 1.0)).xyz;
+ vec3 vertexPosition_cmr = vec4(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;
+ vec3 lightPosition_cmr = vec4(V * vec4(lightPosition_wrld, 1.0)).xyz;
lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr;
- normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz;
+ normal_cmr = vec4(V * itM * vec4(vertexNormal_mdl, 0.0)).xyz;
}
diff --git a/src/datavisualization/engine/shaders/surfaceShadowFlat.frag b/src/datavisualization/engine/shaders/surfaceShadowFlat.frag
index 9b9305ab..0613a40c 100644
--- a/src/datavisualization/engine/shaders/surfaceShadowFlat.frag
+++ b/src/datavisualization/engine/shaders/surfaceShadowFlat.frag
@@ -15,7 +15,7 @@ uniform highp vec3 lightPosition_wrld;
uniform highp float lightStrength;
uniform highp float ambientStrength;
uniform highp float shadowQuality;
-uniform highp vec3 lightColor;
+uniform highp vec4 lightColor;
highp vec2 poissonDisk[16] = vec2[16](vec2(-0.94201624, -0.39906216),
vec2(0.94558609, -0.76890725),
@@ -37,8 +37,8 @@ highp vec2 poissonDisk[16] = vec2[16](vec2(-0.94201624, -0.39906216),
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 = lightColor * ambientStrength * materialDiffuseColor;
- highp vec3 materialSpecularColor = lightColor;
+ highp vec3 materialAmbientColor = lightColor.rgb * ambientStrength * materialDiffuseColor;
+ highp vec3 materialSpecularColor = lightColor.rgb;
highp vec3 n = normalize(normal_cmr);
highp vec3 l = normalize(lightDirection_cmr);
diff --git a/src/datavisualization/engine/shaders/surfaceShadowFlat.vert b/src/datavisualization/engine/shaders/surfaceShadowFlat.vert
index 0a6e967f..8da7b196 100644
--- a/src/datavisualization/engine/shaders/surfaceShadowFlat.vert
+++ b/src/datavisualization/engine/shaders/surfaceShadowFlat.vert
@@ -28,10 +28,10 @@ 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;
+ position_wrld = vec4(M * vec4(vertexPosition_mdl, 1.0)).xyz;
+ vec3 vertexPosition_cmr = vec4(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;
+ vec3 lightPosition_cmr = vec4(V * vec4(lightPosition_wrld, 1.0)).xyz;
lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr;
- normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz;
+ normal_cmr = vec4(V * itM * vec4(vertexNormal_mdl, 0.0)).xyz;
}
diff --git a/src/datavisualization/engine/shaders/surfaceShadowNoTex.frag b/src/datavisualization/engine/shaders/surfaceShadowNoTex.frag
index 3427fbae..1acf8f69 100644
--- a/src/datavisualization/engine/shaders/surfaceShadowNoTex.frag
+++ b/src/datavisualization/engine/shaders/surfaceShadowNoTex.frag
@@ -13,7 +13,7 @@ uniform highp vec3 lightPosition_wrld;
uniform highp float lightStrength;
uniform highp float ambientStrength;
uniform highp float shadowQuality;
-uniform highp vec3 lightColor;
+uniform highp vec4 lightColor;
highp vec2 poissonDisk[16] = vec2[16](vec2(-0.94201624, -0.39906216),
vec2(0.94558609, -0.76890725),
@@ -35,8 +35,8 @@ highp vec2 poissonDisk[16] = vec2[16](vec2(-0.94201624, -0.39906216),
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 = lightColor * ambientStrength * materialDiffuseColor;
- highp vec3 materialSpecularColor = lightColor;
+ highp vec3 materialAmbientColor = lightColor.rgb * ambientStrength * materialDiffuseColor;
+ highp vec3 materialSpecularColor = lightColor.rgb;
highp vec3 n = normalize(normal_cmr);
highp vec3 l = normalize(lightDirection_cmr);
diff --git a/src/datavisualization/engine/shaders/surface_ES2.frag b/src/datavisualization/engine/shaders/surface_ES2.frag
index 0e17cacd..58d13834 100644
--- a/src/datavisualization/engine/shaders/surface_ES2.frag
+++ b/src/datavisualization/engine/shaders/surface_ES2.frag
@@ -4,20 +4,20 @@ varying highp vec3 position_wrld;
varying highp vec3 normal_cmr;
varying highp vec3 eyeDirection_cmr;
varying highp vec3 lightDirection_cmr;
+varying highp vec3 lightPosition_wrld_frag;
uniform sampler2D textureSampler;
-uniform highp vec3 lightPosition_wrld;
uniform highp float lightStrength;
uniform highp float ambientStrength;
-uniform highp vec3 lightColor;
+uniform highp vec4 lightColor;
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 = lightColor * ambientStrength * materialDiffuseColor;
- highp vec3 materialSpecularColor = lightColor;
+ highp vec3 materialAmbientColor = lightColor.rgb * ambientStrength * materialDiffuseColor;
+ highp vec3 materialSpecularColor = lightColor.rgb;
- highp float distance = length(lightPosition_wrld - position_wrld);
+ highp float distance = length(lightPosition_wrld_frag - position_wrld);
highp vec3 n = normalize(normal_cmr);
highp vec3 l = normalize(lightDirection_cmr);
diff --git a/src/datavisualization/engine/shaders/texture.frag b/src/datavisualization/engine/shaders/texture.frag
new file mode 100644
index 00000000..41c4259b
--- /dev/null
+++ b/src/datavisualization/engine/shaders/texture.frag
@@ -0,0 +1,37 @@
+#version 120
+
+varying highp vec2 UV;
+varying highp vec3 position_wrld;
+varying highp vec3 normal_cmr;
+varying highp vec3 eyeDirection_cmr;
+varying highp vec3 lightDirection_cmr;
+
+uniform highp vec3 lightPosition_wrld;
+uniform highp sampler2D textureSampler;
+uniform highp float lightStrength;
+uniform highp float ambientStrength;
+uniform highp vec4 lightColor;
+
+void main() {
+ highp vec3 materialDiffuseColor = texture2D(textureSampler, UV).rgb;
+ highp vec3 materialAmbientColor = lightColor.rgb * ambientStrength * materialDiffuseColor;
+ highp vec3 materialSpecularColor = lightColor.rgb;
+
+ 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 * pow(cosTheta, 2) / distance +
+ materialSpecularColor * lightStrength * pow(cosAlpha, 10) / distance;
+ gl_FragColor.a = texture2D(textureSampler, UV).a;
+ gl_FragColor.rgb = clamp(gl_FragColor.rgb, 0.0, 1.0);
+}
+
diff --git a/src/datavisualization/engine/shaders/texture.vert b/src/datavisualization/engine/shaders/texture.vert
new file mode 100644
index 00000000..90c0ac23
--- /dev/null
+++ b/src/datavisualization/engine/shaders/texture.vert
@@ -0,0 +1,28 @@
+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 vec3 lightPosition_wrld_frag;
+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 = vec4(M * vec4(vertexPosition_mdl, 1.0)).xyz;
+ vec3 vertexPosition_cmr = vec4(V * M * vec4(vertexPosition_mdl, 1.0)).xyz;
+ eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr;
+ vec3 lightPosition_cmr = vec4(V * vec4(lightPosition_wrld, 1.0)).xyz;
+ lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr;
+ normal_cmr = vec4(V * itM * vec4(vertexNormal_mdl, 0.0)).xyz;
+ UV = vertexUV;
+ lightPosition_wrld_frag = lightPosition_wrld;
+}
diff --git a/src/datavisualization/engine/shaders/texture_ES2.frag b/src/datavisualization/engine/shaders/texture_ES2.frag
new file mode 100644
index 00000000..82ad6614
--- /dev/null
+++ b/src/datavisualization/engine/shaders/texture_ES2.frag
@@ -0,0 +1,40 @@
+varying highp vec2 UV;
+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;
+varying highp vec3 lightPosition_wrld_frag;
+
+uniform highp sampler2D textureSampler;
+uniform highp float lightStrength;
+uniform highp float ambientStrength;
+uniform highp vec4 lightColor;
+
+void main() {
+ highp vec3 materialDiffuseColor = texture2D(textureSampler, UV).rgb;
+ highp vec3 materialAmbientColor = lightColor.rgb * ambientStrength * materialDiffuseColor;
+ highp vec3 materialSpecularColor = lightColor.rgb;
+
+ highp float distance = length(lightPosition_wrld_frag - 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 * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha) / distance;
+ gl_FragColor.a = texture2D(textureSampler, UV).a;
+ gl_FragColor.rgb = clamp(gl_FragColor.rgb, 0.0, 1.0);
+}
+
diff --git a/src/datavisualization/engine/surface3dcontroller.cpp b/src/datavisualization/engine/surface3dcontroller.cpp
index 991a1ce8..c03bafd8 100644
--- a/src/datavisualization/engine/surface3dcontroller.cpp
+++ b/src/datavisualization/engine/surface3dcontroller.cpp
@@ -18,15 +18,9 @@
#include "surface3dcontroller_p.h"
#include "surface3drenderer_p.h"
-#include "camerahelper_p.h"
-#include "qabstract3daxis_p.h"
#include "qvalue3daxis_p.h"
-#include "qcategory3daxis.h"
#include "qsurfacedataproxy_p.h"
#include "qsurface3dseries_p.h"
-#include "shaderhelper_p.h"
-
-#include <QtGui/QMatrix4x4>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -66,11 +60,6 @@ void Surface3DController::synchDataToRenderer()
if (!isInitialized())
return;
- if (m_changedSeriesList.size()) {
- m_renderer->modifiedSeriesList(m_changedSeriesList);
- m_changedSeriesList.clear();
- }
-
Abstract3DController::synchDataToRenderer();
// Notify changes to renderer
@@ -81,7 +70,7 @@ void Surface3DController::synchDataToRenderer()
}
if (m_changeTracker.itemChanged) {
- m_renderer->updateItem(m_changedItems);
+ m_renderer->updateItems(m_changedItems);
m_changeTracker.itemChanged = false;
m_changedItems.clear();
}
@@ -98,7 +87,7 @@ void Surface3DController::handleAxisAutoAdjustRangeChangedInOrientation(
Q_UNUSED(orientation)
Q_UNUSED(autoAdjust)
- adjustValueAxisRange();
+ adjustAxisRanges();
}
void Surface3DController::handleAxisRangeChangedBySender(QObject *sender)
@@ -113,8 +102,6 @@ void Surface3DController::handleSeriesVisibilityChangedBySender(QObject *sender)
{
Abstract3DController::handleSeriesVisibilityChangedBySender(sender);
- adjustValueAxisRange();
-
// Visibility changes may require disabling slicing,
// so just reset selection to ensure everything is still valid.
setSelectedPoint(m_selectedPoint, m_selectedSeries, false);
@@ -128,6 +115,8 @@ void Surface3DController::handlePendingClick()
setSelectedPoint(position, series, true);
+ Abstract3DController::handlePendingClick();
+
m_renderer->resetClickedStatus();
}
@@ -148,9 +137,6 @@ void Surface3DController::addSeries(QAbstract3DSeries *series)
Abstract3DController::addSeries(series);
- if (series->isVisible())
- adjustValueAxisRange();
-
QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(series);
if (surfaceSeries->selectedPoint() != invalidSelectionPosition())
setSelectedPoint(surfaceSeries->selectedPoint(), surfaceSeries, false);
@@ -166,7 +152,7 @@ void Surface3DController::removeSeries(QAbstract3DSeries *series)
setSelectedPoint(invalidSelectionPosition(), 0, false);
if (wasVisible)
- adjustValueAxisRange();
+ adjustAxisRanges();
}
QList<QSurface3DSeries *> Surface3DController::surfaceSeriesList()
@@ -214,7 +200,8 @@ void Surface3DController::setSelectionMode(QAbstract3DGraph::SelectionFlags mode
}
}
-void Surface3DController::setSelectedPoint(const QPoint &position, QSurface3DSeries *series, bool enterSlice)
+void Surface3DController::setSelectedPoint(const QPoint &position, QSurface3DSeries *series,
+ bool enterSlice)
{
// If the selection targets non-existent point, clear selection instead.
QPoint pos = position;
@@ -290,13 +277,15 @@ void Surface3DController::handleArrayReset()
{
QSurface3DSeries *series = static_cast<QSurfaceDataProxy *>(sender())->series();
if (series->isVisible()) {
- adjustValueAxisRange();
- if (!m_changedSeriesList.contains(series))
- m_changedSeriesList.append(series);
+ adjustAxisRanges();
m_isDataDirty = true;
}
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
+
// Clear selection unless still valid
setSelectedPoint(m_selectedPoint, m_selectedSeries, false);
+ series->d_ptr->markItemLabelDirty();
emitNeedRender();
}
@@ -315,33 +304,34 @@ void Surface3DController::handleFlatShadingSupportedChange(bool supported)
void Surface3DController::handleRowsChanged(int startIndex, int count)
{
- QSurfaceDataProxy *sender = static_cast<QSurfaceDataProxy *>(QObject::sender());
- if (m_changedRows.size() == 0)
- m_changedRows.reserve(sender->rowCount());
-
- QSurface3DSeries *series = sender->series();
+ QSurface3DSeries *series = static_cast<QSurfaceDataProxy *>(QObject::sender())->series();
int oldChangeCount = m_changedRows.size();
+ if (!oldChangeCount)
+ m_changedRows.reserve(count);
+
+ int selectedRow = m_selectedPoint.x();
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).row == candidate &&
- series == m_changedRows.at(i).series) {
+ for (int j = 0; j < oldChangeCount; j++) {
+ const ChangeRow &oldChangeItem = m_changedRows.at(j);
+ if (oldChangeItem.row == candidate && series == oldChangeItem.series) {
newItem = false;
break;
}
}
if (newItem) {
- ChangeRow newItem = {series, candidate};
- m_changedRows.append(newItem);
+ ChangeRow newChangeItem = {series, candidate};
+ m_changedRows.append(newChangeItem);
+ if (series == m_selectedSeries && selectedRow == candidate)
+ series->d_ptr->markItemLabelDirty();
}
}
- if (m_changedRows.size()) {
+ if (count) {
m_changeTracker.rowsChanged = true;
- adjustValueAxisRange();
- // Clear selection unless still valid
- setSelectedPoint(m_selectedPoint, m_selectedSeries, false);
+ if (series->isVisible())
+ adjustAxisRanges();
emitNeedRender();
}
}
@@ -352,7 +342,7 @@ void Surface3DController::handleItemChanged(int rowIndex, int columnIndex)
QSurface3DSeries *series = sender->series();
bool newItem = true;
- QPoint candidate(columnIndex, rowIndex);
+ QPoint candidate(rowIndex, columnIndex);
foreach (ChangeItem item, m_changedItems) {
if (item.point == candidate && item.series == series) {
newItem = false;
@@ -364,9 +354,11 @@ void Surface3DController::handleItemChanged(int rowIndex, int columnIndex)
m_changedItems.append(newItem);
m_changeTracker.itemChanged = true;
- adjustValueAxisRange();
- // Clear selection unless still valid
- setSelectedPoint(m_selectedPoint, m_selectedSeries, false);
+ if (series == m_selectedSeries && m_selectedPoint == candidate)
+ series->d_ptr->markItemLabelDirty();
+
+ if (series->isVisible())
+ adjustAxisRanges();
emitNeedRender();
}
}
@@ -377,11 +369,11 @@ void Surface3DController::handleRowsAdded(int startIndex, int count)
Q_UNUSED(count)
QSurface3DSeries *series = static_cast<QSurfaceDataProxy *>(sender())->series();
if (series->isVisible()) {
- adjustValueAxisRange();
+ adjustAxisRanges();
m_isDataDirty = true;
- if (!m_changedSeriesList.contains(series))
- m_changedSeriesList.append(series);
}
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
emitNeedRender();
}
@@ -400,11 +392,11 @@ void Surface3DController::handleRowsInserted(int startIndex, int count)
}
if (series->isVisible()) {
- adjustValueAxisRange();
+ adjustAxisRanges();
m_isDataDirty = true;
- if (!m_changedSeriesList.contains(series))
- m_changedSeriesList.append(series);
}
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
emitNeedRender();
}
@@ -428,16 +420,16 @@ void Surface3DController::handleRowsRemoved(int startIndex, int count)
}
if (series->isVisible()) {
- adjustValueAxisRange();
+ adjustAxisRanges();
m_isDataDirty = true;
- if (!m_changedSeriesList.contains(series))
- m_changedSeriesList.append(series);
}
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
emitNeedRender();
}
-void Surface3DController::adjustValueAxisRange()
+void Surface3DController::adjustAxisRanges()
{
QValue3DAxis *valueAxisX = static_cast<QValue3DAxis *>(m_axisX);
QValue3DAxis *valueAxisY = static_cast<QValue3DAxis *>(m_axisY);
@@ -517,7 +509,7 @@ void Surface3DController::adjustValueAxisRange()
adjustment = defaultAdjustment;
}
}
- valueAxisX->dptr()->setRange(minValueX - adjustment, maxValueX + adjustment);
+ valueAxisX->dptr()->setRange(minValueX - adjustment, maxValueX + adjustment, true);
}
if (adjustY) {
// If all points at same coordinate, need to default to some valid range
@@ -525,7 +517,7 @@ void Surface3DController::adjustValueAxisRange()
float adjustment = 0.0f;
if (minValueY == maxValueY)
adjustment = defaultAdjustment;
- valueAxisY->dptr()->setRange(minValueY - adjustment, maxValueY + adjustment);
+ valueAxisY->dptr()->setRange(minValueY - adjustment, maxValueY + adjustment, true);
}
if (adjustZ) {
// If all points at same coordinate, need to default to some valid range
@@ -544,7 +536,7 @@ void Surface3DController::adjustValueAxisRange()
adjustment = defaultAdjustment;
}
}
- valueAxisZ->dptr()->setRange(minValueZ - adjustment, maxValueZ + adjustment);
+ valueAxisZ->dptr()->setRange(minValueZ - adjustment, maxValueZ + adjustment, true);
}
}
}
diff --git a/src/datavisualization/engine/surface3dcontroller_p.h b/src/datavisualization/engine/surface3dcontroller_p.h
index 14c0dd40..2be74f35 100644
--- a/src/datavisualization/engine/surface3dcontroller_p.h
+++ b/src/datavisualization/engine/surface3dcontroller_p.h
@@ -38,15 +38,11 @@ class Surface3DRenderer;
class QSurface3DSeries;
struct Surface3DChangeBitField {
- bool smoothStatusChanged : 1;
- bool surfaceGridChanged : 1;
bool selectedPointChanged : 1;
bool rowsChanged : 1;
bool itemChanged : 1;
Surface3DChangeBitField() :
- smoothStatusChanged(true),
- surfaceGridChanged(true),
selectedPointChanged(true),
rowsChanged(false),
itemChanged(false)
@@ -77,7 +73,6 @@ private:
bool m_flatShadingSupported;
QVector<ChangeItem> m_changedItems;
QVector<ChangeRow> m_changedRows;
- QVector<QSurface3DSeries *> m_changedSeriesList;
public:
explicit Surface3DController(QRect rect, Q3DScene *scene = 0);
@@ -97,6 +92,7 @@ public:
virtual void handleAxisRangeChangedBySender(QObject *sender);
virtual void handleSeriesVisibilityChangedBySender(QObject *sender);
virtual void handlePendingClick();
+ virtual void adjustAxisRanges();
static QPoint invalidSelectionPosition();
bool isFlatShadingSupported();
@@ -119,8 +115,6 @@ signals:
void selectedSeriesChanged(QSurface3DSeries *series);
private:
- void adjustValueAxisRange();
-
Q_DISABLE_COPY(Surface3DController)
};
diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp
index 41415393..12627966 100644
--- a/src/datavisualization/engine/surface3drenderer.cpp
+++ b/src/datavisualization/engine/surface3drenderer.cpp
@@ -16,22 +16,12 @@
**
****************************************************************************/
-#include "surface3dcontroller_p.h"
#include "surface3drenderer_p.h"
-#include "q3dcamera.h"
#include "q3dcamera_p.h"
#include "shaderhelper_p.h"
-#include "objecthelper_p.h"
-#include "surfaceobject_p.h"
#include "texturehelper_p.h"
-#include "selectionpointer_p.h"
#include "utils_p.h"
-#include "drawer_p.h"
-#include "q3dlight.h"
-#include "qsurface3dseries_p.h"
-#include <QtGui/QMatrix4x4>
-#include <QtGui/QMouseEvent>
#include <QtCore/qmath.h>
static const int ID_TO_RGBA_MASK = 0xff;
@@ -40,12 +30,15 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
//#define SHOW_DEPTH_TEXTURE_SCENE
-const GLfloat aspectRatio = 2.0f; // Forced ratio of x and z to y. Dynamic will make it look odd.
-const GLfloat backgroundMargin = 1.1f; // Margin for background (1.1f = make it 10% larger to avoid items being drawn inside background)
-const GLfloat labelMargin = 0.05f;
+// Margin for background (1.10 make it 10% larger to avoid
+// selection ball being drawn inside background)
+const GLfloat backgroundMargin = 1.1f;
const GLfloat gridLineWidth = 0.005f;
const GLfloat sliceZScale = 0.1f;
const GLfloat sliceUnits = 2.5f;
+const uint greenMultiplier = 256;
+const uint blueMultiplier = 65536;
+const uint alphaMultiplier = 16777216;
Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
: Abstract3DRenderer(controller),
@@ -65,15 +58,6 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_scaleZ(0.0f),
m_scaleXWithBackground(0.0f),
m_scaleZWithBackground(0.0f),
- m_minVisibleColumnValue(0.0f),
- m_maxVisibleColumnValue(0.0f),
- m_minVisibleRowValue(0.0f),
- m_maxVisibleRowValue(0.0f),
- m_visibleColumnRange(0.0f),
- m_visibleRowRange(0.0f),
- m_backgroundObj(0),
- m_gridLineObj(0),
- m_labelObj(0),
m_depthTexture(0),
m_depthModelTexture(0),
m_depthFrameBuffer(0),
@@ -83,9 +67,6 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_shadowQualityToShader(33.3f),
m_flatSupported(true),
m_selectionActive(false),
- m_xFlipped(false),
- m_zFlipped(false),
- m_yFlipped(false),
m_shadowQualityMultiplier(3),
m_hasHeightAdjustmentChanged(true),
m_selectedPoint(Surface3DController::invalidSelectionPosition()),
@@ -94,6 +75,9 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_selectionTexturesDirty(false),
m_noShadowTexture(0)
{
+ m_axisCacheY.setScale(2.0f);
+ m_axisCacheY.setTranslate(-1.0f);
+
// Check if flat feature is supported
ShaderHelper tester(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
QStringLiteral(":/shaders/fragmentSurfaceFlat"));
@@ -131,16 +115,6 @@ Surface3DRenderer::~Surface3DRenderer()
delete m_surfaceSliceFlatShader;
delete m_surfaceSliceSmoothShader;
delete m_labelShader;
-
- delete m_backgroundObj;
- delete m_gridLineObj;
- delete m_labelObj;
-
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
- cache->cleanup(m_textureHelper);
- delete cache;
- }
- m_renderCacheList.clear();
}
void Surface3DRenderer::initializeOpenGL()
@@ -160,8 +134,10 @@ void Surface3DRenderer::initializeOpenGL()
// Init selection shader
initSelectionShaders();
+#if !(defined QT_OPENGL_ES_2)
// Load grid line mesh
loadGridLineMesh();
+#endif
// Load label mesh
loadLabelMesh();
@@ -183,22 +159,25 @@ void Surface3DRenderer::updateData()
{
calculateSceneScalingFactors();
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
- const QSurface3DSeries *currentSeries = cache->series();
- QSurfaceDataProxy *dataProxy = currentSeries->dataProxy();
- const QSurfaceDataArray &array = *dataProxy->array();
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
+ if (cache->isVisible() && cache->dataDirty()) {
+ const QSurface3DSeries *currentSeries = cache->series();
+ QSurfaceDataProxy *dataProxy = currentSeries->dataProxy();
+ const QSurfaceDataArray &array = *dataProxy->array();
+ QSurfaceDataArray &dataArray = cache->dataArray();
+ QRect sampleSpace;
- // Need minimum of 2x2 array to draw a surface
- if (array.size() >= 2 && array.at(0)->size() >= 2) {
- QRect sampleSpace = calculateSampleRect(cache, array);
+ // Need minimum of 2x2 array to draw a surface
+ if (array.size() >= 2 && array.at(0)->size() >= 2)
+ sampleSpace = calculateSampleRect(array);
- QSurfaceDataArray &dataArray = cache->dataArray();
- bool dimensionChanged = false;
+ bool dimensionsChanged = false;
if (cache->sampleSpace() != sampleSpace) {
if (sampleSpace.width() >= 2)
m_selectionTexturesDirty = true;
- dimensionChanged = true;
+ dimensionsChanged = true;
cache->setSampleSpace(sampleSpace);
for (int i = 0; i < dataArray.size(); i++)
@@ -207,7 +186,7 @@ void Surface3DRenderer::updateData()
}
if (sampleSpace.width() >= 2 && sampleSpace.height() >= 2) {
- if (dimensionChanged) {
+ if (dimensionsChanged) {
dataArray.reserve(sampleSpace.height());
for (int i = 0; i < sampleSpace.height(); i++)
dataArray << new QSurfaceDataRow(sampleSpace.width());
@@ -219,13 +198,13 @@ void Surface3DRenderer::updateData()
}
}
- if (dataArray.size() > 0 && (cache->objectDirty() || dimensionChanged)) {
- checkFlatSupport(cache);
- updateObjects(cache, dimensionChanged);
- cache->setObjectDirty(false);
- cache->setFlatStatusDirty(false);
- }
+ checkFlatSupport(cache);
+ updateObjects(cache, dimensionsChanged);
+ cache->setFlatStatusDirty(false);
+ } else {
+ cache->surfaceObject()->clear();
}
+ cache->setDataDirty(false);
}
}
@@ -235,31 +214,22 @@ void Surface3DRenderer::updateData()
updateSelectedPoint(m_selectedPoint, m_selectedSeries);
}
-void Surface3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList,
- bool updateVisibility)
+void Surface3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList)
{
- Q_UNUSED(updateVisibility);
-
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList)
- cache->setValid(false);
+ Abstract3DRenderer::updateSeries(seriesList);
+ bool noSelection = true;
foreach (QAbstract3DSeries *series, seriesList) {
- // Item selection label may need update
- if (series->d_ptr->m_changeTracker.nameChanged
- || series->d_ptr->m_changeTracker.itemLabelFormatChanged) {
- m_selectionLabelDirty = true;
- }
-
QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(series);
- SurfaceSeriesRenderCache *cache = m_renderCacheList.value(surfaceSeries);
- if (!cache) {
- cache = new SurfaceSeriesRenderCache;
- m_renderCacheList[surfaceSeries] = cache;
-
- m_selectionTexturesDirty = true;
+ SurfaceSeriesRenderCache *cache =
+ static_cast<SurfaceSeriesRenderCache *>( m_renderCacheList.value(series));
+ if (noSelection
+ && surfaceSeries->selectedPoint() != QSurface3DSeries::invalidSelectionPosition()) {
+ if (selectionLabel() != cache->itemLabel())
+ m_selectionLabelDirty = true;
+ noSelection = false;
}
- cache->setValid(true);
- cache->populate(surfaceSeries, this);
+
if (cache->isFlatStatusDirty() && cache->sampleSpace().width()) {
checkFlatSupport(cache);
updateObjects(cache, true);
@@ -267,24 +237,16 @@ void Surface3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesLis
}
}
- // Remove non-valid objects from the cache list
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
- if (!cache->isValid()) {
- if (cache->series() == m_selectedSeries)
- updateSelectedPoint(Surface3DController::invalidSelectionPosition(), 0);
-
- m_renderCacheList.remove(cache->series());
- cache->cleanup(m_textureHelper);
- delete cache;
-
- m_selectionTexturesDirty = true;
- }
+ if (noSelection && !selectionLabel().isEmpty()) {
+ m_selectionLabelDirty = true;
+ updateSelectedPoint(Surface3DController::invalidSelectionPosition(), 0);
}
// Selection pointer issues
if (m_selectedSeries) {
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
- QVector3D highlightColor =
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
+ QVector4D highlightColor =
Utils::vectorFromColor(cache->series()->singleHighlightColor());
SelectionPointer *slicePointer = cache->sliceSelectionPointer();
if (slicePointer) {
@@ -302,19 +264,23 @@ void Surface3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesLis
}
}
-void Surface3DRenderer::modifiedSeriesList(const QVector<QSurface3DSeries *> &seriesList)
+SeriesRenderCache *Surface3DRenderer::createNewCache(QAbstract3DSeries *series)
{
- foreach (QSurface3DSeries *series, seriesList) {
- SurfaceSeriesRenderCache *cache = m_renderCacheList.value(series);
- if (cache)
- cache->setObjectDirty(true);
- }
+ m_selectionTexturesDirty = true;
+ return new SurfaceSeriesRenderCache(series, this);
+}
+
+void Surface3DRenderer::cleanCache(SeriesRenderCache *cache)
+{
+ Abstract3DRenderer::cleanCache(cache);
+ m_selectionTexturesDirty = true;
}
void Surface3DRenderer::updateRows(const QVector<Surface3DController::ChangeRow> &rows)
{
foreach (Surface3DController::ChangeRow item, rows) {
- SurfaceSeriesRenderCache *cache = m_renderCacheList.value(item.series);
+ SurfaceSeriesRenderCache *cache =
+ static_cast<SurfaceSeriesRenderCache *>(m_renderCacheList.value(item.series));
QSurfaceDataArray &dstArray = cache->dataArray();
const QRect &sampleSpace = cache->sampleSpace();
@@ -335,15 +301,10 @@ void Surface3DRenderer::updateRows(const QVector<Surface3DController::ChangeRow>
srcArray->at(row)->at(j + sampleSpace.x());
}
- if (cache->isFlatShadingEnabled()) {
- cache->surfaceObject()->updateCoarseRow(dstArray, row - sampleSpace.y(),
- m_heightNormalizer,
- m_axisCacheY.min());
- } else {
- cache->surfaceObject()->updateSmoothRow(dstArray, row - sampleSpace.y(),
- m_heightNormalizer,
- m_axisCacheY.min());
- }
+ if (cache->isFlatShadingEnabled())
+ cache->surfaceObject()->updateCoarseRow(dstArray, row - sampleSpace.y());
+ else
+ cache->surfaceObject()->updateSmoothRow(dstArray, row - sampleSpace.y());
}
if (updateBuffers)
cache->surfaceObject()->uploadBuffers();
@@ -353,10 +314,11 @@ void Surface3DRenderer::updateRows(const QVector<Surface3DController::ChangeRow>
updateSelectedPoint(m_selectedPoint, m_selectedSeries);
}
-void Surface3DRenderer::updateItem(const QVector<Surface3DController::ChangeItem> &points)
+void Surface3DRenderer::updateItems(const QVector<Surface3DController::ChangeItem> &points)
{
foreach (Surface3DController::ChangeItem item, points) {
- SurfaceSeriesRenderCache *cache = m_renderCacheList.value(item.series);
+ SurfaceSeriesRenderCache *cache =
+ static_cast<SurfaceSeriesRenderCache *>(m_renderCacheList.value(item.series));
QSurfaceDataArray &dstArray = cache->dataArray();
const QRect &sampleSpace = cache->sampleSpace();
@@ -370,22 +332,20 @@ void Surface3DRenderer::updateItem(const QVector<Surface3DController::ChangeItem
int sampleSpaceTop = sampleSpace.y() + sampleSpace.height();
int sampleSpaceRight = sampleSpace.x() + sampleSpace.width();
bool updateBuffers = false;
+ // Note: Point is (row, column), samplespace is (columns x rows)
QPoint point = item.point;
- if (point.y() <= sampleSpaceTop && point.y() >= sampleSpace.y() &&
- point.x() <= sampleSpaceRight && point.x() >= sampleSpace.x()) {
+ if (point.x() <= sampleSpaceTop && point.x() >= sampleSpace.y() &&
+ point.y() <= sampleSpaceRight && point.y() >= sampleSpace.x()) {
updateBuffers = true;
- int x = point.x() - sampleSpace.x();
- int y = point.y() - sampleSpace.y();
- (*(dstArray.at(y)))[x] = srcArray->at(point.y())->at(point.x());
-
- if (cache->isFlatShadingEnabled()) {
- cache->surfaceObject()->updateCoarseItem(dstArray, y, x, m_heightNormalizer,
- m_axisCacheY.min());
- } else {
- cache->surfaceObject()->updateSmoothItem(dstArray, y, x, m_heightNormalizer,
- m_axisCacheY.min());
- }
+ int x = point.y() - sampleSpace.x();
+ int y = point.x() - sampleSpace.y();
+ (*(dstArray.at(y)))[x] = srcArray->at(point.x())->at(point.y());
+
+ if (cache->isFlatShadingEnabled())
+ cache->surfaceObject()->updateCoarseItem(dstArray, y, x);
+ else
+ cache->surfaceObject()->updateSmoothItem(dstArray, y, x);
}
if (updateBuffers)
cache->surfaceObject()->uploadBuffers();
@@ -396,31 +356,22 @@ void Surface3DRenderer::updateItem(const QVector<Surface3DController::ChangeItem
updateSelectedPoint(m_selectedPoint, m_selectedSeries);
}
-void Surface3DRenderer::updateAxisRange(QAbstract3DAxis::AxisOrientation orientation, float min,
- float max)
-{
- Abstract3DRenderer::updateAxisRange(orientation, min, max);
-
- if (orientation == QAbstract3DAxis::AxisOrientationY) {
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList)
- cache->setObjectDirty(true);
- }
-}
-
void Surface3DRenderer::updateSliceDataModel(const QPoint &point)
{
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList)
- cache->sliceSurfaceObject()->clear();
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList)
+ static_cast<SurfaceSeriesRenderCache *>(baseCache)->sliceSurfaceObject()->clear();
if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionMultiSeries)) {
// Find axis coordinates for the selected point
- SurfaceSeriesRenderCache *selectedCache =
- m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries));
- QSurfaceDataArray &dataArray = selectedCache->dataArray();
+ SeriesRenderCache *selectedCache =
+ m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries));
+ QSurfaceDataArray &dataArray =
+ static_cast<SurfaceSeriesRenderCache *>(selectedCache)->dataArray();
QSurfaceDataItem item = dataArray.at(point.x())->at(point.y());
QPointF coords(item.x(), item.z());
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
if (cache->series() != m_selectedSeries) {
QPoint mappedPoint = mapCoordsToSampleSpace(cache, coords);
updateSliceObject(cache, mappedPoint);
@@ -431,9 +382,10 @@ void Surface3DRenderer::updateSliceDataModel(const QPoint &point)
} else {
if (m_selectedSeries) {
SurfaceSeriesRenderCache *cache =
- m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries));
+ static_cast<SurfaceSeriesRenderCache *>(
+ m_renderCacheList.value(m_selectedSeries));
if (cache)
- updateSliceObject(cache, point);
+ updateSliceObject(static_cast<SurfaceSeriesRenderCache *>(cache), point);
}
}
}
@@ -536,7 +488,7 @@ void Surface3DRenderer::updateSliceObject(SurfaceSeriesRenderCache *cache, const
int row = point.x();
if ((m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow) && row == -1) ||
- (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionColumn) && column == -1)) {
+ (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionColumn) && column == -1)) {
cache->sliceSurfaceObject()->clear();
return;
}
@@ -550,19 +502,27 @@ void Surface3DRenderer::updateSliceObject(SurfaceSeriesRenderCache *cache, const
QSurfaceDataRow *sliceRow;
QSurfaceDataArray &dataArray = cache->dataArray();
float adjust = (0.025f * m_heightNormalizer) / 2.0f;
- float stepDown = 2.0f * adjust;
+ float doubleAdjust = 2.0f * adjust;
+ bool flipZX = false;
+ float zBack;
+ float zFront;
if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow)) {
QSurfaceDataRow *src = dataArray.at(row);
sliceRow = new QSurfaceDataRow(src->size());
+ zBack = m_axisCacheZ.min();
+ zFront = m_axisCacheZ.max();
for (int i = 0; i < sliceRow->size(); i++)
- (*sliceRow)[i].setPosition(QVector3D(src->at(i).x(), src->at(i).y() + adjust, -1.0f));
+ (*sliceRow)[i].setPosition(QVector3D(src->at(i).x(), src->at(i).y() + adjust, zFront));
} else {
+ flipZX = true;
const QRect &sampleSpace = cache->sampleSpace();
sliceRow = new QSurfaceDataRow(sampleSpace.height());
+ zBack = m_axisCacheX.min();
+ zFront = m_axisCacheX.max();
for (int i = 0; i < sampleSpace.height(); i++) {
(*sliceRow)[i].setPosition(QVector3D(dataArray.at(i)->at(column).z(),
dataArray.at(i)->at(column).y() + adjust,
- -1.0f));
+ zFront));
}
}
sliceDataArray << sliceRow;
@@ -571,114 +531,134 @@ void Surface3DRenderer::updateSliceObject(SurfaceSeriesRenderCache *cache, const
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.0f));
+ sliceRow->at(i).y() - doubleAdjust,
+ zBack));
}
sliceDataArray << duplicateRow;
QRect sliceRect(0, 0, sliceRow->size(), 2);
if (sliceRow->size() > 0) {
- if (cache->isFlatShadingEnabled()) {
- cache->sliceSurfaceObject()->setUpData(sliceDataArray, sliceRect,
- m_heightNormalizer,
- m_axisCacheY.min(), true);
+ if (cache->isFlatShadingEnabled())
+ cache->sliceSurfaceObject()->setUpData(sliceDataArray, sliceRect, true, flipZX);
+ else
+ cache->sliceSurfaceObject()->setUpSmoothData(sliceDataArray, sliceRect, true, flipZX);
+ }
+}
+
+inline static float getDataValue(const QSurfaceDataArray &array, bool searchRow, int index)
+{
+ if (searchRow)
+ return array.at(0)->at(index).x();
+ else
+ return array.at(index)->at(0).z();
+}
+
+inline static int binarySearchArray(const QSurfaceDataArray &array, int maxIdx, float limitValue,
+ bool searchRow, bool lowBound, bool ascending)
+{
+ int min = 0;
+ int max = maxIdx;
+ int mid = 0;
+ int retVal;
+ while (max >= min) {
+ mid = (min + max) / 2;
+ float arrayValue = getDataValue(array, searchRow, mid);
+ if (arrayValue == limitValue)
+ return mid;
+ if (ascending) {
+ if (arrayValue < limitValue)
+ min = mid + 1;
+ else
+ max = mid - 1;
} else {
- cache->sliceSurfaceObject()->setUpSmoothData(sliceDataArray, sliceRect,
- m_heightNormalizer,
- m_axisCacheY.min(), true);
+ if (arrayValue > limitValue)
+ min = mid + 1;
+ else
+ max = mid - 1;
}
}
+
+ // Exact match not found, return closest depending on bound.
+ // The boundary is between last mid and min/max.
+ if (lowBound == ascending) {
+ if (mid > max)
+ retVal = mid;
+ else
+ retVal = min;
+ } else {
+ if (mid > max)
+ retVal = max;
+ else
+ retVal = mid;
+ }
+ if (retVal < 0 || retVal > maxIdx) {
+ retVal = -1;
+ } else if (lowBound) {
+ if (getDataValue(array, searchRow, retVal) < limitValue)
+ retVal = -1;
+ } else {
+ if (getDataValue(array, searchRow, retVal) > limitValue)
+ retVal = -1;
+ }
+ return retVal;
}
-QRect Surface3DRenderer::calculateSampleRect(SurfaceSeriesRenderCache *cache,
- const QSurfaceDataArray &array)
+QRect Surface3DRenderer::calculateSampleRect(const QSurfaceDataArray &array)
{
QRect sampleSpace;
- int rowCount = array.size();
- int columnCount = array.at(0)->size();
+ const int maxRow = array.size() - 1;
+ const int maxColumn = array.at(0)->size() - 1;
- int i;
- bool found;
- float axisMinX = m_axisCacheX.min();
- float axisMaxX = m_axisCacheX.max();
- float axisMinZ = m_axisCacheZ.min();
- float axisMaxZ = m_axisCacheZ.max();
+ // We assume data is ordered sequentially in rows for X-value and in columns for Z-value.
+ // Determine if data is ascending or descending in each case.
+ const bool ascendingX = array.at(0)->at(0).x() < array.at(0)->at(maxColumn).x();
+ const bool ascendingZ = array.at(0)->at(0).z() < array.at(maxRow)->at(0).z();
- // m_minVisibleColumnValue
- for (i = 0, found = false; i < columnCount; i++) {
- if (array.at(0)->at(i).x() >= axisMinX) {
- found = true;
- break;
- }
- }
- if (found) {
- m_minVisibleColumnValue = array.at(0)->at(i).x();
- sampleSpace.setLeft(i);
+ int idx = binarySearchArray(array, maxColumn, m_axisCacheX.min(), true, true, ascendingX);
+ if (idx != -1) {
+ if (ascendingX)
+ sampleSpace.setLeft(idx);
+ else
+ sampleSpace.setRight(idx);
} else {
sampleSpace.setWidth(-1); // to indicate nothing needs to be shown
return sampleSpace;
}
- // m_maxVisibleColumnValue
- for (i = columnCount - 1, found = false; i >= 0; i--) {
- if (array.at(0)->at(i).x() <= axisMaxX) {
- found = true;
- break;
- }
- }
- if (found) {
- m_maxVisibleColumnValue = array.at(0)->at(i).x();
- sampleSpace.setRight(i);
+ idx = binarySearchArray(array, maxColumn, m_axisCacheX.max(), true, false, ascendingX);
+ if (idx != -1) {
+ if (ascendingX)
+ sampleSpace.setRight(idx);
+ else
+ sampleSpace.setLeft(idx);
} else {
sampleSpace.setWidth(-1); // to indicate nothing needs to be shown
return sampleSpace;
}
- // m_minVisibleRowValue
- for (i = 0, found = false; i < rowCount; i++) {
- if (array.at(i)->at(0).z() >= axisMinZ) {
- found = true;
- break;
- }
- }
- if (found) {
- m_minVisibleRowValue = array.at(i)->at(0).z();
- sampleSpace.setTop(i);
+ idx = binarySearchArray(array, maxRow, m_axisCacheZ.min(), false, true, ascendingZ);
+ if (idx != -1) {
+ if (ascendingZ)
+ sampleSpace.setTop(idx);
+ else
+ sampleSpace.setBottom(idx);
} else {
sampleSpace.setWidth(-1); // to indicate nothing needs to be shown
return sampleSpace;
}
- // m_maxVisibleRowValue
- for (i = rowCount - 1, found = false; i >= 0; i--) {
- if (array.at(i)->at(0).z() <= axisMaxZ) {
- found = true;
- break;
- }
- }
- if (found) {
- m_maxVisibleRowValue = array.at(i)->at(0).z();
- sampleSpace.setBottom(i);
+ idx = binarySearchArray(array, maxRow, m_axisCacheZ.max(), false, false, ascendingZ);
+ if (idx != -1) {
+ if (ascendingZ)
+ sampleSpace.setBottom(idx);
+ else
+ sampleSpace.setTop(idx);
} else {
sampleSpace.setWidth(-1); // to indicate nothing needs to be shown
return sampleSpace;
}
- m_visibleColumnRange = m_maxVisibleColumnValue - m_minVisibleColumnValue;
- m_visibleRowRange = m_maxVisibleRowValue - m_minVisibleRowValue;
- GLfloat surfaceScaleX = m_scaleX * m_visibleColumnRange / m_areaSize.width();
- GLfloat surfaceScaleZ = m_scaleZ * m_visibleRowRange / m_areaSize.height();
- GLfloat axis2XCenterX = axisMinX + axisMaxX;
- GLfloat axis2XCenterZ = axisMinZ + axisMaxZ;
- GLfloat data2XCenterX = GLfloat(m_minVisibleColumnValue + m_maxVisibleColumnValue);
- GLfloat data2XCenterZ = GLfloat(m_minVisibleRowValue + m_maxVisibleRowValue);
- GLfloat surfaceOffsetX = m_scaleX * (data2XCenterX - axis2XCenterX) / m_areaSize.width();
- GLfloat surfaceOffsetZ = -m_scaleZ * (data2XCenterZ - axis2XCenterZ) / m_areaSize.height();
-
- cache->setScale(QVector3D(surfaceScaleX, 1.0f, surfaceScaleZ));
- cache->setOffset(QVector3D(surfaceOffsetX, 0.0f, surfaceOffsetZ));
-
return sampleSpace;
}
@@ -708,6 +688,13 @@ void Surface3DRenderer::render(GLuint defaultFboHandle)
// Handle GL state setup for FBO buffers and clearing of the render surface
Abstract3DRenderer::render(defaultFboHandle);
+ if (m_axisCacheX.positionsDirty())
+ m_axisCacheX.updateAllPositions();
+ if (m_axisCacheY.positionsDirty())
+ m_axisCacheY.updateAllPositions();
+ if (m_axisCacheZ.positionsDirty())
+ m_axisCacheZ.updateAllPositions();
+
drawScene(defaultFboHandle);
if (m_cachedIsSlicingActivated)
drawSlicedScene();
@@ -715,13 +702,14 @@ void Surface3DRenderer::render(GLuint defaultFboHandle)
// Render selection ball
if (m_selectionActive
&& m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionItem)) {
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
if (cache->slicePointerActive() && cache->renderable() &&
m_cachedIsSlicingActivated ) {
cache->sliceSelectionPointer()->render(defaultFboHandle);
}
if (cache->mainPointerActive() && cache->renderable())
- cache->mainSelectionPointer()->render(defaultFboHandle);
+ cache->mainSelectionPointer()->render(defaultFboHandle, m_useOrthoProjection);
}
}
}
@@ -730,7 +718,7 @@ void Surface3DRenderer::drawSlicedScene()
{
QVector3D lightPos;
- QVector3D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor());
+ QVector4D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor());
// Specify viewport
glViewport(m_secondarySubViewport.x(),
@@ -760,13 +748,18 @@ void Surface3DRenderer::drawSlicedScene()
const Q3DCamera *activeCamera = m_cachedScene->activeCamera();
bool rowMode = m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow);
+ AxisRenderCache &sliceCache = rowMode ? m_axisCacheX : m_axisCacheZ;
GLfloat scaleXBackground = 0.0f;
- if (m_renderCacheList.size()) {
+ // Disable culling to avoid ugly conditionals with reversed axes and data
+ glDisable(GL_CULL_FACE);
+
+ if (!m_renderCacheList.isEmpty()) {
bool drawGrid = false;
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
if (cache->sliceSurfaceObject()->indexCount() && cache->renderable()) {
if (!drawGrid && cache->surfaceGridVisible()) {
glEnable(GL_POLYGON_OFFSET_FILL);
@@ -774,24 +767,16 @@ void Surface3DRenderer::drawSlicedScene()
drawGrid = true;
}
- GLfloat scaleX = 0.0f;
- GLfloat offset = 0.0f;
- if (rowMode) {
- scaleX = cache->scale().x();
+ if (rowMode)
scaleXBackground = m_scaleXWithBackground;
- offset = cache->offset().x();
- } else {
- scaleX = cache->scale().z();
+ else
scaleXBackground = m_scaleZWithBackground;
- offset = -cache->offset().z();
- }
QMatrix4x4 MVPMatrix;
QMatrix4x4 modelMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(offset, 0.0f, 0.0f);
- QVector3D scaling(scaleX, 1.0f, sliceZScale);
+ QVector3D scaling(1.0f, 1.0f, sliceZScale);
modelMatrix.scale(scaling);
itModelMatrix.scale(scaling);
@@ -832,10 +817,13 @@ void Surface3DRenderer::drawSlicedScene()
m_surfaceGridShader->bind();
m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(),
Utils::vectorFromColor(m_cachedTheme->gridLineColor()));
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
- if (cache->sliceSurfaceObject()->indexCount() && cache->isSeriesVisible() &&
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache =
+ static_cast<SurfaceSeriesRenderCache *>(baseCache);
+ if (cache->sliceSurfaceObject()->indexCount() && cache->isVisible() &&
cache->surfaceGridVisible()) {
- m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), cache->MVPMatrix());
+ m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(),
+ cache->MVPMatrix());
m_drawer->drawSurfaceGrid(m_surfaceGridShader, cache->sliceSurfaceObject());
}
}
@@ -845,14 +833,22 @@ void Surface3DRenderer::drawSlicedScene()
// Disable textures
glDisable(GL_TEXTURE_2D);
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+
// Grid lines
if (m_cachedTheme->isGridEnabled() && m_heightNormalizer) {
+#if !(defined QT_OPENGL_ES_2)
ShaderHelper *lineShader = m_backgroundShader;
+#else
+ ShaderHelper *lineShader = m_selectionShader; // Plain color shader for GL_LINES
+#endif
+
// Bind line shader
lineShader->bind();
// Set unchanging shader bindings
- QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
+ QVector4D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
lineShader->setUniformValue(lineShader->lightP(), lightPos);
lineShader->setUniformValue(lineShader->view(), viewMatrix);
lineShader->setUniformValue(lineShader->color(), lineColor);
@@ -862,19 +858,16 @@ void Surface3DRenderer::drawSlicedScene()
lineShader->setUniformValue(lineShader->lightColor(), lightColor);
// Horizontal lines
+ int gridLineCount = m_axisCacheY.gridLineCount();
if (m_axisCacheY.segmentCount() > 0) {
QVector3D gridLineScaleX(scaleXBackground, gridLineWidth, gridLineWidth);
- GLfloat lineStep = 2.0f * m_axisCacheY.subSegmentStep() / m_heightNormalizer;
- GLfloat linePos = -1.0f;
- int lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount();
-
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(0.0f, linePos, -sliceZScale);
+ modelMatrix.translate(0.0f, m_axisCacheY.gridLinePosition(line), -1.0f);
modelMatrix.scale(gridLineScaleX);
itModelMatrix.scale(gridLineScaleX);
@@ -888,36 +881,30 @@ void Surface3DRenderer::drawSlicedScene()
lineShader->setUniformValue(lineShader->MVP(), MVPMatrix);
// Draw the object
+#if !(defined QT_OPENGL_ES_2)
m_drawer->drawObject(lineShader, m_gridLineObj);
-
- linePos += lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
}
// Vertical lines
QVector3D gridLineScaleY(gridLineWidth, backgroundMargin, gridLineWidth);
- int lastSegment;
- GLfloat lineStep;
- GLfloat linePos;
- if (rowMode) {
- lineStep = -2.0f * aspectRatio * m_axisCacheX.subSegmentStep() / m_scaleFactor;
- lastSegment = m_axisCacheX.subSegmentCount() * m_axisCacheX.segmentCount();
- linePos = m_scaleX;
- } else {
- lineStep = -2.0f * aspectRatio * m_axisCacheZ.subSegmentStep() / m_scaleFactor;
- lastSegment = m_axisCacheZ.subSegmentCount() * m_axisCacheZ.segmentCount();
- linePos = m_scaleZ;
- }
-
- for (int segment = 0; segment <= lastSegment; segment++) {
+ gridLineCount = sliceCache.gridLineCount();
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(linePos, 0.0f, -sliceZScale);
+ modelMatrix.translate(sliceCache.gridLinePosition(line), 0.0f, -1.0f);
modelMatrix.scale(gridLineScaleY);
itModelMatrix.scale(gridLineScaleY);
+#if (defined QT_OPENGL_ES_2)
+ modelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f);
+ itModelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f);
+#endif
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -928,9 +915,11 @@ void Surface3DRenderer::drawSlicedScene()
lineShader->setUniformValue(lineShader->MVP(), MVPMatrix);
// Draw the object
+#if !(defined QT_OPENGL_ES_2)
m_drawer->drawObject(lineShader, m_gridLineObj);
-
- linePos += lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
}
@@ -938,96 +927,76 @@ void Surface3DRenderer::drawSlicedScene()
m_labelShader->bind();
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
- glCullFace(GL_BACK);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Y Labels to back wall
- GLfloat posStep = 2.0f * m_axisCacheY.segmentStep() / m_heightNormalizer;
- GLfloat labelPos = -1.0f;
int labelNbr = 0;
QVector3D positionComp(0.0f, 0.0f, 0.0f);
- QVector3D rotation(0.0f, 0.0f, 0.0f);
- QVector3D labelTrans = QVector3D(scaleXBackground + labelMargin, labelPos, 0.0f);
- for (int segment = 0; segment <= m_axisCacheY.segmentCount(); segment++) {
+ QVector3D labelTrans = QVector3D(scaleXBackground + labelMargin, 0.0f, 0.0f);
+ int labelCount = m_axisCacheY.labelCount();
+ for (int label = 0; label < labelCount; label++) {
if (m_axisCacheY.labelItems().size() > labelNbr) {
- labelTrans.setY(labelPos);
+ labelTrans.setY(m_axisCacheY.labelPosition(label));
const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr);
// Draw the label here
m_dummyRenderItem.setTranslation(labelTrans);
m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- positionComp, rotation, 0, m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera,
- true, true, Drawer::LabelMid, Qt::AlignRight, true);
+ positionComp, identityQuaternion, 0, m_cachedSelectionMode,
+ m_labelShader, m_labelObj, activeCamera, true, true,
+ Drawer::LabelMid, Qt::AlignLeft, true);
}
labelNbr++;
- labelPos += posStep;
}
// X Labels to ground
- int countLabelItems;
- int lastSegment;
- if (rowMode) {
- posStep = 2.0f * aspectRatio * m_axisCacheX.segmentStep() / m_scaleFactor;
- labelPos = -m_scaleX;
- lastSegment = m_axisCacheX.segmentCount();
- countLabelItems = m_axisCacheX.labelItems().size();
- } else {
- posStep = 2.0f * aspectRatio * m_axisCacheZ.segmentStep() / m_scaleFactor;
- labelPos = -m_scaleZ;
- lastSegment = m_axisCacheZ.segmentCount();
- countLabelItems = m_axisCacheZ.labelItems().size();
- }
+ int countLabelItems = sliceCache.labelItems().size();
+
+ QVector3D rotation(0.0f, 0.0f, -45.0f);
+ QQuaternion totalRotation = Utils::calculateRotation(rotation);
labelNbr = 0;
positionComp.setY(-0.1f);
- rotation.setZ(-45.0f);
labelTrans.setY(-backgroundMargin);
- for (int segment = 0; segment <= lastSegment; segment++) {
+ labelCount = sliceCache.labelCount();
+ for (int label = 0; label < labelCount; label++) {
if (countLabelItems > labelNbr) {
// Draw the label here
- labelTrans.setX(labelPos);
+ labelTrans.setX(sliceCache.labelPosition(label));
m_dummyRenderItem.setTranslation(labelTrans);
LabelItem *axisLabelItem;
- if (rowMode)
- axisLabelItem = m_axisCacheX.labelItems().at(labelNbr);
- else
- axisLabelItem = m_axisCacheZ.labelItems().at(labelNbr);
+ axisLabelItem = sliceCache.labelItems().at(labelNbr);
m_drawer->drawLabel(m_dummyRenderItem, *axisLabelItem, viewMatrix, projectionMatrix,
- positionComp, rotation, 0, QAbstract3DGraph::SelectionRow,
+ positionComp, totalRotation, 0, QAbstract3DGraph::SelectionRow,
m_labelShader, m_labelObj, activeCamera,
- false, false, Drawer::LabelBelow, Qt::AlignBottom, true);
+ false, false, Drawer::LabelBelow,
+ Qt::AlignmentFlag(Qt::AlignLeft | Qt::AlignTop), true);
}
labelNbr++;
- labelPos += posStep;
}
// Draw labels for axes
AbstractRenderItem *dummyItem(0);
positionComp.setY(m_autoScaleAdjustment);
- if (rowMode) {
- m_drawer->drawLabel(*dummyItem, m_axisCacheX.titleItem(), viewMatrix, projectionMatrix,
- positionComp, zeroVector, 0, m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera, false, false, Drawer::LabelBottom,
- Qt::AlignCenter, true);
- } else {
- m_drawer->drawLabel(*dummyItem, m_axisCacheZ.titleItem(), viewMatrix, projectionMatrix,
- positionComp, zeroVector, 0, m_cachedSelectionMode, m_labelShader,
- m_labelObj, activeCamera, false, false, Drawer::LabelBottom,
- Qt::AlignCenter, true);
- }
+ m_drawer->drawLabel(*dummyItem, sliceCache.titleItem(), viewMatrix, projectionMatrix,
+ positionComp, identityQuaternion, 0, m_cachedSelectionMode, m_labelShader,
+ m_labelObj, activeCamera, false, false, Drawer::LabelBottom,
+ Qt::AlignCenter, true);
+
// Y-axis label
+ rotation = QVector3D(0.0f, 0.0f, 90.0f);
+ totalRotation = Utils::calculateRotation(rotation);
labelTrans = QVector3D(-scaleXBackground - labelMargin, 0.0f, 0.0f);
m_dummyRenderItem.setTranslation(labelTrans);
m_drawer->drawLabel(m_dummyRenderItem, m_axisCacheY.titleItem(), viewMatrix,
- projectionMatrix, zeroVector, QVector3D(0.0f, 0.0f, 90.0f), 0,
+ projectionMatrix, zeroVector, totalRotation, 0,
m_cachedSelectionMode, m_labelShader, m_labelObj, activeCamera,
- false, false, Drawer::LabelMid, Qt::AlignHCenter);
+ false, false, Drawer::LabelMid, Qt::AlignBottom);
glDisable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
@@ -1042,7 +1011,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
bool noShadows = true;
GLfloat backgroundRotation = 0;
- QVector3D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor());
+ QVector4D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor());
glViewport(m_primarySubViewport.x(),
m_primarySubViewport.y(),
@@ -1051,8 +1020,16 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Set up projection matrix
QMatrix4x4 projectionMatrix;
- projectionMatrix.perspective(45.0f, (GLfloat)m_primarySubViewport.width()
- / (GLfloat)m_primarySubViewport.height(), 0.1f, 100.0f);
+ GLfloat viewPortRatio = (GLfloat)m_primarySubViewport.width()
+ / (GLfloat)m_primarySubViewport.height();
+ if (m_useOrthoProjection) {
+ GLfloat orthoRatio = 2.0f;
+ projectionMatrix.ortho(-viewPortRatio * orthoRatio, viewPortRatio * orthoRatio,
+ -orthoRatio, orthoRatio,
+ 0.0f, 100.0f);
+ } else {
+ projectionMatrix.perspective(45.0f, viewPortRatio, 0.1f, 100.0f);
+ }
const Q3DCamera *activeCamera = m_cachedScene->activeCamera();
@@ -1089,8 +1066,9 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Draw depth buffer
#if !defined(QT_OPENGL_ES_2)
- GLfloat adjustedLightStrength = m_cachedTheme->lightStrength() / 10.0f;
- if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone && m_renderCacheList.size()) {
+ GLfloat adjustedLightStrength = m_cachedTheme->lightStrength() / 10.0f;
+ if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone &&
+ (!m_renderCacheList.isEmpty() || !m_customRenderCache.isEmpty())) {
// Render scene into a depth texture for using with shadow mapping
// Enable drawing to depth framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer);
@@ -1121,15 +1099,14 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glDisable(GL_CULL_FACE);
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
SurfaceObject *object = cache->surfaceObject();
- if (object->indexCount() && cache->surfaceVisible() && cache->isSeriesVisible()
+ if (object->indexCount() && cache->surfaceVisible() && cache->isVisible()
&& cache->sampleSpace().width() >= 2 && cache->sampleSpace().height() >= 2) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
- modelMatrix.translate(cache->offset());
- modelMatrix.scale(cache->scale());
MVPMatrix = depthProjectionViewMatrix * modelMatrix;
cache->setMVPMatrix(MVPMatrix);
m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix);
@@ -1149,16 +1126,18 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
}
}
- glEnable(GL_CULL_FACE);
- glCullFace(GL_FRONT);
+ Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, viewMatrix,
+ projectionViewMatrix, depthProjectionViewMatrix,
+ m_depthTexture, m_shadowQualityToShader);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
m_depthModelTexture, 0);
glClear(GL_DEPTH_BUFFER_BIT);
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
SurfaceObject *object = cache->surfaceObject();
- if (object->indexCount() && cache->surfaceVisible() && cache->isSeriesVisible()
+ if (object->indexCount() && cache->surfaceVisible() && cache->isVisible()
&& cache->sampleSpace().width() >= 2 && cache->sampleSpace().height() >= 2) {
m_depthShader->setUniformValue(m_depthShader->MVP(), cache->MVPMatrix());
@@ -1183,6 +1162,10 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glDisableVertexAttribArray(m_depthShader->posAtt());
+ Abstract3DRenderer::drawCustomItems(RenderingDepth, m_depthShader, viewMatrix,
+ projectionViewMatrix, depthProjectionViewMatrix,
+ m_depthTexture, m_shadowQualityToShader);
+
// Disable drawing to depth framebuffer (= enable drawing to screen)
glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle);
@@ -1201,7 +1184,9 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glEnable(GL_TEXTURE_2D);
// Draw selection buffer
- if (!m_cachedIsSlicingActivated && m_renderCacheList.size() && m_selectionState == SelectOnScene
+ if (!m_cachedIsSlicingActivated && (!m_renderCacheList.isEmpty()
+ || !m_customRenderCache.isEmpty())
+ && m_selectionState == SelectOnScene
&& m_cachedSelectionMode > QAbstract3DGraph::SelectionNone) {
m_selectionShader->bind();
glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer);
@@ -1217,14 +1202,12 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glDisable(GL_CULL_FACE);
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
if (cache->surfaceObject()->indexCount() && cache->renderable()) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
- modelMatrix.translate(cache->offset());
- modelMatrix.scale(cache->scale());
-
MVPMatrix = projectionViewMatrix * modelMatrix;
m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix);
@@ -1232,21 +1215,23 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
cache->selectionTexture());
}
}
+ m_surfaceGridShader->bind();
+ Abstract3DRenderer::drawCustomItems(RenderingSelection, m_surfaceGridShader, viewMatrix,
+ projectionViewMatrix, depthProjectionViewMatrix,
+ m_depthTexture, m_shadowQualityToShader);
+ drawLabels(true, activeCamera, viewMatrix, projectionMatrix);
glEnable(GL_DITHER);
- 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);
+ QVector4D clickedColor = Utils::getSelection(m_inputPosition, m_viewport.height());
glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle);
// Put the RGBA value back to uint
-#if !defined(QT_OPENGL_ES_2)
- uint selectionId = pixel[0] + pixel[1] * 256 + pixel[2] * 65536 + pixel[3] * 16777216;
-#else
- uint selectionId = pixel[0] + pixel[1] * 256 + pixel[2] * 65536;
-#endif
+ uint selectionId = uint(clickedColor.x())
+ + uint(clickedColor.y()) * greenMultiplier
+ + uint(clickedColor.z()) * blueMultiplier
+ + uint(clickedColor.w()) * alphaMultiplier;
m_clickedPosition = selectionIdToSurfacePoint(selectionId);
@@ -1260,21 +1245,18 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
}
// Draw the surface
- if (m_renderCacheList.size()) {
+ if (!m_renderCacheList.isEmpty()) {
// For surface we can see climpses from underneath
glDisable(GL_CULL_FACE);
bool drawGrid = false;
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(cache->offset());
- modelMatrix.scale(cache->scale());
- itModelMatrix.scale(cache->scale());
-
#ifdef SHOW_DEPTH_TEXTURE_SCENE
MVPMatrix = depthProjectionViewMatrix * modelMatrix;
#else
@@ -1283,7 +1265,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
cache->setMVPMatrix(MVPMatrix);
const QRect &sampleSpace = cache->sampleSpace();
- if (cache->surfaceObject()->indexCount() && cache->isSeriesVisible() &&
+ if (cache->surfaceObject()->indexCount() && cache->isVisible() &&
sampleSpace.width() >= 2 && sampleSpace.height() >= 2) {
noShadows = false;
if (!drawGrid && cache->surfaceGridVisible()) {
@@ -1346,13 +1328,18 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glDisable(GL_POLYGON_OFFSET_FILL);
m_surfaceGridShader->bind();
m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(),
- Utils::vectorFromColor(m_cachedTheme->gridLineColor()));
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
- m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), cache->MVPMatrix());
+ Utils::vectorFromColor(
+ m_cachedTheme->gridLineColor()));
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache =
+ static_cast<SurfaceSeriesRenderCache *>(baseCache);
+ m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(),
+ cache->MVPMatrix());
const QRect &sampleSpace = cache->sampleSpace();
- if (cache->surfaceObject()->indexCount() && cache->surfaceGridVisible() &&
- cache->isSeriesVisible() && sampleSpace.width() >= 2 && sampleSpace.height() >= 2) {
+ if (cache->surfaceObject()->indexCount() && cache->surfaceGridVisible()
+ && cache->isVisible() && sampleSpace.width() >= 2
+ && sampleSpace.height() >= 2) {
m_drawer->drawSurfaceGrid(m_surfaceGridShader, cache->surfaceObject());
}
}
@@ -1388,7 +1375,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
- QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme->backgroundColor());
+ QVector4D backgroundColor = Utils::vectorFromColor(m_cachedTheme->backgroundColor());
// Set shader bindings
m_backgroundShader->setUniformValue(m_backgroundShader->lightP(), lightPos);
@@ -1412,7 +1399,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_backgroundShader->setUniformValue(m_backgroundShader->lightS(),
adjustedLightStrength);
// Draw the object
- if (noShadows)
+ if (noShadows && m_customRenderCache.isEmpty())
m_drawer->drawObject(m_backgroundShader, m_backgroundObj, 0, m_noShadowTexture);
else
m_drawer->drawObject(m_backgroundShader, m_backgroundObj, 0, m_depthTexture);
@@ -1436,13 +1423,17 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
QVector3D gridLineScaleY(gridLineWidth, backgroundMargin, gridLineWidth);
if (m_cachedTheme->isGridEnabled() && m_heightNormalizer) {
+#if !(defined QT_OPENGL_ES_2)
ShaderHelper *lineShader = m_backgroundShader;
+#else
+ ShaderHelper *lineShader = m_selectionShader; // Plain color shader for GL_LINES
+#endif
// Bind line shader
lineShader->bind();
// Set unchanging shader bindings
- QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
+ QVector4D lineColor = Utils::vectorFromColor(m_cachedTheme->gridLineColor());
lineShader->setUniformValue(lineShader->lightP(), lightPos);
lineShader->setUniformValue(lineShader->view(), viewMatrix);
lineShader->setUniformValue(lineShader->color(), lineColor);
@@ -1482,16 +1473,15 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Rows (= Z)
if (m_axisCacheZ.segmentCount() > 0) {
// Floor lines
- GLfloat lineStep = 2.0f * aspectRatio * m_axisCacheZ.subSegmentStep() / m_scaleFactor;
- GLfloat linePos = m_scaleZ; // Start line
- int lastSegment = m_axisCacheZ.subSegmentCount() * m_axisCacheZ.segmentCount();
+ int gridLineCount = m_axisCacheZ.gridLineCount();
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(0.0f, yFloorLinePosition, linePos);
+ modelMatrix.translate(0.0f, yFloorLinePosition,
+ m_axisCacheZ.gridLinePosition(line));
modelMatrix.scale(gridLineScaleX);
itModelMatrix.scale(gridLineScaleX);
@@ -1514,34 +1504,38 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- linePos -= lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
// Side wall lines
GLfloat lineXTrans = m_scaleXWithBackground - gridLineOffset;
- linePos = m_scaleZ; // Start line
if (!m_xFlipped)
lineXTrans = -lineXTrans;
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(lineXTrans, 0.0f, linePos);
+ modelMatrix.translate(lineXTrans, 0.0f, m_axisCacheZ.gridLinePosition(line));
modelMatrix.scale(gridLineScaleY);
itModelMatrix.scale(gridLineScaleY);
+#if !defined(QT_OPENGL_ES_2)
modelMatrix.rotate(lineYRotation);
itModelMatrix.rotate(lineYRotation);
+#else
+ modelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f);
+ itModelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f);
+#endif
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -1558,29 +1552,31 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- linePos -= lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
}
// Columns (= X)
if (m_axisCacheX.segmentCount() > 0) {
+#if defined(QT_OPENGL_ES_2)
+ lineXRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, 90.0f);
+#endif
// Floor lines
- GLfloat lineStep = -2.0f * aspectRatio * m_axisCacheX.subSegmentStep() / m_scaleFactor;
- GLfloat linePos = m_scaleX;
- int lastSegment = m_axisCacheX.subSegmentCount() * m_axisCacheX.segmentCount();
+ int gridLineCount = m_axisCacheX.gridLineCount();
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(linePos, yFloorLinePosition, 0.0f);
+ modelMatrix.translate(m_axisCacheX.gridLinePosition(line), yFloorLinePosition,
+ 0.0f);
modelMatrix.scale(gridLineScaleZ);
itModelMatrix.scale(gridLineScaleZ);
@@ -1603,36 +1599,40 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- linePos += lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
// Back wall lines
GLfloat lineZTrans = m_scaleZWithBackground - gridLineOffset;
- linePos = m_scaleX;
if (!m_zFlipped)
lineZTrans = -lineZTrans;
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(linePos, 0.0f, lineZTrans);
+ modelMatrix.translate(m_axisCacheX.gridLinePosition(line), 0.0f, lineZTrans);
modelMatrix.scale(gridLineScaleY);
itModelMatrix.scale(gridLineScaleY);
+#if !defined(QT_OPENGL_ES_2)
if (m_zFlipped) {
modelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
itModelMatrix.rotate(180.0f, 1.0f, 0.0f, 0.0f);
}
+#else
+ modelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f);
+ itModelMatrix.rotate(90.0f, 0.0f, 0.0f, 1.0f);
+#endif
MVPMatrix = projectionViewMatrix * modelMatrix;
@@ -1649,34 +1649,32 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- linePos += lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
}
// Horizontal wall lines
if (m_axisCacheY.segmentCount() > 0) {
// Back wall
- GLfloat lineStep = 2.0f * m_axisCacheY.subSegmentStep() / m_heightNormalizer;
- GLfloat linePos = -1.0f;
- int lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount();
+ int gridLineCount = m_axisCacheY.gridLineCount();
GLfloat lineZTrans = m_scaleZWithBackground - gridLineOffset;
if (!m_zFlipped)
lineZTrans = -lineZTrans;
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(0.0f, linePos, lineZTrans);
+ modelMatrix.translate(0.0f, m_axisCacheY.gridLinePosition(line), lineZTrans);
modelMatrix.scale(gridLineScaleX);
itModelMatrix.scale(gridLineScaleX);
@@ -1701,29 +1699,27 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- linePos += lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
// Side wall
- linePos = -1.0f;
- lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount();
GLfloat lineXTrans = m_scaleXWithBackground - gridLineOffset;
if (!m_xFlipped)
lineXTrans = -lineXTrans;
- for (int segment = 0; segment <= lastSegment; segment++) {
+ for (int line = 0; line < gridLineCount; line++) {
QMatrix4x4 modelMatrix;
QMatrix4x4 MVPMatrix;
QMatrix4x4 itModelMatrix;
- modelMatrix.translate(lineXTrans, linePos, 0.0f);
+ modelMatrix.translate(lineXTrans, m_axisCacheY.gridLinePosition(line), 0.0f);
modelMatrix.scale(gridLineScaleZ);
itModelMatrix.scale(gridLineScaleZ);
@@ -1746,221 +1742,434 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix);
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture);
- } else
-#endif
- {
+ } else {
// Draw the object
m_drawer->drawObject(lineShader, m_gridLineObj);
}
- linePos += lineStep;
+#else
+ m_drawer->drawLine(lineShader);
+#endif
}
}
}
- // Draw axis labels
- m_labelShader->bind();
+ Abstract3DRenderer::drawCustomItems(RenderingNormal, m_customItemShader, viewMatrix,
+ projectionViewMatrix, depthProjectionViewMatrix,
+ m_depthTexture, m_shadowQualityToShader);
+
+ drawLabels(false, activeCamera, viewMatrix, projectionMatrix);
+
+ // Release shader
+ glUseProgram(0);
+
+ // Selection handling
+ if (m_selectionDirty || m_selectionLabelDirty) {
+ QPoint visiblePoint = Surface3DController::invalidSelectionPosition();
+ if (m_selectedSeries) {
+ SurfaceSeriesRenderCache *cache =
+ static_cast<SurfaceSeriesRenderCache *>(
+ m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries)));
+ if (cache && m_selectedPoint != Surface3DController::invalidSelectionPosition()) {
+ const QRect &sampleSpace = cache->sampleSpace();
+ int x = m_selectedPoint.x() - sampleSpace.y();
+ int y = m_selectedPoint.y() - sampleSpace.x();
+ if (x >= 0 && y >= 0 && x < sampleSpace.height() && y < sampleSpace.width()
+ && cache->dataArray().size()) {
+ visiblePoint = QPoint(x, y);
+ }
+ }
+ }
+
+ if (m_cachedSelectionMode == QAbstract3DGraph::SelectionNone
+ || visiblePoint == Surface3DController::invalidSelectionPosition()) {
+ m_selectionActive = false;
+ } else {
+ if (m_cachedIsSlicingActivated)
+ updateSliceDataModel(visiblePoint);
+ if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionItem))
+ surfacePointSelected(visiblePoint);
+ m_selectionActive = true;
+ }
+
+ m_selectionDirty = false;
+ }
+}
+
+void Surface3DRenderer::drawLabels(bool drawSelection, const Q3DCamera *activeCamera,
+ const QMatrix4x4 &viewMatrix,
+ const QMatrix4x4 &projectionMatrix)
+{
+ ShaderHelper *shader = 0;
+ GLfloat alphaForValueSelection = labelValueAlpha / 255.0f;
+ GLfloat alphaForRowSelection = labelRowAlpha / 255.0f;
+ GLfloat alphaForColumnSelection = labelColumnAlpha / 255.0f;
+ if (drawSelection) {
+ shader = m_surfaceGridShader;
+ } else {
+ shader = m_labelShader;
+ shader->bind();
+ glEnable(GL_TEXTURE_2D);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_POLYGON_OFFSET_FILL);
+ float labelAutoAngle = m_axisCacheZ.labelAutoRotation();
+ float labelAngleFraction = labelAutoAngle / 90.0f;
+ float fractionCamY = activeCamera->yRotation() * labelAngleFraction;
+ float fractionCamX = activeCamera->xRotation() * labelAngleFraction;
+ float labelsMaxWidth = 0.0f;
+
+ int startIndex;
+ int endIndex;
+ int indexStep;
+
// Z Labels
QVector3D positionZComp(0.0f, 0.0f, 0.0f);
if (m_axisCacheZ.segmentCount() > 0) {
- GLfloat posStep = 2.0f * aspectRatio * m_axisCacheZ.segmentStep() / m_scaleFactor;
- GLfloat labelPos = m_scaleZ;
- int lastSegment = m_axisCacheZ.segmentCount();
- int labelNbr = 0;
+ int labelCount = m_axisCacheZ.labelCount();
GLfloat labelXTrans = m_scaleXWithBackground + labelMargin;
GLfloat labelYTrans = -backgroundMargin;
- GLfloat rotLabelX = -90.0f;
- GLfloat rotLabelY = 0.0f;
- GLfloat rotLabelZ = 0.0f;
- Qt::AlignmentFlag alignment = Qt::AlignRight;
- if (m_zFlipped)
- rotLabelY = 180.0f;
- if (m_xFlipped) {
+ Qt::AlignmentFlag alignment = (m_xFlipped == m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight;
+ QVector3D labelRotation;
+ if (m_xFlipped)
labelXTrans = -labelXTrans;
- alignment = Qt::AlignLeft;
- }
- if (m_yFlipped) {
- rotLabelZ += 180.0f;
- rotLabelY += 180.0f;
+ if (m_yFlipped)
labelYTrans = -labelYTrans;
+ if (labelAutoAngle == 0.0f) {
+ labelRotation.setX(-90.0f);
+ if (m_zFlipped)
+ labelRotation.setY(180.0f);
+ if (m_yFlipped) {
+ if (m_zFlipped)
+ labelRotation.setY(0.0f);
+ else
+ labelRotation.setY(180.0f);
+ labelRotation.setZ(180.0f);
+ }
+ } else {
+ if (m_zFlipped)
+ labelRotation.setY(180.0f);
+ if (m_yFlipped) {
+ if (m_zFlipped) {
+ if (m_xFlipped) {
+ labelRotation.setX(90.0f - (labelAutoAngle - fractionCamX)
+ * (-labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle + fractionCamY);
+ } else {
+ labelRotation.setX(90.0f + (labelAutoAngle + fractionCamX)
+ * (labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle - fractionCamY);
+ }
+ } else {
+ if (m_xFlipped) {
+ labelRotation.setX(90.0f + (labelAutoAngle - fractionCamX)
+ * -(labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle - fractionCamY);
+ } else {
+ labelRotation.setX(90.0f - (labelAutoAngle + fractionCamX)
+ * (labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle + fractionCamY);
+ }
+ }
+ } else {
+ if (m_zFlipped) {
+ if (m_xFlipped) {
+ labelRotation.setX(-90.0f + (labelAutoAngle - fractionCamX)
+ * (-labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle + fractionCamY);
+ } else {
+ labelRotation.setX(-90.0f - (labelAutoAngle + fractionCamX)
+ * (labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle - fractionCamY);
+ }
+ } else {
+ if (m_xFlipped) {
+ labelRotation.setX(-90.0f - (labelAutoAngle - fractionCamX)
+ * (-labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle - fractionCamY);
+ } else {
+ labelRotation.setX(-90.0f + (labelAutoAngle + fractionCamX)
+ * (labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle + fractionCamY);
+ }
+ }
+ }
}
+
+ QQuaternion totalRotation = Utils::calculateRotation(labelRotation);
+
QVector3D labelTrans = QVector3D(labelXTrans,
labelYTrans,
- labelPos);
- QVector3D rotation(rotLabelX, rotLabelY, rotLabelZ);
-
- for (int segment = 0; segment <= lastSegment; segment++) {
- if (m_axisCacheZ.labelItems().size() > labelNbr) {
- 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);
-
- m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- positionZComp, rotation, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, activeCamera,
- true, true, Drawer::LabelMid, alignment);
+ 0.0f);
+
+ if (m_zFlipped) {
+ startIndex = 0;
+ endIndex = labelCount;
+ indexStep = 1;
+ } else {
+ startIndex = labelCount - 1;
+ endIndex = -1;
+ indexStep = -1;
+ }
+ for (int label = startIndex; label != endIndex; label = label + indexStep) {
+ glPolygonOffset(GLfloat(label) / -10.0f, 1.0f);
+ // Draw the label here
+ labelTrans.setZ(m_axisCacheZ.labelPosition(label));
+ m_dummyRenderItem.setTranslation(labelTrans);
+ const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(label);
+
+ if (drawSelection) {
+ QVector4D labelColor = QVector4D(label / 255.0f, 0.0f, 0.0f,
+ alphaForRowSelection);
+ shader->setUniformValue(shader->color(), labelColor);
}
- labelNbr++;
- labelPos -= posStep;
+
+ m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
+ positionZComp, totalRotation, 0, m_cachedSelectionMode,
+ shader, m_labelObj, activeCamera,
+ true, true, Drawer::LabelMid, alignment, false, drawSelection);
+ labelsMaxWidth = qMax(labelsMaxWidth, float(axisLabelItem.size().width()));
+ }
+ if (!drawSelection && m_axisCacheZ.isTitleVisible()) {
+ labelTrans.setZ(0.0f);
+ drawAxisTitleZ(labelRotation, labelTrans, totalRotation, m_dummyRenderItem,
+ activeCamera, labelsMaxWidth, viewMatrix, projectionMatrix, shader);
}
}
// X Labels
if (m_axisCacheX.segmentCount() > 0) {
- GLfloat posStep = 2.0f * aspectRatio * m_axisCacheX.segmentStep() / m_scaleFactor;
- GLfloat labelPos = -m_scaleX;
- int lastSegment = m_axisCacheX.segmentCount();
+ labelsMaxWidth = 0.0f;
+ labelAutoAngle = m_axisCacheX.labelAutoRotation();
+ labelAngleFraction = labelAutoAngle / 90.0f;
+ fractionCamY = activeCamera->yRotation() * labelAngleFraction;
+ fractionCamX = activeCamera->xRotation() * labelAngleFraction;
+ int labelCount = m_axisCacheX.labelCount();
- int labelNbr = 0;
GLfloat labelZTrans = m_scaleZWithBackground + labelMargin;
GLfloat labelYTrans = -backgroundMargin;
- GLfloat rotLabelX = -90.0f;
- GLfloat rotLabelY = 90.0f;
- GLfloat rotLabelZ = 0.0f;
- Qt::AlignmentFlag alignment = Qt::AlignLeft;
- if (m_xFlipped)
- rotLabelY = -90.0f;
- if (m_zFlipped) {
+ Qt::AlignmentFlag alignment = (m_xFlipped != m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight;
+ QVector3D labelRotation;
+ if (m_zFlipped)
labelZTrans = -labelZTrans;
- alignment = Qt::AlignRight;
- }
- if (m_yFlipped) {
- rotLabelZ += 180.0f;
- rotLabelY += 180.0f;
+ if (m_yFlipped)
labelYTrans = -labelYTrans;
+ if (labelAutoAngle == 0.0f) {
+ labelRotation = QVector3D(-90.0f, 90.0f, 0.0f);
+ if (m_xFlipped)
+ labelRotation.setY(-90.0f);
+ if (m_yFlipped) {
+ if (m_xFlipped)
+ labelRotation.setY(90.0f);
+ else
+ labelRotation.setY(-90.0f);
+ labelRotation.setZ(180.0f);
+ }
+ } else {
+ if (m_xFlipped)
+ labelRotation.setY(-90.0f);
+ else
+ labelRotation.setY(90.0f);
+ if (m_yFlipped) {
+ if (m_zFlipped) {
+ if (m_xFlipped) {
+ labelRotation.setX(90.0f - (2.0f * labelAutoAngle - fractionCamX)
+ * (labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle - fractionCamY);
+ } else {
+ labelRotation.setX(90.0f - (2.0f * labelAutoAngle + fractionCamX)
+ * (labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle + fractionCamY);
+ }
+ } else {
+ if (m_xFlipped) {
+ labelRotation.setX(90.0f + fractionCamX
+ * -(labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle + fractionCamY);
+ } else {
+ labelRotation.setX(90.0f - fractionCamX
+ * (-labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle - fractionCamY);
+ }
+ }
+ } else {
+ if (m_zFlipped) {
+ if (m_xFlipped) {
+ labelRotation.setX(-90.0f + (2.0f * labelAutoAngle - fractionCamX)
+ * (labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle - fractionCamY);
+ } else {
+ labelRotation.setX(-90.0f + (2.0f * labelAutoAngle + fractionCamX)
+ * (labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle + fractionCamY);
+ }
+ } else {
+ if (m_xFlipped) {
+ labelRotation.setX(-90.0f - fractionCamX
+ * (-labelAutoAngle + fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(-labelAutoAngle + fractionCamY);
+ } else {
+ labelRotation.setX(-90.0f + fractionCamX
+ * -(labelAutoAngle - fractionCamY) / labelAutoAngle);
+ labelRotation.setZ(labelAutoAngle - fractionCamY);
+ }
+ }
+ }
}
- QVector3D labelTrans = QVector3D(labelPos,
+ QQuaternion totalRotation = Utils::calculateRotation(labelRotation);
+
+ QVector3D labelTrans = QVector3D(0.0f,
labelYTrans,
labelZTrans);
- QVector3D rotation(rotLabelX, rotLabelY, rotLabelZ);
-
- 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);
- const LabelItem &axisLabelItem = *m_axisCacheX.labelItems().at(labelNbr);
-
- m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- positionZComp, rotation, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, activeCamera,
- true, true, Drawer::LabelMid, alignment);
+
+ if (m_xFlipped) {
+ startIndex = labelCount - 1;
+ endIndex = -1;
+ indexStep = -1;
+ } else {
+ startIndex = 0;
+ endIndex = labelCount;
+ indexStep = 1;
+ }
+ for (int label = startIndex; label != endIndex; label = label + indexStep) {
+ glPolygonOffset(GLfloat(label) / -10.0f, 1.0f);
+ // Draw the label here
+ labelTrans.setX(m_axisCacheX.labelPosition(label));
+ m_dummyRenderItem.setTranslation(labelTrans);
+ const LabelItem &axisLabelItem = *m_axisCacheX.labelItems().at(label);
+
+ if (drawSelection) {
+ QVector4D labelColor = QVector4D(0.0f, label / 255.0f, 0.0f,
+ alphaForColumnSelection);
+ shader->setUniformValue(shader->color(), labelColor);
}
- labelNbr++;
- labelPos += posStep;
+
+ m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
+ positionZComp, totalRotation, 0, m_cachedSelectionMode,
+ shader, m_labelObj, activeCamera,
+ true, true, Drawer::LabelMid, alignment, false, drawSelection);
+ labelsMaxWidth = qMax(labelsMaxWidth, float(axisLabelItem.size().width()));
+ }
+ if (!drawSelection && m_axisCacheX.isTitleVisible()) {
+ labelTrans.setX(0.0f);
+ drawAxisTitleX(labelRotation, labelTrans, totalRotation, m_dummyRenderItem,
+ activeCamera, labelsMaxWidth, viewMatrix, projectionMatrix, shader);
}
}
// Y Labels
if (m_axisCacheY.segmentCount() > 0) {
- GLfloat posStep = 2.0f * m_axisCacheY.segmentStep() / m_heightNormalizer;
- GLfloat labelPos = -1.0f;
- int labelNbr = 0;
+ labelsMaxWidth = 0.0f;
+ labelAutoAngle = m_axisCacheY.labelAutoRotation();
+ labelAngleFraction = labelAutoAngle / 90.0f;
+ fractionCamY = activeCamera->yRotation() * labelAngleFraction;
+ fractionCamX = activeCamera->xRotation() * labelAngleFraction;
+ int labelCount = m_axisCacheY.labelCount();
+
GLfloat labelXTrans = m_scaleXWithBackground;
GLfloat labelZTrans = m_scaleZWithBackground;
- // Back wall init
+ // Back & side wall
GLfloat labelMarginXTrans = labelMargin;
GLfloat labelMarginZTrans = labelMargin;
- GLfloat rotLabelX = 0.0f;
- GLfloat rotLabelY = -90.0f;
- GLfloat rotLabelZ = 0.0f;
- Qt::AlignmentFlag alignmentBack = Qt::AlignLeft;
+ QVector3D backLabelRotation(0.0f, -90.0f, 0.0f);
+ QVector3D sideLabelRotation(0.0f, 0.0f, 0.0f);
+ Qt::AlignmentFlag backAlignment =
+ (m_xFlipped != m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight;
+ Qt::AlignmentFlag sideAlignment =
+ (m_xFlipped == m_zFlipped) ? Qt::AlignLeft : Qt::AlignRight;
if (!m_xFlipped) {
labelXTrans = -labelXTrans;
labelMarginXTrans = -labelMargin;
- rotLabelY = 90.0f;
}
if (m_zFlipped) {
labelZTrans = -labelZTrans;
labelMarginZTrans = -labelMargin;
- alignmentBack = Qt::AlignRight;
}
- QVector3D labelRotateVectorBack(rotLabelX, rotLabelY, rotLabelZ);
- QVector3D labelTransBack = QVector3D(labelXTrans, 0.0f, labelZTrans + labelMarginZTrans);
+ if (labelAutoAngle == 0.0f) {
+ if (!m_xFlipped)
+ backLabelRotation.setY(90.0f);
+ if (m_zFlipped)
+ sideLabelRotation.setY(180.f);
+ } else {
+ // Orient side labels somewhat towards the camera
+ if (m_xFlipped) {
+ if (m_zFlipped)
+ sideLabelRotation.setY(180.0f + (2.0f * labelAutoAngle) - fractionCamX);
+ else
+ sideLabelRotation.setY(-fractionCamX);
+ backLabelRotation.setY(-90.0f + labelAutoAngle - fractionCamX);
+ } else {
+ if (m_zFlipped)
+ sideLabelRotation.setY(180.0f - (2.0f * labelAutoAngle) - fractionCamX);
+ else
+ sideLabelRotation.setY(-fractionCamX);
+ backLabelRotation.setY(90.0f - labelAutoAngle - fractionCamX);
+ }
+ }
+ sideLabelRotation.setX(-fractionCamY);
+ backLabelRotation.setX(-fractionCamY);
- // Side wall init
- Qt::AlignmentFlag alignmentSide = Qt::AlignLeft;
- if (m_xFlipped)
- alignmentSide = Qt::AlignLeft;
- else
- alignmentSide = Qt::AlignRight;
- if (m_zFlipped)
- rotLabelY = 180.0f;
- else
- rotLabelY = 0.0f;
+ QQuaternion totalSideRotation = Utils::calculateRotation(sideLabelRotation);
+ QQuaternion totalBackRotation = Utils::calculateRotation(backLabelRotation);
- QVector3D labelRotateVectorSide(rotLabelX, rotLabelY, rotLabelZ);
+ QVector3D labelTransBack = QVector3D(labelXTrans, 0.0f, labelZTrans + labelMarginZTrans);
QVector3D labelTransSide(-labelXTrans - labelMarginXTrans, 0.0f, -labelZTrans);
- for (int segment = 0; segment <= m_axisCacheY.segmentCount(); segment++) {
- 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);
- m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- positionZComp, labelRotateVectorBack, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, activeCamera,
- true, true, Drawer::LabelMid, alignmentBack);
-
- // Side wall
- labelTransSide.setY(labelPos);
- m_dummyRenderItem.setTranslation(labelTransSide);
- m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
- positionZComp, labelRotateVectorSide, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, activeCamera,
- true, true, Drawer::LabelMid, alignmentSide);
- }
- labelNbr++;
- labelPos += posStep;
+ if (m_yFlipped) {
+ startIndex = labelCount - 1;
+ endIndex = -1;
+ indexStep = -1;
+ } else {
+ startIndex = 0;
+ endIndex = labelCount;
+ indexStep = 1;
}
- }
- glDisable(GL_POLYGON_OFFSET_FILL);
+ for (int label = startIndex; label != endIndex; label = label + indexStep) {
+ const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(label);
+ const GLfloat labelYTrans = m_axisCacheY.labelPosition(label);
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_BLEND);
+ glPolygonOffset(GLfloat(label) / -10.0f, 1.0f);
- // Release shader
- glUseProgram(0);
-
- // Selection handling
- if (m_selectionDirty || m_selectionLabelDirty) {
- QPoint visiblePoint = Surface3DController::invalidSelectionPosition();
- if (m_selectedSeries) {
- SurfaceSeriesRenderCache *cache =
- m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries));
- if (cache && m_selectedPoint != Surface3DController::invalidSelectionPosition()) {
- const QRect &sampleSpace = cache->sampleSpace();
- int x = m_selectedPoint.x() - sampleSpace.y();
- int y = m_selectedPoint.y() - sampleSpace.x();
- if (x >= 0 && y >= 0 && x < sampleSpace.height() && y < sampleSpace.width()
- && cache->dataArray().size()) {
- visiblePoint = QPoint(x, y);
- }
+ if (drawSelection) {
+ QVector4D labelColor = QVector4D(0.0f, 0.0f, label / 255.0f,
+ alphaForValueSelection);
+ shader->setUniformValue(shader->color(), labelColor);
}
- }
- if (m_cachedSelectionMode == QAbstract3DGraph::SelectionNone
- || visiblePoint == Surface3DController::invalidSelectionPosition()) {
- m_selectionActive = false;
- } else {
- if (m_cachedIsSlicingActivated)
- updateSliceDataModel(visiblePoint);
- if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionItem))
- surfacePointSelected(visiblePoint);
- m_selectionActive = true;
+ // Back wall
+ labelTransBack.setY(labelYTrans);
+ m_dummyRenderItem.setTranslation(labelTransBack);
+ m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
+ positionZComp, totalBackRotation, 0, m_cachedSelectionMode,
+ shader, m_labelObj, activeCamera,
+ true, true, Drawer::LabelMid, backAlignment, false,
+ drawSelection);
+
+ // Side wall
+ labelTransSide.setY(labelYTrans);
+ m_dummyRenderItem.setTranslation(labelTransSide);
+ m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
+ positionZComp, totalSideRotation, 0, m_cachedSelectionMode,
+ shader, m_labelObj, activeCamera,
+ true, true, Drawer::LabelMid, sideAlignment, false,
+ drawSelection);
+ labelsMaxWidth = qMax(labelsMaxWidth, float(axisLabelItem.size().width()));
+ }
+ if (!drawSelection && m_axisCacheY.isTitleVisible()) {
+ labelTransSide.setY(0.0f);
+ labelTransBack.setY(0.0f);
+ drawAxisTitleY(sideLabelRotation, backLabelRotation, labelTransSide, labelTransBack,
+ totalSideRotation, totalBackRotation, m_dummyRenderItem, activeCamera,
+ labelsMaxWidth, viewMatrix, projectionMatrix,
+ shader);
}
+ }
+ glDisable(GL_POLYGON_OFFSET_FILL);
- m_selectionDirty = false;
+ if (!drawSelection) {
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
}
}
@@ -1976,7 +2185,9 @@ void Surface3DRenderer::updateSelectionTextures()
{
uint lastSelectionId = 1;
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache =
+ static_cast<SurfaceSeriesRenderCache *>(baseCache);
GLuint texture = cache->selectionTexture();
m_textureHelper->deleteTexture(&texture);
createSelectionTexture(cache, lastSelectionId);
@@ -1992,6 +2203,13 @@ void Surface3DRenderer::createSelectionTexture(SurfaceSeriesRenderCache *cache,
const QRect &sampleSpace = cache->sampleSpace();
int idImageWidth = (sampleSpace.width() - 1) * 4;
int idImageHeight = (sampleSpace.height() - 1) * 4;
+
+ if (idImageHeight <= 0 || idImageWidth <= 0) {
+ cache->setSelectionIdRange(-1, -1);
+ cache->setSelectionTexture(0);
+ return;
+ }
+
int stride = idImageWidth * 4 * sizeof(uchar); // 4 = number of color components (rgba)
uint idStart = lastSelectionId;
@@ -2031,10 +2249,7 @@ void Surface3DRenderer::createSelectionTexture(SurfaceSeriesRenderCache *cache,
void Surface3DRenderer::initSelectionBuffer()
{
// Create the result selection texture and buffers
- if (m_selectionResultTexture) {
- m_textureHelper->deleteTexture(&m_selectionResultTexture);
- m_selectionResultTexture = 0;
- }
+ m_textureHelper->deleteTexture(&m_selectionResultTexture);
m_selectionResultTexture = m_textureHelper->createSelectionTexture(m_primarySubViewport.size(),
m_selectionFrameBuffer,
@@ -2076,10 +2291,16 @@ void Surface3DRenderer::calculateSceneScalingFactors()
m_areaSize.setHeight(m_axisCacheZ.max() - m_axisCacheZ.min());
m_areaSize.setWidth(m_axisCacheX.max() - m_axisCacheX.min());
m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height());
- m_scaleX = aspectRatio * m_areaSize.width() / m_scaleFactor;
- m_scaleZ = aspectRatio * m_areaSize.height() / m_scaleFactor;
- m_scaleXWithBackground = m_scaleX * backgroundMargin;
- m_scaleZWithBackground = m_scaleZ * backgroundMargin;
+ m_scaleX = m_graphAspectRatio * m_areaSize.width() / m_scaleFactor;
+ m_scaleZ = m_graphAspectRatio * m_areaSize.height() / m_scaleFactor;
+ m_scaleXWithBackground = m_scaleX + backgroundMargin - 1.0f;
+ m_scaleZWithBackground = m_scaleZ + backgroundMargin - 1.0f;
+
+ float factorScaler = 2.0f * m_graphAspectRatio / m_scaleFactor;
+ m_axisCacheX.setScale(factorScaler * m_areaSize.width());
+ m_axisCacheZ.setScale(-factorScaler * m_areaSize.height());
+ m_axisCacheX.setTranslate(-m_axisCacheX.scale() / 2.0f);
+ m_axisCacheZ.setTranslate(-m_axisCacheZ.scale() / 2.0f);
}
void Surface3DRenderer::checkFlatSupport(SurfaceSeriesRenderCache *cache)
@@ -2098,17 +2319,13 @@ void Surface3DRenderer::updateObjects(SurfaceSeriesRenderCache *cache, bool dime
QSurfaceDataArray &dataArray = cache->dataArray();
const QRect &sampleSpace = cache->sampleSpace();
-
- if (cache->isFlatShadingEnabled()) {
- cache->surfaceObject()->setUpData(dataArray, sampleSpace, m_heightNormalizer,
- m_axisCacheY.min(), dimensionChanged);
- } else {
- cache->surfaceObject()->setUpSmoothData(dataArray, sampleSpace, m_heightNormalizer,
- m_axisCacheY.min(), dimensionChanged);
- }
+ if (cache->isFlatShadingEnabled())
+ cache->surfaceObject()->setUpData(dataArray, sampleSpace, dimensionChanged);
+ else
+ cache->surfaceObject()->setUpSmoothData(dataArray, sampleSpace, dimensionChanged);
}
-void Surface3DRenderer::updateSelectedPoint(const QPoint &position, const QSurface3DSeries *series)
+void Surface3DRenderer::updateSelectedPoint(const QPoint &position, QSurface3DSeries *series)
{
m_selectedPoint = position;
m_selectedSeries = series;
@@ -2123,23 +2340,15 @@ void Surface3DRenderer::resetClickedStatus()
void Surface3DRenderer::loadBackgroundMesh()
{
- if (m_backgroundObj)
- delete m_backgroundObj;
- m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/background"));
- m_backgroundObj->load();
-}
-
-void Surface3DRenderer::loadGridLineMesh()
-{
- if (m_gridLineObj)
- delete m_gridLineObj;
- m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
- m_gridLineObj->load();
+ ObjectHelper::resetObjectHelper(this, m_backgroundObj,
+ QStringLiteral(":/defaultMeshes/background"));
}
void Surface3DRenderer::surfacePointSelected(const QPoint &point)
{
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache =
+ static_cast<SurfaceSeriesRenderCache *>(baseCache);
cache->setSlicePointerActivity(false);
cache->setMainPointerActivity(false);
}
@@ -2147,12 +2356,15 @@ void Surface3DRenderer::surfacePointSelected(const QPoint &point)
if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionMultiSeries)) {
// Find axis coordinates for the selected point
SurfaceSeriesRenderCache *selectedCache =
- m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries));
+ static_cast<SurfaceSeriesRenderCache *>(
+ m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries)));
QSurfaceDataArray &dataArray = selectedCache->dataArray();
QSurfaceDataItem item = dataArray.at(point.x())->at(point.y());
QPointF coords(item.x(), item.z());
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache =
+ static_cast<SurfaceSeriesRenderCache *>(baseCache);
if (cache->series() != m_selectedSeries) {
QPoint mappedPoint = mapCoordsToSampleSpace(cache, coords);
updateSelectionPoint(cache, mappedPoint, false);
@@ -2163,7 +2375,8 @@ void Surface3DRenderer::surfacePointSelected(const QPoint &point)
} else {
if (m_selectedSeries) {
SurfaceSeriesRenderCache *cache =
- m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries));
+ static_cast<SurfaceSeriesRenderCache *>(
+ m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries)));
if (cache)
updateSelectionPoint(cache, point, true);
}
@@ -2179,9 +2392,6 @@ void Surface3DRenderer::updateSelectionPoint(SurfaceSeriesRenderCache *cache, co
if (column < 0 || row < 0)
return;
- QSurfaceDataArray &dataArray = cache->dataArray();
- float value = dataArray.at(row)->at(column).y();
-
SelectionPointer *slicePointer = cache->sliceSelectionPointer();
if (!slicePointer && m_cachedIsSlicingActivated) {
slicePointer = new SelectionPointer(m_drawer);
@@ -2193,28 +2403,28 @@ void Surface3DRenderer::updateSelectionPoint(SurfaceSeriesRenderCache *cache, co
cache->setMainSelectionPointer(mainPointer);
}
- const QVector3D &scale = cache->scale();
- const QVector3D &offset = cache->offset();
QString selectionLabel;
- if (label)
- selectionLabel = createSelectionLabel(cache, value, column, row);
+ if (label) {
+ m_selectionLabelDirty = false;
+ selectionLabel = cache->itemLabel();
+ }
if (m_cachedIsSlicingActivated) {
- QVector3D subPos;
+ QVector3D subPosFront;
+ QVector3D subPosBack;
if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow)) {
- subPos = cache->sliceSurfaceObject()->vertexAt(column, 0);
- subPos *= QVector3D(scale.x(), 1.0f, 0.0f);
- subPos += QVector3D(offset.x(), 0.0f, 0.0f);
+ subPosFront = cache->sliceSurfaceObject()->vertexAt(column, 0);
+ subPosBack = cache->sliceSurfaceObject()->vertexAt(column, 1);
} else if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionColumn)) {
- subPos = cache->sliceSurfaceObject()->vertexAt(row, 0);
- subPos *= QVector3D(scale.z(), 1.0f, 0.0f);
- subPos += QVector3D(-offset.z(), 0.0f, 0.0f);
+ subPosFront = cache->sliceSurfaceObject()->vertexAt(row, 0);
+ subPosBack = cache->sliceSurfaceObject()->vertexAt(row, 1);
}
slicePointer->updateBoundingRect(m_secondarySubViewport);
slicePointer->updateSliceData(true, m_autoScaleAdjustment);
- slicePointer->setPosition(subPos);
+ slicePointer->setPosition((subPosFront + subPosBack) / 2.0f);
slicePointer->setLabel(selectionLabel);
slicePointer->setPointerObject(cache->object());
+ slicePointer->setLabelObject(m_labelObj);
slicePointer->setHighlightColor(cache->singleHighlightColor());
slicePointer->updateScene(m_cachedScene);
slicePointer->setRotation(cache->meshRotation());
@@ -2223,13 +2433,12 @@ void Surface3DRenderer::updateSelectionPoint(SurfaceSeriesRenderCache *cache, co
QVector3D mainPos;
mainPos = cache->surfaceObject()->vertexAt(column, row);
- mainPos *= scale;
- mainPos += offset;
mainPointer->updateBoundingRect(m_primarySubViewport);
mainPointer->updateSliceData(false, m_autoScaleAdjustment);
mainPointer->setPosition(mainPos);
mainPointer->setLabel(selectionLabel);
mainPointer->setPointerObject(cache->object());
+ mainPointer->setLabelObject(m_labelObj);
mainPointer->setHighlightColor(cache->singleHighlightColor());
mainPointer->updateScene(m_cachedScene);
mainPointer->setRotation(cache->meshRotation());
@@ -2239,8 +2448,33 @@ void Surface3DRenderer::updateSelectionPoint(SurfaceSeriesRenderCache *cache, co
// Maps selection Id to surface point in data array
QPoint Surface3DRenderer::selectionIdToSurfacePoint(uint id)
{
+ m_clickedType = QAbstract3DGraph::ElementNone;
+ m_selectedLabelIndex = -1;
+ m_selectedCustomItemIndex = -1;
+ // Check for label and custom item selection
+ if (id / alphaMultiplier == labelRowAlpha) {
+ m_selectedLabelIndex = id - (alphaMultiplier * uint(labelRowAlpha));
+ m_clickedType = QAbstract3DGraph::ElementAxisZLabel;
+ return Surface3DController::invalidSelectionPosition();
+ } else if (id / alphaMultiplier == labelColumnAlpha) {
+ m_selectedLabelIndex = (id - (alphaMultiplier * uint(labelColumnAlpha))) / greenMultiplier;
+ m_clickedType = QAbstract3DGraph::ElementAxisXLabel;
+ return Surface3DController::invalidSelectionPosition();
+ } else if (id / alphaMultiplier == labelValueAlpha) {
+ m_selectedLabelIndex = (id - (alphaMultiplier * uint(labelValueAlpha))) / blueMultiplier;
+ m_clickedType = QAbstract3DGraph::ElementAxisYLabel;
+ return Surface3DController::invalidSelectionPosition();
+ } else if (id / alphaMultiplier == customItemAlpha) {
+ // Custom item selection
+ m_clickedType = QAbstract3DGraph::ElementCustomItem;
+ m_selectedCustomItemIndex = id - (alphaMultiplier * uint(customItemAlpha));
+ return Surface3DController::invalidSelectionPosition();
+ }
+
+ // Not a label selection
SurfaceSeriesRenderCache *selectedCache = 0;
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
if (cache->isWithinIdRange(id)) {
selectedCache = cache;
break;
@@ -2257,57 +2491,10 @@ QPoint Surface3DRenderer::selectionIdToSurfacePoint(uint id)
int row = ((idInSeries - 1) / sampleSpace.width()) + sampleSpace.y();
m_clickedSeries = selectedCache->series();
+ m_clickedType = QAbstract3DGraph::ElementSeries;
return QPoint(row, column);
}
-QString Surface3DRenderer::createSelectionLabel(SurfaceSeriesRenderCache *cache, float value,
- int column, int row)
-{
- QSurfaceDataArray &dataArray = cache->dataArray();
- QString labelText = cache->itemLabelFormat();
- static const QString xTitleTag(QStringLiteral("@xTitle"));
- static const QString yTitleTag(QStringLiteral("@yTitle"));
- static const QString zTitleTag(QStringLiteral("@zTitle"));
- static const QString xLabelTag(QStringLiteral("@xLabel"));
- static const QString yLabelTag(QStringLiteral("@yLabel"));
- static const QString zLabelTag(QStringLiteral("@zLabel"));
- static const QString seriesNameTag(QStringLiteral("@seriesName"));
-
- labelText.replace(xTitleTag, m_axisCacheX.title());
- labelText.replace(yTitleTag, m_axisCacheY.title());
- labelText.replace(zTitleTag, m_axisCacheZ.title());
-
- if (labelText.contains(xLabelTag)) {
- QString labelFormat = m_axisCacheX.labelFormat();
- if (labelFormat.isEmpty())
- labelFormat = Utils::defaultLabelFormat();
- QString valueLabelText = generateValueLabel(labelFormat,
- dataArray.at(row)->at(column).x());
- labelText.replace(xLabelTag, valueLabelText);
- }
- if (labelText.contains(yLabelTag)) {
- QString labelFormat = m_axisCacheY.labelFormat();
- if (labelFormat.isEmpty())
- labelFormat = Utils::defaultLabelFormat();
- QString valueLabelText = generateValueLabel(labelFormat, value);
- labelText.replace(yLabelTag, valueLabelText);
- }
- if (labelText.contains(zLabelTag)) {
- QString labelFormat = m_axisCacheZ.labelFormat();
- if (labelFormat.isEmpty())
- labelFormat = Utils::defaultLabelFormat();
- QString valueLabelText = generateValueLabel(labelFormat,
- dataArray.at(row)->at(column).z());
- labelText.replace(zLabelTag, valueLabelText);
- }
-
- labelText.replace(seriesNameTag, cache->name());
-
- m_selectionLabelDirty = false;
-
- return labelText;
-}
-
void Surface3DRenderer::updateShadowQuality(QAbstract3DGraph::ShadowQuality quality)
{
m_cachedShadowQuality = quality;
@@ -2371,20 +2558,13 @@ void Surface3DRenderer::updateSlicingActive(bool isSlicing)
m_selectionDirty = true;
- foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ foreach (SeriesRenderCache *baseCache, m_renderCacheList) {
+ SurfaceSeriesRenderCache *cache = static_cast<SurfaceSeriesRenderCache *>(baseCache);
if (cache->mainSelectionPointer())
cache->mainSelectionPointer()->updateBoundingRect(m_primarySubViewport);
}
}
-void Surface3DRenderer::loadLabelMesh()
-{
- if (m_labelObj)
- delete m_labelObj;
- m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/plane"));
- m_labelObj->load();
-}
-
void Surface3DRenderer::initShaders(const QString &vertexShader, const QString &fragmentShader)
{
Q_UNUSED(vertexShader);
@@ -2408,17 +2588,22 @@ void Surface3DRenderer::initShaders(const QString &vertexShader, const QString &
m_surfaceSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragmentSurface"));
}
- if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
- m_surfaceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceShadowFlat"),
- QStringLiteral(":/shaders/fragmentSurfaceShadowFlat"));
- } else {
- m_surfaceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
- QStringLiteral(":/shaders/fragmentSurfaceFlat"));
- }
m_surfaceSliceSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragmentSurface"));
- m_surfaceSliceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
- QStringLiteral(":/shaders/fragmentSurfaceFlat"));
+ if (m_flatSupported) {
+ if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
+ m_surfaceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceShadowFlat"),
+ QStringLiteral(":/shaders/fragmentSurfaceShadowFlat"));
+ } else {
+ m_surfaceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
+ QStringLiteral(":/shaders/fragmentSurfaceFlat"));
+ }
+ m_surfaceSliceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
+ QStringLiteral(":/shaders/fragmentSurfaceFlat"));
+ } else {
+ m_surfaceFlatShader = 0;
+ m_surfaceSliceFlatShader = 0;
+ }
#else
m_surfaceSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
QStringLiteral(":/shaders/fragmentSurfaceES2"));
@@ -2430,9 +2615,11 @@ void Surface3DRenderer::initShaders(const QString &vertexShader, const QString &
QStringLiteral(":/shaders/fragmentSurfaceES2"));
#endif
m_surfaceSmoothShader->initialize();
- m_surfaceFlatShader->initialize();
m_surfaceSliceSmoothShader->initialize();
- m_surfaceSliceFlatShader->initialize();
+ if (m_flatSupported) {
+ m_surfaceFlatShader->initialize();
+ m_surfaceSliceFlatShader->initialize();
+ }
}
void Surface3DRenderer::initBackgroundShaders(const QString &vertexShader,
@@ -2486,14 +2673,8 @@ void Surface3DRenderer::initDepthShader()
void Surface3DRenderer::updateDepthBuffer()
{
- if (m_depthTexture) {
- m_textureHelper->deleteTexture(&m_depthTexture);
- m_depthTexture = 0;
- }
- if (m_depthModelTexture) {
- m_textureHelper->deleteTexture(&m_depthModelTexture);
- m_depthModelTexture = 0;
- }
+ m_textureHelper->deleteTexture(&m_depthTexture);
+ m_textureHelper->deleteTexture(&m_depthModelTexture);
if (m_primarySubViewport.size().isEmpty())
return;
@@ -2512,4 +2693,22 @@ void Surface3DRenderer::updateDepthBuffer()
}
#endif
+QVector3D Surface3DRenderer::convertPositionToTranslation(const QVector3D &position,
+ bool isAbsolute)
+{
+ float xTrans = 0.0f;
+ float yTrans = 0.0f;
+ float zTrans = 0.0f;
+ if (!isAbsolute) {
+ xTrans = m_axisCacheX.positionAt(position.x());
+ yTrans = m_axisCacheY.positionAt(position.y());
+ zTrans = m_axisCacheZ.positionAt(position.z());
+ } else {
+ xTrans = position.x() * m_scaleX;
+ yTrans = position.y();
+ zTrans = position.z() * m_scaleZ;
+ }
+ return QVector3D(xTrans, yTrans, zTrans);
+}
+
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h
index 2c55d902..efa8ff7e 100644
--- a/src/datavisualization/engine/surface3drenderer_p.h
+++ b/src/datavisualization/engine/surface3drenderer_p.h
@@ -32,17 +32,12 @@
#include "datavisualizationglobal_p.h"
#include "surface3dcontroller_p.h"
#include "abstract3drenderer_p.h"
-#include "scatterrenderitem_p.h"
-#include "qsurfacedataproxy.h"
#include "surfaceseriesrendercache_p.h"
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
class ShaderHelper;
-class ObjectHelper;
-class SurfaceObject;
class Q3DScene;
-class SelectionPointer;
class QT_DATAVISUALIZATION_EXPORT Surface3DRenderer : public Abstract3DRenderer
{
@@ -67,15 +62,6 @@ private:
GLfloat m_scaleZ;
GLfloat m_scaleXWithBackground;
GLfloat m_scaleZWithBackground;
- GLfloat m_minVisibleColumnValue;
- GLfloat m_maxVisibleColumnValue;
- GLfloat m_minVisibleRowValue;
- GLfloat m_maxVisibleRowValue;
- GLfloat m_visibleColumnRange;
- GLfloat m_visibleRowRange;
- ObjectHelper *m_backgroundObj;
- ObjectHelper *m_gridLineObj;
- ObjectHelper *m_labelObj;
GLuint m_depthTexture;
GLuint m_depthModelTexture;
GLuint m_depthFrameBuffer;
@@ -85,17 +71,13 @@ private:
GLfloat m_shadowQualityToShader;
bool m_flatSupported;
bool m_selectionActive;
- bool m_xFlipped;
- bool m_zFlipped;
- bool m_yFlipped;
AbstractRenderItem m_dummyRenderItem;
GLint m_shadowQualityMultiplier;
QSizeF m_areaSize;
bool m_hasHeightAdjustmentChanged;
QPoint m_selectedPoint;
- const QSurface3DSeries *m_selectedSeries;
+ QSurface3DSeries *m_selectedSeries;
QPoint m_clickedPosition;
- QHash<QSurface3DSeries *, SurfaceSeriesRenderCache *> m_renderCacheList;
bool m_selectionTexturesDirty;
GLuint m_noShadowTexture;
@@ -104,19 +86,19 @@ public:
~Surface3DRenderer();
void updateData();
- void updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility);
+ void updateSeries(const QList<QAbstract3DSeries *> &seriesList);
+ SeriesRenderCache *createNewCache(QAbstract3DSeries *series);
+ void cleanCache(SeriesRenderCache *cache);
void updateSelectionMode(QAbstract3DGraph::SelectionFlags mode);
- void modifiedSeriesList(const QVector<QSurface3DSeries *> &seriesList);
void updateRows(const QVector<Surface3DController::ChangeRow> &rows);
- void updateItem(const QVector<Surface3DController::ChangeItem> &points);
- void updateAxisRange(QAbstract3DAxis::AxisOrientation orientation, float min, float max);
+ void updateItems(const QVector<Surface3DController::ChangeItem> &points);
void updateScene(Q3DScene *scene);
void updateSlicingActive(bool isSlicing);
- void updateSelectedPoint(const QPoint &position, const QSurface3DSeries *series);
+ void updateSelectedPoint(const QPoint &position, QSurface3DSeries *series);
inline QPoint clickedPosition() const { return m_clickedPosition; }
void resetClickedStatus();
+ QVector3D convertPositionToTranslation(const QVector3D &position, bool isAbsolute);
- void drawSlicedScene();
void render(GLuint defaultFboHandle = 0);
protected:
@@ -136,11 +118,14 @@ private:
void updateShadowQuality(QAbstract3DGraph::ShadowQuality quality);
void updateTextures();
void initShaders(const QString &vertexShader, const QString &fragmentShader);
- QRect calculateSampleRect(SurfaceSeriesRenderCache *cache, const QSurfaceDataArray &array);
+ QRect calculateSampleRect(const QSurfaceDataArray &array);
void loadBackgroundMesh();
- void loadGridLineMesh();
- void loadLabelMesh();
+
+ void drawSlicedScene();
void drawScene(GLuint defaultFboHandle);
+ void drawLabels(bool drawSelection, const Q3DCamera *activeCamera,
+ const QMatrix4x4 &viewMatrix, const QMatrix4x4 &projectionMatrix);
+
void calculateSceneScalingFactors();
void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader);
void initLabelShaders(const QString &vertexShader, const QString &fragmentShader);
@@ -155,13 +140,14 @@ private:
void surfacePointSelected(const QPoint &point);
void updateSelectionPoint(SurfaceSeriesRenderCache *cache, const QPoint &point, bool label);
QPoint selectionIdToSurfacePoint(uint id);
- QString createSelectionLabel(SurfaceSeriesRenderCache *cache, float value, int column, int row);
#if !defined(QT_OPENGL_ES_2)
void updateDepthBuffer();
#endif
void emitSelectedPointChanged(QPoint position);
Q_DISABLE_COPY(Surface3DRenderer)
+
+ friend class SurfaceObject;
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/surfaceseriesrendercache.cpp b/src/datavisualization/engine/surfaceseriesrendercache.cpp
index ba25d71d..1cce5288 100644
--- a/src/datavisualization/engine/surfaceseriesrendercache.cpp
+++ b/src/datavisualization/engine/surfaceseriesrendercache.cpp
@@ -16,35 +16,30 @@
**
****************************************************************************/
-#include "seriesrendercache_p.h"
#include "surfaceseriesrendercache_p.h"
-#include "objecthelper_p.h"
-#include "abstract3drenderer_p.h"
+#include "surface3drenderer_p.h"
#include "texturehelper_p.h"
-#include "utils_p.h"
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
-SurfaceSeriesRenderCache::SurfaceSeriesRenderCache()
- : m_surfaceVisible(false),
+SurfaceSeriesRenderCache::SurfaceSeriesRenderCache(QAbstract3DSeries *series,
+ Surface3DRenderer *renderer)
+ : SeriesRenderCache(series, renderer),
+ m_surfaceVisible(false),
m_surfaceGridVisible(false),
- m_surfaceFlatShading(true),
- m_surfaceObj(new SurfaceObject),
- m_sliceSurfaceObj(new SurfaceObject),
- m_sampleSpace(QRect(0, 0, 0 , 0)),
+ m_surfaceFlatShading(false),
+ m_surfaceObj(new SurfaceObject(renderer)),
+ m_sliceSurfaceObj(new SurfaceObject(renderer)),
+ m_sampleSpace(QRect(0, 0, 0, 0)),
m_selectionTexture(0),
m_selectionIdStart(0),
m_selectionIdEnd(0),
m_flatChangeAllowed(true),
- m_flatStatusDirty(false),
- m_scale(QVector3D(1.0f, 1.0f, 1.0f)),
- m_offset(QVector3D(0.0f, 0.0f, 0.0f)),
+ m_flatStatusDirty(true),
m_sliceSelectionPointer(0),
m_mainSelectionPointer(0),
m_slicePointerActive(false),
- m_mainPointerActive(false),
- m_valid(false),
- m_objectDirty(true)
+ m_mainPointerActive(false)
{
}
@@ -52,17 +47,15 @@ SurfaceSeriesRenderCache::~SurfaceSeriesRenderCache()
{
}
-void SurfaceSeriesRenderCache::populate(QSurface3DSeries *series, Abstract3DRenderer *renderer)
+void SurfaceSeriesRenderCache::populate(bool newSeries)
{
- Q_ASSERT(series);
+ SeriesRenderCache::populate(newSeries);
- SeriesRenderCache::populate(series, renderer);
-
- QSurface3DSeries::DrawFlags drawMode = series->drawMode();
+ QSurface3DSeries::DrawFlags drawMode = series()->drawMode();
m_surfaceVisible = drawMode.testFlag(QSurface3DSeries::DrawSurface);
m_surfaceGridVisible = drawMode.testFlag(QSurface3DSeries::DrawWireframe);
- if (m_flatChangeAllowed && m_surfaceFlatShading != series->isFlatShadingEnabled()) {
- m_surfaceFlatShading = series->isFlatShadingEnabled();
+ if (m_flatChangeAllowed && m_surfaceFlatShading != series()->isFlatShadingEnabled()) {
+ m_surfaceFlatShading = series()->isFlatShadingEnabled();
m_flatStatusDirty = true;
}
}
diff --git a/src/datavisualization/engine/surfaceseriesrendercache_p.h b/src/datavisualization/engine/surfaceseriesrendercache_p.h
index 2dda0670..b6254a75 100644
--- a/src/datavisualization/engine/surfaceseriesrendercache_p.h
+++ b/src/datavisualization/engine/surfaceseriesrendercache_p.h
@@ -31,7 +31,6 @@
#include "datavisualizationglobal_p.h"
#include "seriesrendercache_p.h"
-#include "qabstract3dseries_p.h"
#include "qsurface3dseries_p.h"
#include "surfaceobject_p.h"
#include "selectionpointer_p.h"
@@ -40,17 +39,15 @@
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
-class Abstract3DRenderer;
-class ObjectHelper;
-class TextureHelper;
+class Surface3DRenderer;
class SurfaceSeriesRenderCache : public SeriesRenderCache
{
public:
- SurfaceSeriesRenderCache();
+ SurfaceSeriesRenderCache(QAbstract3DSeries *series, Surface3DRenderer *renderer);
virtual ~SurfaceSeriesRenderCache();
- void populate(QSurface3DSeries *series, Abstract3DRenderer *renderer);
+ virtual void populate(bool newSeries);
virtual void cleanup(TextureHelper *texHelper);
inline bool surfaceVisible() const { return m_surfaceVisible; }
@@ -58,8 +55,6 @@ public:
inline bool isFlatShadingEnabled() const { return m_surfaceFlatShading; }
inline void setFlatShadingEnabled(bool enabled) { m_surfaceFlatShading = enabled; }
inline void setFlatChangeAllowed(bool allowed) { m_flatChangeAllowed = allowed; }
- inline void setValid(bool valid) { m_valid = valid; }
- inline bool isValid() const { return m_valid; }
inline SurfaceObject *surfaceObject() { return m_surfaceObj; }
inline SurfaceObject *sliceSurfaceObject() { return m_sliceSurfaceObj; }
inline const QRect &sampleSpace() const { return m_sampleSpace; }
@@ -67,11 +62,8 @@ public:
inline QSurface3DSeries *series() const { return static_cast<QSurface3DSeries *>(m_series); }
inline QSurfaceDataArray &dataArray() { return m_dataArray; }
inline QSurfaceDataArray &sliceDataArray() { return m_sliceDataArray; }
- inline bool isSeriesVisible() const { return m_series->isVisible(); }
- inline bool renderable() const { return m_series->isVisible() && (m_surfaceVisible ||
- m_surfaceGridVisible); }
- inline void setObjectDirty(bool state) { m_objectDirty = state; }
- inline bool objectDirty() const { return m_objectDirty; }
+ inline bool renderable() const { return m_visible && (m_surfaceVisible ||
+ m_surfaceGridVisible); }
inline void setSelectionTexture(GLuint texture) { m_selectionTexture = texture; }
inline GLuint selectionTexture() const { return m_selectionTexture; }
inline void setSelectionIdRange(uint start, uint end) { m_selectionIdStart = start;
@@ -81,11 +73,6 @@ public:
selection <= m_selectionIdEnd; }
inline bool isFlatStatusDirty() const { return m_flatStatusDirty; }
inline void setFlatStatusDirty(bool status) { m_flatStatusDirty = status; }
- inline void setScale(const QVector3D &scale) { m_scale = scale; }
- inline const QVector3D &scale() const { return m_scale; }
- inline void setOffset(const QVector3D &offset) { m_offset = offset; }
- inline const QVector3D &offset() const { return m_offset; }
- // m_MVPMatrix is volatile, used only for optimizing rendering a bit
inline void setMVPMatrix(const QMatrix4x4 &matrix) { m_MVPMatrix = matrix; }
inline const QMatrix4x4 &MVPMatrix() { return m_MVPMatrix; }
@@ -113,16 +100,11 @@ protected:
uint m_selectionIdEnd;
bool m_flatChangeAllowed;
bool m_flatStatusDirty;
- QVector3D m_scale;
- QVector3D m_offset;
QMatrix4x4 m_MVPMatrix;
SelectionPointer *m_sliceSelectionPointer;
SelectionPointer *m_mainSelectionPointer;
bool m_slicePointerActive;
bool m_mainPointerActive;
-
- bool m_valid;
- bool m_objectDirty;
};
QT_END_NAMESPACE_DATAVISUALIZATION