summaryrefslogtreecommitdiffstats
path: root/src/datavisualization/engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/datavisualization/engine')
-rw-r--r--src/datavisualization/engine/abstract3dcontroller.cpp3
-rw-r--r--src/datavisualization/engine/abstract3dcontroller_p.h5
-rw-r--r--src/datavisualization/engine/abstract3drenderer.cpp38
-rw-r--r--src/datavisualization/engine/abstract3drenderer_p.h11
-rw-r--r--src/datavisualization/engine/axisrendercache.cpp5
-rw-r--r--src/datavisualization/engine/bars3dcontroller.cpp34
-rw-r--r--src/datavisualization/engine/bars3dcontroller_p.h8
-rw-r--r--src/datavisualization/engine/bars3drenderer.cpp142
-rw-r--r--src/datavisualization/engine/bars3drenderer_p.h3
-rw-r--r--src/datavisualization/engine/drawer.cpp12
-rw-r--r--src/datavisualization/engine/drawer_p.h4
-rw-r--r--src/datavisualization/engine/engine.pri10
-rw-r--r--src/datavisualization/engine/q3dbars.cpp13
-rw-r--r--src/datavisualization/engine/q3dbars.h15
-rw-r--r--src/datavisualization/engine/q3dbox.cpp485
-rw-r--r--src/datavisualization/engine/q3dbox.h158
-rw-r--r--src/datavisualization/engine/q3dcamera.cpp514
-rw-r--r--src/datavisualization/engine/q3dcamera.h43
-rw-r--r--src/datavisualization/engine/q3dcamera_p.h31
-rw-r--r--src/datavisualization/engine/q3dlight.h1
-rw-r--r--src/datavisualization/engine/q3dobject.h10
-rw-r--r--src/datavisualization/engine/q3dscatter.cpp12
-rw-r--r--src/datavisualization/engine/q3dscatter.h12
-rw-r--r--src/datavisualization/engine/q3dscene.cpp38
-rw-r--r--src/datavisualization/engine/q3dscene.h27
-rw-r--r--src/datavisualization/engine/q3dscene_p.h6
-rw-r--r--src/datavisualization/engine/q3dsurface.cpp23
-rw-r--r--src/datavisualization/engine/q3dsurface.h10
-rw-r--r--src/datavisualization/engine/q3dsurface_p.h2
-rw-r--r--src/datavisualization/engine/qabstract3dgraph.cpp19
-rw-r--r--src/datavisualization/engine/qabstract3dgraph.h16
-rw-r--r--src/datavisualization/engine/qabstract3dgraph_p.h2
-rw-r--r--src/datavisualization/engine/scatter3dcontroller.cpp8
-rw-r--r--src/datavisualization/engine/scatter3dcontroller_p.h5
-rw-r--r--src/datavisualization/engine/scatter3drenderer.cpp38
-rw-r--r--src/datavisualization/engine/scatter3drenderer_p.h4
-rw-r--r--src/datavisualization/engine/selectionpointer.cpp12
-rw-r--r--src/datavisualization/engine/selectionpointer_p.h2
-rw-r--r--src/datavisualization/engine/seriesrendercache.cpp18
-rw-r--r--src/datavisualization/engine/seriesrendercache_p.h4
-rw-r--r--src/datavisualization/engine/surface3dcontroller.cpp140
-rw-r--r--src/datavisualization/engine/surface3dcontroller_p.h22
-rw-r--r--src/datavisualization/engine/surface3drenderer.cpp1316
-rw-r--r--src/datavisualization/engine/surface3drenderer_p.h57
-rw-r--r--src/datavisualization/engine/surfaceseriesrendercache.cpp91
-rw-r--r--src/datavisualization/engine/surfaceseriesrendercache_p.h130
46 files changed, 1705 insertions, 1854 deletions
diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp
index 4989ddb5..d2b59c58 100644
--- a/src/datavisualization/engine/abstract3dcontroller.cpp
+++ b/src/datavisualization/engine/abstract3dcontroller.cpp
@@ -32,8 +32,7 @@
#include "q3dtheme_p.h"
#include "q3dscene_p.h"
#include "q3dscene.h"
-
-#include <QThread>
+#include <QtCore/QThread>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/abstract3dcontroller_p.h b/src/datavisualization/engine/abstract3dcontroller_p.h
index cac46ddf..f9b6588d 100644
--- a/src/datavisualization/engine/abstract3dcontroller_p.h
+++ b/src/datavisualization/engine/abstract3dcontroller_p.h
@@ -35,10 +35,7 @@
#include "qabstract3dinputhandler.h"
#include "qabstractdataproxy.h"
#include "q3dscene_p.h"
-#include "q3dbox.h"
-
-#include <QObject>
-#include <QLinearGradient>
+#include <QtGui/QLinearGradient>
class QFont;
diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp
index 7824000e..3122cf76 100644
--- a/src/datavisualization/engine/abstract3drenderer.cpp
+++ b/src/datavisualization/engine/abstract3drenderer.cpp
@@ -44,7 +44,8 @@ Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller)
m_devicePixelRatio(1.0f),
m_selectionLabelDirty(true),
m_clickPending(false),
- m_clickedSeries(0)
+ m_clickedSeries(0),
+ m_selectionLabelItem(0)
#ifdef DISPLAY_RENDER_SPEED
, m_isFirstFrame(true),
m_numFrames(0)
@@ -67,6 +68,7 @@ Abstract3DRenderer::~Abstract3DRenderer()
delete m_textureHelper;
delete m_cachedScene;
delete m_cachedTheme;
+ delete m_selectionLabelItem;
}
void Abstract3DRenderer::initializeOpenGL()
@@ -188,7 +190,7 @@ void Abstract3DRenderer::updateScene(Q3DScene *scene)
scene->activeCamera()->d_ptr->updateViewMatrix(m_autoScaleAdjustment);
// Set light position (rotate light with activeCamera, a bit above it (as set in defaultLightPos))
- scene->setLightPositionRelativeToCamera(defaultLightPos);
+ scene->d_ptr->setLightPositionRelativeToCamera(defaultLightPos);
QPoint logicalPixelPosition = scene->selectionQueryPosition();
updateInputPosition(QPoint(logicalPixelPosition.x() * m_devicePixelRatio,
@@ -426,8 +428,17 @@ void Abstract3DRenderer::lowerShadowQuality()
updateShadowQuality(newQuality);
}
-void Abstract3DRenderer::fixGradientAndGenerateTexture(QLinearGradient *gradient,
- GLuint *gradientTexture)
+void Abstract3DRenderer::generateBaseColorTexture(const QColor &color, GLuint *texture)
+{
+ if (*texture) {
+ m_textureHelper->deleteTexture(texture);
+ *texture = 0;
+ }
+
+ *texture = m_textureHelper->createUniformTexture(color);
+}
+
+void Abstract3DRenderer::fixGradientAndGenerateTexture(QLinearGradient *gradient, GLuint *gradientTexture)
{
// Readjust start/stop to match gradient texture size
gradient->setStart(qreal(gradientTextureWidth), qreal(gradientTextureHeight));
@@ -441,4 +452,23 @@ void Abstract3DRenderer::fixGradientAndGenerateTexture(QLinearGradient *gradient
*gradientTexture = m_textureHelper->createGradientTexture(*gradient);
}
+LabelItem &Abstract3DRenderer::selectionLabelItem()
+{
+ if (!m_selectionLabelItem)
+ m_selectionLabelItem = new LabelItem;
+ return *m_selectionLabelItem;
+}
+
+void Abstract3DRenderer::setSelectionLabel(const QString &label)
+{
+ if (m_selectionLabelItem)
+ m_selectionLabelItem->clear();
+ m_selectionLabel = label;
+}
+
+QString &Abstract3DRenderer::selectionLabel()
+{
+ return m_selectionLabel;
+}
+
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h
index e7591a10..4eb8426f 100644
--- a/src/datavisualization/engine/abstract3drenderer_p.h
+++ b/src/datavisualization/engine/abstract3drenderer_p.h
@@ -33,7 +33,7 @@
#include <QtGui/QOpenGLFunctions>
#ifdef DISPLAY_RENDER_SPEED
-#include <QTime>
+#include <QtCore/QTime>
#endif
#include "datavisualizationglobal_p.h"
@@ -94,12 +94,17 @@ public:
virtual void updateAxisLabelFormat(QAbstract3DAxis::AxisOrientation orientation, const QString &format);
virtual void fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh mesh);
+ 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; }
+ LabelItem &selectionLabelItem();
+ void setSelectionLabel(const QString &label);
+ QString &selectionLabel();
+
signals:
void needRender(); // Emit this if something in renderer causes need for another render pass.
void requestShadowQuality(QAbstract3DGraph::ShadowQuality quality); // For automatic quality adjustments
@@ -132,7 +137,6 @@ protected:
AxisRenderCache m_axisCacheY;
AxisRenderCache m_axisCacheZ;
TextureHelper *m_textureHelper;
- Q3DBox m_boundingBox;
Q3DScene *m_cachedScene;
bool m_selectionDirty;
@@ -146,6 +150,9 @@ protected:
bool m_clickPending;
QAbstract3DSeries *m_clickedSeries;
+ QString m_selectionLabel;
+ LabelItem *m_selectionLabelItem;
+
#ifdef DISPLAY_RENDER_SPEED
bool m_isFirstFrame;
QTime m_lastFrameTime;
diff --git a/src/datavisualization/engine/axisrendercache.cpp b/src/datavisualization/engine/axisrendercache.cpp
index c1c2d5bd..a107dd23 100644
--- a/src/datavisualization/engine/axisrendercache.cpp
+++ b/src/datavisualization/engine/axisrendercache.cpp
@@ -17,8 +17,9 @@
****************************************************************************/
#include "axisrendercache_p.h"
-#include "qmath.h"
-#include <QFontMetrics>
+
+#include <QtCore/qmath.h>
+#include <QtGui/QFontMetrics>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/bars3dcontroller.cpp b/src/datavisualization/engine/bars3dcontroller.cpp
index 5bd37ccf..442601eb 100644
--- a/src/datavisualization/engine/bars3dcontroller.cpp
+++ b/src/datavisualization/engine/bars3dcontroller.cpp
@@ -27,8 +27,8 @@
#include "thememanager_p.h"
#include "q3dtheme_p.h"
-#include <QMatrix4x4>
-#include <qmath.h>
+#include <QtGui/QMatrix4x4>
+#include <QtCore/qmath.h>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -109,7 +109,7 @@ void Bars3DController::handleArrayReset()
m_isDataDirty = true;
}
// Clear selection unless still valid
- setSelectedBar(m_selectedBar, m_selectedBarSeries);
+ setSelectedBar(m_selectedBar, m_selectedBarSeries, false);
emitNeedRender();
}
@@ -152,7 +152,7 @@ void Bars3DController::handleRowsRemoved(int startIndex, int count)
else
selectedRow -= count; // Move selected row down by amount of rows removed
- setSelectedBar(QPoint(selectedRow, m_selectedBar.y()), m_selectedBarSeries);
+ setSelectedBar(QPoint(selectedRow, m_selectedBar.y()), m_selectedBarSeries, false);
}
}
@@ -174,7 +174,7 @@ void Bars3DController::handleRowsInserted(int startIndex, int count)
int selectedRow = m_selectedBar.x();
if (startIndex <= selectedRow) {
selectedRow += count;
- setSelectedBar(QPoint(selectedRow, m_selectedBar.y()), m_selectedBarSeries);
+ setSelectedBar(QPoint(selectedRow, m_selectedBar.y()), m_selectedBarSeries, false);
}
}
@@ -240,9 +240,9 @@ void Bars3DController::handleSeriesVisibilityChangedBySender(QObject *sender)
adjustAxisRanges();
- // Visibility changes may require disabling/enabling slicing,
+ // Visibility changes may require disabling slicing,
// so just reset selection to ensure everything is still valid.
- setSelectedBar(m_selectedBar, m_selectedBarSeries);
+ setSelectedBar(m_selectedBar, m_selectedBarSeries, false);
}
void Bars3DController::handlePendingClick()
@@ -251,7 +251,7 @@ void Bars3DController::handlePendingClick()
QPoint position = m_renderer->clickedPosition();
QBar3DSeries *series = static_cast<QBar3DSeries *>(m_renderer->clickedSeries());
- setSelectedBar(position, series);
+ setSelectedBar(position, series, true);
m_renderer->resetClickedStatus();
}
@@ -309,7 +309,7 @@ void Bars3DController::removeSeries(QAbstract3DSeries *series)
Abstract3DController::removeSeries(series);
if (m_selectedBarSeries == series)
- setSelectedBar(invalidSelectionPosition(), 0);
+ setSelectedBar(invalidSelectionPosition(), 0, false);
if (wasVisible)
adjustAxisRanges();
@@ -348,7 +348,7 @@ void Bars3DController::insertSeries(int index, QAbstract3DSeries *series)
}
if (barSeries->selectedBar() != invalidSelectionPosition())
- setSelectedBar(barSeries->selectedBar(), barSeries);
+ setSelectedBar(barSeries->selectedBar(), barSeries, false);
if (!oldSize)
emit primarySeriesChanged(m_primarySeries);
@@ -381,7 +381,7 @@ void Bars3DController::handleAxisRangeChangedBySender(QObject *sender)
Abstract3DController::handleAxisRangeChangedBySender(sender);
// Update selected bar - may be moved offscreen
- setSelectedBar(m_selectedBar, m_selectedBarSeries);
+ setSelectedBar(m_selectedBar, m_selectedBarSeries, false);
}
void Bars3DController::setMultiSeriesScaling(bool uniform)
@@ -436,7 +436,7 @@ void Bars3DController::setSelectionMode(QAbstract3DGraph::SelectionFlags mode)
if (mode != oldMode) {
// Refresh selection upon mode change to ensure slicing is correctly updated
// according to series the visibility.
- setSelectedBar(m_selectedBar, m_selectedBarSeries);
+ setSelectedBar(m_selectedBar, m_selectedBarSeries, true);
// Special case: Always deactivate slicing when changing away from slice
// automanagement, as this can't be handled in setSelectedBar.
@@ -448,7 +448,7 @@ void Bars3DController::setSelectionMode(QAbstract3DGraph::SelectionFlags mode)
}
}
-void Bars3DController::setSelectedBar(const QPoint &position, QBar3DSeries *series)
+void Bars3DController::setSelectedBar(const QPoint &position, QBar3DSeries *series, bool enterSlice)
{
// If the selection targets non-existent bar, clear selection instead.
QPoint pos = position;
@@ -465,13 +465,14 @@ void Bars3DController::setSelectedBar(const QPoint &position, QBar3DSeries *seri
|| pos.y() < m_axisX->min() || pos.y() > m_axisX->max()
|| !series->isVisible()) {
scene()->setSlicingActive(false);
- } else {
+ } else if (enterSlice) {
scene()->setSlicingActive(true);
}
emitNeedRender();
}
if (pos != m_selectedBar || series != m_selectedBarSeries) {
+ bool seriesChanged = (series != m_selectedBarSeries);
m_selectedBar = pos;
m_selectedBarSeries = series;
m_changeTracker.selectedBarChanged = true;
@@ -485,13 +486,16 @@ void Bars3DController::setSelectedBar(const QPoint &position, QBar3DSeries *seri
if (m_selectedBarSeries)
m_selectedBarSeries->dptr()->setSelectedBar(m_selectedBar);
+ if (seriesChanged)
+ emit selectedSeriesChanged(m_selectedBarSeries);
+
emitNeedRender();
}
}
void Bars3DController::clearSelection()
{
- setSelectedBar(invalidSelectionPosition(), 0);
+ setSelectedBar(invalidSelectionPosition(), 0, false);
}
void Bars3DController::adjustAxisRanges()
diff --git a/src/datavisualization/engine/bars3dcontroller_p.h b/src/datavisualization/engine/bars3dcontroller_p.h
index e704aea1..9ea59c89 100644
--- a/src/datavisualization/engine/bars3dcontroller_p.h
+++ b/src/datavisualization/engine/bars3dcontroller_p.h
@@ -94,11 +94,14 @@ public:
QSizeF barSpacing();
bool isBarSpecRelative();
+ inline QBar3DSeries *selectedSeries() const { return m_selectedBarSeries; }
+
void setSelectionMode(QAbstract3DGraph::SelectionFlags mode);
- void setSelectedBar(const QPoint &position, QBar3DSeries *series);
+ void setSelectedBar(const QPoint &position, QBar3DSeries *series, bool enterSlice);
virtual void clearSelection();
- virtual void handleAxisAutoAdjustRangeChangedInOrientation(QAbstract3DAxis::AxisOrientation orientation, bool autoAdjust);
+ virtual void handleAxisAutoAdjustRangeChangedInOrientation(
+ QAbstract3DAxis::AxisOrientation orientation, bool autoAdjust);
virtual void handleSeriesVisibilityChangedBySender(QObject *sender);
virtual void handlePendingClick();
@@ -128,6 +131,7 @@ public slots:
signals:
void primarySeriesChanged(QBar3DSeries *series);
+ void selectedSeriesChanged(QBar3DSeries *series);
protected:
virtual QAbstract3DAxis *createDefaultAxis(QAbstract3DAxis::AxisOrientation orientation);
diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp
index 664dbabd..be1be0dc 100644
--- a/src/datavisualization/engine/bars3drenderer.cpp
+++ b/src/datavisualization/engine/bars3drenderer.cpp
@@ -28,11 +28,10 @@
#include "q3dlight.h"
#include "qbar3dseries_p.h"
-#include <QMatrix4x4>
-#include <QMouseEvent>
-#include <QThread>
-#include <qmath.h>
-#include <QDebug>
+#include <QtGui/QMatrix4x4>
+#include <QtGui/QMouseEvent>
+#include <QtCore/QThread>
+#include <QtCore/qmath.h>
// You can verify that depth buffer drawing works correctly by uncommenting this.
// You should see the scene from where the light is
@@ -44,7 +43,6 @@ const GLfloat labelMargin = 0.05f;
const GLfloat gridLineWidth = 0.005f;
const bool sliceGridLabels = true;
-const QQuaternion identityQuaternion;
Bars3DRenderer::Bars3DRenderer(Bars3DController *controller)
: Abstract3DRenderer(controller),
@@ -168,7 +166,6 @@ void Bars3DRenderer::updateData()
m_seriesStart = -((float(seriesCount) - 1.0f) / 2.0f) * m_seriesStep;
}
-
if (m_keepSeriesUniform)
m_seriesScaleZ = m_seriesScaleX;
else
@@ -259,30 +256,18 @@ void Bars3DRenderer::updateData()
updateSelectedBar(m_selectedBarPos, m_selectedBarSeries);
}
-void Bars3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility)
-{
- Abstract3DRenderer::updateSeries(seriesList, updateVisibility);
-
- // Fix the series rotations - ignore any rotations that are not along Y-axis
- for (int series = 0; series < m_visibleSeriesList.size(); series++) {
- QVector3D vector = m_visibleSeriesList.at(series).meshRotation().vector();
- if (vector.x() || vector.z())
- m_visibleSeriesList[series].setMeshRotation(identityQuaternion);
- }
-}
-
void Bars3DRenderer::updateScene(Q3DScene *scene)
{
if (m_hasNegativeValues)
- scene->activeCamera()->setMinYRotation(-90.0);
+ scene->activeCamera()->d_ptr->setMinYRotation(-90.0);
else
- scene->activeCamera()->setMinYRotation(0.0f);
+ scene->activeCamera()->d_ptr->setMinYRotation(0.0f);
if (m_hasHeightAdjustmentChanged) {
// Set initial camera position. Also update if height adjustment has changed.
- scene->activeCamera()->setBaseOrientation(cameraDistanceVector,
- zeroVector,
- upVector);
+ scene->activeCamera()->d_ptr->setBaseOrientation(cameraDistanceVector,
+ zeroVector,
+ upVector);
m_hasHeightAdjustmentChanged = false;
}
@@ -499,14 +484,14 @@ void Bars3DRenderer::drawSlicedScene()
int sliceItemCount = m_sliceSelection.size();
for (int bar = 0; bar < sliceItemCount; bar++) {
- BarRenderItem *item = m_sliceSelection.at(bar);
- if (!item)
+ const BarRenderSliceItem &item = m_sliceSelection.at(bar);
+ if (!item.value())
continue;
QQuaternion seriesRotation;
- if (item->seriesIndex() != currentSeriesIndex) {
- currentSeriesIndex = item->seriesIndex();
+ if (item.seriesIndex() != currentSeriesIndex) {
+ currentSeriesIndex = item.seriesIndex();
currentSeries = &(m_visibleSeriesList.at(currentSeriesIndex));
barObj = currentSeries->object();
colorStyle = currentSeries->colorStyle();
@@ -538,7 +523,7 @@ void Bars3DRenderer::drawSlicedScene()
seriesRotation = currentSeries->meshRotation();
}
- if (item->height() < 0)
+ if (item.height() < 0)
glCullFace(GL_FRONT);
else
glCullFace(GL_BACK);
@@ -546,18 +531,18 @@ void Bars3DRenderer::drawSlicedScene()
QMatrix4x4 MVPMatrix;
QMatrix4x4 modelMatrix;
QMatrix4x4 itModelMatrix;
- QQuaternion barRotation = item->rotation();
- GLfloat barPosY = item->translation().y() + barPosYAdjustment - zeroPosAdjustment;
+ QQuaternion barRotation = item.rotation();
+ GLfloat barPosY = item.translation().y() + barPosYAdjustment - zeroPosAdjustment;
if (rowMode) {
- barPosX = item->translation().x();
+ barPosX = item.translation().x();
} else {
- barPosX = -(item->translation().z()); // flip z; frontmost bar to the left
+ barPosX = -(item.translation().z()); // flip z; frontmost bar to the left
barRotation *= ninetyDegreeRotation;
}
modelMatrix.translate(barPosX, barPosY, 0.0f);
- modelMatrixScaler.setY(item->height());
+ modelMatrixScaler.setY(item.height());
if (!seriesRotation.isIdentity())
barRotation *= seriesRotation;
@@ -575,8 +560,8 @@ void Bars3DRenderer::drawSlicedScene()
QVector3D barColor;
GLuint gradientTexture = 0;
- if (itemMode && m_visualSelectedBarPos.x() == item->position().x()
- && m_visualSelectedBarPos.y() == item->position().y()) {
+ if (itemMode && m_visualSelectedBarPos.x() == item.position().x()
+ && m_visualSelectedBarPos.y() == item.position().y()) {
if (colorStyleIsUniform)
barColor = highlightColor;
else
@@ -588,7 +573,7 @@ void Bars3DRenderer::drawSlicedScene()
gradientTexture = baseGradientTexture;
}
- if (item->height() != 0) {
+ if (item.height() != 0) {
// Set shader bindings
barShader->setUniformValue(barShader->model(), modelMatrix);
barShader->setUniformValue(barShader->nModel(),
@@ -598,7 +583,7 @@ void Bars3DRenderer::drawSlicedScene()
barShader->setUniformValue(barShader->color(), barColor);
} else if (colorStyle == Q3DTheme::ColorStyleRangeGradient) {
barShader->setUniformValue(barShader->gradientHeight(),
- (qAbs(item->height()) / m_gradientFraction));
+ (qAbs(item.height()) / m_gradientFraction));
}
// Draw the object
@@ -628,10 +613,10 @@ void Bars3DRenderer::drawSlicedScene()
for (int labelNo = 0; labelNo <= lastLabel; labelNo++) {
// Get labels from first series only
- BarRenderItem *item = m_sliceSelection.at(labelNo);
- m_dummyBarRenderItem.setTranslation(QVector3D(item->translation().x(),
+ const BarRenderSliceItem &item = m_sliceSelection.at(labelNo);
+ m_dummyBarRenderItem.setTranslation(QVector3D(item.translation().x(),
barLabelYPos,
- item->translation().z()));
+ item.translation().z()));
// Draw labels
m_drawer->drawLabel(m_dummyBarRenderItem, *m_sliceCache->labelItems().at(labelNo),
viewMatrix, projectionMatrix, positionComp, sliceLabelRotation,
@@ -641,53 +626,53 @@ void Bars3DRenderer::drawSlicedScene()
}
for (int col = 0; col < sliceItemCount; col++) {
- BarRenderItem *item = m_sliceSelection.at(col);
+ BarRenderSliceItem &item = m_sliceSelection[col];
if (!sliceGridLabels) {
// Draw values
- if (item->height() != 0.0f || (!m_noZeroInRange && item->value() == 0.0f)) {
+ 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());
+ 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(),
+ 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()));
+ + item.height(),
+ item.translation().z()));
- m_drawer->drawLabel(m_dummyBarRenderItem, item->sliceLabelItem(), viewMatrix,
+ m_drawer->drawLabel(m_dummyBarRenderItem, item.sliceLabelItem(), viewMatrix,
projectionMatrix, zeroVector, sliceValueRotation,
- item->height(), m_cachedSelectionMode, m_labelShader,
+ 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) {
+ 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());
+ 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(),
+ 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()));
+ + item.height(),
+ item.translation().z()));
- m_drawer->drawLabel(m_dummyBarRenderItem, item->sliceLabelItem(), viewMatrix,
+ m_drawer->drawLabel(m_dummyBarRenderItem, item.sliceLabelItem(), viewMatrix,
projectionMatrix, zeroVector, sliceValueRotation,
- item->height(), m_cachedSelectionMode, m_labelShader,
+ item.height(), m_cachedSelectionMode, m_labelShader,
m_labelObj, activeCamera, false, false, labelPos,
alignment, true);
}
@@ -767,7 +752,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
projectionMatrix.perspective(45.0f, viewPortRatio, 0.1f, 100.0f);
// Get the view matrix
- QMatrix4x4 viewMatrix = activeCamera->viewMatrix();
+ QMatrix4x4 viewMatrix = activeCamera->d_ptr->viewMatrix();
// Calculate drawing order
// Draw order is reversed to optimize amount of drawing (ie. draw front objects first,
@@ -842,7 +827,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
// Get the depth view matrix
// It may be possible to hack lightPos here if we want to make some tweaks to shadow
- QVector3D depthLightPos = activeCamera->calculatePositionRelativeToCamera(
+ QVector3D depthLightPos = activeCamera->d_ptr->calculatePositionRelativeToCamera(
zeroVector, 0.0f, 3.5f / m_autoScaleAdjustment);
depthViewMatrix.lookAt(depthLightPos, zeroVector, upVector);
@@ -1213,9 +1198,9 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
item.setPosition(QPoint(row, bar));
item.setSeriesIndex(series);
if (rowMode)
- m_sliceSelection[sliceSeriesAdjust + bar] = &item;
+ m_sliceSelection[sliceSeriesAdjust + bar].setItem(item);
else
- m_sliceSelection[sliceSeriesAdjust + row] = &item;
+ m_sliceSelection[sliceSeriesAdjust + row].setItem(item);
}
break;
}
@@ -1235,7 +1220,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
item.setSeriesIndex(series);
if (!m_sliceTitleItem && m_axisCacheZ.labelItems().size() > row)
m_sliceTitleItem = m_axisCacheZ.labelItems().at(row);
- m_sliceSelection[sliceSeriesAdjust + bar] = &item;
+ m_sliceSelection[sliceSeriesAdjust + bar].setItem(item);
}
}
break;
@@ -1262,7 +1247,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
item.setSeriesIndex(series);
if (!m_sliceTitleItem && m_axisCacheX.labelItems().size() > bar)
m_sliceTitleItem = m_axisCacheX.labelItems().at(bar);
- m_sliceSelection[sliceSeriesAdjust + row] = &item;
+ m_sliceSelection[sliceSeriesAdjust + row].setItem(item);
}
}
break;
@@ -1304,6 +1289,8 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
// Draw the object
m_drawer->drawObject(barShader, barObj, gradientTexture, m_depthTexture);
} else
+#else
+ Q_UNUSED(shadowLightStrength);
#endif
{
// Set shadowless shader bindings
@@ -1816,10 +1803,10 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
// Print value of selected bar
glDisable(GL_DEPTH_TEST);
// Draw the selection label
- LabelItem &labelItem = selectedBar->selectionLabelItem();
+ LabelItem &labelItem = selectionLabelItem();
if (m_selectedBar != selectedBar || m_updateLabels || !labelItem.textureId()
|| m_selectionLabelDirty) {
- QString labelText = selectedBar->selectionLabel();
+ QString labelText = selectionLabel();
if (labelText.isNull() || m_selectionLabelDirty) {
static const QString rowIndexTag(QStringLiteral("@rowIdx"));
static const QString rowLabelTag(QStringLiteral("@rowLabel"));
@@ -1863,7 +1850,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
labelText.replace(seriesNameTag,
m_visibleSeriesList[m_visualSelectedBarSeriesIndex].name());
- selectedBar->setSelectionLabel(labelText);
+ setSelectionLabel(labelText);
m_selectionLabelDirty = false;
}
m_drawer->generateLabelItem(labelItem, labelText);
@@ -1954,6 +1941,7 @@ void Bars3DRenderer::updateSelectedBar(const QPoint &position, const QBar3DSerie
m_selectedBarPos = position;
m_selectedBarSeries = series;
m_selectionDirty = true;
+ m_selectionLabelDirty = true;
m_visualSelectedBarSeriesIndex = -1;
if (m_renderingArrays.isEmpty()) {
diff --git a/src/datavisualization/engine/bars3drenderer_p.h b/src/datavisualization/engine/bars3drenderer_p.h
index e53f9bc5..37ac2b76 100644
--- a/src/datavisualization/engine/bars3drenderer_p.h
+++ b/src/datavisualization/engine/bars3drenderer_p.h
@@ -60,7 +60,7 @@ private:
// Internal state
BarRenderItem *m_selectedBar; // points to renderitem array
- QVector<BarRenderItem *> m_sliceSelection;
+ QVector<BarRenderSliceItem> m_sliceSelection;
AxisRenderCache *m_sliceCache; // not owned
const LabelItem *m_sliceTitleItem; // not owned
bool m_xFlipped;
@@ -114,7 +114,6 @@ public:
~Bars3DRenderer();
void updateData();
- void updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility);
void updateScene(Q3DScene *scene);
void render(GLuint defaultFboHandle = 0);
diff --git a/src/datavisualization/engine/drawer.cpp b/src/datavisualization/engine/drawer.cpp
index dd82eadc..55a2c2a5 100644
--- a/src/datavisualization/engine/drawer.cpp
+++ b/src/datavisualization/engine/drawer.cpp
@@ -24,8 +24,10 @@
#include "q3dcamera.h"
#include "utils_p.h"
#include "texturehelper_p.h"
-#include <QMatrix4x4>
-#include <qmath.h>
+#include "abstract3drenderer_p.h"
+
+#include <QtGui/QMatrix4x4>
+#include <QtCore/qmath.h>
// Resources need to be explicitly initialized when building as static library
class StaticLibInitializer
@@ -348,10 +350,10 @@ void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelIte
drawObject(shader, object, labelItem.textureId());
}
-void Drawer::generateSelectionLabelTexture(AbstractRenderItem *item)
+void Drawer::generateSelectionLabelTexture(Abstract3DRenderer *renderer)
{
- LabelItem &labelItem = item->selectionLabelItem();
- generateLabelItem(labelItem, item->selectionLabel());
+ LabelItem &labelItem = renderer->selectionLabelItem();
+ generateLabelItem(labelItem, renderer->selectionLabel());
}
void Drawer::generateLabelItem(LabelItem &item, const QString &text, int widestLabel)
diff --git a/src/datavisualization/engine/drawer_p.h b/src/datavisualization/engine/drawer_p.h
index 35a0a7ff..8e98aa3a 100644
--- a/src/datavisualization/engine/drawer_p.h
+++ b/src/datavisualization/engine/drawer_p.h
@@ -34,7 +34,6 @@
#include "q3dtheme.h"
#include "labelitem_p.h"
#include "abstractrenderitem_p.h"
-#include <QFont>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -44,6 +43,7 @@ class AbstractObjectHelper;
class SurfaceObject;
class TextureHelper;
class Q3DCamera;
+class Abstract3DRenderer;
class Drawer : public QObject, public QOpenGLFunctions
{
@@ -84,7 +84,7 @@ public:
LabelPosition position = LabelOver,
Qt::AlignmentFlag alignment = Qt::AlignCenter, bool isSlicing = false);
- void generateSelectionLabelTexture(AbstractRenderItem *item);
+ void generateSelectionLabelTexture(Abstract3DRenderer *item);
void generateLabelItem(LabelItem &item, const QString &text, int widestLabel = 0);
Q_SIGNALS:
diff --git a/src/datavisualization/engine/engine.pri b/src/datavisualization/engine/engine.pri
index e13a9a04..9c2e71e4 100644
--- a/src/datavisualization/engine/engine.pri
+++ b/src/datavisualization/engine/engine.pri
@@ -23,10 +23,10 @@ HEADERS += $$PWD/qabstract3dgraph_p.h \
$$PWD/q3dscene.h \
$$PWD/q3dlight.h \
$$PWD/q3dlight_p.h \
- $$PWD/q3dbox.h \
$$PWD/q3dobject.h \
$$PWD/q3dobject_p.h \
- $$PWD/q3dscene_p.h
+ $$PWD/q3dscene_p.h \
+ $$PWD/surfaceseriesrendercache_p.h
SOURCES += $$PWD/qabstract3dgraph.cpp \
$$PWD/q3dbars.cpp \
@@ -46,8 +46,10 @@ SOURCES += $$PWD/qabstract3dgraph.cpp \
$$PWD/selectionpointer.cpp \
$$PWD/q3dcamera.cpp \
$$PWD/q3dlight.cpp \
- $$PWD/q3dbox.cpp \
$$PWD/q3dobject.cpp \
- $$PWD/q3dscene.cpp
+ $$PWD/q3dscene.cpp \
+ $$PWD/surfaceseriesrendercache.cpp
RESOURCES += engine/engine.qrc
+
+OTHER_FILES += $$PWD/meshes/* $$PWD/shaders/*
diff --git a/src/datavisualization/engine/q3dbars.cpp b/src/datavisualization/engine/q3dbars.cpp
index 787033ad..7b37715f 100644
--- a/src/datavisualization/engine/q3dbars.cpp
+++ b/src/datavisualization/engine/q3dbars.cpp
@@ -104,6 +104,8 @@ Q3DBars::Q3DBars(const QSurfaceFormat *format, QWindow *parent)
dptr()->m_shared->initializeOpenGL();
QObject::connect(dptr()->m_shared, &Bars3DController::primarySeriesChanged,
this, &Q3DBars::primarySeriesChanged);
+ QObject::connect(dptr()->m_shared, &Bars3DController::selectedSeriesChanged,
+ this, &Q3DBars::selectedSeriesChanged);
}
/*!
@@ -328,6 +330,17 @@ QValue3DAxis *Q3DBars::valueAxis() const
}
/*!
+ * \property Q3DBars::selectedSeries
+ *
+ * The selected series or \c null. If selectionMode has \c SelectionMultiSeries flag set, this
+ * property holds the series which owns the selected bar.
+ */
+QBar3DSeries *Q3DBars::selectedSeries() const
+{
+ return dptrc()->m_shared->selectedSeries();
+}
+
+/*!
* Adds \a axis to the graph. The axes added via addAxis are not yet taken to use,
* addAxis is simply used to give the ownership of the \a axis to the graph.
* The \a axis must not be null or added to another graph.
diff --git a/src/datavisualization/engine/q3dbars.h b/src/datavisualization/engine/q3dbars.h
index 06dcfedb..7f9c981f 100644
--- a/src/datavisualization/engine/q3dbars.h
+++ b/src/datavisualization/engine/q3dbars.h
@@ -20,16 +20,13 @@
#define Q3DBARS_H
#include <QtDataVisualization/qabstract3dgraph.h>
-#include <QFont>
-#include <QLinearGradient>
+#include <QtDataVisualization/qvalue3daxis.h>
+#include <QtDataVisualization/qcategory3daxis.h>
+#include <QtDataVisualization/qbar3dseries.h>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
class Q3DBarsPrivate;
-class QAbstract3DAxis;
-class QCategory3DAxis;
-class QValue3DAxis;
-class QBar3DSeries;
class QT_DATAVISUALIZATION_EXPORT Q3DBars : public QAbstract3DGraph
{
@@ -42,6 +39,7 @@ class QT_DATAVISUALIZATION_EXPORT Q3DBars : public QAbstract3DGraph
Q_PROPERTY(QCategory3DAxis *columnAxis READ columnAxis WRITE setColumnAxis NOTIFY columnAxisChanged)
Q_PROPERTY(QValue3DAxis *valueAxis READ valueAxis WRITE setValueAxis NOTIFY valueAxisChanged)
Q_PROPERTY(QBar3DSeries *primarySeries READ primarySeries WRITE setPrimarySeries NOTIFY primarySeriesChanged)
+ Q_PROPERTY(QBar3DSeries *selectedSeries READ selectedSeries NOTIFY selectedSeriesChanged)
public:
explicit Q3DBars(const QSurfaceFormat *format = 0, QWindow *parent = 0);
@@ -76,15 +74,18 @@ public:
void releaseAxis(QAbstract3DAxis *axis);
QList<QAbstract3DAxis *> axes() const;
+ QBar3DSeries *selectedSeries() const;
+
signals:
void multiSeriesUniformChanged(bool uniform);
void barThicknessChanged(float thicknessRatio);
- void barSpacingChanged(QSizeF spacing);
+ void barSpacingChanged(const QSizeF &spacing);
void barSpacingRelativeChanged(bool relative);
void rowAxisChanged(QCategory3DAxis *axis);
void columnAxisChanged(QCategory3DAxis *axis);
void valueAxisChanged(QValue3DAxis *axis);
void primarySeriesChanged(QBar3DSeries *series);
+ void selectedSeriesChanged(QBar3DSeries *series);
private:
Q3DBarsPrivate *dptr();
diff --git a/src/datavisualization/engine/q3dbox.cpp b/src/datavisualization/engine/q3dbox.cpp
deleted file mode 100644
index c5caea75..00000000
--- a/src/datavisualization/engine/q3dbox.cpp
+++ /dev/null
@@ -1,485 +0,0 @@
-/****************************************************************************
-**
-** 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 "datavisualizationglobal_p.h"
-#include "q3dbox.h"
-#include <QtCore/QList>
-
-QT_BEGIN_NAMESPACE_DATAVISUALIZATION
-
-/*!
- \class Q3DBox
- \inmodule QtDataVisualization
- \brief The Q3DBox class represents an axis-aligned box in 3D space.
- \since Qt Data Visualization 1.0
-
- Q3DBox can be used to represent the bounding box of objects in a 3D
- scene so that they can be easily culled if they are out of view.
-
- The sides of the box are always aligned with the x, y, and z axes of
- the world co-ordinate system. Transforming a box with transformed()
- will result in the smallest axis-aligned bounding box that contains
- the transformed box.
-
- Boxes may be null, finite, or infinite. A null box does not occupy
- any space and does not intersect with any other box. A finite
- box consists of a minimum() and maximum() extent in 3D space.
- An infinite box encompasses all points in 3D space.
-
- The extents of a finite box are also included within the box.
- A box with minimum() and maximum() set to the same value
- contains a single point.
-*/
-
-/*!
- \fn Q3DBox::Q3DBox()
-
- Constructs a null box in 3D space.
-
- \sa isNull()
-*/
-
-/*!
- \fn Q3DBox::Q3DBox(const QVector3D& corner1, const QVector3D& corner2)
-
- Constructs a finite box in 3D space from \a corner1 to \a corner2.
- The minimum() and maximum() co-ordinates of the new box are set
- to the minimum and maximum x, y, and z values from \a corner1 and
- \a corner2. The \a corner1 and \a corner2 values can be any two
- opposite corners that define the box.
-
- \sa isFinite(), minimum(), maximum()
-*/
-
-/*!
- \fn bool Q3DBox::isNull() const
-
- Returns true if this box is null; false otherwise.
-
- \sa isFinite(), isInfinite(), setToNull()
-*/
-
-/*!
- \fn bool Q3DBox::isFinite() const
-
- Returns true if this box is finite in size; false otherwise.
-
- \sa isNull(), isInfinite(), setExtents()
-*/
-
-/*!
- \fn bool Q3DBox::isInfinite() const
-
- Returns true if this box is infinite in size; false otherwise.
-
- \sa isNull(), isFinite(), setToInfinite()
-*/
-
-/*!
- \fn QVector3D Q3DBox::minimum() const
-
- Returns the minimum corner of this box.
-
- \sa maximum(), setExtents()
-*/
-
-/*!
- \fn QVector3D Q3DBox::maximum() const
-
- Returns the maximum corner of this box.
-
- \sa minimum(), setExtents()
-*/
-
-/*!
- \fn void Q3DBox::setExtents(const QVector3D& corner1, const QVector3D& corner2)
-
- Sets the extents of this box to a finite region from \a corner1 to
- \a corner2. The minimum() and maximum() co-ordinates of the box are
- set to the minimum and maximum x, y, and z values from \a corner1 and
- \a corner2. The \a corner1 and \a corner2 values can be any two
- opposite corners that define the box.
-
- \sa minimum(), maximum()
-*/
-
-/*!
- \fn void Q3DBox::setToNull()
-
- Sets this box to null.
-
- \sa isNull()
-*/
-
-/*!
- \fn void Q3DBox::setToInfinite()
-
- Sets this box to be infinite in size.
-
- \sa isInfinite()
-*/
-
-/*!
- \fn QVector3D Q3DBox::size() const
-
- Returns the finite size of this box. If this box is null or
- infinite, the returned value will be zero.
-
- \sa center(), isNull(), isInfinite()
-*/
-
-/*!
- \fn QVector3D Q3DBox::center() const
-
- Returns the finite center of this box. If this box is null
- or infinite, the returned value will be zero.
-
- \sa size(), isNull(), isInfinite()
-*/
-
-/*!
- \fn bool Q3DBox::contains(const QVector3D& point) const
-
- Returns true if this box contains \a point; false otherwise.
- Null boxes do not contain any points and infinite boxes contain
- all points.
-
- Containment is not a strict test: the point is contained if it
- lies on one of the faces of the box.
-
- \sa intersects()
-*/
-
-/*!
- \fn bool Q3DBox::contains(const Q3DBox& box) const
-
- Returns true if this box completely contains \a box. If this box
- is null, then it will not contain \a box. If this box is infinite,
- and \a box is not null, then \a box will be contained within this box.
- If \a box is infinite, then this box must also be infinite to contain it.
-
- \sa intersects()
-*/
-
-/*!
- Returns true if \a box intersects this box; false otherwise.
-
- \sa intersect(), intersected(), contains()
-*/
-bool Q3DBox::intersects(const Q3DBox& box) const
-{
- if (boxtype == Null)
- return false;
- else if (boxtype == Infinite)
- return box.boxtype != Null;
- else if (box.boxtype == Null)
- return false;
- else if (box.boxtype == Infinite)
- return true;
-
- if (maxcorner.x() < box.mincorner.x())
- return false;
- if (mincorner.x() > box.maxcorner.x())
- return false;
-
- if (maxcorner.y() < box.mincorner.y())
- return false;
- if (mincorner.y() > box.maxcorner.y())
- return false;
-
- if (maxcorner.z() < box.mincorner.z())
- return false;
- if (mincorner.z() > box.maxcorner.z())
- return false;
-
- return true;
-}
-
-/*!
- Intersects this box with \a box.
-
- \sa intersected(), intersects(), unite()
-*/
-void Q3DBox::intersect(const Q3DBox& box)
-{
- // Handle the simple cases first.
- if (boxtype == Null) {
- // Null intersected with anything is null.
- return;
- } else if (boxtype == Infinite) {
- // Infinity intersected with a box is that box.
- *this = box;
- return;
- } else if (box.boxtype == Null) {
- // Anything intersected with null is null.
- setToNull();
- return;
- } else if (box.boxtype == Infinite) {
- // Box intersected with infinity is the box.
- return;
- }
-
- // Intersect two finite boxes.
- QVector3D min1 = mincorner;
- QVector3D max1 = maxcorner;
- QVector3D min2 = box.mincorner;
- QVector3D max2 = box.maxcorner;
- if (min2.x() > min1.x())
- min1.setX(min2.x());
- if (min2.y() > min1.y())
- min1.setY(min2.y());
- if (min2.z() > min1.z())
- min1.setZ(min2.z());
- if (max2.x() < max1.x())
- max1.setX(max2.x());
- if (max2.y() < max1.y())
- max1.setY(max2.y());
- if (max2.z() < max1.z())
- max1.setZ(max2.z());
- if (min1.x() > max1.x() || min1.y() > max1.y() || min1.z() > max1.z()) {
- setToNull();
- } else {
- mincorner = min1;
- maxcorner = max1;
- }
-}
-
-/*!
- Returns a new box which is the intersection of this box with \a box.
-
- \sa intersect(), intersects(), united()
-*/
-Q3DBox Q3DBox::intersected(const Q3DBox& box) const
-{
- Q3DBox result(*this);
- result.intersect(box);
- return result;
-}
-
-/*!
- Unites this box with \a point by expanding it to encompass \a point.
- If \a point is already contained within this box, then this box
- will be unchanged.
-
- \sa united(), intersect()
-*/
-void Q3DBox::unite(const QVector3D& point)
-{
- if (boxtype == Finite) {
- if (point.x() < mincorner.x())
- mincorner.setX(point.x());
- else if (point.x() > maxcorner.x())
- maxcorner.setX(point.x());
- if (point.y() < mincorner.y())
- mincorner.setY(point.y());
- else if (point.y() > maxcorner.y())
- maxcorner.setY(point.y());
- if (point.z() < mincorner.z())
- mincorner.setZ(point.z());
- else if (point.z() > maxcorner.z())
- maxcorner.setZ(point.z());
- } else if (boxtype == Null) {
- boxtype = Finite;
- mincorner = point;
- maxcorner = point;
- }
-}
-
-/*!
- Unites this box with \a box by expanding this box to encompass the
- region defined by \a box. If \a box is already contained within
- this box, then this box will be unchanged.
-
- \sa united(), intersect()
-*/
-void Q3DBox::unite(const Q3DBox& box)
-{
- if (box.boxtype == Finite) {
- unite(box.minimum());
- unite(box.maximum());
- } else if (box.boxtype == Infinite) {
- setToInfinite();
- }
-}
-
-/*!
- Returns a new box which unites this box with \a point. The returned
- value will be the smallest box that contains both this box and \a point.
-
- \sa unite(), intersected()
-*/
-Q3DBox Q3DBox::united(const QVector3D& point) const
-{
- if (boxtype == Finite) {
- Q3DBox result(*this);
- result.unite(point);
- return result;
- } else if (boxtype == Null) {
- return Q3DBox(point, point);
- } else {
- return *this;
- }
-}
-
-/*!
- Returns a new box which unites this box with \a box. The returned value
- will be the smallest box that contains both this box and \a box.
-
- \sa unite(), intersected()
-*/
-Q3DBox Q3DBox::united(const Q3DBox& box) const
-{
- if (boxtype == Finite) {
- Q3DBox result(*this);
- result.unite(box);
- return result;
- } else if (boxtype == Null) {
- return box;
- } else {
- return *this;
- }
-}
-
-/*!
- Transforms this box according to \a matrix. Each of the 8 box
- corners are transformed and then a new box that encompasses all
- of the transformed corner values is created.
-
- \sa transformed()
-*/
-void Q3DBox::transform(const QMatrix4x4& matrix)
-{
- *this = transformed(matrix);
-}
-
-/*!
- Returns this box transformed by \a matrix. Each of the 8 box
- corners are transformed and then a new box that encompasses all
- of the transformed corner values is returned.
-
- \sa transform()
-*/
-Q3DBox Q3DBox::transformed(const QMatrix4x4& matrix) const
-{
- if (boxtype != Finite)
- return *this;
- Q3DBox result;
- result.unite(matrix * mincorner);
- result.unite(matrix * QVector3D(mincorner.x(), mincorner.y(), maxcorner.z()));
- result.unite(matrix * QVector3D(mincorner.x(), maxcorner.y(), maxcorner.z()));
- result.unite(matrix * QVector3D(mincorner.x(), maxcorner.y(), mincorner.z()));
- result.unite(matrix * QVector3D(maxcorner.x(), mincorner.y(), mincorner.z()));
- result.unite(matrix * QVector3D(maxcorner.x(), maxcorner.y(), mincorner.z()));
- result.unite(matrix * QVector3D(maxcorner.x(), mincorner.y(), maxcorner.z()));
- result.unite(matrix * maxcorner);
- return result;
-}
-
-/*!
- \fn bool Q3DBox::operator==(const Q3DBox& box) const
-
- Returns true if this box is identical to \a box.
-*/
-
-/*!
- \fn bool Q3DBox::operator!=(const Q3DBox& box) const
-
- Returns true if this box is not identical to \a box.
-*/
-
-/*!
- \fn bool qFuzzyCompare(const Q3DBox& box1, const Q3DBox& box2)
- \relates Q3DBox
-
- Returns true if \a box1 and \a box2 are almost equal; false otherwise.
-*/
-
-#ifndef QT_NO_DEBUG_STREAM
-
-/*!
- \fn operator<<(QDebug dbg, const Q3DBox &box)
- \internal
- */
-QDebug operator<<(QDebug dbg, const Q3DBox &box)
-{
- if (box.isFinite()) {
- dbg.nospace() << "Q3DBox(("
- << box.minimum().x() << ", " << box.minimum().y() << ", "
- << box.minimum().z() << ") - ("
- << box.maximum().x() << ", " << box.maximum().y() << ", "
- << box.maximum().z() << "))";
- return dbg.space();
- } else if (box.isNull()) {
- dbg << "Q3DBox(null)";
- return dbg;
- } else {
- dbg << "Q3DBox(infinite)";
- return dbg;
- }
-}
-
-#endif
-
-#ifndef QT_NO_DATASTREAM
-
-/*!
- \relates Q3DBox
-
- Writes the given \a box to the given \a stream and returns a
- reference to the stream.
-*/
-QDataStream &operator<<(QDataStream &stream, const Q3DBox &box)
-{
- if (box.isNull()) {
- stream << int(0);
- } else if (box.isInfinite()) {
- stream << int(2);
- } else {
- stream << int(1);
- stream << box.minimum();
- stream << box.maximum();
- }
- return stream;
-}
-
-/*!
- \relates Q3DBox
-
- Reads a 3D box from the given \a stream into the given \a box
- and returns a reference to the stream.
-*/
-QDataStream &operator>>(QDataStream &stream, Q3DBox &box)
-{
- int type;
- stream >> type;
- if (type == 1) {
- QVector3D minimum, maximum;
- stream >> minimum;
- stream >> maximum;
- box = Q3DBox(minimum, maximum);
- } else if (type == 2) {
- box.setToInfinite();
- } else {
- box.setToNull();
- }
- return stream;
-}
-
-#endif
-
-QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/q3dbox.h b/src/datavisualization/engine/q3dbox.h
deleted file mode 100644
index 6dbaefa1..00000000
--- a/src/datavisualization/engine/q3dbox.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/****************************************************************************
-**
-** 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
-**
-****************************************************************************/
-
-#ifndef Q3DBOX_H
-#define Q3DBOX_H
-
-#include <QtDataVisualization/qdatavisualizationglobal.h>
-#include <QtGui/QMatrix4x4>
-#include <QtGui/QVector3D>
-
-QT_BEGIN_NAMESPACE_DATAVISUALIZATION
-
-class Q3DBox; // Needed to circumvent an issue with qdoc. If this line is removed, make docs will not work for this.
-
-class QT_DATAVISUALIZATION_EXPORT Q3DBox
-{
-public:
- inline Q3DBox() : boxtype(Null), mincorner(0, 0, 0), maxcorner(0, 0, 0) {}
- inline Q3DBox(const QVector3D& corner1, const QVector3D& corner2): boxtype(Finite),
- mincorner(qMin(corner1.x(), corner2.x()),
- qMin(corner1.y(), corner2.y()),
- qMin(corner1.z(), corner2.z())),
- maxcorner(qMax(corner1.x(), corner2.x()),
- qMax(corner1.y(), corner2.y()),
- qMax(corner1.z(), corner2.z())) {}
-
- inline bool isNull() const { return (boxtype == Null); }
- inline bool isFinite() const { return (boxtype == Finite); }
- inline bool isInfinite() const { return (boxtype == Infinite); }
-
- inline QVector3D minimum() const { return mincorner; }
- inline QVector3D maximum() const { return maxcorner; }
- inline void setExtents(const QVector3D& corner1, const QVector3D& corner2)
- {
- boxtype = Finite;
- mincorner = QVector3D(qMin(corner1.x(), corner2.x()),
- qMin(corner1.y(), corner2.y()),
- qMin(corner1.z(), corner2.z()));
- maxcorner = QVector3D(qMax(corner1.x(), corner2.x()),
- qMax(corner1.y(), corner2.y()),
- qMax(corner1.z(), corner2.z()));
- }
-
- inline void setToNull()
- {
- boxtype = Null;
- mincorner = QVector3D(0, 0, 0);
- maxcorner = QVector3D(0, 0, 0);
- }
-
- inline void setToInfinite()
- {
- boxtype = Infinite;
- mincorner = QVector3D(0, 0, 0);
- maxcorner = QVector3D(0, 0, 0);
- }
-
- inline QVector3D size() const { return maxcorner - mincorner; }
- inline QVector3D center() const { return (mincorner + maxcorner) * 0.5f; }
-
- inline bool contains(const QVector3D& point) const
- {
- if (boxtype == Finite) {
- return (point.x() >= mincorner.x() && point.x() <= maxcorner.x() &&
- point.y() >= mincorner.y() && point.y() <= maxcorner.y() &&
- point.z() >= mincorner.z() && point.z() <= maxcorner.z());
- } else if (boxtype == Infinite) {
- return true;
- } else {
- return false;
- }
- }
-
- inline bool contains(const Q3DBox& box) const
- {
- if (box.boxtype == Finite)
- return contains(box.mincorner) && contains(box.maxcorner);
- else if (box.boxtype == Infinite)
- return (boxtype == Infinite);
- else
- return false;
- }
-
- bool intersects(const Q3DBox& box) const;
- void intersect(const Q3DBox& box);
- Q3DBox intersected(const Q3DBox& box) const;
-
- void unite(const QVector3D& point);
- void unite(const Q3DBox& box);
-
- Q3DBox united(const QVector3D& point) const;
- Q3DBox united(const Q3DBox& box) const;
-
- void transform(const QMatrix4x4& matrix);
- Q3DBox transformed(const QMatrix4x4& matrix) const;
-
- inline bool operator==(const Q3DBox& box) const
- {
- return (boxtype == box.boxtype &&
- mincorner == box.mincorner &&
- maxcorner == box.maxcorner);
- }
-
- inline bool operator!=(const Q3DBox& box) const
- {
- return (boxtype != box.boxtype ||
- mincorner != box.mincorner ||
- maxcorner != box.maxcorner);
- }
-
- friend bool qFuzzyCompare(const Q3DBox& box1, const Q3DBox& box2);
-
-private:
- enum Type
- {
- Null,
- Finite,
- Infinite
- };
-
- Q3DBox::Type boxtype;
- QVector3D mincorner, maxcorner;
-};
-
-inline bool qFuzzyCompare(const Q3DBox& box1, const Q3DBox& box2)
-{
- return box1.boxtype == box2.boxtype &&
- qFuzzyCompare(box1.mincorner, box2.mincorner) &&
- qFuzzyCompare(box1.maxcorner, box2.maxcorner);
-}
-
-#ifndef QT_NO_DEBUG_STREAM
-QT_DATAVISUALIZATION_EXPORT QDebug operator<<(QDebug dbg, const Q3DBox &box);
-#endif
-
-#ifndef QT_NO_DATASTREAM
-QT_DATAVISUALIZATION_EXPORT QDataStream &operator<<(QDataStream &stream, const Q3DBox &box);
-QT_DATAVISUALIZATION_EXPORT QDataStream &operator>>(QDataStream &stream, Q3DBox &box);
-#endif
-
-QT_END_NAMESPACE_DATAVISUALIZATION
-
-#endif
diff --git a/src/datavisualization/engine/q3dcamera.cpp b/src/datavisualization/engine/q3dcamera.cpp
index 426fa51d..c7342aa9 100644
--- a/src/datavisualization/engine/q3dcamera.cpp
+++ b/src/datavisualization/engine/q3dcamera.cpp
@@ -19,12 +19,10 @@
#include "q3dcamera.h"
#include "q3dcamera_p.h"
#include "q3dscene.h"
-#include "q3dbox.h"
#include "q3dobject.h"
#include "utils_p.h"
-#include <qmath.h>
-#include <QVector3D>
+#include <QtCore/qmath.h>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -35,9 +33,8 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
* \since Qt Data Visualization 1.0
*
* Q3DCamera represents a basic orbit around centerpoint 3D camera that is used when rendering the
- * data visualization. The class offers simple methods for setting the orbit point in rotations,
- * but allows also setting the 4x4 view matrix directly in case a more customized camera behavior is
- * needed.
+ * data visualization. The class offers simple methods for rotating the camera around the origin
+ * and setting zoom level.
*/
/*!
@@ -85,9 +82,8 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
* \brief Representation of a camera in 3D space.
*
* Camera3D represents a basic orbit around centerpoint 3D camera that is used when rendering the
- * data visualization. The class offers simple methods for setting the orbit point in rotations,
- * but allows also setting the 4x4 view matrix directly in case a more customized camera behavior is
- * needed.
+ * 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
*/
@@ -107,74 +103,6 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
*/
/*!
- * \qmlproperty float Camera3D::minXRotation
- *
- * This property contains the current minimum X-rotation for the camera.
- * The full circle range is \c{[-180, 180]} and the minimum value is limited to \c -180.
- * Also the value can't be higher than the maximum, and is adjusted if necessary.
- *
- * \sa wrapXRotation, maxXRotation
- */
-
-/*!
- * \qmlproperty float Camera3D::minYRotation
- *
- * This property contains the current minimum Y-rotation for the camera.
- * The full Y angle range is \c{[-90, 90]} and the minimum value is limited to \c -90.
- * Also the value can't be higher than the maximum, and is adjusted if necessary.
- *
- * \sa wrapYRotation, maxYRotation
- */
-
-/*!
- * \qmlproperty float Camera3D::maxXRotation
- *
- * This property contains the current maximum X-rotation for the camera.
- * The full circle range is \c{[-180, 180]} and the maximum value is limited to \c 180.
- * Also the value can't be lower than the minimum, and is adjusted if necessary.
- *
- * \sa wrapXRotation, minXRotation
- */
-
-/*!
- * \qmlproperty float Camera3D::maxYRotation
- *
- * This property contains the current maximum Y-rotation for the camera.
- * The full Y angle range is \c{[-90, 90]} and the maximum value is limited to \c 90.
- * Also the value can't be lower than the minimum, and is adjusted if necessary.
- *
- * \sa wrapYRotation, minYRotation
- */
-
-/*!
- * \qmlmethod void Camera3D::setBaseOrientation(vector3d basePosition, vector3d target, vector3d baseUp)
- *
- * Sets the base values for the camera that are used when calculating the camera position using the
- * rotation values. The base position of the camera is defined by \a basePosition, expectation is
- * that the x and y values are 0. Look at target point is defined by \a target and the camera
- * rotates around it. Up direction for the camera is defined by \a baseUp, normally this is a
- * vector with only y value set to 1.
- */
-
-/*!
- * \qmlproperty matrix4x4 Camera3D::viewMatrix
- *
- * This property contains the view matrix used in the 3D calculations. When the default orbiting
- * camera behavior is sufficient, there is no need to touch this property. If the default
- * behavior is insufficient, the view matrix can be set directly.
- * \note When setting the view matrix directly remember to set viewMatrixAutoUpdateEnabled
- * property to \c false.
- */
-
-/*!
- * \qmlproperty bool Camera3D::viewMatrixAutoUpdateEnabled
- *
- * This property determines if view matrix is automatically updated each render cycle using the
- * current base orientation and rotations. If set to \c false, no automatic recalculation is done and
- * the view matrix can be set using the viewMatrix property.
- */
-
-/*!
* \qmlproperty Camera3D.CameraPreset Camera3D::cameraPreset
*
* This property contains the currently active camera preset, which is one of
@@ -272,8 +200,7 @@ void Q3DCamera::copyValuesFrom(const Q3DObject &source)
/*!
* \property Q3DCamera::xRotation
*
- * This property contains the X-rotation angle of the camera around the target point in degrees
- * starting from the current base position set by the setBaseOrientation() method.
+ * This property contains the X-rotation angle of the camera around the target point in degrees.
*/
float Q3DCamera::xRotation() const {
return d_ptr->m_xRotation;
@@ -300,8 +227,7 @@ void Q3DCamera::setXRotation(float rotation)
/*!
* \property Q3DCamera::yRotation
*
- * This property contains the Y-rotation angle of the camera around the target point in degrees
- * starting from the current base position set by the setBaseOrientation() method.
+ * This property contains the Y-rotation angle of the camera around the target point in degrees.
*/
float Q3DCamera::yRotation() const {
return d_ptr->m_yRotation;
@@ -326,192 +252,10 @@ void Q3DCamera::setYRotation(float rotation)
}
/*!
- * \property Q3DCamera::minXRotation
- *
- * This property contains the current minimum X-rotation for the camera.
- * The full circle range is \c{[-180, 180]} and the minimum value is limited to \c -180.
- * Also the value can't be higher than the maximum, and is adjusted if necessary.
- *
- * \sa wrapXRotation, maxXRotation
- */
-float Q3DCamera::minXRotation() const
-{
- return d_ptr->m_minXRotation;
-}
-
-void Q3DCamera::setMinXRotation(float minRotation)
-{
- minRotation = qBound(-180.0f, minRotation, 180.0f);
- if (minRotation > d_ptr->m_maxXRotation)
- minRotation = d_ptr->m_maxXRotation;
-
- if (d_ptr->m_minXRotation != minRotation) {
- d_ptr->m_minXRotation = minRotation;
- emit minXRotationChanged(minRotation);
-
- if (d_ptr->m_xRotation < d_ptr->m_minXRotation)
- setXRotation(d_ptr->m_xRotation);
- }
-}
-
-/*!
- * \property Q3DCamera::minYRotation
- *
- * This property contains the current minimum Y-rotation for the camera.
- * The full Y angle range is \c{[-90, 90]} and the minimum value is limited to \c -90.
- * Also the value can't be higher than the maximum, and is adjusted if necessary.
- *
- * \sa wrapYRotation, maxYRotation
- */
-float Q3DCamera::minYRotation() const
-{
- return d_ptr->m_minYRotation;
-}
-
-void Q3DCamera::setMinYRotation(float minRotation)
-{
- minRotation = qBound(-90.0f, minRotation, 90.0f);
- if (minRotation > d_ptr->m_maxYRotation)
- minRotation = d_ptr->m_maxYRotation;
-
- if (d_ptr->m_minYRotation != minRotation) {
- d_ptr->m_minYRotation = minRotation;
- emit minYRotationChanged(minRotation);
-
- if (d_ptr->m_yRotation < d_ptr->m_minYRotation)
- setYRotation(d_ptr->m_yRotation);
- }
-}
-
-/*!
- * \property Q3DCamera::maxXRotation
- *
- * This property contains the current maximum X-rotation for the camera.
- * The full circle range is \c{[-180, 180]} and the maximum value is limited to \c 180.
- * Also the value can't be lower than the minimum, and is adjusted if necessary.
- *
- * \sa wrapXRotation, minXRotation
- */
-float Q3DCamera::maxXRotation() const
-{
- return d_ptr->m_maxXRotation;
-}
-
-void Q3DCamera::setMaxXRotation(float maxRotation)
-{
- maxRotation = qBound(-180.0f, maxRotation, 180.0f);
-
- if (maxRotation < d_ptr->m_minXRotation)
- maxRotation = d_ptr->m_minXRotation;
-
- if (d_ptr->m_maxXRotation != maxRotation) {
- d_ptr->m_maxXRotation = maxRotation;
- emit maxXRotationChanged(maxRotation);
-
- if (d_ptr->m_xRotation > d_ptr->m_maxXRotation)
- setXRotation(d_ptr->m_xRotation);
- }
-}
-
-/*!
- * \property Q3DCamera::maxYRotation
- *
- * This property contains the current maximum Y-rotation for the camera.
- * The full Y angle range is \c{[-90, 90]} and the maximum value is limited to \c 90.
- * Also the value can't be lower than the minimum, and is adjusted if necessary.
- *
- * \sa wrapYRotation, minYRotation
- */
-float Q3DCamera::maxYRotation() const
-{
- return d_ptr->m_maxYRotation;
-}
-
-void Q3DCamera::setMaxYRotation(float maxRotation)
-{
- maxRotation = qBound(-90.0f, maxRotation, 90.0f);
-
- if (maxRotation < d_ptr->m_minYRotation)
- maxRotation = d_ptr->m_minYRotation;
-
- if (d_ptr->m_maxYRotation != maxRotation) {
- d_ptr->m_maxYRotation = maxRotation;
- emit maxYRotationChanged(maxRotation);
-
- if (d_ptr->m_yRotation > d_ptr->m_maxYRotation)
- setYRotation(d_ptr->m_yRotation);
- }
-}
-
-/*!
- * Sets the base values for the camera that are used when calculating the camera position using the
- * rotation values. The base position of the camera is defined by \a basePosition, expectation is
- * that the x and y values are 0. Look at target point is defined by \a target and the camera
- * rotates around it. Up direction for the camera is defined by \a baseUp, normally this is a
- * vector with only y value set to 1.
- */
-void Q3DCamera::setBaseOrientation(const QVector3D &basePosition,
- const QVector3D &target,
- const QVector3D &baseUp)
-{
- if (position() != basePosition
- || d_ptr->m_target != target
- || d_ptr->m_up != baseUp) {
- setPosition(basePosition);
- d_ptr->m_target = target;
- d_ptr->m_up = baseUp;
- setDirty(true);
- }
-}
-
-/*!
- * \property Q3DCamera::viewMatrix
- *
- * This property contains the view matrix used in the 3D calculations. When the default orbiting
- * camera behavior is sufficient, there is no need to touch this property. If the default
- * behavior is insufficient, the view matrix can be set directly.
- * \note When setting the view matrix directly remember to set viewMatrixAutoUpdateEnabled to
- * \c false.
- */
-QMatrix4x4 Q3DCamera::viewMatrix() const
-{
- return d_ptr->m_viewMatrix;
-}
-
-void Q3DCamera::setViewMatrix(const QMatrix4x4 &viewMatrix)
-{
- if (d_ptr->m_viewMatrix != viewMatrix) {
- d_ptr->m_viewMatrix = viewMatrix;
- setDirty(true);
- emit viewMatrixChanged(d_ptr->m_viewMatrix);
- }
-}
-
-/*!
- * \property Q3DCamera::viewMatrixAutoUpdateEnabled
- *
- * This property determines if view matrix is automatically updated each render cycle using the
- * current base orientation and rotations. If set to \c false, no automatic recalculation is done
- * and the view matrix can be set using the viewMatrix property.
- */
-bool Q3DCamera::isViewMatrixAutoUpdateEnabled() const
-{
- return d_ptr->m_isViewMatrixUpdateActive;
-}
-
-void Q3DCamera::setViewMatrixAutoUpdateEnabled(bool isEnabled)
-{
- d_ptr->m_isViewMatrixUpdateActive = isEnabled;
- emit viewMatrixAutoUpdateChanged(isEnabled);
-}
-
-/*!
* \property Q3DCamera::cameraPreset
*
* This property contains the currently active camera preset, if no preset is active the value
* is CameraPresetNone.
- * \note The base camera orientation set by setBaseOrientation() will affect
- * the presets as all calculations are based on those values.
*/
Q3DCamera::CameraPreset Q3DCamera::cameraPreset() const
{
@@ -674,42 +418,6 @@ void Q3DCamera::setZoomLevel(int zoomLevel)
}
/*!
- * Calculates and returns a position relative to the camera using the given parameters
- * and the current camera viewMatrix property.
- * The relative 3D offset to the current camera position is defined in \a relativePosition.
- * An optional fixed rotation of the calculated point around the data visualization area can be
- * given in \a fixedRotation. The rotation is given in degrees.
- * An optional \a distanceModifier modifies the distance of the calculated point from the data
- * visualization.
- * \return calculated position relative to this camera's position.
- */
-QVector3D Q3DCamera::calculatePositionRelativeToCamera(const QVector3D &relativePosition,
- float fixedRotation,
- float distanceModifier) const
-{
- // Move the position with camera
- GLfloat radiusFactor = cameraDistance * (1.5f + distanceModifier);
- GLfloat xAngle;
- GLfloat yAngle;
- if (!fixedRotation) {
- xAngle = qDegreesToRadians(d_ptr->m_xRotation);
- yAngle = qDegreesToRadians(d_ptr->m_yRotation);
- } else {
- xAngle = qDegreesToRadians(fixedRotation);
- yAngle = 0;
- }
- GLfloat radius = (radiusFactor + relativePosition.y()); // set radius to match the highest height of the position
- GLfloat zPos = radius * qCos(xAngle) * qCos(yAngle);
- GLfloat xPos = radius * qSin(xAngle) * qCos(yAngle);
- GLfloat yPos = (radiusFactor + relativePosition.y()) * qSin(yAngle);
-
- // Keep in the set position in relation to camera
- return QVector3D(-xPos + relativePosition.x(),
- yPos + relativePosition.y(),
- zPos + relativePosition.z());
-}
-
-/*!
* \property Q3DCamera::wrapXRotation
*
* This property determines the behavior of the minimum and maximum limits in the X-rotation.
@@ -809,34 +517,120 @@ void Q3DCameraPrivate::setYRotation(const float rotation)
}
}
-void Q3DCameraPrivate::setMinXRotation(const float rotation)
+/*!
+ * \internal
+ * This property contains the current minimum X-rotation for the camera.
+ * The full circle range is \c{[-180, 180]} and the minimum value is limited to \c -180.
+ * Also the value can't be higher than the maximum, and is adjusted if necessary.
+ *
+ * \sa wrapXRotation, maxXRotation
+ */
+float Q3DCameraPrivate::minXRotation() const
+{
+ return m_minXRotation;
+}
+
+void Q3DCameraPrivate::setMinXRotation(float minRotation)
{
- if (m_minXRotation != rotation) {
- m_minXRotation = rotation;
+ minRotation = qBound(-180.0f, minRotation, 180.0f);
+ if (minRotation > m_maxXRotation)
+ minRotation = m_maxXRotation;
+
+ if (m_minXRotation != minRotation) {
+ m_minXRotation = minRotation;
+ emit minXRotationChanged(minRotation);
+
+ if (m_xRotation < m_minXRotation)
+ setXRotation(m_xRotation);
q_ptr->setDirty(true);
}
}
-void Q3DCameraPrivate::setMinYRotation(const float rotation)
+/*!
+ * \internal
+ * This property contains the current minimum Y-rotation for the camera.
+ * The full Y angle range is \c{[-90, 90]} and the minimum value is limited to \c -90.
+ * Also the value can't be higher than the maximum, and is adjusted if necessary.
+ *
+ * \sa wrapYRotation, maxYRotation
+ */
+float Q3DCameraPrivate::minYRotation() const
+{
+ return m_minYRotation;
+}
+
+void Q3DCameraPrivate::setMinYRotation(float minRotation)
{
- if (m_minYRotation != rotation) {
- m_minYRotation = rotation;
+ minRotation = qBound(-90.0f, minRotation, 90.0f);
+ if (minRotation > m_maxYRotation)
+ minRotation = m_maxYRotation;
+
+ if (m_minYRotation != minRotation) {
+ m_minYRotation = minRotation;
+ emit minYRotationChanged(minRotation);
+
+ if (m_yRotation < m_minYRotation)
+ setYRotation(m_yRotation);
q_ptr->setDirty(true);
}
}
-void Q3DCameraPrivate::setMaxXRotation(const float rotation)
+/*!
+ * \internal
+ * This property contains the current maximum X-rotation for the camera.
+ * The full circle range is \c{[-180, 180]} and the maximum value is limited to \c 180.
+ * Also the value can't be lower than the minimum, and is adjusted if necessary.
+ *
+ * \sa wrapXRotation, minXRotation
+ */
+float Q3DCameraPrivate::maxXRotation() const
{
- if (m_maxXRotation != rotation) {
- m_maxXRotation = rotation;
+ return m_maxXRotation;
+}
+
+void Q3DCameraPrivate::setMaxXRotation(float maxRotation)
+{
+ maxRotation = qBound(-180.0f, maxRotation, 180.0f);
+
+ if (maxRotation < m_minXRotation)
+ maxRotation = m_minXRotation;
+
+ if (m_maxXRotation != maxRotation) {
+ m_maxXRotation = maxRotation;
+ emit maxXRotationChanged(maxRotation);
+
+ if (m_xRotation > m_maxXRotation)
+ setXRotation(m_xRotation);
q_ptr->setDirty(true);
}
}
-void Q3DCameraPrivate::setMaxYRotation(const float rotation)
+/*!
+ * \internal
+ * This property contains the current maximum Y-rotation for the camera.
+ * The full Y angle range is \c{[-90, 90]} and the maximum value is limited to \c 90.
+ * Also the value can't be lower than the minimum, and is adjusted if necessary.
+ *
+ * \sa wrapYRotation, minYRotation
+ */
+float Q3DCameraPrivate::maxYRotation() const
+{
+ return m_maxYRotation;
+}
+
+void Q3DCameraPrivate::setMaxYRotation(float maxRotation)
{
- if (m_maxYRotation != rotation) {
- m_maxYRotation = rotation;
+ maxRotation = qBound(-90.0f, maxRotation, 90.0f);
+
+ if (maxRotation < m_minYRotation)
+ maxRotation = m_minYRotation;
+
+ if (m_maxYRotation != maxRotation) {
+ m_maxYRotation = maxRotation;
+ emit maxYRotationChanged(maxRotation);
+
+ if (m_yRotation > m_maxYRotation)
+ setYRotation(m_yRotation);
q_ptr->setDirty(true);
}
}
@@ -866,7 +660,103 @@ void Q3DCameraPrivate::updateViewMatrix(float zoomAdjustment)
// Compensate for translation (if d_ptr->m_target is off origin)
viewMatrix.translate(-m_target.x(), -m_target.y(), -m_target.z());
- q_ptr->setViewMatrix(viewMatrix);
+ setViewMatrix(viewMatrix);
+}
+
+/*!
+ * \internal
+ * This property contains the view matrix used in the 3D calculations. When the default orbiting
+ * camera behavior is sufficient, there is no need to touch this property. If the default
+ * behavior is insufficient, the view matrix can be set directly.
+ * \note When setting the view matrix directly remember to set viewMatrixAutoUpdateEnabled to
+ * \c false.
+ */
+QMatrix4x4 Q3DCameraPrivate::viewMatrix() const
+{
+ return m_viewMatrix;
+}
+
+void Q3DCameraPrivate::setViewMatrix(const QMatrix4x4 &viewMatrix)
+{
+ if (m_viewMatrix != viewMatrix) {
+ m_viewMatrix = viewMatrix;
+ q_ptr->setDirty(true);
+ emit viewMatrixChanged(m_viewMatrix);
+ }
+}
+
+/*!
+ * \internal
+ * This property determines if view matrix is automatically updated each render cycle using the
+ * current base orientation and rotations. If set to \c false, no automatic recalculation is done
+ * and the view matrix can be set using the viewMatrix property.
+ */
+bool Q3DCameraPrivate::isViewMatrixAutoUpdateEnabled() const
+{
+ return m_isViewMatrixUpdateActive;
+}
+
+void Q3DCameraPrivate::setViewMatrixAutoUpdateEnabled(bool isEnabled)
+{
+ m_isViewMatrixUpdateActive = isEnabled;
+ emit viewMatrixAutoUpdateChanged(isEnabled);
+}
+
+/*!
+ * \internal
+ * Sets the base values for the camera that are used when calculating the camera position using the
+ * rotation values. The base position of the camera is defined by \a basePosition, expectation is
+ * that the x and y values are 0. Look at target point is defined by \a target and the camera
+ * rotates around it. Up direction for the camera is defined by \a baseUp, normally this is a
+ * vector with only y value set to 1.
+ */
+void Q3DCameraPrivate::setBaseOrientation(const QVector3D &basePosition,
+ const QVector3D &target,
+ const QVector3D &baseUp)
+{
+ if (q_ptr->position() != basePosition || m_target != target || m_up != baseUp) {
+ q_ptr->setPosition(basePosition);
+ m_target = target;
+ m_up = baseUp;
+ q_ptr->setDirty(true);
+ }
+}
+
+/*!
+ * \internal
+ * Calculates and returns a position relative to the camera using the given parameters
+ * and the current camera viewMatrix property.
+ * The relative 3D offset to the current camera position is defined in \a relativePosition.
+ * An optional fixed rotation of the calculated point around the data visualization area can be
+ * given in \a fixedRotation. The rotation is given in degrees.
+ * An optional \a distanceModifier modifies the distance of the calculated point from the data
+ * visualization.
+ * \return calculated position relative to this camera's position.
+ */
+QVector3D Q3DCameraPrivate::calculatePositionRelativeToCamera(const QVector3D &relativePosition,
+ float fixedRotation,
+ float distanceModifier) const
+{
+ // Move the position with camera
+ GLfloat radiusFactor = cameraDistance * (1.5f + distanceModifier);
+ GLfloat xAngle;
+ GLfloat yAngle;
+ if (!fixedRotation) {
+ xAngle = qDegreesToRadians(m_xRotation);
+ yAngle = qDegreesToRadians(m_yRotation);
+ } else {
+ xAngle = qDegreesToRadians(fixedRotation);
+ yAngle = 0;
+ }
+ GLfloat radius = (radiusFactor + relativePosition.y()); // set radius to match the highest height of the position
+ GLfloat zPos = radius * qCos(xAngle) * qCos(yAngle);
+ GLfloat xPos = radius * qSin(xAngle) * qCos(yAngle);
+ GLfloat yPos = (radiusFactor + relativePosition.y()) * qSin(yAngle);
+
+ // Keep in the set position in relation to camera
+ return QVector3D(-xPos + relativePosition.x(),
+ yPos + relativePosition.y(),
+ zPos + relativePosition.z());
}
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/q3dcamera.h b/src/datavisualization/engine/q3dcamera.h
index 1a3a3284..87602e5c 100644
--- a/src/datavisualization/engine/q3dcamera.h
+++ b/src/datavisualization/engine/q3dcamera.h
@@ -20,10 +20,6 @@
#define Q3DCAMERA_H
#include <QtDataVisualization/q3dobject.h>
-#include <QMatrix4x4>
-
-class QVector3D;
-class QPoint;
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -35,14 +31,8 @@ class QT_DATAVISUALIZATION_EXPORT Q3DCamera : public Q3DObject
Q_ENUMS(CameraPreset)
Q_PROPERTY(float xRotation READ xRotation WRITE setXRotation NOTIFY xRotationChanged)
Q_PROPERTY(float yRotation READ yRotation WRITE setYRotation NOTIFY yRotationChanged)
- Q_PROPERTY(float minXRotation READ minXRotation NOTIFY minXRotationChanged)
- Q_PROPERTY(float minYRotation READ minYRotation NOTIFY minYRotationChanged)
- Q_PROPERTY(float maxXRotation READ maxXRotation NOTIFY maxXRotationChanged)
- Q_PROPERTY(float maxYRotation READ maxYRotation NOTIFY maxYRotationChanged)
Q_PROPERTY(int zoomLevel READ zoomLevel WRITE setZoomLevel NOTIFY zoomLevelChanged)
- Q_PROPERTY(QMatrix4x4 viewMatrix READ viewMatrix WRITE setViewMatrix NOTIFY viewMatrixChanged)
Q_PROPERTY(CameraPreset cameraPreset READ cameraPreset WRITE setCameraPreset NOTIFY cameraPresetChanged)
- Q_PROPERTY(bool viewMatrixAutoUpdateEnabled READ isViewMatrixAutoUpdateEnabled WRITE setViewMatrixAutoUpdateEnabled NOTIFY viewMatrixAutoUpdateChanged)
Q_PROPERTY(bool wrapXRotation READ wrapXRotation WRITE setWrapXRotation NOTIFY wrapXRotationChanged)
Q_PROPERTY(bool wrapYRotation READ wrapYRotation WRITE setWrapYRotation NOTIFY wrapYRotationChanged)
@@ -75,7 +65,6 @@ public:
CameraPresetDirectlyBelow
};
-public:
Q3DCamera(QObject *parent = 0);
virtual ~Q3DCamera();
@@ -84,12 +73,6 @@ public:
float yRotation() const;
void setYRotation(float rotation);
- float minXRotation() const;
- float maxXRotation() const;
-
- float minYRotation() const;
- float maxYRotation() const;
-
bool wrapXRotation() const;
void setWrapXRotation(bool isEnabled);
@@ -98,48 +81,23 @@ public:
virtual void copyValuesFrom(const Q3DObject &source);
- QMatrix4x4 viewMatrix() const;
- void setViewMatrix(const QMatrix4x4 &viewMatrix);
-
- bool isViewMatrixAutoUpdateEnabled() const;
- void setViewMatrixAutoUpdateEnabled(bool isEnabled);
-
CameraPreset cameraPreset() const;
void setCameraPreset(CameraPreset preset);
int zoomLevel() const;
void setZoomLevel(int zoomLevel);
- Q_INVOKABLE void setBaseOrientation(const QVector3D &defaultPosition,
- const QVector3D &defaultTarget,
- const QVector3D &defaultUp);
-
- QVector3D calculatePositionRelativeToCamera(const QVector3D &relativePosition,
- float fixedRotation,
- float distanceModifier) const;
void setCameraPosition(float horizontal, float vertical, float distance = 100.0f);
signals:
void xRotationChanged(float rotation);
void yRotationChanged(float rotation);
- void minXRotationChanged(float rotation);
- void minYRotationChanged(float rotation);
- void maxXRotationChanged(float rotation);
- void maxYRotationChanged(float rotation);
void zoomLevelChanged(int zoomLevel);
- void viewMatrixChanged(QMatrix4x4 viewMatrix);
void cameraPresetChanged(CameraPreset preset);
- void viewMatrixAutoUpdateChanged(bool enabled);
void wrapXRotationChanged(bool isEnabled);
void wrapYRotationChanged(bool isEnabled);
private:
- void setMinXRotation(float rotation);
- void setMinYRotation(float rotation);
- void setMaxXRotation(float rotation);
- void setMaxYRotation(float rotation);
-
-private:
QScopedPointer<Q3DCameraPrivate> d_ptr;
Q_DISABLE_COPY(Q3DCamera)
@@ -153,7 +111,6 @@ private:
friend class SelectionPointer;
friend class Q3DInputHandler;
friend class QTouch3DInputHandlerPrivate;
- friend class QMac3DInputHandler;
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/q3dcamera_p.h b/src/datavisualization/engine/q3dcamera_p.h
index b55010c8..884229e3 100644
--- a/src/datavisualization/engine/q3dcamera_p.h
+++ b/src/datavisualization/engine/q3dcamera_p.h
@@ -31,13 +31,15 @@
#include "datavisualizationglobal_p.h"
#include "q3dcamera.h"
+#include <QtGui/QMatrix4x4>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
class Q3DCamera;
-class Q3DCameraPrivate
+class Q3DCameraPrivate : public QObject
{
+ Q_OBJECT
public:
Q3DCameraPrivate(Q3DCamera *q);
~Q3DCameraPrivate();
@@ -47,12 +49,38 @@ public:
void setXRotation(float rotation);
void setYRotation(float rotation);
void setMinXRotation(float rotation);
+ float minXRotation() const;
void setMinYRotation(float rotation);
+ float minYRotation() const;
void setMaxXRotation(float rotation);
+ float maxXRotation() const;
void setMaxYRotation(float rotation);
+ float maxYRotation() const;
void updateViewMatrix(float zoomAdjustment);
+ QMatrix4x4 viewMatrix() const;
+ void setViewMatrix(const QMatrix4x4 &viewMatrix);
+
+ bool isViewMatrixAutoUpdateEnabled() const;
+ void setViewMatrixAutoUpdateEnabled(bool isEnabled);
+
+ void setBaseOrientation(const QVector3D &defaultPosition,
+ const QVector3D &defaultTarget,
+ const QVector3D &defaultUp);
+
+ QVector3D calculatePositionRelativeToCamera(const QVector3D &relativePosition,
+ float fixedRotation,
+ float distanceModifier) const;
+
+signals:
+ void minXRotationChanged(float rotation);
+ void minYRotationChanged(float rotation);
+ void maxXRotationChanged(float rotation);
+ void maxYRotationChanged(float rotation);
+ void viewMatrixChanged(QMatrix4x4 viewMatrix);
+ void viewMatrixAutoUpdateChanged(bool enabled);
+
public:
Q3DCamera *q_ptr;
@@ -79,7 +107,6 @@ public:
friend class SelectionPointer;
friend class Q3DInputHandler;
friend class QTouch3DInputHandler;
- friend class QMac3DInputHandler;
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/q3dlight.h b/src/datavisualization/engine/q3dlight.h
index 876601a7..6d51b90f 100644
--- a/src/datavisualization/engine/q3dlight.h
+++ b/src/datavisualization/engine/q3dlight.h
@@ -24,7 +24,6 @@
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
class Q3DLightPrivate;
-class Q3DScene;
class QT_DATAVISUALIZATION_EXPORT Q3DLight : public Q3DObject
{
diff --git a/src/datavisualization/engine/q3dobject.h b/src/datavisualization/engine/q3dobject.h
index 07506f63..4ea505bb 100644
--- a/src/datavisualization/engine/q3dobject.h
+++ b/src/datavisualization/engine/q3dobject.h
@@ -19,14 +19,14 @@
#ifndef Q3DOBJECT_H
#define Q3DOBJECT_H
-#include <QtDataVisualization/q3dscene.h>
-
-#include <QObject>
-#include <QVector3D>
+#include <QtDataVisualization/qdatavisualizationglobal.h>
+#include <QtCore/QObject>
+#include <QtGui/QVector3D>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
class Q3DObjectPrivate;
+class Q3DScene;
class QT_DATAVISUALIZATION_EXPORT Q3DObject : public QObject
{
@@ -46,7 +46,7 @@ public:
void setPosition(const QVector3D &position);
signals:
- void positionChanged(QVector3D position);
+ void positionChanged(const QVector3D &position);
protected:
void setDirty(bool dirty);
diff --git a/src/datavisualization/engine/q3dscatter.cpp b/src/datavisualization/engine/q3dscatter.cpp
index db7d2491..7c7809f3 100644
--- a/src/datavisualization/engine/q3dscatter.cpp
+++ b/src/datavisualization/engine/q3dscatter.cpp
@@ -87,6 +87,8 @@ Q3DScatter::Q3DScatter(const QSurfaceFormat *format, QWindow *parent)
dptr()->m_shared = new Scatter3DController(geometry());
d_ptr->setVisualController(dptr()->m_shared);
dptr()->m_shared->initializeOpenGL();
+ QObject::connect(dptr()->m_shared, &Scatter3DController::selectedSeriesChanged,
+ this, &Q3DScatter::selectedSeriesChanged);
}
/*!
@@ -202,6 +204,16 @@ QValue3DAxis *Q3DScatter::axisZ() const
}
/*!
+ * \property Q3DScatter::selectedSeries
+ *
+ * The selected series or \c null.
+ */
+QScatter3DSeries *Q3DScatter::selectedSeries() const
+{
+ return dptrc()->m_shared->selectedSeries();
+}
+
+/*!
* Adds \a axis to the graph. The axes added via addAxis are not yet taken to use,
* addAxis is simply used to give the ownership of the \a axis to the graph.
* The \a axis must not be null or added to another graph.
diff --git a/src/datavisualization/engine/q3dscatter.h b/src/datavisualization/engine/q3dscatter.h
index 55158537..016431af 100644
--- a/src/datavisualization/engine/q3dscatter.h
+++ b/src/datavisualization/engine/q3dscatter.h
@@ -20,16 +20,12 @@
#define Q3DSCATTER_H
#include <QtDataVisualization/qabstract3dgraph.h>
-#include <QtDataVisualization/q3dscene.h>
-#include <QFont>
-#include <QLinearGradient>
+#include <QtDataVisualization/qvalue3daxis.h>
+#include <QtDataVisualization/qscatter3dseries.h>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
class Q3DScatterPrivate;
-class QValue3DAxis;
-class QCategory3DAxis;
-class QScatter3DSeries;
class QT_DATAVISUALIZATION_EXPORT Q3DScatter : public QAbstract3DGraph
{
@@ -37,6 +33,7 @@ class QT_DATAVISUALIZATION_EXPORT Q3DScatter : public QAbstract3DGraph
Q_PROPERTY(QValue3DAxis *axisX READ axisX WRITE setAxisX NOTIFY axisXChanged)
Q_PROPERTY(QValue3DAxis *axisY READ axisY WRITE setAxisY NOTIFY axisYChanged)
Q_PROPERTY(QValue3DAxis *axisZ READ axisZ WRITE setAxisZ NOTIFY axisZChanged)
+ Q_PROPERTY(QScatter3DSeries *selectedSeries READ selectedSeries NOTIFY selectedSeriesChanged)
public:
explicit Q3DScatter(const QSurfaceFormat *format = 0, QWindow *parent = 0);
@@ -56,10 +53,13 @@ public:
void releaseAxis(QValue3DAxis *axis);
QList<QValue3DAxis *> axes() const;
+ QScatter3DSeries *selectedSeries() const;
+
signals:
void axisXChanged(QValue3DAxis *axis);
void axisYChanged(QValue3DAxis *axis);
void axisZChanged(QValue3DAxis *axis);
+ void selectedSeriesChanged(QScatter3DSeries *series);
private:
Q3DScatterPrivate *dptr();
diff --git a/src/datavisualization/engine/q3dscene.cpp b/src/datavisualization/engine/q3dscene.cpp
index 6ee4e275..be64b928 100644
--- a/src/datavisualization/engine/q3dscene.cpp
+++ b/src/datavisualization/engine/q3dscene.cpp
@@ -16,8 +16,6 @@
**
****************************************************************************/
-#include <qmath.h>
-
#include "datavisualizationglobal_p.h"
#include "q3dscene.h"
@@ -25,6 +23,8 @@
#include "q3dcamera_p.h"
#include "q3dlight_p.h"
+#include <QtCore/qmath.h>
+
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
/*!
@@ -438,23 +438,6 @@ void Q3DScene::setDevicePixelRatio(float pixelRatio)
}
}
-/*!
- * Calculates and sets the light position relative to the currently active camera using the given
- * parameters.
- * The relative 3D offset to the current camera position is defined in \a relativePosition.
- * Optional \a fixedRotation fixes the light rotation around the data visualization area to the
- * given value in degrees.
- * Optional \a distanceModifier modifies the distance of the light from the data visualization.
- */
-void Q3DScene::setLightPositionRelativeToCamera(const QVector3D &relativePosition,
- float fixedRotation, float distanceModifier)
-{
- d_ptr->m_light->setPosition(
- d_ptr->m_camera->calculatePositionRelativeToCamera(relativePosition,
- fixedRotation,
- distanceModifier));
-}
-
Q3DScenePrivate::Q3DScenePrivate(Q3DScene *q) :
QObject(0),
q_ptr(q),
@@ -650,4 +633,21 @@ QRect Q3DScenePrivate::glSecondarySubViewport()
return m_glSecondarySubViewport;
}
+/*!
+ * \internal
+ * Calculates and sets the light position relative to the currently active camera using the given
+ * parameters.
+ * The relative 3D offset to the current camera position is defined in \a relativePosition.
+ * Optional \a fixedRotation fixes the light rotation around the data visualization area to the
+ * given value in degrees.
+ * Optional \a distanceModifier modifies the distance of the light from the data visualization.
+ */
+void Q3DScenePrivate::setLightPositionRelativeToCamera(const QVector3D &relativePosition,
+ float fixedRotation, float distanceModifier)
+{
+ m_light->setPosition(m_camera->d_ptr->calculatePositionRelativeToCamera(relativePosition,
+ fixedRotation,
+ distanceModifier));
+}
+
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/q3dscene.h b/src/datavisualization/engine/q3dscene.h
index 61a18c9d..d663744e 100644
--- a/src/datavisualization/engine/q3dscene.h
+++ b/src/datavisualization/engine/q3dscene.h
@@ -20,15 +20,13 @@
#define Q3DSCENE_H
#include <QtDataVisualization/qdatavisualizationglobal.h>
-
-#include <QObject>
-#include <QRect>
+#include <QtDataVisualization/q3dcamera.h>
+#include <QtDataVisualization/q3dlight.h>
+#include <QtCore/QObject>
+#include <QtCore/QRect>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
-class Q3DCamera;
-class Q3DBox;
-class Q3DLight;
class Q3DScenePrivate;
class QT_DATAVISUALIZATION_EXPORT Q3DScene : public QObject
@@ -46,7 +44,7 @@ class QT_DATAVISUALIZATION_EXPORT Q3DScene : public QObject
public:
Q3DScene(QObject *parent = 0);
- ~Q3DScene();
+ virtual ~Q3DScene();
QRect viewport() const;
@@ -77,19 +75,16 @@ public:
float devicePixelRatio() const;
void setDevicePixelRatio(float pixelRatio);
- Q_INVOKABLE void setLightPositionRelativeToCamera(const QVector3D &relativePosition,
- float fixedRotation = 0.0f,
- float distanceModifier = 0.0f);
signals:
- void viewportChanged(QRect viewport);
- void primarySubViewportChanged(QRect subViewport);
- void secondarySubViewportChanged(QRect subViewport);
+ void viewportChanged(const QRect &viewport);
+ void primarySubViewportChanged(const QRect &subViewport);
+ void secondarySubViewportChanged(const QRect &subViewport);
void secondarySubviewOnTopChanged(bool isSecondaryOnTop);
void slicingActiveChanged(bool isSlicingActive);
- void activeCameraChanged(const Q3DCamera *camera);
- void activeLightChanged(const Q3DLight *light);
+ void activeCameraChanged(Q3DCamera *camera);
+ void activeLightChanged(Q3DLight *light);
void devicePixelRatioChanged(float pixelRatio);
- void selectionQueryPositionChanged(const QPoint position);
+ void selectionQueryPositionChanged(const QPoint &position);
private:
QScopedPointer<Q3DScenePrivate> d_ptr;
diff --git a/src/datavisualization/engine/q3dscene_p.h b/src/datavisualization/engine/q3dscene_p.h
index be0d3dc5..bc6a7223 100644
--- a/src/datavisualization/engine/q3dscene_p.h
+++ b/src/datavisualization/engine/q3dscene_p.h
@@ -30,7 +30,7 @@
#define Q3DSCENE_P_H
#include "datavisualizationglobal_p.h"
-#include <QRect>
+#include "q3dscene.h"
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -86,6 +86,10 @@ public:
QRect glPrimarySubViewport();
QRect glSecondarySubViewport();
+ void setLightPositionRelativeToCamera(const QVector3D &relativePosition,
+ float fixedRotation = 0.0f,
+ float distanceModifier = 0.0f);
+
signals:
void needRender();
diff --git a/src/datavisualization/engine/q3dsurface.cpp b/src/datavisualization/engine/q3dsurface.cpp
index a8a8235e..7724cb24 100644
--- a/src/datavisualization/engine/q3dsurface.cpp
+++ b/src/datavisualization/engine/q3dsurface.cpp
@@ -32,8 +32,8 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
* \since Qt Data Visualization 1.0
*
* This class enables developers to render 3D surface plots and to view them by rotating the scene
- * freely. The surface plotting includes also gridline that can be set on or off.
- * The visual appearance of the surface can be changed by controlling the smooth status.
+ * freely. The visual properties of the surface such as draw mode and shading can be controlled
+ * via QSurface3DSeries.
*
* The Q3DSurface supports selection by showing a highlighted ball on the data point where the user has clicked
* with left mouse button (when default input handler is in use) or selected via QSurface3DSeries.
@@ -49,8 +49,6 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
* These default axes can be modified via axis accessors, but as soon any axis is set explicitly
* for the orientation, the default axis for that orientation is destroyed.
*
- * Q3DSurface supports only single series at a time.
- *
* \section1 How to construct a minimal Q3DSurface graph
*
* First, construct Q3DSurface. Since we are running the graph as top level window
@@ -100,6 +98,8 @@ Q3DSurface::Q3DSurface(const QSurfaceFormat *format, QWindow *parent)
dptr()->m_shared = new Surface3DController(geometry());
d_ptr->setVisualController(dptr()->m_shared);
dptr()->m_shared->initializeOpenGL();
+ QObject::connect(dptr()->m_shared, &Surface3DController::selectedSeriesChanged,
+ this, &Q3DSurface::selectedSeriesChanged);
}
/*!
@@ -111,8 +111,6 @@ Q3DSurface::~Q3DSurface()
/*!
* Adds the \a series to the graph.
- *
- * \note The surface graph currently supports only a single series at a time.
*/
void Q3DSurface::addSeries(QSurface3DSeries *series)
{
@@ -129,8 +127,6 @@ void Q3DSurface::removeSeries(QSurface3DSeries *series)
/*!
* \return list of series added to this graph.
- *
- * \note The surface graph currently supports only a single series at a time.
*/
QList<QSurface3DSeries *> Q3DSurface::seriesList() const
{
@@ -223,6 +219,17 @@ QValue3DAxis *Q3DSurface::axisZ() const
}
/*!
+ * \property Q3DSurface::selectedSeries
+ *
+ * The selected series or \c null. If selectionMode has \c SelectionMultiSeries flag set, this
+ * property holds the series which owns the selected point.
+ */
+QSurface3DSeries *Q3DSurface::selectedSeries() const
+{
+ return dptrc()->m_shared->selectedSeries();
+}
+
+/*!
* Adds \a axis to the graph. The axes added via addAxis are not yet taken to use,
* addAxis is simply used to give the ownership of the \a axis to the graph.
* The \a axis must not be null or added to another graph.
diff --git a/src/datavisualization/engine/q3dsurface.h b/src/datavisualization/engine/q3dsurface.h
index 7fb6e58a..9868c844 100644
--- a/src/datavisualization/engine/q3dsurface.h
+++ b/src/datavisualization/engine/q3dsurface.h
@@ -20,14 +20,12 @@
#define Q3DSURFACE_H
#include <QtDataVisualization/qabstract3dgraph.h>
-#include <QtDataVisualization/q3dscene.h>
-#include <QFont>
+#include <QtDataVisualization/qvalue3daxis.h>
+#include <QtDataVisualization/qsurface3dseries.h>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
class Q3DSurfacePrivate;
-class QValue3DAxis;
-class QSurface3DSeries;
class QT_DATAVISUALIZATION_EXPORT Q3DSurface : public QAbstract3DGraph
{
@@ -35,6 +33,7 @@ class QT_DATAVISUALIZATION_EXPORT Q3DSurface : public QAbstract3DGraph
Q_PROPERTY(QValue3DAxis *axisX READ axisX WRITE setAxisX NOTIFY axisXChanged)
Q_PROPERTY(QValue3DAxis *axisY READ axisY WRITE setAxisY NOTIFY axisYChanged)
Q_PROPERTY(QValue3DAxis *axisZ READ axisZ WRITE setAxisZ NOTIFY axisZChanged)
+ Q_PROPERTY(QSurface3DSeries *selectedSeries READ selectedSeries NOTIFY selectedSeriesChanged)
public:
explicit Q3DSurface(const QSurfaceFormat *format = 0, QWindow *parent = 0);
@@ -55,10 +54,13 @@ public:
void releaseAxis(QValue3DAxis *axis);
QList<QValue3DAxis *> axes() const;
+ QSurface3DSeries *selectedSeries() const;
+
signals:
void axisXChanged(QValue3DAxis *axis);
void axisYChanged(QValue3DAxis *axis);
void axisZChanged(QValue3DAxis *axis);
+ void selectedSeriesChanged(QSurface3DSeries *series);
private:
Q3DSurfacePrivate *dptr();
diff --git a/src/datavisualization/engine/q3dsurface_p.h b/src/datavisualization/engine/q3dsurface_p.h
index 540956b6..0e5a5121 100644
--- a/src/datavisualization/engine/q3dsurface_p.h
+++ b/src/datavisualization/engine/q3dsurface_p.h
@@ -32,8 +32,6 @@
#include "surface3dcontroller_p.h"
#include "qabstract3dgraph_p.h"
-#include <QList>
-
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
class Q3DSurface;
diff --git a/src/datavisualization/engine/qabstract3dgraph.cpp b/src/datavisualization/engine/qabstract3dgraph.cpp
index d8146149..f2102b29 100644
--- a/src/datavisualization/engine/qabstract3dgraph.cpp
+++ b/src/datavisualization/engine/qabstract3dgraph.cpp
@@ -23,11 +23,10 @@
#include "q3dscene_p.h"
#include "qutils.h"
-#include <QGuiApplication>
-#include <QOpenGLContext>
-#include <QOpenGLPaintDevice>
-#include <QPainter>
-
+#include <QtGui/QGuiApplication>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLPaintDevice>
+#include <QtGui/QPainter>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -85,10 +84,16 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
automatically. If you wish to control the slice view yourself via Q3DScene, do not set this
flag. When setting this mode flag, either \c SelectionRow or \c SelectionColumn must also
be set, but not both. Slicing is supported by Q3DBars and Q3DSurface only.
+ When this flag is set, slice mode is entered in the following situations:
+ \list
+ \li When selection is changed explicitly via series API to a visible item
+ \li When selection is changed by clicking on the graph
+ \li When the selection mode changes and the selected item is visible
+ \endlist
\value SelectionMultiSeries
Setting this mode means that items for all series at same position are highlighted, instead
of just the selected item. The actual selection in the other series doesn't change.
- Multi-series selection is only supported for Q3DBars.
+ Multi-series selection is not supported for Q3DScatter.
*/
/*!
@@ -216,7 +221,7 @@ void QAbstract3DGraph::setActiveInputHandler(QAbstract3DInputHandler *inputHandl
d_ptr->m_visualController->setActiveInputHandler(inputHandler);
}
-QAbstract3DInputHandler *QAbstract3DGraph::activeInputHandler()
+QAbstract3DInputHandler *QAbstract3DGraph::activeInputHandler() const
{
return d_ptr->m_visualController->activeInputHandler();
}
diff --git a/src/datavisualization/engine/qabstract3dgraph.h b/src/datavisualization/engine/qabstract3dgraph.h
index 9534ce5c..adf67912 100644
--- a/src/datavisualization/engine/qabstract3dgraph.h
+++ b/src/datavisualization/engine/qabstract3dgraph.h
@@ -20,18 +20,15 @@
#define QABSTRACT3DGRAPH_H
#include <QtDataVisualization/qdatavisualizationglobal.h>
-
-#include <QWindow>
-#include <QOpenGLFunctions>
-#include <QScreen>
+#include <QtDataVisualization/q3dtheme.h>
+#include <QtDataVisualization/q3dscene.h>
+#include <QtDataVisualization/qabstract3dinputhandler.h>
+#include <QtGui/QWindow>
+#include <QtGui/QOpenGLFunctions>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
class QAbstract3DGraphPrivate;
-class Abstract3DController;
-class QAbstract3DInputHandler;
-class Q3DTheme;
-class Q3DScene;
class QT_DATAVISUALIZATION_EXPORT QAbstract3DGraph : public QWindow, protected QOpenGLFunctions
{
@@ -78,7 +75,7 @@ public:
void addInputHandler(QAbstract3DInputHandler *inputHandler);
void releaseInputHandler(QAbstract3DInputHandler *inputHandler);
void setActiveInputHandler(QAbstract3DInputHandler *inputHandler);
- QAbstract3DInputHandler *activeInputHandler();
+ QAbstract3DInputHandler *activeInputHandler() const;
QList<QAbstract3DInputHandler *> inputHandlers() const;
void addTheme(Q3DTheme *theme);
@@ -117,6 +114,7 @@ signals:
void shadowQualityChanged(ShadowQuality quality);
private:
+ Q_DISABLE_COPY(QAbstract3DGraph)
QScopedPointer<QAbstract3DGraphPrivate> d_ptr;
friend class Q3DBars;
diff --git a/src/datavisualization/engine/qabstract3dgraph_p.h b/src/datavisualization/engine/qabstract3dgraph_p.h
index a353797b..d28495ab 100644
--- a/src/datavisualization/engine/qabstract3dgraph_p.h
+++ b/src/datavisualization/engine/qabstract3dgraph_p.h
@@ -31,8 +31,6 @@
#include "datavisualizationglobal_p.h"
-#include <QObject>
-
class QOpenGLContext;
class QOpenGLPaintDevice;
diff --git a/src/datavisualization/engine/scatter3dcontroller.cpp b/src/datavisualization/engine/scatter3dcontroller.cpp
index a1850a3c..54292ac0 100644
--- a/src/datavisualization/engine/scatter3dcontroller.cpp
+++ b/src/datavisualization/engine/scatter3dcontroller.cpp
@@ -24,8 +24,8 @@
#include "qscatterdataproxy_p.h"
#include "qscatter3dseries_p.h"
-#include <QMatrix4x4>
-#include <qmath.h>
+#include <QtGui/QMatrix4x4>
+#include <QtCore/qmath.h>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -303,6 +303,7 @@ void Scatter3DController::setSelectedItem(int index, QScatter3DSeries *series)
index = invalidSelectionIndex();
if (index != m_selectedItem || series != m_selectedItemSeries) {
+ bool seriesChanged = (series != m_selectedItemSeries);
m_selectedItem = index;
m_selectedItemSeries = series;
m_changeTracker.selectedItemChanged = true;
@@ -316,6 +317,9 @@ void Scatter3DController::setSelectedItem(int index, QScatter3DSeries *series)
if (m_selectedItemSeries)
m_selectedItemSeries->dptr()->setSelectedItem(m_selectedItem);
+ if (seriesChanged)
+ emit selectedSeriesChanged(m_selectedItemSeries);
+
emitNeedRender();
}
}
diff --git a/src/datavisualization/engine/scatter3dcontroller_p.h b/src/datavisualization/engine/scatter3dcontroller_p.h
index 173d4e05..53d24549 100644
--- a/src/datavisualization/engine/scatter3dcontroller_p.h
+++ b/src/datavisualization/engine/scatter3dcontroller_p.h
@@ -93,6 +93,8 @@ public:
// Change selection mode
void setSelectionMode(QAbstract3DGraph::SelectionFlags mode);
+ inline QScatter3DSeries *selectedSeries() const { return m_selectedItemSeries; }
+
void setSelectedItem(int index, QScatter3DSeries *series);
static inline int invalidSelectionIndex() { return -1; }
virtual void clearSelection();
@@ -116,6 +118,9 @@ public slots:
void handleItemsRemoved(int startIndex, int count);
void handleItemsInserted(int startIndex, int count);
+signals:
+ void selectedSeriesChanged(QScatter3DSeries *series);
+
protected:
virtual void startRecordingRemovesAndInserts();
diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp
index cf9dbefe..de1a769a 100644
--- a/src/datavisualization/engine/scatter3drenderer.cpp
+++ b/src/datavisualization/engine/scatter3drenderer.cpp
@@ -27,11 +27,10 @@
#include "q3dlight.h"
#include "qscatter3dseries_p.h"
-#include <QMatrix4x4>
-#include <QMouseEvent>
-#include <QThread>
-#include <qmath.h>
-#include <QDebug>
+#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.
@@ -210,7 +209,10 @@ void Scatter3DRenderer::updateData()
&& (dotPos.z() >= minZ && dotPos.z() <= maxZ)) {
renderItem.setPosition(dotPos);
renderItem.setVisible(true);
- renderItem.setRotation(dataArray.at(i).rotation());
+ if (!dataArray.at(i).rotation().isIdentity())
+ renderItem.setRotation(dataArray.at(i).rotation().normalized());
+ else
+ renderItem.setRotation(identityQuaternion);
calculateTranslation(renderItem);
} else {
renderItem.setVisible(false);
@@ -225,11 +227,11 @@ void Scatter3DRenderer::updateData()
void Scatter3DRenderer::updateScene(Q3DScene *scene)
{
- scene->activeCamera()->setMinYRotation(-90.0f);
+ scene->activeCamera()->d_ptr->setMinYRotation(-90.0f);
if (m_hasHeightAdjustmentChanged) {
// Set initial camera position. Also update if height adjustment has changed.
- scene->activeCamera()->setBaseOrientation(cameraDistanceVector, zeroVector, upVector);
+ scene->activeCamera()->d_ptr->setBaseOrientation(cameraDistanceVector, zeroVector, upVector);
m_hasHeightAdjustmentChanged = false;
}
@@ -273,7 +275,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
projectionMatrix.perspective(45.0f, viewPortRatio, 0.1f, 100.0f);
// Calculate view matrix
- QMatrix4x4 viewMatrix = activeCamera->viewMatrix();
+ QMatrix4x4 viewMatrix = activeCamera->d_ptr->viewMatrix();
QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix;
int seriesCount = m_visibleSeriesList.size();
@@ -354,7 +356,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
// Get the depth view matrix
// It may be possible to hack lightPos here if we want to make some tweaks to shadow
- QVector3D depthLightPos = activeCamera->calculatePositionRelativeToCamera(
+ QVector3D depthLightPos = activeCamera->d_ptr->calculatePositionRelativeToCamera(
zeroVector, 0.0f, 2.5f / m_autoScaleAdjustment);
depthViewMatrix.lookAt(depthLightPos, zeroVector, upVector);
// Set the depth projection matrix
@@ -444,6 +446,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
ShaderHelper *pointSelectionShader = m_selectionShader;
#else
+ Q_UNUSED(havePointSeries);
ShaderHelper *pointSelectionShader = m_pointShader;
#endif
ShaderHelper *selectionShader = m_selectionShader;
@@ -714,7 +717,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
dotShader->setUniformValue(dotShader->color(), dotColor);
} else if (colorStyle == Q3DTheme::ColorStyleRangeGradient) {
dotShader->setUniformValue(dotShader->gradientMin(),
- (item.position().y() + 1.0f) / 2.0f);
+ (item.translation().y() + 1.0f) / 2.0f);
}
#if !defined(QT_OPENGL_ES_2)
if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
@@ -1457,10 +1460,10 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
} else {
glDisable(GL_DEPTH_TEST);
// Draw the selection label
- LabelItem &labelItem = selectedItem->selectionLabelItem();
+ LabelItem &labelItem = selectionLabelItem();
if (m_selectedItem != selectedItem || m_updateLabels
|| !labelItem.textureId() || m_selectionLabelDirty) {
- QString labelText = selectedItem->selectionLabel();
+ QString labelText = selectionLabel();
if (labelText.isNull() || m_selectionLabelDirty) {
static const QString xTitleTag(QStringLiteral("@xTitle"));
static const QString yTitleTag(QStringLiteral("@yTitle"));
@@ -1502,7 +1505,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
}
labelText.replace(seriesNameTag, m_visibleSeriesList[m_selectedItemSeriesIndex].name());
- selectedItem->setSelectionLabel(labelText);
+ setSelectionLabel(labelText);
m_selectionLabelDirty = false;
}
m_drawer->generateLabelItem(labelItem, labelText);
@@ -1531,6 +1534,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
void Scatter3DRenderer::updateSelectedItem(int index, const QScatter3DSeries *series)
{
m_selectionDirty = true;
+ m_selectionLabelDirty = true;
m_selectedSeries = series;
m_selectedItemIndex = Scatter3DController::invalidSelectionIndex();
m_selectedItemTotalIndex = Scatter3DController::invalidSelectionIndex();
@@ -1633,12 +1637,6 @@ void Scatter3DRenderer::fixMeshFileName(QString &fileName, QAbstract3DSeries::Me
}
}
-void Scatter3DRenderer::updateAxisRange(QAbstract3DAxis::AxisOrientation orientation,
- float min, float max)
-{
- Abstract3DRenderer::updateAxisRange(orientation, min, max);
-}
-
void Scatter3DRenderer::calculateTranslation(ScatterRenderItem &item)
{
// We need to normalize translations
diff --git a/src/datavisualization/engine/scatter3drenderer_p.h b/src/datavisualization/engine/scatter3drenderer_p.h
index d7a880f9..5591a362 100644
--- a/src/datavisualization/engine/scatter3drenderer_p.h
+++ b/src/datavisualization/engine/scatter3drenderer_p.h
@@ -141,10 +141,6 @@ private:
friend class ScatterRenderItem;
public slots:
- // Overloaded from abstract renderer
- virtual void updateAxisRange(QAbstract3DAxis::AxisOrientation orientation, float min,
- float max);
-
void updateSelectedItem(int index, const QScatter3DSeries *series);
private:
diff --git a/src/datavisualization/engine/selectionpointer.cpp b/src/datavisualization/engine/selectionpointer.cpp
index 4f5e2114..d4e635bc 100644
--- a/src/datavisualization/engine/selectionpointer.cpp
+++ b/src/datavisualization/engine/selectionpointer.cpp
@@ -21,12 +21,12 @@
#include "shaderhelper_p.h"
#include "objecthelper_p.h"
#include "texturehelper_p.h"
-#include "q3dcamera.h"
+#include "q3dcamera_p.h"
#include "drawer_p.h"
#include "utils_p.h"
#include "q3dlight.h"
-#include <QMatrix4x4>
+#include <QtGui/QMatrix4x4>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -91,11 +91,13 @@ void SelectionPointer::render(GLuint defaultFboHandle)
QMatrix4x4 projectionMatrix;
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(-sliceUnits * aspect, sliceUnits * aspect,
- -sliceUnits, sliceUnits, -1.0f, 4.0f);
+ projectionMatrix.ortho(-sliceUnitsScaled * aspect, sliceUnitsScaled * aspect,
+ -sliceUnitsScaled, sliceUnitsScaled,
+ -1.0f, 4.0f);
} else {
- viewMatrix = camera->viewMatrix();
+ viewMatrix = camera->d_ptr->viewMatrix();
projectionMatrix.perspective(45.0f, (GLfloat)m_mainViewPort.width()
/ (GLfloat)m_mainViewPort.height(), 0.1f, 100.0f);
}
diff --git a/src/datavisualization/engine/selectionpointer_p.h b/src/datavisualization/engine/selectionpointer_p.h
index c72b3510..1eac22be 100644
--- a/src/datavisualization/engine/selectionpointer_p.h
+++ b/src/datavisualization/engine/selectionpointer_p.h
@@ -29,8 +29,6 @@
#ifndef SELECTIONPOINTER_P_H
#define SELECTIONPOINTER_P_H
-#include <QVector3D>
-
#include "q3dscene.h"
#include "datavisualizationglobal_p.h"
#include "surface3dcontroller_p.h"
diff --git a/src/datavisualization/engine/seriesrendercache.cpp b/src/datavisualization/engine/seriesrendercache.cpp
index fe2db319..896b3b28 100644
--- a/src/datavisualization/engine/seriesrendercache.cpp
+++ b/src/datavisualization/engine/seriesrendercache.cpp
@@ -30,6 +30,7 @@ SeriesRenderCache::SeriesRenderCache()
: m_series(0),
m_object(0),
m_mesh(QAbstract3DSeries::MeshCube),
+ m_baseUniformTexture(0),
m_baseGradientTexture(0),
m_singleHighlightGradientTexture(0),
m_multiHighlightGradientTexture(0)
@@ -127,7 +128,11 @@ void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer *
}
if (seriesChanged || changeTracker.meshRotationChanged) {
- m_meshRotation = series->meshRotation();
+ m_meshRotation = series->meshRotation().normalized();
+ if (m_series->type() == QAbstract3DSeries::SeriesTypeBar
+ && (m_meshRotation.x() || m_meshRotation.z())) {
+ m_meshRotation = identityQuaternion;
+ }
changeTracker.meshRotationChanged = false;
}
@@ -138,6 +143,8 @@ void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer *
if (seriesChanged || changeTracker.baseColorChanged) {
m_baseColor = Utils::vectorFromColor(series->baseColor());
+ if (m_series->type() == QAbstract3DSeries::SeriesTypeSurface)
+ renderer->generateBaseColorTexture(series->baseColor(), &m_baseUniformTexture);
changeTracker.baseColorChanged = false;
}
@@ -178,9 +185,12 @@ void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer *
void SeriesRenderCache::cleanup(TextureHelper *texHelper)
{
delete m_object;
- texHelper->deleteTexture(&m_baseGradientTexture);
- texHelper->deleteTexture(&m_singleHighlightGradientTexture);
- texHelper->deleteTexture(&m_multiHighlightGradientTexture);
+ if (QOpenGLContext::currentContext()) {
+ texHelper->deleteTexture(&m_baseUniformTexture);
+ texHelper->deleteTexture(&m_baseGradientTexture);
+ texHelper->deleteTexture(&m_singleHighlightGradientTexture);
+ texHelper->deleteTexture(&m_multiHighlightGradientTexture);
+ }
}
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/seriesrendercache_p.h b/src/datavisualization/engine/seriesrendercache_p.h
index 82f69ccd..77e050b0 100644
--- a/src/datavisualization/engine/seriesrendercache_p.h
+++ b/src/datavisualization/engine/seriesrendercache_p.h
@@ -45,7 +45,7 @@ public:
virtual ~SeriesRenderCache();
void populate(QAbstract3DSeries *series, Abstract3DRenderer *renderer);
- void cleanup(TextureHelper *texHelper);
+ 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.
@@ -58,6 +58,7 @@ public:
inline ObjectHelper *object() const { return m_object; }
inline const Q3DTheme::ColorStyle &colorStyle() const { return m_colorStyle; }
inline const QVector3D &baseColor() const { return m_baseColor; }
+ inline const GLuint &baseUniformTexture() const { return m_baseUniformTexture; }
inline const GLuint &baseGradientTexture() const { return m_baseGradientTexture; }
inline const QVector3D &singleHighlightColor() const { return m_singleHighlightColor; }
inline const GLuint &singleHighlightGradientTexture() const { return m_singleHighlightGradientTexture; }
@@ -74,6 +75,7 @@ protected:
Q3DTheme::ColorStyle m_colorStyle;
QVector3D m_baseColor;
+ GLuint m_baseUniformTexture;
GLuint m_baseGradientTexture;
QVector3D m_singleHighlightColor;
GLuint m_singleHighlightGradientTexture;
diff --git a/src/datavisualization/engine/surface3dcontroller.cpp b/src/datavisualization/engine/surface3dcontroller.cpp
index 0eb66d0e..991a1ce8 100644
--- a/src/datavisualization/engine/surface3dcontroller.cpp
+++ b/src/datavisualization/engine/surface3dcontroller.cpp
@@ -26,9 +26,7 @@
#include "qsurface3dseries_p.h"
#include "shaderhelper_p.h"
-#include <QMatrix4x4>
-
-#include <QDebug>
+#include <QtGui/QMatrix4x4>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -68,6 +66,11 @@ void Surface3DController::synchDataToRenderer()
if (!isInitialized())
return;
+ if (m_changedSeriesList.size()) {
+ m_renderer->modifiedSeriesList(m_changedSeriesList);
+ m_changedSeriesList.clear();
+ }
+
Abstract3DController::synchDataToRenderer();
// Notify changes to renderer
@@ -103,7 +106,7 @@ void Surface3DController::handleAxisRangeChangedBySender(QObject *sender)
Abstract3DController::handleAxisRangeChangedBySender(sender);
// Update selected point - may be moved offscreen
- setSelectedPoint(m_selectedPoint, m_selectedSeries);
+ setSelectedPoint(m_selectedPoint, m_selectedSeries, false);
}
void Surface3DController::handleSeriesVisibilityChangedBySender(QObject *sender)
@@ -112,9 +115,9 @@ void Surface3DController::handleSeriesVisibilityChangedBySender(QObject *sender)
adjustValueAxisRange();
- // Visibility changes may require disabling/enabling slicing,
+ // Visibility changes may require disabling slicing,
// so just reset selection to ensure everything is still valid.
- setSelectedPoint(m_selectedPoint, m_selectedSeries);
+ setSelectedPoint(m_selectedPoint, m_selectedSeries, false);
}
void Surface3DController::handlePendingClick()
@@ -123,7 +126,7 @@ void Surface3DController::handlePendingClick()
QPoint position = m_renderer->clickedPosition();
QSurface3DSeries *series = static_cast<QSurface3DSeries *>(m_renderer->clickedSeries());
- setSelectedPoint(position, series);
+ setSelectedPoint(position, series, true);
m_renderer->resetClickedStatus();
}
@@ -143,18 +146,14 @@ void Surface3DController::addSeries(QAbstract3DSeries *series)
{
Q_ASSERT(series && series->type() == QAbstract3DSeries::SeriesTypeSurface);
- if (!m_seriesList.size()) {
- Abstract3DController::addSeries(series);
+ Abstract3DController::addSeries(series);
- if (series->isVisible())
- adjustValueAxisRange();
- } else {
- qWarning("Surface graph only supports a single series.");
- }
+ if (series->isVisible())
+ adjustValueAxisRange();
QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(series);
if (surfaceSeries->selectedPoint() != invalidSelectionPosition())
- setSelectedPoint(surfaceSeries->selectedPoint(), surfaceSeries);
+ setSelectedPoint(surfaceSeries->selectedPoint(), surfaceSeries, false);
}
void Surface3DController::removeSeries(QAbstract3DSeries *series)
@@ -164,7 +163,7 @@ void Surface3DController::removeSeries(QAbstract3DSeries *series)
Abstract3DController::removeSeries(series);
if (m_selectedSeries == series)
- setSelectedPoint(invalidSelectionPosition(), 0);
+ setSelectedPoint(invalidSelectionPosition(), 0, false);
if (wasVisible)
adjustValueAxisRange();
@@ -203,7 +202,7 @@ void Surface3DController::setSelectionMode(QAbstract3DGraph::SelectionFlags mode
if (mode != oldMode) {
// Refresh selection upon mode change to ensure slicing is correctly updated
// according to series the visibility.
- setSelectedPoint(m_selectedPoint, m_selectedSeries);
+ setSelectedPoint(m_selectedPoint, m_selectedSeries, true);
// Special case: Always deactivate slicing when changing away from slice
// automanagement, as this can't be handled in setSelectedBar.
@@ -215,7 +214,7 @@ void Surface3DController::setSelectionMode(QAbstract3DGraph::SelectionFlags mode
}
}
-void Surface3DController::setSelectedPoint(const QPoint &position, QSurface3DSeries *series)
+void Surface3DController::setSelectedPoint(const QPoint &position, QSurface3DSeries *series, bool enterSlice)
{
// If the selection targets non-existent point, clear selection instead.
QPoint pos = position;
@@ -253,14 +252,15 @@ void Surface3DController::setSelectedPoint(const QPoint &position, QSurface3DSer
if (item.x() < axisMinX || item.x() > axisMaxX
|| item.z() < axisMinZ || item.z() > axisMaxZ) {
scene()->setSlicingActive(false);
- } else {
+ } else if (enterSlice) {
scene()->setSlicingActive(true);
}
}
emitNeedRender();
}
- if (pos != m_selectedPoint) {
+ if (pos != m_selectedPoint || series != m_selectedSeries) {
+ bool seriesChanged = (series != m_selectedSeries);
m_selectedPoint = pos;
m_selectedSeries = series;
m_changeTracker.selectedPointChanged = true;
@@ -274,13 +274,16 @@ void Surface3DController::setSelectedPoint(const QPoint &position, QSurface3DSer
if (m_selectedSeries)
m_selectedSeries->dptr()->setSelectedPoint(m_selectedPoint);
+ if (seriesChanged)
+ emit selectedSeriesChanged(m_selectedSeries);
+
emitNeedRender();
}
}
void Surface3DController::clearSelection()
{
- setSelectedPoint(invalidSelectionPosition(), 0);
+ setSelectedPoint(invalidSelectionPosition(), 0, false);
}
void Surface3DController::handleArrayReset()
@@ -288,10 +291,12 @@ void Surface3DController::handleArrayReset()
QSurface3DSeries *series = static_cast<QSurfaceDataProxy *>(sender())->series();
if (series->isVisible()) {
adjustValueAxisRange();
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
m_isDataDirty = true;
}
// Clear selection unless still valid
- setSelectedPoint(m_selectedPoint, m_selectedSeries);
+ setSelectedPoint(m_selectedPoint, m_selectedSeries, false);
emitNeedRender();
}
@@ -315,56 +320,55 @@ void Surface3DController::handleRowsChanged(int startIndex, int count)
m_changedRows.reserve(sender->rowCount());
QSurface3DSeries *series = sender->series();
- if (series->isVisible()) {
- // Change is for the visible series, put the change to queue
- int oldChangeCount = m_changedRows.size();
- for (int i = 0; i < count; i++) {
- bool newItem = true;
- int candidate = startIndex + i;
- for (int i = 0; i < oldChangeCount; i++) {
- if (m_changedRows.at(i) == candidate) {
- newItem = false;
- break;
- }
+ int oldChangeCount = m_changedRows.size();
+ for (int i = 0; i < count; i++) {
+ bool newItem = true;
+ int candidate = startIndex + i;
+ for (int i = 0; i < oldChangeCount; i++) {
+ if (m_changedRows.at(i).row == candidate &&
+ series == m_changedRows.at(i).series) {
+ newItem = false;
+ break;
}
- if (newItem)
- m_changedRows.append(candidate);
}
- if (m_changedRows.size()) {
- m_changeTracker.rowsChanged = true;
-
- adjustValueAxisRange();
- // Clear selection unless still valid
- setSelectedPoint(m_selectedPoint, m_selectedSeries);
- emitNeedRender();
+ if (newItem) {
+ ChangeRow newItem = {series, candidate};
+ m_changedRows.append(newItem);
}
}
+ if (m_changedRows.size()) {
+ m_changeTracker.rowsChanged = true;
+
+ adjustValueAxisRange();
+ // Clear selection unless still valid
+ setSelectedPoint(m_selectedPoint, m_selectedSeries, false);
+ emitNeedRender();
+ }
}
void Surface3DController::handleItemChanged(int rowIndex, int columnIndex)
{
QSurfaceDataProxy *sender = static_cast<QSurfaceDataProxy *>(QObject::sender());
QSurface3DSeries *series = sender->series();
- if (series->isVisible()) {
- // Change is for the visible series, put the change to queue
- bool newItem = true;
- QPoint candidate(columnIndex, rowIndex);
- foreach (QPoint item, m_changedItems) {
- if (item == candidate) {
- newItem = false;
- break;
- }
- }
- if (newItem) {
- m_changedItems.append(candidate);
- m_changeTracker.itemChanged = true;
- adjustValueAxisRange();
- // Clear selection unless still valid
- setSelectedPoint(m_selectedPoint, m_selectedSeries);
- emitNeedRender();
+ bool newItem = true;
+ QPoint candidate(columnIndex, rowIndex);
+ 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;
+
+ adjustValueAxisRange();
+ // Clear selection unless still valid
+ setSelectedPoint(m_selectedPoint, m_selectedSeries, false);
+ emitNeedRender();
+ }
}
void Surface3DController::handleRowsAdded(int startIndex, int count)
@@ -375,6 +379,8 @@ void Surface3DController::handleRowsAdded(int startIndex, int count)
if (series->isVisible()) {
adjustValueAxisRange();
m_isDataDirty = true;
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
}
emitNeedRender();
}
@@ -389,13 +395,15 @@ void Surface3DController::handleRowsInserted(int startIndex, int count)
int selectedRow = m_selectedPoint.x();
if (startIndex <= selectedRow) {
selectedRow += count;
- setSelectedPoint(QPoint(selectedRow, m_selectedPoint.y()), m_selectedSeries);
+ setSelectedPoint(QPoint(selectedRow, m_selectedPoint.y()), m_selectedSeries, false);
}
}
if (series->isVisible()) {
adjustValueAxisRange();
m_isDataDirty = true;
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
}
emitNeedRender();
@@ -415,13 +423,15 @@ void Surface3DController::handleRowsRemoved(int startIndex, int count)
else
selectedRow -= count; // Move selected row down by amount of rows removed
- setSelectedPoint(QPoint(selectedRow, m_selectedPoint.y()), m_selectedSeries);
+ setSelectedPoint(QPoint(selectedRow, m_selectedPoint.y()), m_selectedSeries, false);
}
}
if (series->isVisible()) {
adjustValueAxisRange();
m_isDataDirty = true;
+ if (!m_changedSeriesList.contains(series))
+ m_changedSeriesList.append(series);
}
emitNeedRender();
@@ -435,6 +445,7 @@ void Surface3DController::adjustValueAxisRange()
bool adjustX = (valueAxisX && valueAxisX->isAutoAdjustRange());
bool adjustY = (valueAxisY && valueAxisY->isAutoAdjustRange());
bool adjustZ = (valueAxisZ && valueAxisZ->isAutoAdjustRange());
+ bool first = true;
if (adjustX || adjustY || adjustZ) {
float minValueX = 0.0f;
@@ -453,7 +464,7 @@ void Surface3DController::adjustValueAxisRange()
QVector3D maxLimits;
proxy->dptrc()->limitValues(minLimits, maxLimits);
if (adjustX) {
- if (!series) {
+ if (first) {
// First series initializes the values
minValueX = minLimits.x();
maxValueX = maxLimits.x();
@@ -463,7 +474,7 @@ void Surface3DController::adjustValueAxisRange()
}
}
if (adjustY) {
- if (!series) {
+ if (first) {
// First series initializes the values
minValueY = minLimits.y();
maxValueY = maxLimits.y();
@@ -473,7 +484,7 @@ void Surface3DController::adjustValueAxisRange()
}
}
if (adjustZ) {
- if (!series) {
+ if (first) {
// First series initializes the values
minValueZ = minLimits.z();
maxValueZ = maxLimits.z();
@@ -482,6 +493,7 @@ void Surface3DController::adjustValueAxisRange()
maxValueZ = qMax(maxValueZ, maxLimits.z());
}
}
+ first = false;
}
}
diff --git a/src/datavisualization/engine/surface3dcontroller_p.h b/src/datavisualization/engine/surface3dcontroller_p.h
index 624bea47..14c0dd40 100644
--- a/src/datavisualization/engine/surface3dcontroller_p.h
+++ b/src/datavisualization/engine/surface3dcontroller_p.h
@@ -58,6 +58,16 @@ class QT_DATAVISUALIZATION_EXPORT Surface3DController : public Abstract3DControl
{
Q_OBJECT
+public:
+ struct ChangeItem {
+ QSurface3DSeries *series;
+ QPoint point;
+ };
+ struct ChangeRow {
+ QSurface3DSeries *series;
+ int row;
+ };
+
private:
Surface3DChangeBitField m_changeTracker;
Surface3DRenderer *m_renderer;
@@ -65,8 +75,9 @@ private:
QSurface3DSeries *m_selectedSeries; // Points to the series for which the point is selected in
// single series selection cases.
bool m_flatShadingSupported;
- QVector<QPoint> m_changedItems;
- QVector<int> m_changedRows;
+ QVector<ChangeItem> m_changedItems;
+ QVector<ChangeRow> m_changedRows;
+ QVector<QSurface3DSeries *> m_changedSeriesList;
public:
explicit Surface3DController(QRect rect, Q3DScene *scene = 0);
@@ -76,9 +87,11 @@ public:
virtual void synchDataToRenderer();
void setSelectionMode(QAbstract3DGraph::SelectionFlags mode);
- void setSelectedPoint(const QPoint &position, QSurface3DSeries *series);
+ void setSelectedPoint(const QPoint &position, QSurface3DSeries *series, bool enterSlice);
virtual void clearSelection();
+ inline QSurface3DSeries *selectedSeries() const { return m_selectedSeries; }
+
virtual void handleAxisAutoAdjustRangeChangedInOrientation(
QAbstract3DAxis::AxisOrientation orientation, bool autoAdjust);
virtual void handleAxisRangeChangedBySender(QObject *sender);
@@ -102,6 +115,9 @@ public slots:
void handleFlatShadingSupportedChange(bool supported);
+signals:
+ void selectedSeriesChanged(QSurface3DSeries *series);
+
private:
void adjustValueAxisRange();
diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp
index 82f9eae1..ffcdeb7a 100644
--- a/src/datavisualization/engine/surface3drenderer.cpp
+++ b/src/datavisualization/engine/surface3drenderer.cpp
@@ -30,11 +30,9 @@
#include "q3dlight.h"
#include "qsurface3dseries_p.h"
-#include <QMatrix4x4>
-#include <QMouseEvent>
-#include <qmath.h>
-
-#include <QDebug>
+#include <QtGui/QMatrix4x4>
+#include <QtGui/QMouseEvent>
+#include <QtCore/qmath.h>
static const int ID_TO_RGBA_MASK = 0xff;
@@ -45,22 +43,17 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
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;
-const GLfloat backgroundBottom = 1.0f;
const GLfloat gridLineWidth = 0.005f;
const GLfloat sliceZScale = 0.1f;
const GLfloat sliceUnits = 2.5f;
-const int subViewDivider = 5;
-const uint invalidSelectionId = uint(-1);
Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
: Abstract3DRenderer(controller),
- m_labelBackground(false),
- m_font(QFont(QStringLiteral("Arial"))),
- m_isGridEnabled(true),
m_cachedIsSlicingActivated(false),
m_depthShader(0),
m_backgroundShader(0),
- m_surfaceShader(0),
+ m_surfaceFlatShader(0),
+ m_surfaceSmoothShader(0),
m_surfaceGridShader(0),
m_selectionShader(0),
m_labelShader(0),
@@ -70,10 +63,6 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_scaleZ(0.0f),
m_scaleXWithBackground(0.0f),
m_scaleZWithBackground(0.0f),
- m_surfaceScaleX(0.0f),
- m_surfaceScaleZ(0.0f),
- m_surfaceOffsetX(0.0f),
- m_surfaceOffsetZ(0.0f),
m_minVisibleColumnValue(0.0f),
m_maxVisibleColumnValue(0.0f),
m_minVisibleRowValue(0.0f),
@@ -83,33 +72,25 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
m_backgroundObj(0),
m_gridLineObj(0),
m_labelObj(0),
- m_surfaceObj(0),
- m_sliceSurfaceObj(0),
m_depthTexture(0),
m_depthModelTexture(0),
m_depthFrameBuffer(0),
m_selectionFrameBuffer(0),
m_selectionDepthBuffer(0),
- m_selectionTexture(0),
m_selectionResultTexture(0),
m_shadowQualityToShader(33.3f),
- m_cachedFlatShading(false),
m_flatSupported(true),
- m_cachedSurfaceVisible(true),
- m_cachedSurfaceGridOn(true),
- m_selectionPointer(0),
m_selectionActive(false),
m_xFlipped(false),
m_zFlipped(false),
m_yFlipped(false),
- m_sampleSpace(QRect(0, 0, 0, 0)),
m_shadowQualityMultiplier(3),
- m_clickedPointId(invalidSelectionId),
m_hasHeightAdjustmentChanged(true),
m_selectedPoint(Surface3DController::invalidSelectionPosition()),
m_selectedSeries(0),
- m_uniformGradientTexture(0),
- m_clickedPosition(Surface3DController::invalidSelectionPosition())
+ m_clickedPosition(Surface3DController::invalidSelectionPosition()),
+ m_selectionTexturesDirty(false),
+ m_noShadowTexture(0)
{
// Check if flat feature is supported
ShaderHelper tester(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
@@ -125,9 +106,6 @@ Surface3DRenderer::Surface3DRenderer(Surface3DController *controller)
initializeOpenGLFunctions();
initializeOpenGL();
-
- // Create initial uniform gradient
- generateUniformGradient(m_uniformGradientTextureColor);
}
Surface3DRenderer::~Surface3DRenderer()
@@ -137,34 +115,28 @@ Surface3DRenderer::~Surface3DRenderer()
m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer);
m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer);
+ m_textureHelper->deleteTexture(&m_noShadowTexture);
m_textureHelper->deleteTexture(&m_depthTexture);
m_textureHelper->deleteTexture(&m_depthModelTexture);
- m_textureHelper->deleteTexture(&m_selectionTexture);
m_textureHelper->deleteTexture(&m_selectionResultTexture);
- m_textureHelper->deleteTexture(&m_uniformGradientTexture);
}
delete m_depthShader;
delete m_backgroundShader;
delete m_selectionShader;
- delete m_surfaceShader;
+ delete m_surfaceFlatShader;
+ delete m_surfaceSmoothShader;
delete m_surfaceGridShader;
delete m_labelShader;
delete m_backgroundObj;
- delete m_surfaceObj;
- delete m_sliceSurfaceObj;
delete m_gridLineObj;
delete m_labelObj;
- delete m_selectionPointer;
-
- for (int i = 0; i < m_dataArray.size(); i++)
- delete m_dataArray.at(i);
- m_dataArray.clear();
-
- for (int i = 0; i < m_sliceDataArray.size(); i++)
- delete m_sliceDataArray.at(i);
- m_sliceDataArray.clear();
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ cache->cleanup(m_textureHelper);
+ delete cache;
+ }
+ m_renderCacheList.clear();
}
void Surface3DRenderer::initializeOpenGL()
@@ -196,81 +168,65 @@ void Surface3DRenderer::initializeOpenGL()
// Load background mesh (we need to be initialized first)
loadBackgroundMesh();
+
+ // Create texture for no shadows
+ QImage image(2, 2, QImage::Format_RGB32);
+ image.fill(Qt::white);
+ m_noShadowTexture = m_textureHelper->create2DTexture(image, false, true, false, true);
}
void Surface3DRenderer::updateData()
{
- // Surface only supports single series for now, so we are only interested in the first series
- const QSurfaceDataArray *array = 0;
- if (m_visibleSeriesList.size()) {
- QSurface3DSeries *firstSeries = static_cast<QSurface3DSeries *>(m_visibleSeriesList.at(0).series());
- QSurfaceDataProxy *dataProxy = firstSeries->dataProxy();
- if (dataProxy)
- array = dataProxy->array();
- }
-
calculateSceneScalingFactors();
- // Need minimum of 2x2 array to draw a surface
- if (array && array->size() >= 2 && array->at(0)->size() >= 2) {
- QRect sampleSpace = calculateSampleRect(*array);
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ const QSurface3DSeries *currentSeries = cache->series();
+ QSurfaceDataProxy *dataProxy = currentSeries->dataProxy();
+ const QSurfaceDataArray &array = *dataProxy->array();
- bool dimensionChanged = false;
- if (m_sampleSpace != sampleSpace) {
- dimensionChanged = true;
- m_sampleSpace = sampleSpace;
+ // Need minimum of 2x2 array to draw a surface
+ if (array.size() >= 2 && array.at(0)->size() >= 2) {
+ QRect sampleSpace = calculateSampleRect(cache, array);
- for (int i = 0; i < m_dataArray.size(); i++)
- delete m_dataArray.at(i);
- m_dataArray.clear();
- }
+ QSurfaceDataArray &dataArray = cache->dataArray();
+ bool dimensionChanged = false;
+ if (cache->sampleSpace() != sampleSpace) {
+ if (sampleSpace.width() >= 2)
+ m_selectionTexturesDirty = true;
- if (sampleSpace.width() >= 2 && sampleSpace.height() >= 2) {
- if (dimensionChanged) {
- m_dataArray.reserve(sampleSpace.height());
- for (int i = 0; i < sampleSpace.height(); i++)
- m_dataArray << new QSurfaceDataRow(sampleSpace.width());
- }
- for (int i = 0; i < sampleSpace.height(); i++) {
- for (int j = 0; j < sampleSpace.width(); j++)
- (*(m_dataArray.at(i)))[j] = array->at(i + sampleSpace.y())->at(
- j + sampleSpace.x());
- }
+ dimensionChanged = true;
+ cache->setSampleSpace(sampleSpace);
- if (m_dataArray.size() > 0) {
- if (!m_surfaceObj)
- loadSurfaceObj();
+ for (int i = 0; i < dataArray.size(); i++)
+ delete dataArray.at(i);
+ dataArray.clear();
+ }
- // Note: Data setup can change sample space (as min width/height is 1)
- if (!m_cachedFlatShading) {
- m_surfaceObj->setUpSmoothData(m_dataArray, m_sampleSpace, m_heightNormalizer,
- m_axisCacheY.min(), dimensionChanged);
- } else {
- m_surfaceObj->setUpData(m_dataArray, m_sampleSpace, m_heightNormalizer,
- m_axisCacheY.min(), dimensionChanged);
+ if (sampleSpace.width() >= 2 && sampleSpace.height() >= 2) {
+ if (dimensionChanged) {
+ dataArray.reserve(sampleSpace.height());
+ for (int i = 0; i < sampleSpace.height(); i++)
+ dataArray << new QSurfaceDataRow(sampleSpace.width());
+ }
+ for (int i = 0; i < sampleSpace.height(); i++) {
+ for (int j = 0; j < sampleSpace.width(); j++) {
+ (*(dataArray.at(i)))[j] = array.at(i + sampleSpace.y())->at(
+ j + sampleSpace.x());
+ }
}
- if (dimensionChanged)
- updateSelectionTexture();
+ if (dataArray.size() > 0 && (cache->objectDirty() || dimensionChanged)) {
+ checkFlatSupport(cache);
+ updateObjects(cache, dimensionChanged);
+ cache->setObjectDirty(false);
+ cache->setFlatStatusDirty(false);
+ }
}
}
- } else {
- for (int i = 0; i < m_dataArray.size(); i++)
- delete m_dataArray.at(i);
- m_dataArray.clear();
- m_sampleSpace = QRect();
-
- delete m_surfaceObj;
- m_surfaceObj = 0;
-#if !defined(QT_OPENGL_ES_2)
- m_textureHelper->fillDepthTexture(m_depthTexture, m_primarySubViewport.size(),
- m_shadowQualityMultiplier, 1.0f);
-#endif
}
- for (int i = 0; i < m_sliceDataArray.size(); i++)
- delete m_sliceDataArray.at(i);
- m_sliceDataArray.clear();
+ if (m_selectionTexturesDirty && m_cachedSelectionMode > QAbstract3DGraph::SelectionNone)
+ updateSelectionTextures();
updateSelectedPoint(m_selectedPoint, m_selectedSeries);
}
@@ -278,171 +234,360 @@ void Surface3DRenderer::updateData()
void Surface3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesList,
bool updateVisibility)
{
- Abstract3DRenderer::updateSeries(seriesList, updateVisibility);
+ Q_UNUSED(updateVisibility);
- if (m_visibleSeriesList.size()) {
- QSurface3DSeries *series = static_cast<QSurface3DSeries *>(m_visibleSeriesList.at(0).series());
- updateFlatStatus(series->isFlatShadingEnabled());
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList)
+ cache->setValid(false);
- QSurface3DSeries::DrawFlags drawMode = series->drawMode();
- m_cachedSurfaceVisible = drawMode.testFlag(QSurface3DSeries::DrawSurface);
-#if !defined(QT_OPENGL_ES_2)
- if (!m_cachedSurfaceVisible) {
- m_textureHelper->fillDepthTexture(m_depthTexture, m_primarySubViewport.size(),
- m_shadowQualityMultiplier, 1.0f);
+ 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;
}
-#endif
- m_cachedSurfaceGridOn = drawMode.testFlag(QSurface3DSeries::DrawWireframe);
-
- QVector3D seriesColor = Utils::vectorFromColor(series->baseColor());
- if (m_uniformGradientTextureColor != seriesColor)
- generateUniformGradient(seriesColor);
- if (m_selectionPointer) {
- m_selectionPointer->setHighlightColor(
- Utils::vectorFromColor(series->singleHighlightColor()));
- // Make sure selection pointer object reference is still good
- m_selectionPointer->setPointerObject(m_visibleSeriesList.at(0).object());
- m_selectionPointer->setRotation(m_visibleSeriesList.at(0).meshRotation());
+
+ QSurface3DSeries *surfaceSeries = static_cast<QSurface3DSeries *>(series);
+ SurfaceSeriesRenderCache *cache = m_renderCacheList.value(surfaceSeries);
+ if (!cache) {
+ cache = new SurfaceSeriesRenderCache;
+ m_renderCacheList[surfaceSeries] = cache;
+
+ m_selectionTexturesDirty = true;
+ }
+ cache->setValid(true);
+ cache->populate(surfaceSeries, this);
+ if (cache->isFlatStatusDirty() && cache->sampleSpace().width()) {
+ checkFlatSupport(cache);
+ updateObjects(cache, true);
+ cache->setFlatStatusDirty(false);
+ }
+ }
+
+ // 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;
+ }
+ }
+
+ // Selection pointer issues
+ if (m_selectedSeries) {
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ QVector3D highlightColor =
+ Utils::vectorFromColor(cache->series()->singleHighlightColor());
+ SelectionPointer *slicePointer = cache->sliceSelectionPointer();
+ if (slicePointer) {
+ slicePointer->setHighlightColor(highlightColor);
+ slicePointer->setPointerObject(cache->object());
+ slicePointer->setRotation(cache->meshRotation());
+ }
+ SelectionPointer *mainPointer = cache->mainSelectionPointer();
+ if (mainPointer) {
+ mainPointer->setHighlightColor(highlightColor);
+ mainPointer->setPointerObject(cache->object());
+ mainPointer->setRotation(cache->meshRotation());
+ }
}
}
}
-void Surface3DRenderer::updateRows(const QVector<int> &rows)
+void Surface3DRenderer::modifiedSeriesList(const QVector<QSurface3DSeries *> &seriesList)
{
- // Surface only supports single series for now, so we are only interested in the first series
- const QSurfaceDataArray *array = 0;
- if (m_visibleSeriesList.size()) {
- QSurface3DSeries *firstSeries = static_cast<QSurface3DSeries *>(m_visibleSeriesList.at(0).series());
- QSurfaceDataProxy *dataProxy = firstSeries->dataProxy();
- if (dataProxy)
- array = dataProxy->array();
+ foreach (QSurface3DSeries *series, seriesList) {
+ SurfaceSeriesRenderCache *cache = m_renderCacheList.value(series);
+ if (cache)
+ cache->setObjectDirty(true);
}
+}
+
+void Surface3DRenderer::updateRows(const QVector<Surface3DController::ChangeRow> &rows)
+{
+ foreach (Surface3DController::ChangeRow item, rows) {
+ SurfaceSeriesRenderCache *cache = m_renderCacheList.value(item.series);
+ QSurfaceDataArray &dstArray = cache->dataArray();
+ const QRect &sampleSpace = cache->sampleSpace();
- if (array && array->size() >= 2 && array->at(0)->size() >= 2
- && m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) {
- bool updateBuffers = false;
- int sampleSpaceTop = m_sampleSpace.y() + m_sampleSpace.height();
- foreach (int row, rows) {
- if (row >= m_sampleSpace.y() && row <= sampleSpaceTop) {
+ const QSurfaceDataArray *srcArray = 0;
+ QSurfaceDataProxy *dataProxy = item.series->dataProxy();
+ if (dataProxy)
+ srcArray = dataProxy->array();
+
+ if (cache && srcArray->size() >= 2 && srcArray->at(0)->size() >= 2 &&
+ sampleSpace.width() >= 2 && sampleSpace.height() >= 2) {
+ bool updateBuffers = false;
+ int sampleSpaceTop = sampleSpace.y() + sampleSpace.height();
+ int row = item.row;
+ if (row >= sampleSpace.y() && row <= sampleSpaceTop) {
updateBuffers = true;
- for (int j = 0; j < m_sampleSpace.width(); j++)
- (*(m_dataArray.at(row - m_sampleSpace.y())))[j] =
- array->at(row)->at(j + m_sampleSpace.x());
-
- if (m_cachedFlatShading) {
- m_surfaceObj->updateCoarseRow(m_dataArray, row - m_sampleSpace.y(),
- m_heightNormalizer,
- m_axisCacheY.min());
+ for (int j = 0; j < sampleSpace.width(); j++) {
+ (*(dstArray.at(row - sampleSpace.y())))[j] =
+ srcArray->at(row)->at(j + sampleSpace.x());
+ }
+
+ if (cache->isFlatShadingEnabled()) {
+ cache->surfaceObject()->updateCoarseRow(dstArray, row - sampleSpace.y(),
+ m_heightNormalizer,
+ m_axisCacheY.min());
} else {
- m_surfaceObj->updateSmoothRow(m_dataArray, row - m_sampleSpace.y(),
- m_heightNormalizer,
- m_axisCacheY.min());
+ cache->surfaceObject()->updateSmoothRow(dstArray, row - sampleSpace.y(),
+ m_heightNormalizer,
+ m_axisCacheY.min());
}
}
+ if (updateBuffers)
+ cache->surfaceObject()->uploadBuffers();
}
- if (updateBuffers)
- m_surfaceObj->uploadBuffers();
}
updateSelectedPoint(m_selectedPoint, m_selectedSeries);
}
-void Surface3DRenderer::updateItem(const QVector<QPoint> &points)
+void Surface3DRenderer::updateItem(const QVector<Surface3DController::ChangeItem> &points)
{
- // Surface only supports single series for now, so we are only interested in the first series
- const QSurfaceDataArray *array = 0;
- if (m_visibleSeriesList.size()) {
- QSurface3DSeries *firstSeries = static_cast<QSurface3DSeries *>(m_visibleSeriesList.at(0).series());
- QSurfaceDataProxy *dataProxy = firstSeries->dataProxy();
+ foreach (Surface3DController::ChangeItem item, points) {
+ SurfaceSeriesRenderCache *cache = m_renderCacheList.value(item.series);
+ QSurfaceDataArray &dstArray = cache->dataArray();
+ const QRect &sampleSpace = cache->sampleSpace();
+
+ const QSurfaceDataArray *srcArray = 0;
+ QSurfaceDataProxy *dataProxy = item.series->dataProxy();
if (dataProxy)
- array = dataProxy->array();
- }
+ srcArray = dataProxy->array();
- if (array && array->size() >= 2 && array->at(0)->size() >= 2
- && m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) {
- int sampleSpaceTop = m_sampleSpace.y() + m_sampleSpace.height();
- int sampleSpaceRight = m_sampleSpace.x() + m_sampleSpace.width();
- bool updateBuffers = false;
- foreach (QPoint item, points) {
- if (item.y() <= sampleSpaceTop && item.y() >= m_sampleSpace.y() &&
- item.x() <= sampleSpaceRight && item.x() >= m_sampleSpace.x()) {
+ if (cache && srcArray->size() >= 2 && srcArray->at(0)->size() >= 2 &&
+ sampleSpace.width() >= 2 && sampleSpace.height() >= 2) {
+ int sampleSpaceTop = sampleSpace.y() + sampleSpace.height();
+ int sampleSpaceRight = sampleSpace.x() + sampleSpace.width();
+ bool updateBuffers = false;
+ QPoint point = item.point;
+
+ if (point.y() <= sampleSpaceTop && point.y() >= sampleSpace.y() &&
+ point.x() <= sampleSpaceRight && point.x() >= sampleSpace.x()) {
updateBuffers = true;
- int x = item.x() - m_sampleSpace.x();
- int y = item.y() - m_sampleSpace.y();
- (*(m_dataArray.at(y)))[x] = array->at(item.y())->at(item.x());
+ int x = point.x() - sampleSpace.x();
+ int y = point.y() - sampleSpace.y();
+ (*(dstArray.at(y)))[x] = srcArray->at(point.y())->at(point.x());
- if (m_cachedFlatShading) {
- m_surfaceObj->updateCoarseItem(m_dataArray, y, x, m_heightNormalizer,
- m_axisCacheY.min());
+ if (cache->isFlatShadingEnabled()) {
+ cache->surfaceObject()->updateCoarseItem(dstArray, y, x, m_heightNormalizer,
+ m_axisCacheY.min());
} else {
- m_surfaceObj->updateSmoothItem(m_dataArray, y, x, m_heightNormalizer,
- m_axisCacheY.min());
+ cache->surfaceObject()->updateSmoothItem(dstArray, y, x, m_heightNormalizer,
+ m_axisCacheY.min());
}
}
+ if (updateBuffers)
+ cache->surfaceObject()->uploadBuffers();
}
- if (updateBuffers)
- m_surfaceObj->uploadBuffers();
+
}
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();
+
+ 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();
+ QSurfaceDataItem item = dataArray.at(point.x())->at(point.y());
+ QPointF coords(item.x(), item.z());
+
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ if (cache->series() != m_selectedSeries) {
+ QPoint mappedPoint = mapCoordsToSampleSpace(cache, coords);
+ updateSliceObject(cache, mappedPoint);
+ } else {
+ updateSliceObject(cache, point);
+ }
+ }
+ } else {
+ if (m_selectedSeries) {
+ SurfaceSeriesRenderCache *cache =
+ m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries));
+ if (cache)
+ updateSliceObject(cache, point);
+ }
+ }
+}
+
+QPoint Surface3DRenderer::mapCoordsToSampleSpace(SurfaceSeriesRenderCache *cache,
+ const QPointF &coords)
+{
+ QPoint point(-1, -1);
+
+ QSurfaceDataArray &dataArray = cache->dataArray();
+ int top = dataArray.size() - 1;
+ int right = dataArray.at(top)->size() - 1;
+ QSurfaceDataItem itemBottomLeft = dataArray.at(0)->at(0);
+ QSurfaceDataItem itemTopRight = dataArray.at(top)->at(right);
+
+ if (itemBottomLeft.x() <= coords.x() && itemTopRight.x() >= coords.x()) {
+ float modelX = coords.x() - itemBottomLeft.x();
+ float spanX = itemTopRight.x() - itemBottomLeft.x();
+ float stepX = spanX / float(right);
+ int sampleX = int((modelX + (stepX / 2.0f)) / stepX);
+
+ QSurfaceDataItem item = dataArray.at(0)->at(sampleX);
+ if (!::qFuzzyCompare(float(coords.x()), item.x())) {
+ int direction = 1;
+ if (item.x() > coords.x())
+ direction = -1;
+
+ findMatchingColumn(coords.x(), sampleX, direction, dataArray);
+ }
+
+ if (sampleX >= 0 && sampleX <= right)
+ point.setY(sampleX);
+ }
+
+ if (itemBottomLeft.z() <= coords.y() && itemTopRight.z() >= coords.y()) {
+ float modelY = coords.y() - itemBottomLeft.z();
+ float spanY = itemTopRight.z() - itemBottomLeft.z();
+ float stepY = spanY / float(top);
+ int sampleY = int((modelY + (stepY / 2.0f)) / stepY);
+
+ QSurfaceDataItem item = dataArray.at(sampleY)->at(0);
+ if (!::qFuzzyCompare(float(coords.y()), item.z())) {
+ int direction = 1;
+ if (item.z() > coords.y())
+ direction = -1;
+
+ findMatchingRow(coords.y(), sampleY, direction, dataArray);
+ }
+
+ if (sampleY >= 0 && sampleY <= top)
+ point.setX(sampleY);
+ }
+
+ return point;
+}
+
+void Surface3DRenderer::findMatchingRow(float z, int &sample, int direction,
+ QSurfaceDataArray &dataArray)
+{
+ int maxZ = dataArray.size() - 1;
+ QSurfaceDataItem item = dataArray.at(sample)->at(0);
+ float distance = qAbs(z - item.z());
+ int newSample = sample + direction;
+ while (newSample >= 0 && newSample <= maxZ) {
+ item = dataArray.at(newSample)->at(0);
+ float newDist = qAbs(z - item.z());
+ if (newDist < distance) {
+ sample = newSample;
+ distance = newDist;
+ } else {
+ break;
+ }
+ newSample = sample + direction;
+ }
+}
+
+void Surface3DRenderer::findMatchingColumn(float x, int &sample, int direction,
+ QSurfaceDataArray &dataArray)
+{
+ int maxX = dataArray.at(0)->size() - 1;
+ QSurfaceDataItem item = dataArray.at(0)->at(sample);
+ float distance = qAbs(x - item.x());
+ int newSample = sample + direction;
+ while (newSample >= 0 && newSample <= maxX) {
+ item = dataArray.at(0)->at(newSample);
+ float newDist = qAbs(x - item.x());
+ if (newDist < distance) {
+ sample = newSample;
+ distance = newDist;
+ } else {
+ break;
+ }
+ newSample = sample + direction;
+ }
+}
+
+void Surface3DRenderer::updateSliceObject(SurfaceSeriesRenderCache *cache, const QPoint &point)
+{
int column = point.y();
int row = point.x();
- for (int i = 0; i < m_sliceDataArray.size(); i++)
- delete m_sliceDataArray.at(i);
- m_sliceDataArray.clear();
+ if ((m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow) && row == -1) ||
+ (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionColumn) && column == -1)) {
+ cache->sliceSurfaceObject()->clear();
+ return;
+ }
- m_sliceDataArray.reserve(2);
- QSurfaceDataRow *sliceRow;
+ QSurfaceDataArray &sliceDataArray = cache->sliceDataArray();
+ for (int i = 0; i < sliceDataArray.size(); i++)
+ delete sliceDataArray.at(i);
+ sliceDataArray.clear();
+ sliceDataArray.reserve(2);
+ QSurfaceDataRow *sliceRow;
+ QSurfaceDataArray &dataArray = cache->dataArray();
float adjust = (0.025f * m_heightNormalizer) / 2.0f;
float stepDown = 2.0f * adjust;
if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow)) {
- QSurfaceDataRow *src = m_dataArray.at(row);
+ QSurfaceDataRow *src = dataArray.at(row);
sliceRow = new QSurfaceDataRow(src->size());
for (int i = 0; i < sliceRow->size(); i++)
(*sliceRow)[i].setPosition(QVector3D(src->at(i).x(), src->at(i).y() + adjust, -1.0f));
} else {
- sliceRow = new QSurfaceDataRow(m_sampleSpace.height());
- for (int i = 0; i < m_sampleSpace.height(); i++) {
- (*sliceRow)[i].setPosition(QVector3D(m_dataArray.at(i)->at(column).z(),
- m_dataArray.at(i)->at(column).y() + adjust,
+ const QRect &sampleSpace = cache->sampleSpace();
+ sliceRow = new QSurfaceDataRow(sampleSpace.height());
+ 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));
}
}
-
- m_sliceDataArray << sliceRow;
+ sliceDataArray << sliceRow;
// Make a duplicate, so that we get a little bit depth
QSurfaceDataRow *duplicateRow = new QSurfaceDataRow(*sliceRow);
for (int i = 0; i < sliceRow->size(); i++) {
- (*sliceRow)[i].setPosition(QVector3D(sliceRow->at(i).x(), sliceRow->at(i).y() - stepDown,
+ (*sliceRow)[i].setPosition(QVector3D(sliceRow->at(i).x(),
+ sliceRow->at(i).y() - stepDown,
1.0f));
}
-
- m_sliceDataArray << duplicateRow;
+ sliceDataArray << duplicateRow;
QRect sliceRect(0, 0, sliceRow->size(), 2);
-
if (sliceRow->size() > 0) {
- if (!m_sliceSurfaceObj)
- loadSliceSurfaceObj();
-
- if (!m_cachedFlatShading) {
- m_sliceSurfaceObj->setUpSmoothData(m_sliceDataArray, sliceRect, m_heightNormalizer,
- m_axisCacheY.min(), true);
+ if (cache->isFlatShadingEnabled()) {
+ cache->sliceSurfaceObject()->setUpData(sliceDataArray, sliceRect,
+ m_heightNormalizer,
+ m_axisCacheY.min(), true);
} else {
- m_sliceSurfaceObj->setUpData(m_sliceDataArray, sliceRect, m_heightNormalizer,
- m_axisCacheY.min(), true);
+ cache->sliceSurfaceObject()->setUpSmoothData(sliceDataArray, sliceRect,
+ m_heightNormalizer,
+ m_axisCacheY.min(), true);
}
}
}
-QRect Surface3DRenderer::calculateSampleRect(const QSurfaceDataArray &array)
+QRect Surface3DRenderer::calculateSampleRect(SurfaceSeriesRenderCache *cache,
+ const QSurfaceDataArray &array)
{
QRect sampleSpace;
@@ -518,14 +663,17 @@ QRect Surface3DRenderer::calculateSampleRect(const QSurfaceDataArray &array)
m_visibleColumnRange = m_maxVisibleColumnValue - m_minVisibleColumnValue;
m_visibleRowRange = m_maxVisibleRowValue - m_minVisibleRowValue;
- m_surfaceScaleX = m_scaleX * m_visibleColumnRange / m_areaSize.width();
- m_surfaceScaleZ = m_scaleZ * m_visibleRowRange / m_areaSize.height();
+ 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);
- m_surfaceOffsetX = m_scaleX * (data2XCenterX - axis2XCenterX) / m_areaSize.width();
- m_surfaceOffsetZ = -m_scaleZ * (data2XCenterZ - axis2XCenterZ) / m_areaSize.height();
+ 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;
}
@@ -535,14 +683,15 @@ void Surface3DRenderer::updateScene(Q3DScene *scene)
// Set initial camera position
// X must be 0 for rotation to work - we can use "setCameraRotation" for setting it later
if (m_hasHeightAdjustmentChanged) {
- scene->activeCamera()->setBaseOrientation(cameraDistanceVector, zeroVector, upVector);
+ scene->activeCamera()->d_ptr->setBaseOrientation(cameraDistanceVector, zeroVector,
+ upVector);
// For now this is used just to make things once. Proper use will come
m_hasHeightAdjustmentChanged = false;
}
Abstract3DRenderer::updateScene(scene);
- if (m_selectionPointer && m_selectionActive
+ if (m_selectionActive
&& m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionItem)) {
m_selectionDirty = true; // Ball may need repositioning if scene changes
}
@@ -560,9 +709,16 @@ void Surface3DRenderer::render(GLuint defaultFboHandle)
drawSlicedScene();
// Render selection ball
- if (m_selectionPointer && m_selectionActive
+ if (m_selectionActive
&& m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionItem)) {
- m_selectionPointer->render(defaultFboHandle);
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ if (cache->slicePointerActive() && cache->renderable() &&
+ m_cachedIsSlicingActivated ) {
+ cache->sliceSelectionPointer()->render(defaultFboHandle);
+ }
+ if (cache->mainPointerActive() && cache->renderable())
+ cache->mainSelectionPointer()->render(defaultFboHandle);
+ }
}
}
@@ -583,8 +739,10 @@ void Surface3DRenderer::drawSlicedScene()
GLfloat aspect = (GLfloat)m_secondarySubViewport.width()
/ (GLfloat)m_secondarySubViewport.height();
- projectionMatrix.ortho(-sliceUnits * aspect, sliceUnits * aspect,
- -sliceUnits, sliceUnits, -1.0f, 4.0f);
+ GLfloat sliceUnitsScaled = sliceUnits / m_autoScaleAdjustment;
+ projectionMatrix.ortho(-sliceUnitsScaled * aspect, sliceUnitsScaled * aspect,
+ -sliceUnitsScaled, sliceUnitsScaled,
+ -1.0f, 4.0f);
// Set view matrix
QMatrix4x4 viewMatrix;
@@ -595,72 +753,85 @@ void Surface3DRenderer::drawSlicedScene()
QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix;
+ const Q3DCamera *activeCamera = m_cachedScene->activeCamera();
+
bool rowMode = m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow);
- GLfloat scaleX = 0.0f;
GLfloat scaleXBackground = 0.0f;
- GLfloat offset = 0.0f;
- if (rowMode) {
- scaleX = m_surfaceScaleX;
- scaleXBackground = m_scaleXWithBackground;
- offset = m_surfaceOffsetX;
- } else {
- scaleX = m_surfaceScaleZ;
- scaleXBackground = m_scaleZWithBackground;
- offset = -m_surfaceOffsetZ;
- }
- if (m_surfaceObj) {
- QMatrix4x4 MVPMatrix;
- QMatrix4x4 modelMatrix;
- QMatrix4x4 itModelMatrix;
+ if (m_renderCacheList.size()) {
+ bool drawGrid = false;
- const SeriesRenderCache &series = m_visibleSeriesList.at(0);
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ if (cache->sliceSurfaceObject()->indexCount() && cache->renderable()) {
+ if (!drawGrid && cache->surfaceGridVisible()) {
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(0.5f, 1.0f);
+ drawGrid = true;
+ }
- modelMatrix.translate(offset, 0.0f, 0.0f);
- QVector3D scaling(scaleX, 1.0f, sliceZScale);
- modelMatrix.scale(scaling);
- itModelMatrix.scale(scaling);
+ GLfloat scaleX = 0.0f;
+ GLfloat offset = 0.0f;
+ if (rowMode) {
+ scaleX = cache->scale().x();
+ scaleXBackground = m_scaleXWithBackground;
+ offset = cache->offset().x();
+ } else {
+ scaleX = cache->scale().z();
+ scaleXBackground = m_scaleZWithBackground;
+ offset = -cache->offset().z();
+ }
- MVPMatrix = projectionViewMatrix * modelMatrix;
+ QMatrix4x4 MVPMatrix;
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 itModelMatrix;
- if (m_cachedSurfaceVisible) {
- if (m_cachedSurfaceGridOn) {
- glEnable(GL_POLYGON_OFFSET_FILL);
- glPolygonOffset(0.5f, 1.0f);
- }
+ modelMatrix.translate(offset, 0.0f, 0.0f);
+ QVector3D scaling(scaleX, 1.0f, sliceZScale);
+ modelMatrix.scale(scaling);
+ itModelMatrix.scale(scaling);
- ShaderHelper *surfaceShader = m_surfaceShader;
- surfaceShader->bind();
-
- GLuint baseGradientTexture = m_uniformGradientTexture;
- if (series.colorStyle() != Q3DTheme::ColorStyleUniform)
- baseGradientTexture = series.baseGradientTexture();
-
- // Set shader bindings
- surfaceShader->setUniformValue(surfaceShader->lightP(), lightPos);
- surfaceShader->setUniformValue(surfaceShader->view(), viewMatrix);
- surfaceShader->setUniformValue(surfaceShader->model(), modelMatrix);
- surfaceShader->setUniformValue(surfaceShader->nModel(),
- itModelMatrix.inverted().transposed());
- surfaceShader->setUniformValue(surfaceShader->MVP(), MVPMatrix);
- surfaceShader->setUniformValue(surfaceShader->lightS(), 0.15f);
- surfaceShader->setUniformValue(surfaceShader->ambientS(),
- m_cachedTheme->ambientLightStrength() * 2.3f);
- surfaceShader->setUniformValue(surfaceShader->lightColor(), lightColor);
-
- m_drawer->drawObject(surfaceShader, m_sliceSurfaceObj, baseGradientTexture);
+ MVPMatrix = projectionViewMatrix * modelMatrix;
+ cache->setMVPMatrix(MVPMatrix);
+
+ if (cache->surfaceVisible()) {
+ ShaderHelper *surfaceShader = m_surfaceFlatShader;
+ surfaceShader->bind();
+
+ GLuint colorTexture = cache->baseUniformTexture();;
+ if (cache->colorStyle() != Q3DTheme::ColorStyleUniform)
+ colorTexture = cache->baseGradientTexture();
+
+ // Set shader bindings
+ surfaceShader->setUniformValue(surfaceShader->lightP(), lightPos);
+ surfaceShader->setUniformValue(surfaceShader->view(), viewMatrix);
+ surfaceShader->setUniformValue(surfaceShader->model(), modelMatrix);
+ surfaceShader->setUniformValue(surfaceShader->nModel(),
+ itModelMatrix.inverted().transposed());
+ surfaceShader->setUniformValue(surfaceShader->MVP(), MVPMatrix);
+ surfaceShader->setUniformValue(surfaceShader->lightS(), 0.15f);
+ surfaceShader->setUniformValue(surfaceShader->ambientS(),
+ m_cachedTheme->ambientLightStrength() * 2.3f);
+ surfaceShader->setUniformValue(surfaceShader->lightColor(), lightColor);
+
+ m_drawer->drawObject(surfaceShader, cache->sliceSurfaceObject(), colorTexture);
+ }
+ }
}
// Draw surface grid
- if (m_cachedSurfaceGridOn) {
+ if (drawGrid) {
+ glDisable(GL_POLYGON_OFFSET_FILL);
m_surfaceGridShader->bind();
m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(),
Utils::vectorFromColor(m_cachedTheme->gridLineColor()));
- m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), MVPMatrix);
- m_drawer->drawSurfaceGrid(m_surfaceGridShader, m_sliceSurfaceObj);
-
- glDisable(GL_POLYGON_OFFSET_FILL);
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ if (cache->sliceSurfaceObject()->indexCount() && cache->isSeriesVisible() &&
+ cache->surfaceGridVisible()) {
+ m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), cache->MVPMatrix());
+ m_drawer->drawSurfaceGrid(m_surfaceGridShader, cache->sliceSurfaceObject());
+ }
+ }
}
}
@@ -756,7 +927,7 @@ void Surface3DRenderer::drawSlicedScene()
}
}
- // Draw axis labels
+ // Draw labels
m_labelShader->bind();
glEnable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
@@ -781,7 +952,7 @@ void Surface3DRenderer::drawSlicedScene()
m_dummyRenderItem.setTranslation(labelTrans);
m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
positionComp, rotation, 0, m_cachedSelectionMode, m_labelShader,
- m_labelObj, m_cachedScene->activeCamera(),
+ m_labelObj, activeCamera,
true, true, Drawer::LabelMid, Qt::AlignRight, true);
}
labelNbr++;
@@ -822,13 +993,35 @@ void Surface3DRenderer::drawSlicedScene()
m_drawer->drawLabel(m_dummyRenderItem, *axisLabelItem, viewMatrix, projectionMatrix,
positionComp, rotation, 0, QAbstract3DGraph::SelectionRow,
- m_labelShader, m_labelObj, m_cachedScene->activeCamera(),
+ m_labelShader, m_labelObj, activeCamera,
false, false, Drawer::LabelBelow, Qt::AlignBottom, 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);
+ }
+ // Y-axis label
+ 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,
+ m_cachedSelectionMode, m_labelShader, m_labelObj, activeCamera,
+ false, false, Drawer::LabelMid, Qt::AlignHCenter);
+
glDisable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
@@ -839,6 +1032,8 @@ void Surface3DRenderer::drawSlicedScene()
void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
{
+ bool noShadows = true;
+
GLfloat backgroundRotation = 0;
QVector3D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor());
@@ -847,15 +1042,15 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_primarySubViewport.width(),
m_primarySubViewport.height());
- // Specify viewport
-
// Set up projection matrix
QMatrix4x4 projectionMatrix;
projectionMatrix.perspective(45.0f, (GLfloat)m_primarySubViewport.width()
/ (GLfloat)m_primarySubViewport.height(), 0.1f, 100.0f);
+ const Q3DCamera *activeCamera = m_cachedScene->activeCamera();
+
// Calculate view matrix
- QMatrix4x4 viewMatrix = m_cachedScene->activeCamera()->viewMatrix();
+ QMatrix4x4 viewMatrix = activeCamera->d_ptr->viewMatrix();
QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix;
@@ -885,14 +1080,10 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
QMatrix4x4 depthProjectionMatrix;
QMatrix4x4 depthProjectionViewMatrix;
- QVector3D surfaceScaler(m_surfaceScaleX, 1.0f, m_surfaceScaleZ);
- QVector3D surfaceOffset(m_surfaceOffsetX, 0.0f, m_surfaceOffsetZ);
-
// Draw depth buffer
#if !defined(QT_OPENGL_ES_2)
GLfloat adjustedLightStrength = m_cachedTheme->lightStrength() / 10.0f;
- if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone && m_surfaceObj
- && m_cachedSurfaceVisible) {
+ if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone && m_renderCacheList.size()) {
// Render scene into a depth texture for using with shadow mapping
// Enable drawing to depth framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer);
@@ -912,47 +1103,44 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Get the depth view matrix
// It may be possible to hack lightPos here if we want to make some tweaks to shadow
- QVector3D depthLightPos = m_cachedScene->activeCamera()->calculatePositionRelativeToCamera(
- zeroVector, 0.0f, 3.5f / m_autoScaleAdjustment);
+ QVector3D depthLightPos = activeCamera->d_ptr->calculatePositionRelativeToCamera(
+ zeroVector, 0.0f, 4.0f / m_autoScaleAdjustment);
depthViewMatrix.lookAt(depthLightPos, zeroVector, upVector);
// Set the depth projection matrix
-#ifndef USE_WIDER_SHADOWS
- // Use this for perspective shadows
depthProjectionMatrix.perspective(10.0f, (GLfloat)m_primarySubViewport.width()
/ (GLfloat)m_primarySubViewport.height(), 3.0f, 100.0f);
-#else
- // Use these for orthographic shadows
- depthProjectionMatrix.ortho(-2.0f * 2.0f, 2.0f * 2.0f,
- -2.0f, 2.0f,
- 0.0f, 100.0f);
-#endif
depthProjectionViewMatrix = depthProjectionMatrix * depthViewMatrix;
glDisable(GL_CULL_FACE);
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
-
- modelMatrix.translate(surfaceOffset);
- modelMatrix.scale(surfaceScaler);
-
- MVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ SurfaceObject *object = cache->surfaceObject();
+ if (object->indexCount() && cache->surfaceVisible() && cache->isSeriesVisible()
+ && cache->sampleSpace().width() >= 2 && cache->sampleSpace().height() >= 2) {
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
- m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix);
+ modelMatrix.translate(cache->offset());
+ modelMatrix.scale(cache->scale());
+ MVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ cache->setMVPMatrix(MVPMatrix);
+ m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix);
- // 1st attribute buffer : vertices
- glEnableVertexAttribArray(m_depthShader->posAtt());
- glBindBuffer(GL_ARRAY_BUFFER, m_surfaceObj->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, object->vertexBuf());
+ glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0,
+ (void *)0);
- // Index buffer
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_surfaceObj->elementBuf());
+ // Index buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object->elementBuf());
- // Draw the triangles
- glDrawElements(GL_TRIANGLES, m_surfaceObj->indexCount(), m_surfaceObj->indicesType(),
- (void *)0);
+ // Draw the triangles
+ glDrawElements(GL_TRIANGLES, object->indexCount(),
+ object->indicesType(), (void *)0);
+ }
+ }
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
@@ -961,9 +1149,26 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_depthModelTexture, 0);
glClear(GL_DEPTH_BUFFER_BIT);
- // Draw the triangles
- glDrawElements(GL_TRIANGLES, m_surfaceObj->indexCount(), m_surfaceObj->indicesType(),
- (void *)0);
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ SurfaceObject *object = cache->surfaceObject();
+ if (object->indexCount() && cache->surfaceVisible() && cache->isSeriesVisible()
+ && cache->sampleSpace().width() >= 2 && cache->sampleSpace().height() >= 2) {
+ m_depthShader->setUniformValue(m_depthShader->MVP(), cache->MVPMatrix());
+
+ // 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);
@@ -989,10 +1194,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glEnable(GL_TEXTURE_2D);
// Draw selection buffer
- if (!m_cachedIsSlicingActivated && m_surfaceObj && m_selectionState == SelectOnScene
- && m_cachedSelectionMode > QAbstract3DGraph::SelectionNone
- && (m_cachedSurfaceVisible || m_cachedSurfaceGridOn)
- && m_visibleSeriesList.size() > 0) {
+ if (!m_cachedIsSlicingActivated && m_renderCacheList.size() && m_selectionState == SelectOnScene
+ && m_cachedSelectionMode > QAbstract3DGraph::SelectionNone) {
m_selectionShader->bind();
glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer);
glViewport(0,
@@ -1007,17 +1210,21 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
glDisable(GL_CULL_FACE);
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
-
- modelMatrix.translate(surfaceOffset);
- modelMatrix.scale(surfaceScaler);
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ if (cache->surfaceObject()->indexCount() && cache->renderable()) {
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
- MVPMatrix = projectionViewMatrix * modelMatrix;
+ modelMatrix.translate(cache->offset());
+ modelMatrix.scale(cache->scale());
- m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix);
+ MVPMatrix = projectionViewMatrix * modelMatrix;
+ m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix);
- m_drawer->drawObject(m_selectionShader, m_surfaceObj, m_selectionTexture);
+ m_drawer->drawObject(m_selectionShader, cache->surfaceObject(),
+ cache->selectionTexture());
+ }
+ }
glEnable(GL_DITHER);
@@ -1035,7 +1242,6 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
#endif
m_clickedPosition = selectionIdToSurfacePoint(selectionId);
- m_clickedSeries = m_visibleSeriesList.at(0).series();
emit needRender();
@@ -1047,81 +1253,102 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
}
// Draw the surface
- if (m_surfaceObj && m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) {
- m_surfaceShader->bind();
+ if (m_renderCacheList.size()) {
// For surface we can see climpses from underneath
glDisable(GL_CULL_FACE);
- if (m_cachedSurfaceGridOn) {
- glEnable(GL_POLYGON_OFFSET_FILL);
- glPolygonOffset(0.5f, 1.0f);
- }
- QMatrix4x4 modelMatrix;
- QMatrix4x4 MVPMatrix;
- QMatrix4x4 itModelMatrix;
+ bool drawGrid = false;
+
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 MVPMatrix;
+ QMatrix4x4 itModelMatrix;
- modelMatrix.translate(surfaceOffset);
- modelMatrix.scale(surfaceScaler);
- itModelMatrix.scale(surfaceScaler);
+ modelMatrix.translate(cache->offset());
+ modelMatrix.scale(cache->scale());
+ itModelMatrix.scale(cache->scale());
#ifdef SHOW_DEPTH_TEXTURE_SCENE
- MVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ MVPMatrix = depthProjectionViewMatrix * modelMatrix;
#else
- MVPMatrix = projectionViewMatrix * modelMatrix;
+ MVPMatrix = projectionViewMatrix * modelMatrix;
#endif
+ cache->setMVPMatrix(MVPMatrix);
+
+ const QRect &sampleSpace = cache->sampleSpace();
+ if (cache->surfaceObject()->indexCount() && cache->isSeriesVisible() &&
+ sampleSpace.width() >= 2 && sampleSpace.height() >= 2) {
+ noShadows = false;
+ if (!drawGrid && cache->surfaceGridVisible()) {
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(0.5f, 1.0f);
+ drawGrid = true;
+ }
- if (m_cachedSurfaceVisible) {
- // Set shader bindings
- m_surfaceShader->setUniformValue(m_surfaceShader->lightP(), lightPos);
- m_surfaceShader->setUniformValue(m_surfaceShader->view(), viewMatrix);
- m_surfaceShader->setUniformValue(m_surfaceShader->model(), modelMatrix);
- m_surfaceShader->setUniformValue(m_surfaceShader->nModel(),
- itModelMatrix.inverted().transposed());
- m_surfaceShader->setUniformValue(m_surfaceShader->MVP(), MVPMatrix);
- m_surfaceShader->setUniformValue(m_surfaceShader->ambientS(),
- m_cachedTheme->ambientLightStrength());
- m_surfaceShader->setUniformValue(m_surfaceShader->lightColor(), lightColor);
-
- GLuint gradientTexture;
- if (m_visibleSeriesList.at(0).colorStyle() == Q3DTheme::ColorStyleUniform)
- gradientTexture = m_uniformGradientTexture;
- else
- gradientTexture = m_visibleSeriesList.at(0).baseGradientTexture();
+ if (cache->surfaceVisible()) {
+ ShaderHelper *shader = m_surfaceFlatShader;
+ if (!cache->isFlatShadingEnabled())
+ shader = m_surfaceSmoothShader;
+ shader->bind();
+
+ // Set shader bindings
+ shader->setUniformValue(shader->lightP(), lightPos);
+ shader->setUniformValue(shader->view(), viewMatrix);
+ shader->setUniformValue(shader->model(), modelMatrix);
+ shader->setUniformValue(shader->nModel(),
+ itModelMatrix.inverted().transposed());
+ shader->setUniformValue(shader->MVP(), MVPMatrix);
+ shader->setUniformValue(shader->ambientS(),
+ m_cachedTheme->ambientLightStrength());
+ shader->setUniformValue(shader->lightColor(), lightColor);
-#if !defined(QT_OPENGL_ES_2)
- if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
- // Set shadow shader bindings
- QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix;
- m_surfaceShader->setUniformValue(m_surfaceShader->shadowQ(),
- m_shadowQualityToShader);
- m_surfaceShader->setUniformValue(m_surfaceShader->depth(), depthMVPMatrix);
- m_surfaceShader->setUniformValue(m_surfaceShader->lightS(), adjustedLightStrength);
+ GLuint gradientTexture;
+ if (cache->colorStyle() == Q3DTheme::ColorStyleUniform)
+ gradientTexture = cache->baseUniformTexture();
+ else
+ gradientTexture = cache->baseGradientTexture();
- // Draw the object
- m_drawer->drawObject(m_surfaceShader, m_surfaceObj, gradientTexture,
- m_depthModelTexture);
- } else
+#if !defined(QT_OPENGL_ES_2)
+ if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
+ // Set shadow shader bindings
+ QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix;
+ shader->setUniformValue(shader->shadowQ(), m_shadowQualityToShader);
+ shader->setUniformValue(shader->depth(), depthMVPMatrix);
+ shader->setUniformValue(shader->lightS(), adjustedLightStrength);
+
+ // Draw the objects
+ m_drawer->drawObject(shader, cache->surfaceObject(), gradientTexture,
+ m_depthModelTexture);
+ } else
#endif
- {
- // Set shadowless shader bindings
- m_surfaceShader->setUniformValue(m_surfaceShader->lightS(),
- m_cachedTheme->lightStrength());
+ {
+ // Set shadowless shader bindings
+ shader->setUniformValue(shader->lightS(),
+ m_cachedTheme->lightStrength());
- // Draw the object
- m_drawer->drawObject(m_surfaceShader, m_surfaceObj, gradientTexture);
+ // Draw the objects
+ m_drawer->drawObject(shader, cache->surfaceObject(), gradientTexture);
+ }
+ }
}
- glEnable(GL_CULL_FACE);
}
+ glEnable(GL_CULL_FACE);
// Draw surface grid
- if (m_cachedSurfaceGridOn) {
+ if (drawGrid) {
+ glDisable(GL_POLYGON_OFFSET_FILL);
m_surfaceGridShader->bind();
m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(),
Utils::vectorFromColor(m_cachedTheme->gridLineColor()));
- m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), MVPMatrix);
- m_drawer->drawSurfaceGrid(m_surfaceGridShader, m_surfaceObj);
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), cache->MVPMatrix());
- glDisable(GL_POLYGON_OFFSET_FILL);
+ const QRect &sampleSpace = cache->sampleSpace();
+ if (cache->surfaceObject()->indexCount() && cache->surfaceGridVisible() &&
+ cache->isSeriesVisible() && sampleSpace.width() >= 2 && sampleSpace.height() >= 2) {
+ m_drawer->drawSurfaceGrid(m_surfaceGridShader, cache->surfaceObject());
+ }
+ }
}
}
@@ -1177,10 +1404,14 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_backgroundShader->setUniformValue(m_backgroundShader->depth(), depthMVPMatrix);
m_backgroundShader->setUniformValue(m_backgroundShader->lightS(),
adjustedLightStrength);
-
// Draw the object
- m_drawer->drawObject(m_backgroundShader, m_backgroundObj, 0, m_depthTexture);
+ if (noShadows)
+ m_drawer->drawObject(m_backgroundShader, m_backgroundObj, 0, m_noShadowTexture);
+ else
+ m_drawer->drawObject(m_backgroundShader, m_backgroundObj, 0, m_depthTexture);
} else
+#else
+ Q_UNUSED(noShadows);
#endif
{
// Set shadowless shader bindings
@@ -1565,7 +1796,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
positionZComp, rotation, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, m_cachedScene->activeCamera(),
+ m_labelShader, m_labelObj, activeCamera,
true, true, Drawer::LabelMid, alignment);
}
labelNbr++;
@@ -1611,7 +1842,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
positionZComp, rotation, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, m_cachedScene->activeCamera(),
+ m_labelShader, m_labelObj, activeCamera,
true, true, Drawer::LabelMid, alignment);
}
labelNbr++;
@@ -1671,7 +1902,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_dummyRenderItem.setTranslation(labelTransBack);
m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
positionZComp, labelRotateVectorBack, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, m_cachedScene->activeCamera(),
+ m_labelShader, m_labelObj, activeCamera,
true, true, Drawer::LabelMid, alignmentBack);
// Side wall
@@ -1679,7 +1910,7 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_dummyRenderItem.setTranslation(labelTransSide);
m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix,
positionZComp, labelRotateVectorSide, 0, m_cachedSelectionMode,
- m_labelShader, m_labelObj, m_cachedScene->activeCamera(),
+ m_labelShader, m_labelObj, activeCamera,
true, true, Drawer::LabelMid, alignmentSide);
}
labelNbr++;
@@ -1697,12 +1928,17 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
// Selection handling
if (m_selectionDirty || m_selectionLabelDirty) {
QPoint visiblePoint = Surface3DController::invalidSelectionPosition();
- if (m_selectedPoint != Surface3DController::invalidSelectionPosition()) {
- int x = m_selectedPoint.x() - m_sampleSpace.y();
- int y = m_selectedPoint.y() - m_sampleSpace.x();
- if (x >= 0 && y >= 0 && x < m_sampleSpace.height() && y < m_sampleSpace.width()
- && m_dataArray.size()) {
- visiblePoint = QPoint(x, y);
+ 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);
+ }
}
}
@@ -1721,47 +1957,65 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
}
}
-// This one needs to be called when the data size changes
-void Surface3DRenderer::updateSelectionTexture()
+void Surface3DRenderer::updateSelectionMode(QAbstract3DGraph::SelectionFlags mode)
+{
+ Abstract3DRenderer::updateSelectionMode(mode);
+
+ if (m_cachedSelectionMode > QAbstract3DGraph::SelectionNone)
+ updateSelectionTextures();
+}
+
+void Surface3DRenderer::updateSelectionTextures()
+{
+ uint lastSelectionId = 1;
+
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ GLuint texture = cache->selectionTexture();
+ m_textureHelper->deleteTexture(&texture);
+ createSelectionTexture(cache, lastSelectionId);
+ }
+ m_selectionTexturesDirty = false;
+}
+
+void Surface3DRenderer::createSelectionTexture(SurfaceSeriesRenderCache *cache,
+ uint &lastSelectionId)
{
// Create the selection ID image. Each grid corner gets 2x2 pixel area of
// ID color so that each vertex (data point) has 4x4 pixel area of ID color
- int idImageWidth = (m_sampleSpace.width() - 1) * 4;
- int idImageHeight = (m_sampleSpace.height() - 1) * 4;
+ const QRect &sampleSpace = cache->sampleSpace();
+ int idImageWidth = (sampleSpace.width() - 1) * 4;
+ int idImageHeight = (sampleSpace.height() - 1) * 4;
int stride = idImageWidth * 4 * sizeof(uchar); // 4 = number of color components (rgba)
+ uint idStart = lastSelectionId;
uchar *bits = new uchar[idImageWidth * idImageHeight * 4 * sizeof(uchar)];
- uint id = 1;
for (int i = 0; i < idImageHeight; i += 4) {
for (int j = 0; j < idImageWidth; j += 4) {
int p = (i * idImageWidth + j) * 4;
uchar r, g, b, a;
- idToRGBA(id, &r, &g, &b, &a);
+ idToRGBA(lastSelectionId, &r, &g, &b, &a);
fillIdCorner(&bits[p], r, g, b, a, stride);
- idToRGBA(id + 1, &r, &g, &b, &a);
+ idToRGBA(lastSelectionId + 1, &r, &g, &b, &a);
fillIdCorner(&bits[p + 8], r, g, b, a, stride);
- idToRGBA(id + m_sampleSpace.width(), &r, &g, &b, &a);
+ idToRGBA(lastSelectionId + sampleSpace.width(), &r, &g, &b, &a);
fillIdCorner(&bits[p + 2 * stride], r, g, b, a, stride);
- idToRGBA(id + m_sampleSpace.width() + 1, &r, &g, &b, &a);
+ idToRGBA(lastSelectionId + sampleSpace.width() + 1, &r, &g, &b, &a);
fillIdCorner(&bits[p + 2 * stride + 8], r, g, b, a, stride);
- id++;
+ lastSelectionId++;
}
- id++;
- }
-
- // If old texture exists, delete it
- if (m_selectionTexture) {
- m_textureHelper->deleteTexture(&m_selectionTexture);
- m_selectionTexture = 0;
+ lastSelectionId++;
}
+ lastSelectionId += sampleSpace.width();
+ cache->setSelectionIdRange(idStart, lastSelectionId - 1);
// Move the ID image (bits) to the texture
QImage image = QImage(bits, idImageWidth, idImageHeight, QImage::Format_RGB32);
- m_selectionTexture = m_textureHelper->create2DTexture(image, false, false, false);
+ GLuint selectionTexture = m_textureHelper->create2DTexture(image, false, false, false);
+ cache->setSelectionTexture(selectionTexture);
// Release the temp bits allocation
delete[] bits;
@@ -1821,33 +2075,30 @@ void Surface3DRenderer::calculateSceneScalingFactors()
m_scaleZWithBackground = m_scaleZ * backgroundMargin;
}
-bool Surface3DRenderer::updateFlatStatus(bool enable)
+void Surface3DRenderer::checkFlatSupport(SurfaceSeriesRenderCache *cache)
{
- if (enable && !m_flatSupported) {
+ bool flatEnable = cache->isFlatShadingEnabled();
+ if (flatEnable && !m_flatSupported) {
qWarning() << "Warning: Flat qualifier not supported on your platform's GLSL language."
" Requires at least GLSL version 1.2 with GL_EXT_gpu_shader4 extension.";
- enable = false;
+ cache->setFlatShadingEnabled(false);
+ cache->setFlatChangeAllowed(false);
}
+}
- bool changed = false;
- if (enable != m_cachedFlatShading) {
- m_cachedFlatShading = enable;
- changed = true;
- initSurfaceShaders();
- }
+void Surface3DRenderer::updateObjects(SurfaceSeriesRenderCache *cache, bool dimensionChanged)
+{
+ QSurfaceDataArray &dataArray = cache->dataArray();
+ const QRect &sampleSpace = cache->sampleSpace();
- // If no surface object created yet, don't try to update the object
- if (m_surfaceObj && changed && m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) {
- if (!m_cachedFlatShading) {
- m_surfaceObj->setUpSmoothData(m_dataArray, m_sampleSpace, m_heightNormalizer,
- m_axisCacheY.min(), true);
- } else {
- m_surfaceObj->setUpData(m_dataArray, m_sampleSpace, m_heightNormalizer,
- m_axisCacheY.min(), true);
- }
- }
- return m_cachedFlatShading;
+ 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);
+ }
}
void Surface3DRenderer::updateSelectedPoint(const QPoint &position, const QSurface3DSeries *series)
@@ -1863,11 +2114,6 @@ void Surface3DRenderer::resetClickedStatus()
m_clickedSeries = 0;
}
-void Surface3DRenderer::updateSurfaceGridStatus(bool enable)
-{
- m_cachedSurfaceGridOn = enable;
-}
-
void Surface3DRenderer::loadBackgroundMesh()
{
if (m_backgroundObj)
@@ -1876,20 +2122,6 @@ void Surface3DRenderer::loadBackgroundMesh()
m_backgroundObj->load();
}
-void Surface3DRenderer::loadSurfaceObj()
-{
- if (m_surfaceObj)
- delete m_surfaceObj;
- m_surfaceObj = new SurfaceObject();
-}
-
-void Surface3DRenderer::loadSliceSurfaceObj()
-{
- if (m_sliceSurfaceObj)
- delete m_sliceSurfaceObj;
- m_sliceSurfaceObj = new SurfaceObject();
-}
-
void Surface3DRenderer::loadGridLineMesh()
{
if (m_gridLineObj)
@@ -1900,56 +2132,132 @@ void Surface3DRenderer::loadGridLineMesh()
void Surface3DRenderer::surfacePointSelected(const QPoint &point)
{
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ cache->setSlicePointerActivity(false);
+ cache->setMainPointerActivity(false);
+ }
+
+ 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();
+ QSurfaceDataItem item = dataArray.at(point.x())->at(point.y());
+ QPointF coords(item.x(), item.z());
+
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ if (cache->series() != m_selectedSeries) {
+ QPoint mappedPoint = mapCoordsToSampleSpace(cache, coords);
+ updateSelectionPoint(cache, mappedPoint, false);
+ } else {
+ updateSelectionPoint(cache, point, true);
+ }
+ }
+ } else {
+ if (m_selectedSeries) {
+ SurfaceSeriesRenderCache *cache =
+ m_renderCacheList.value(const_cast<QSurface3DSeries *>(m_selectedSeries));
+ if (cache)
+ updateSelectionPoint(cache, point, true);
+ }
+ }
+}
+
+void Surface3DRenderer::updateSelectionPoint(SurfaceSeriesRenderCache *cache, const QPoint &point,
+ bool label)
+{
int row = point.x();
int column = point.y();
- float value = m_dataArray.at(row)->at(column).y();
+ 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);
+ cache->setSliceSelectionPointer(slicePointer);
+ }
+ SelectionPointer *mainPointer = cache->mainSelectionPointer();
+ if (!mainPointer) {
+ mainPointer = new SelectionPointer(m_drawer);
+ cache->setMainSelectionPointer(mainPointer);
+ }
- if (!m_selectionPointer)
- m_selectionPointer = new SelectionPointer(m_drawer);
+ const QVector3D &scale = cache->scale();
+ const QVector3D &offset = cache->offset();
+ QString selectionLabel;
+ if (label)
+ selectionLabel = createSelectionLabel(cache, value, column, row);
- QVector3D pos;
if (m_cachedIsSlicingActivated) {
+ QVector3D subPos;
if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionRow)) {
- pos = m_sliceSurfaceObj->vertexAt(column, 0);
- pos *= QVector3D(m_surfaceScaleX, 1.0f, 0.0f);
- pos += QVector3D(m_surfaceOffsetX, 0.0f, 0.0f);
- m_selectionPointer->updateBoundingRect(m_secondarySubViewport);
- m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment);
+ subPos = cache->sliceSurfaceObject()->vertexAt(column, 0);
+ subPos *= QVector3D(scale.x(), 1.0f, 0.0f);
+ subPos += QVector3D(offset.x(), 0.0f, 0.0f);
} else if (m_cachedSelectionMode.testFlag(QAbstract3DGraph::SelectionColumn)) {
- pos = m_sliceSurfaceObj->vertexAt(row, 0);
- pos *= QVector3D(m_surfaceScaleZ, 1.0f, 0.0f);
- pos += QVector3D(-m_surfaceOffsetZ, 0.0f, 0.0f);
- m_selectionPointer->updateBoundingRect(m_secondarySubViewport);
- m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment);
+ subPos = cache->sliceSurfaceObject()->vertexAt(row, 0);
+ subPos *= QVector3D(scale.z(), 1.0f, 0.0f);
+ subPos += QVector3D(-offset.z(), 0.0f, 0.0f);
}
- } else {
- pos = m_surfaceObj->vertexAt(column, row);
- pos *= QVector3D(m_surfaceScaleX, 1.0f, m_surfaceScaleZ);;
- pos += QVector3D(m_surfaceOffsetX, 0.0f, m_surfaceOffsetZ);
- m_selectionPointer->updateBoundingRect(m_primarySubViewport);
- m_selectionPointer->updateSliceData(false, m_autoScaleAdjustment);
- }
-
- m_selectionPointer->setPosition(pos);
- m_selectionPointer->setLabel(createSelectionLabel(value, column, row));
- m_selectionPointer->setPointerObject(m_visibleSeriesList.at(0).object());
- m_selectionPointer->setHighlightColor(m_visibleSeriesList.at(0).singleHighlightColor());
- m_selectionPointer->updateScene(m_cachedScene);
- m_selectionPointer->setRotation(m_visibleSeriesList.at(0).meshRotation());
+ slicePointer->updateBoundingRect(m_secondarySubViewport);
+ slicePointer->updateSliceData(true, m_autoScaleAdjustment);
+ slicePointer->setPosition(subPos);
+ slicePointer->setLabel(selectionLabel);
+ slicePointer->setPointerObject(cache->object());
+ slicePointer->setHighlightColor(cache->singleHighlightColor());
+ slicePointer->updateScene(m_cachedScene);
+ slicePointer->setRotation(cache->meshRotation());
+ cache->setSlicePointerActivity(true);
+ }
+
+ 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->setHighlightColor(cache->singleHighlightColor());
+ mainPointer->updateScene(m_cachedScene);
+ mainPointer->setRotation(cache->meshRotation());
+ cache->setMainPointerActivity(true);
}
// Maps selection Id to surface point in data array
QPoint Surface3DRenderer::selectionIdToSurfacePoint(uint id)
{
- int column = ((id - 1) % m_sampleSpace.width()) + m_sampleSpace.x();
- int row = ((id - 1) / m_sampleSpace.width()) + m_sampleSpace.y();
+ SurfaceSeriesRenderCache *selectedCache = 0;
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ if (cache->isWithinIdRange(id)) {
+ selectedCache = cache;
+ break;
+ }
+ }
+ if (!selectedCache) {
+ m_clickedSeries = 0;
+ return Surface3DController::invalidSelectionPosition();
+ }
+
+ uint idInSeries = id - selectedCache->selectionIdStart() + 1;
+ const QRect &sampleSpace = selectedCache->sampleSpace();
+ int column = ((idInSeries - 1) % sampleSpace.width()) + sampleSpace.x();
+ int row = ((idInSeries - 1) / sampleSpace.width()) + sampleSpace.y();
+
+ m_clickedSeries = selectedCache->series();
return QPoint(row, column);
}
-QString Surface3DRenderer::createSelectionLabel(float value, int column, int row)
+QString Surface3DRenderer::createSelectionLabel(SurfaceSeriesRenderCache *cache, float value,
+ int column, int row)
{
- QString labelText = m_visibleSeriesList[0].itemLabelFormat();
+ 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"));
@@ -1967,7 +2275,7 @@ QString Surface3DRenderer::createSelectionLabel(float value, int column, int row
if (labelFormat.isEmpty())
labelFormat = Utils::defaultLabelFormat();
QString valueLabelText = generateValueLabel(labelFormat,
- m_dataArray.at(row)->at(column).x());
+ dataArray.at(row)->at(column).x());
labelText.replace(xLabelTag, valueLabelText);
}
if (labelText.contains(yLabelTag)) {
@@ -1982,11 +2290,11 @@ QString Surface3DRenderer::createSelectionLabel(float value, int column, int row
if (labelFormat.isEmpty())
labelFormat = Utils::defaultLabelFormat();
QString valueLabelText = generateValueLabel(labelFormat,
- m_dataArray.at(row)->at(column).z());
+ dataArray.at(row)->at(column).z());
labelText.replace(zLabelTag, valueLabelText);
}
- labelText.replace(seriesNameTag, m_visibleSeriesList[0].name());
+ labelText.replace(seriesNameTag, cache->name());
m_selectionLabelDirty = false;
@@ -2055,6 +2363,11 @@ void Surface3DRenderer::updateSlicingActive(bool isSlicing)
#endif
m_selectionDirty = true;
+
+ foreach (SurfaceSeriesRenderCache *cache, m_renderCacheList) {
+ if (cache->mainSelectionPointer())
+ cache->mainSelectionPointer()->updateBoundingRect(m_primarySubViewport);
+ }
}
void Surface3DRenderer::loadLabelMesh()
@@ -2071,31 +2384,34 @@ void Surface3DRenderer::initShaders(const QString &vertexShader, const QString &
Q_UNUSED(fragmentShader);
// draw the shader for the surface according to smooth status, shadow and uniform color
- if (m_surfaceShader)
- delete m_surfaceShader;
+ if (m_surfaceFlatShader)
+ delete m_surfaceFlatShader;
+ if (m_surfaceSmoothShader)
+ delete m_surfaceSmoothShader;
+
#if !defined(QT_OPENGL_ES_2)
- if (!m_cachedFlatShading) {
- if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
- m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexShadow"),
- QStringLiteral(":/shaders/fragmentSurfaceShadowNoTex"));
- } else {
- m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
- QStringLiteral(":/shaders/fragmentSurface"));
- }
+ if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
+ m_surfaceSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexShadow"),
+ QStringLiteral(":/shaders/fragmentSurfaceShadowNoTex"));
} else {
- if (m_cachedShadowQuality > QAbstract3DGraph::ShadowQualityNone) {
- m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceShadowFlat"),
+ 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_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
+ } else {
+ m_surfaceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"),
QStringLiteral(":/shaders/fragmentSurfaceFlat"));
- }
}
#else
- m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
- QStringLiteral(":/shaders/fragmentSurfaceES2"));
+ m_surfaceSmoothShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragmentSurfaceES2"));
+ m_surfaceFlatShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"),
+ QStringLiteral(":/shaders/fragmentSurfaceES2"));
#endif
- m_surfaceShader->initialize();
+ m_surfaceSmoothShader->initialize();
+ m_surfaceFlatShader->initialize();
}
void Surface3DRenderer::initBackgroundShaders(const QString &vertexShader,
@@ -2175,16 +2491,4 @@ void Surface3DRenderer::updateDepthBuffer()
}
#endif
-void Surface3DRenderer::generateUniformGradient(const QVector3D newColor)
-{
- if (m_visibleSeriesList.size()) {
- QColor newQColor = Utils::colorFromVector(newColor);
- m_uniformGradientTextureColor = newColor;
- QLinearGradient newGradient;
- newGradient.setColorAt(0.0, newQColor);
- newGradient.setColorAt(1.0, newQColor);
- fixGradientAndGenerateTexture(&newGradient, &m_uniformGradientTexture);
- }
-}
-
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h
index 06973f43..7a4422e4 100644
--- a/src/datavisualization/engine/surface3drenderer_p.h
+++ b/src/datavisualization/engine/surface3drenderer_p.h
@@ -34,6 +34,7 @@
#include "abstract3drenderer_p.h"
#include "scatterrenderitem_p.h"
#include "qsurfacedataproxy.h"
+#include "surfaceseriesrendercache_p.h"
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -47,20 +48,14 @@ class QT_DATAVISUALIZATION_EXPORT Surface3DRenderer : public Abstract3DRenderer
{
Q_OBJECT
-public:
- // Visual parameters
- QRect m_boundingRect;
- bool m_labelBackground;
- QFont m_font;
- bool m_isGridEnabled;
-
private:
bool m_cachedIsSlicingActivated;
// Internal attributes purely related to how the scene is drawn with GL.
ShaderHelper *m_depthShader;
ShaderHelper *m_backgroundShader;
- ShaderHelper *m_surfaceShader;
+ ShaderHelper *m_surfaceFlatShader;
+ ShaderHelper *m_surfaceSmoothShader;
ShaderHelper *m_surfaceGridShader;
ShaderHelper *m_selectionShader;
ShaderHelper *m_labelShader;
@@ -70,10 +65,6 @@ private:
GLfloat m_scaleZ;
GLfloat m_scaleXWithBackground;
GLfloat m_scaleZWithBackground;
- GLfloat m_surfaceScaleX;
- GLfloat m_surfaceScaleZ;
- GLfloat m_surfaceOffsetX;
- GLfloat m_surfaceOffsetZ;
GLfloat m_minVisibleColumnValue;
GLfloat m_maxVisibleColumnValue;
GLfloat m_minVisibleRowValue;
@@ -83,38 +74,28 @@ private:
ObjectHelper *m_backgroundObj;
ObjectHelper *m_gridLineObj;
ObjectHelper *m_labelObj;
- SurfaceObject *m_surfaceObj;
- SurfaceObject *m_sliceSurfaceObj;
GLuint m_depthTexture;
GLuint m_depthModelTexture;
GLuint m_depthFrameBuffer;
GLuint m_selectionFrameBuffer;
GLuint m_selectionDepthBuffer;
- GLuint m_selectionTexture;
GLuint m_selectionResultTexture;
GLfloat m_shadowQualityToShader;
- bool m_cachedFlatShading;
bool m_flatSupported;
- bool m_cachedSurfaceVisible;
- bool m_cachedSurfaceGridOn;
- SelectionPointer *m_selectionPointer;
bool m_selectionActive;
bool m_xFlipped;
bool m_zFlipped;
bool m_yFlipped;
AbstractRenderItem m_dummyRenderItem;
- QSurfaceDataArray m_dataArray;
- QSurfaceDataArray m_sliceDataArray;
- QRect m_sampleSpace;
GLint m_shadowQualityMultiplier;
QSizeF m_areaSize;
- uint m_clickedPointId;
bool m_hasHeightAdjustmentChanged;
QPoint m_selectedPoint;
const QSurface3DSeries *m_selectedSeries;
- GLuint m_uniformGradientTexture;
- QVector3D m_uniformGradientTextureColor;
QPoint m_clickedPosition;
+ QHash<QSurface3DSeries *, SurfaceSeriesRenderCache *> m_renderCacheList;
+ bool m_selectionTexturesDirty;
+ GLuint m_noShadowTexture;
public:
explicit Surface3DRenderer(Surface3DController *controller);
@@ -122,11 +103,12 @@ public:
void updateData();
void updateSeries(const QList<QAbstract3DSeries *> &seriesList, bool updateVisibility);
- void updateRows(const QVector<int> &rows);
- void updateItem(const QVector<QPoint> &points);
+ 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 updateScene(Q3DScene *scene);
- bool updateFlatStatus(bool enable);
- void updateSurfaceGridStatus(bool enable);
void updateSlicingActive(bool isSlicing);
void updateSelectedPoint(const QPoint &position, const QSurface3DSeries *series);
inline QPoint clickedPosition() const { return m_clickedPosition; }
@@ -142,16 +124,20 @@ signals:
void flatShadingSupportedChanged(bool supported);
private:
+ void checkFlatSupport(SurfaceSeriesRenderCache *cache);
+ void updateObjects(SurfaceSeriesRenderCache *cache, bool dimensionChanged);
void updateSliceDataModel(const QPoint &point);
+ QPoint mapCoordsToSampleSpace(SurfaceSeriesRenderCache *cache, const QPointF &coords);
+ void findMatchingRow(float z, int &sample, int direction, QSurfaceDataArray &dataArray);
+ void findMatchingColumn(float x, int &sample, int direction, QSurfaceDataArray &dataArray);
+ void updateSliceObject(SurfaceSeriesRenderCache *cache, const QPoint &point);
void updateShadowQuality(QAbstract3DGraph::ShadowQuality quality);
void updateTextures();
void initShaders(const QString &vertexShader, const QString &fragmentShader);
- QRect calculateSampleRect(const QSurfaceDataArray &array);
+ QRect calculateSampleRect(SurfaceSeriesRenderCache *cache, const QSurfaceDataArray &array);
void loadBackgroundMesh();
void loadGridLineMesh();
void loadLabelMesh();
- void loadSurfaceObj();
- void loadSliceSurfaceObj();
void drawScene(GLuint defaultFboHandle);
void calculateSceneScalingFactors();
void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader);
@@ -160,17 +146,18 @@ private:
void initSurfaceShaders();
void initSelectionBuffer();
void initDepthShader();
- void updateSelectionTexture();
+ void updateSelectionTextures();
+ void createSelectionTexture(SurfaceSeriesRenderCache *cache, uint &lastSelectionId);
void idToRGBA(uint id, uchar *r, uchar *g, uchar *b, uchar *a);
void fillIdCorner(uchar *p, uchar r, uchar g, uchar b, uchar a, int stride);
void surfacePointSelected(const QPoint &point);
+ void updateSelectionPoint(SurfaceSeriesRenderCache *cache, const QPoint &point, bool label);
QPoint selectionIdToSurfacePoint(uint id);
- QString createSelectionLabel(float value, int column, int row);
+ QString createSelectionLabel(SurfaceSeriesRenderCache *cache, float value, int column, int row);
#if !defined(QT_OPENGL_ES_2)
void updateDepthBuffer();
#endif
void emitSelectedPointChanged(QPoint position);
- void generateUniformGradient(const QVector3D newColor);
Q_DISABLE_COPY(Surface3DRenderer)
};
diff --git a/src/datavisualization/engine/surfaceseriesrendercache.cpp b/src/datavisualization/engine/surfaceseriesrendercache.cpp
new file mode 100644
index 00000000..ba25d71d
--- /dev/null
+++ b/src/datavisualization/engine/surfaceseriesrendercache.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** 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 "seriesrendercache_p.h"
+#include "surfaceseriesrendercache_p.h"
+#include "objecthelper_p.h"
+#include "abstract3drenderer_p.h"
+#include "texturehelper_p.h"
+#include "utils_p.h"
+
+QT_BEGIN_NAMESPACE_DATAVISUALIZATION
+
+SurfaceSeriesRenderCache::SurfaceSeriesRenderCache()
+ : 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_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_sliceSelectionPointer(0),
+ m_mainSelectionPointer(0),
+ m_slicePointerActive(false),
+ m_mainPointerActive(false),
+ m_valid(false),
+ m_objectDirty(true)
+{
+}
+
+SurfaceSeriesRenderCache::~SurfaceSeriesRenderCache()
+{
+}
+
+void SurfaceSeriesRenderCache::populate(QSurface3DSeries *series, Abstract3DRenderer *renderer)
+{
+ Q_ASSERT(series);
+
+ SeriesRenderCache::populate(series, renderer);
+
+ 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();
+ m_flatStatusDirty = true;
+ }
+}
+
+void SurfaceSeriesRenderCache::cleanup(TextureHelper *texHelper)
+{
+ if (QOpenGLContext::currentContext())
+ texHelper->deleteTexture(&m_selectionTexture);
+
+ delete m_surfaceObj;
+ delete m_sliceSurfaceObj;
+ for (int i = 0; i < m_dataArray.size(); i++)
+ delete m_dataArray.at(i);
+ m_dataArray.clear();
+
+ for (int i = 0; i < m_sliceDataArray.size(); i++)
+ delete m_sliceDataArray.at(i);
+ m_sliceDataArray.clear();
+
+ delete m_sliceSelectionPointer;
+ delete m_mainSelectionPointer;
+
+ SeriesRenderCache::cleanup(texHelper);
+}
+
+QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/surfaceseriesrendercache_p.h b/src/datavisualization/engine/surfaceseriesrendercache_p.h
new file mode 100644
index 00000000..2dda0670
--- /dev/null
+++ b/src/datavisualization/engine/surfaceseriesrendercache_p.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** 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 SURFACESERIESRENDERCACHE_P_H
+#define SURFACESERIESRENDERCACHE_P_H
+
+#include "datavisualizationglobal_p.h"
+#include "seriesrendercache_p.h"
+#include "qabstract3dseries_p.h"
+#include "qsurface3dseries_p.h"
+#include "surfaceobject_p.h"
+#include "selectionpointer_p.h"
+
+#include <QtGui/QMatrix4x4>
+
+QT_BEGIN_NAMESPACE_DATAVISUALIZATION
+
+class Abstract3DRenderer;
+class ObjectHelper;
+class TextureHelper;
+
+class SurfaceSeriesRenderCache : public SeriesRenderCache
+{
+public:
+ SurfaceSeriesRenderCache();
+ virtual ~SurfaceSeriesRenderCache();
+
+ void populate(QSurface3DSeries *series, Abstract3DRenderer *renderer);
+ virtual void cleanup(TextureHelper *texHelper);
+
+ inline bool surfaceVisible() const { return m_surfaceVisible; }
+ inline bool surfaceGridVisible() const { return m_surfaceGridVisible; }
+ 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; }
+ inline void setSampleSpace(const QRect &sampleSpace) { m_sampleSpace = sampleSpace; }
+ 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 void setSelectionTexture(GLuint texture) { m_selectionTexture = texture; }
+ inline GLuint selectionTexture() const { return m_selectionTexture; }
+ inline void setSelectionIdRange(uint start, uint end) { m_selectionIdStart = start;
+ m_selectionIdEnd = end; }
+ inline uint selectionIdStart() const { return m_selectionIdStart; }
+ inline bool isWithinIdRange(uint selection) const { return selection >= m_selectionIdStart &&
+ 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; }
+
+ inline void setSliceSelectionPointer(SelectionPointer *pointer) { m_sliceSelectionPointer = pointer; }
+ inline SelectionPointer *sliceSelectionPointer() const { return m_sliceSelectionPointer; }
+ inline void setMainSelectionPointer(SelectionPointer *pointer) { m_mainSelectionPointer = pointer; }
+ inline SelectionPointer *mainSelectionPointer() const { return m_mainSelectionPointer; }
+
+ inline void setSlicePointerActivity(bool activity) { m_slicePointerActive = activity; }
+ inline bool slicePointerActive() const { return m_slicePointerActive; }
+ inline void setMainPointerActivity(bool activity) { m_mainPointerActive = activity; }
+ inline bool mainPointerActive() const { return m_mainPointerActive; }
+
+protected:
+ bool m_surfaceVisible;
+ bool m_surfaceGridVisible;
+ bool m_surfaceFlatShading;
+ SurfaceObject *m_surfaceObj;
+ SurfaceObject *m_sliceSurfaceObj;
+ QRect m_sampleSpace;
+ QSurfaceDataArray m_dataArray;
+ QSurfaceDataArray m_sliceDataArray;
+ GLuint m_selectionTexture;
+ uint m_selectionIdStart;
+ 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
+
+#endif