summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@digia.com>2014-01-24 13:45:18 +0200
committerMiikka Heikkinen <miikka.heikkinen@digia.com>2014-01-27 07:51:17 +0200
commit71b501d31ae7c5d3aab987b54acccecce1136896 (patch)
tree7898e60da146dadd8ed665b21d35960efa5f61fa
parent8178f10769f7f7d84d4d1180994d0232e5fc8f93 (diff)
Added series rotation and bar item rotation support
Task-number: QTRD-2654 Change-Id: I864d33bc173b35b8680eddb402bdf1817ecb031f Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
-rw-r--r--src/datavisualization/data/barrenderitem.cpp3
-rw-r--r--src/datavisualization/data/barrenderitem_p.h8
-rw-r--r--src/datavisualization/data/qabstract3dseries.cpp47
-rw-r--r--src/datavisualization/data/qabstract3dseries.h6
-rw-r--r--src/datavisualization/data/qabstract3dseries_p.h4
-rw-r--r--src/datavisualization/data/qbardataitem.cpp27
-rw-r--r--src/datavisualization/data/qbardataitem.h8
-rw-r--r--src/datavisualization/data/qscatterdataitem.cpp5
-rw-r--r--src/datavisualization/data/scatterrenderitem.cpp1
-rw-r--r--src/datavisualization/engine/bars3drenderer.cpp78
-rw-r--r--src/datavisualization/engine/bars3drenderer_p.h1
-rw-r--r--src/datavisualization/engine/engine.qrc4
-rw-r--r--src/datavisualization/engine/scatter3drenderer.cpp34
-rw-r--r--src/datavisualization/engine/selectionpointer.cpp20
-rw-r--r--src/datavisualization/engine/selectionpointer_p.h8
-rw-r--r--src/datavisualization/engine/seriesrendercache.cpp5
-rw-r--r--src/datavisualization/engine/seriesrendercache_p.h3
-rw-r--r--src/datavisualization/engine/surface3drenderer.cpp6
-rw-r--r--tests/barstest/chart.cpp38
-rw-r--r--tests/barstest/chart.h4
-rw-r--r--tests/barstest/main.cpp7
-rw-r--r--tests/directional/main.cpp6
-rw-r--r--tests/directional/scatterdatamodifier.cpp29
-rw-r--r--tests/directional/scatterdatamodifier.h4
24 files changed, 308 insertions, 48 deletions
diff --git a/src/datavisualization/data/barrenderitem.cpp b/src/datavisualization/data/barrenderitem.cpp
index 1bb1271d..a558e1fd 100644
--- a/src/datavisualization/data/barrenderitem.cpp
+++ b/src/datavisualization/data/barrenderitem.cpp
@@ -39,6 +39,7 @@ BarRenderItem::BarRenderItem(const BarRenderItem &other)
m_sliceLabel = other.m_sliceLabel;
m_sliceLabelItem = 0;
m_seriesIndex = other.m_seriesIndex;
+ m_rotation = other.m_rotation;
}
BarRenderItem::~BarRenderItem()
@@ -60,7 +61,7 @@ void BarRenderItem::setSliceLabel(const QString &label)
m_sliceLabel = label;
}
-QString &BarRenderItem::sliceLabel()
+const QString &BarRenderItem::sliceLabel() const
{
return m_sliceLabel;
}
diff --git a/src/datavisualization/data/barrenderitem_p.h b/src/datavisualization/data/barrenderitem_p.h
index 7704d65e..66c9c460 100644
--- a/src/datavisualization/data/barrenderitem_p.h
+++ b/src/datavisualization/data/barrenderitem_p.h
@@ -67,12 +67,15 @@ public:
// Formatted label for item.
void setSliceLabel(const QString &label);
- QString &sliceLabel(); // Formats label if not previously formatted
+ const QString &sliceLabel() const; // Formats label if not previously formatted
// Series index in visual series that this item belongs to.
// This is only utilized by slicing, so it may not be up to date on all items.
inline void setSeriesIndex(int seriesIndex) { m_seriesIndex = seriesIndex; }
- inline int seriesIndex() { return m_seriesIndex; }
+ inline int seriesIndex() const { return m_seriesIndex; }
+
+ inline void setRotation(const QQuaternion &rotation) { m_rotation = rotation; }
+ inline const QQuaternion &rotation() const { return m_rotation; }
protected:
float m_value;
@@ -81,6 +84,7 @@ protected:
QString m_sliceLabel;
LabelItem *m_sliceLabelItem;
int m_seriesIndex;
+ QQuaternion m_rotation;
friend class QBarDataItem;
};
diff --git a/src/datavisualization/data/qabstract3dseries.cpp b/src/datavisualization/data/qabstract3dseries.cpp
index a3f766a8..d80879f0 100644
--- a/src/datavisualization/data/qabstract3dseries.cpp
+++ b/src/datavisualization/data/qabstract3dseries.cpp
@@ -142,6 +142,18 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
*/
/*!
+ * \qmlproperty quaternion Abstract3DSeries::meshRotation
+ *
+ * Sets the mesh \a rotation that is applied to all items of the series.
+ * The \a rotation should be a normalized quaternion.
+ * For those series types that support item specific rotation, the rotations are
+ * multiplied together.
+ * Bar3DSeries ignores any rotation that is not around Y-axis.
+ * Surface3DSeries applies the rotation only to the selection pointer.
+ * Defaults to no rotation.
+ */
+
+/*!
* \qmlproperty string Abstract3DSeries::userDefinedMesh
*
* Sets the \a fileName for user defined custom mesh for objects that is used when mesh
@@ -303,7 +315,8 @@ bool QAbstract3DSeries::isVisible() const
*/
void QAbstract3DSeries::setMesh(QAbstract3DSeries::Mesh mesh)
{
- if ((mesh == QAbstract3DSeries::MeshPoint || mesh == QAbstract3DSeries::MeshMinimal)
+ if ((mesh == QAbstract3DSeries::MeshPoint || mesh == QAbstract3DSeries::MeshMinimal
+ || mesh == QAbstract3DSeries::MeshArrow)
&& type() != QAbstract3DSeries::SeriesTypeScatter) {
qWarning() << "Specified style is only supported for QScatter3DSeries.";
} else if (d_ptr->m_mesh != mesh) {
@@ -338,6 +351,30 @@ bool QAbstract3DSeries::isMeshSmooth() const
}
/*!
+ * \property QAbstract3DSeries::meshRotation
+ *
+ * Sets the mesh \a rotation that is applied to all items of the series.
+ * The \a rotation should be a normalized QQuaternion.
+ * For those series types that support item specific rotation, the rotations are
+ * multiplied together.
+ * QBar3DSeries ignores any rotation that is not around Y-axis.
+ * QSurface3DSeries applies the rotation only to the selection pointer.
+ * Defaults to no rotation.
+ */
+void QAbstract3DSeries::setMeshRotation(const QQuaternion &rotation)
+{
+ if (d_ptr->m_meshRotation != rotation) {
+ d_ptr->setMeshRotation(rotation);
+ emit meshRotationChanged(rotation);
+ }
+}
+
+QQuaternion QAbstract3DSeries::meshRotation() const
+{
+ return d_ptr->m_meshRotation;
+}
+
+/*!
* \property QAbstract3DSeries::userDefinedMesh
*
* Sets the \a fileName for user defined custom mesh for objects that is used when mesh
@@ -608,6 +645,14 @@ void QAbstract3DSeriesPrivate::setMeshSmooth(bool enable)
m_controller->markSeriesVisualsDirty();
}
+void QAbstract3DSeriesPrivate::setMeshRotation(const QQuaternion &rotation)
+{
+ m_meshRotation = rotation;
+ m_changeTracker.meshRotationChanged = true;
+ if (m_controller)
+ m_controller->markSeriesVisualsDirty();
+}
+
void QAbstract3DSeriesPrivate::setUserDefinedMesh(const QString &meshFile)
{
m_userDefinedMesh = meshFile;
diff --git a/src/datavisualization/data/qabstract3dseries.h b/src/datavisualization/data/qabstract3dseries.h
index df6dada8..5e7fe016 100644
--- a/src/datavisualization/data/qabstract3dseries.h
+++ b/src/datavisualization/data/qabstract3dseries.h
@@ -23,6 +23,7 @@
#include <QObject>
#include <QScopedPointer>
#include <QLinearGradient>
+#include <QQuaternion>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -38,6 +39,7 @@ class QT_DATAVISUALIZATION_EXPORT QAbstract3DSeries : public QObject
Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibilityChanged)
Q_PROPERTY(Mesh mesh READ mesh WRITE setMesh NOTIFY meshChanged)
Q_PROPERTY(bool meshSmooth READ isMeshSmooth WRITE setMeshSmooth NOTIFY meshSmoothChanged)
+ Q_PROPERTY(QQuaternion meshRotation READ meshRotation WRITE setMeshRotation NOTIFY meshRotationChanged)
Q_PROPERTY(QString userDefinedMesh READ userDefinedMesh WRITE setUserDefinedMesh NOTIFY userDefinedMeshChanged)
Q_PROPERTY(QtDataVisualization::Q3DTheme::ColorStyle colorStyle READ colorStyle WRITE setColorStyle NOTIFY colorStyleChanged)
Q_PROPERTY(QColor baseColor READ baseColor WRITE setBaseColor NOTIFY baseColorChanged)
@@ -91,6 +93,9 @@ public:
void setMeshSmooth(bool enable);
bool isMeshSmooth() const;
+ void setMeshRotation(const QQuaternion &rotation);
+ QQuaternion meshRotation() const;
+
void setUserDefinedMesh(const QString &fileName);
QString userDefinedMesh() const;
@@ -117,6 +122,7 @@ signals:
void visibilityChanged(bool visible);
void meshChanged(Mesh mesh);
void meshSmoothChanged(bool enabled);
+ void meshRotationChanged(QQuaternion rotation);
void userDefinedMeshChanged(QString fileName);
void colorStyleChanged(Q3DTheme::ColorStyle style);
void baseColorChanged(QColor color);
diff --git a/src/datavisualization/data/qabstract3dseries_p.h b/src/datavisualization/data/qabstract3dseries_p.h
index f1bc1f95..565d35a2 100644
--- a/src/datavisualization/data/qabstract3dseries_p.h
+++ b/src/datavisualization/data/qabstract3dseries_p.h
@@ -42,6 +42,7 @@ struct QAbstract3DSeriesChangeBitField {
bool itemLabelFormatChanged : 1;
bool meshChanged : 1;
bool meshSmoothChanged : 1;
+ bool meshRotationChanged : 1;
bool userDefinedMeshChanged : 1;
bool colorStyleChanged : 1;
bool baseColorChanged : 1;
@@ -56,6 +57,7 @@ struct QAbstract3DSeriesChangeBitField {
: itemLabelFormatChanged(true),
meshChanged(true),
meshSmoothChanged(true),
+ meshRotationChanged(true),
userDefinedMeshChanged(true),
colorStyleChanged(true),
baseColorChanged(true),
@@ -106,6 +108,7 @@ public:
void setVisible(bool visible);
void setMesh(QAbstract3DSeries::Mesh mesh);
void setMeshSmooth(bool enable);
+ void setMeshRotation(const QQuaternion &rotation);
void setUserDefinedMesh(const QString &meshFile);
void setColorStyle(Q3DTheme::ColorStyle style);
@@ -129,6 +132,7 @@ public:
Abstract3DController *m_controller;
QAbstract3DSeries::Mesh m_mesh;
bool m_meshSmooth;
+ QQuaternion m_meshRotation;
QString m_userDefinedMesh;
Q3DTheme::ColorStyle m_colorStyle;
diff --git a/src/datavisualization/data/qbardataitem.cpp b/src/datavisualization/data/qbardataitem.cpp
index 3e8ebee2..eb14c7f9 100644
--- a/src/datavisualization/data/qbardataitem.cpp
+++ b/src/datavisualization/data/qbardataitem.cpp
@@ -37,7 +37,8 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
*/
QBarDataItem::QBarDataItem()
: d_ptr(0), // private data doesn't exist by default (optimization)
- m_value(0.0f)
+ m_value(0.0f),
+ m_angle(0.0f)
{
}
@@ -46,7 +47,18 @@ QBarDataItem::QBarDataItem()
*/
QBarDataItem::QBarDataItem(float value)
: d_ptr(0),
- m_value(value)
+ m_value(value),
+ m_angle(0.0f)
+{
+}
+
+/*!
+ * Constructs QBarDataItem with \a value and \a angle
+ */
+QBarDataItem::QBarDataItem(float value, float angle)
+ : d_ptr(0),
+ m_value(value),
+ m_angle(angle)
{
}
@@ -72,6 +84,7 @@ QBarDataItem::~QBarDataItem()
QBarDataItem &QBarDataItem::operator=(const QBarDataItem &other)
{
m_value = other.m_value;
+ m_angle = other.m_angle;
if (other.d_ptr)
createExtraData();
else
@@ -90,6 +103,16 @@ QBarDataItem &QBarDataItem::operator=(const QBarDataItem &other)
*/
/*!
+ * \fn void QBarDataItem::setRotation(float angle)
+ * Sets rotation \a angle in degrees for this data item.
+ */
+
+/*!
+ * \fn float QBarDataItem::rotation() const
+ * \return rotation angle in degrees for this data item.
+ */
+
+/*!
* \internal
*/
void QBarDataItem::createExtraData()
diff --git a/src/datavisualization/data/qbardataitem.h b/src/datavisualization/data/qbardataitem.h
index 57a14efb..f16a21b7 100644
--- a/src/datavisualization/data/qbardataitem.h
+++ b/src/datavisualization/data/qbardataitem.h
@@ -30,13 +30,16 @@ class QT_DATAVISUALIZATION_EXPORT QBarDataItem
public:
QBarDataItem();
QBarDataItem(float value);
+ QBarDataItem(float value, float angle);
QBarDataItem(const QBarDataItem &other);
~QBarDataItem();
QBarDataItem &operator=(const QBarDataItem &other);
- void setValue(float value) { m_value = value; }
- float value() const { return m_value; }
+ inline void setValue(float value) { m_value = value; }
+ inline float value() const { return m_value; }
+ inline void setRotation(float angle) { m_angle = angle; }
+ inline float rotation() const { return m_angle; }
protected:
virtual void createExtraData();
@@ -45,6 +48,7 @@ protected:
private:
float m_value;
+ float m_angle;
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/data/qscatterdataitem.cpp b/src/datavisualization/data/qscatterdataitem.cpp
index d4641c7f..b8b85381 100644
--- a/src/datavisualization/data/qscatterdataitem.cpp
+++ b/src/datavisualization/data/qscatterdataitem.cpp
@@ -72,6 +72,7 @@ QScatterDataItem::~QScatterDataItem()
QScatterDataItem &QScatterDataItem::operator=(const QScatterDataItem &other)
{
m_position = other.m_position;
+ m_rotation = other.m_rotation;
if (other.d_ptr)
createExtraData();
@@ -94,11 +95,15 @@ QScatterDataItem &QScatterDataItem::operator=(const QScatterDataItem &other)
/*!
* \fn void QScatterDataItem::setRotation(const QQuaternion &rotation)
* Sets \a rotation to this data item.
+ * The \a rotation should be a normalized QQuaternion.
+ * If the series also has rotation, item and series rotations are multiplied together.
+ * Defaults to no rotation.
*/
/*!
* \fn QQuaternion QScatterDataItem::rotation() const
* \return rotation of this data item.
+ * \sa setRotation()
*/
/*!
diff --git a/src/datavisualization/data/scatterrenderitem.cpp b/src/datavisualization/data/scatterrenderitem.cpp
index 635f11cb..236893a8 100644
--- a/src/datavisualization/data/scatterrenderitem.cpp
+++ b/src/datavisualization/data/scatterrenderitem.cpp
@@ -33,6 +33,7 @@ ScatterRenderItem::ScatterRenderItem(const ScatterRenderItem &other)
m_visible(false)
{
m_position = other.m_position;
+ m_rotation = other.m_rotation;
}
ScatterRenderItem::~ScatterRenderItem()
diff --git a/src/datavisualization/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp
index 4140f01c..7e727645 100644
--- a/src/datavisualization/engine/bars3drenderer.cpp
+++ b/src/datavisualization/engine/bars3drenderer.cpp
@@ -44,6 +44,7 @@ const GLfloat labelMargin = 0.05f;
const GLfloat gridLineWidth = 0.005f;
const bool sliceGridLabels = true;
+const QQuaternion identityQuaternion;
Bars3DRenderer::Bars3DRenderer(Bars3DController *controller)
: Abstract3DRenderer(controller),
@@ -190,12 +191,13 @@ void Bars3DRenderer::updateData()
}
for (int series = 0; series < seriesCount; series++) {
- if (newRows != m_renderingArrays.at(series).size()
- || newColumns != m_renderingArrays.at(series).at(0).size()) {
+ BarRenderItemArray &renderArray = m_renderingArrays[series];
+ if (newRows != renderArray.size()
+ || newColumns != renderArray.at(0).size()) {
// Destroy old render items and reallocate new array
- m_renderingArrays[series].resize(newRows);
+ renderArray.resize(newRows);
for (int i = 0; i < newRows; i++)
- m_renderingArrays[series][i].resize(newColumns);
+ renderArray[i].resize(newColumns);
}
// Update cached data window
@@ -208,10 +210,10 @@ void Bars3DRenderer::updateData()
GLfloat heightValue = 0.0f;
for (int i = 0; i < newRows; i++) {
int j = 0;
+ BarRenderItemRow &renderRow = renderArray[i];
if (dataRowIndex < dataRowCount) {
const QBarDataRow *dataRow = dataProxy->rowAt(dataRowIndex);
- updateSize = qMin((dataRow->size() - minCol),
- m_renderingArrays.at(series).at(i).size());
+ updateSize = qMin((dataRow->size() - minCol), renderRow.size());
if (dataRow) {
int dataColIndex = minCol;
for (; j < updateSize ; j++) {
@@ -230,15 +232,24 @@ void Bars3DRenderer::updateData()
heightValue = 0.0f;
}
}
- m_renderingArrays[series][i][j].setValue(value);
- m_renderingArrays[series][i][j].setHeight(heightValue / m_heightNormalizer);
+ renderRow[j].setValue(value);
+ renderRow[j].setHeight(heightValue / m_heightNormalizer);
+ float angle = dataRow->at(dataColIndex).rotation();
+ if (angle) {
+ renderRow[j].setRotation(
+ QQuaternion::fromAxisAndAngle(
+ upVector, angle));
+ } else {
+ renderRow[j].setRotation(identityQuaternion);
+ }
dataColIndex++;
}
}
}
for (; j < m_renderingArrays.at(series).at(i).size(); j++) {
- m_renderingArrays[series][i][j].setValue(0.0f);
- m_renderingArrays[series][i][j].setHeight(0.0f);
+ renderRow[j].setValue(0.0f);
+ renderRow[j].setHeight(0.0f);
+ renderRow[j].setRotation(identityQuaternion);
}
dataRowIndex++;
}
@@ -248,6 +259,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)
@@ -283,6 +306,7 @@ void Bars3DRenderer::drawSlicedScene()
GLfloat barPosX = 0;
QVector3D lightPos;
QVector3D lightColor = Utils::vectorFromColor(m_cachedTheme->lightColor());
+ static QQuaternion ninetyDegreeRotation = QQuaternion::fromAxisAndAngle(upVector, 90.0f);
// Specify viewport
glViewport(m_secondarySubViewport.x(),
@@ -479,6 +503,8 @@ void Bars3DRenderer::drawSlicedScene()
if (!item)
continue;
+ QQuaternion seriesRotation;
+
if (item->seriesIndex() != currentSeriesIndex) {
currentSeriesIndex = item->seriesIndex();
currentSeries = &(m_visibleSeriesList.at(currentSeriesIndex));
@@ -509,6 +535,7 @@ void Bars3DRenderer::drawSlicedScene()
}
previousColorStyle = colorStyle;
+ seriesRotation = currentSeries->meshRotation();
}
if (item->height() < 0)
@@ -519,20 +546,27 @@ void Bars3DRenderer::drawSlicedScene()
QMatrix4x4 MVPMatrix;
QMatrix4x4 modelMatrix;
QMatrix4x4 itModelMatrix;
- GLfloat barRotation = 0.0f;
+ QQuaternion barRotation = item->rotation();
GLfloat barPosY = item->translation().y() + barPosYAdjustment - zeroPosAdjustment;
if (rowMode) {
barPosX = item->translation().x();
} else {
barPosX = -(item->translation().z()); // flip z; frontmost bar to the left
- barRotation = 90.0f;
+ barRotation *= ninetyDegreeRotation;
}
modelMatrix.translate(barPosX, barPosY, 0.0f);
modelMatrixScaler.setY(item->height());
- modelMatrix.rotate(barRotation, 0.0f, 1.0f, 0.0f);
- itModelMatrix.rotate(barRotation, 0.0f, 1.0f, 0.0f);
+
+ if (!seriesRotation.isIdentity())
+ barRotation *= seriesRotation;
+
+ if (!barRotation.isIdentity()) {
+ modelMatrix.rotate(barRotation);
+ itModelMatrix.rotate(barRotation);
+ }
+
modelMatrix.scale(modelMatrixScaler);
itModelMatrix.scale(modelMatrixScaler);
@@ -822,6 +856,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
float seriesPos = m_seriesStart;
for (int series = 0; series < seriesCount; series++) {
ObjectHelper *barObj = m_visibleSeriesList.at(series).object();
+ QQuaternion seriesRotation(m_visibleSeriesList.at(series).meshRotation());
for (int row = startRow; row != stopRow; row += stepRow) {
for (int bar = startBar; bar != stopBar; bar += stepBar) {
GLfloat shadowOffset = 0.0f;
@@ -853,6 +888,8 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
(m_columnDepth - rowPos) / m_scaleFactor);
// Scale the bars down in X and Z to reduce self-shadowing issues
shadowScaler.setY(item.height());
+ if (!seriesRotation.isIdentity() || !item.rotation().isIdentity())
+ modelMatrix.rotate(seriesRotation * item.rotation());
modelMatrix.scale(shadowScaler);
MVPMatrix = depthProjectionViewMatrix * modelMatrix;
@@ -915,6 +952,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
float seriesPos = m_seriesStart;
for (int series = 0; series < seriesCount; series++) {
ObjectHelper *barObj = m_visibleSeriesList.at(series).object();
+ QQuaternion seriesRotation(m_visibleSeriesList.at(series).meshRotation());
for (int row = startRow; row != stopRow; row += stepRow) {
for (int bar = startBar; bar != stopBar; bar += stepBar) {
const BarRenderItem &item = m_renderingArrays.at(series).at(row).at(bar);
@@ -935,6 +973,8 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor,
item.height(),
(m_columnDepth - rowPos) / m_scaleFactor);
+ if (!seriesRotation.isIdentity() || !item.rotation().isIdentity())
+ modelMatrix.rotate(seriesRotation * item.rotation());
modelMatrix.scale(QVector3D(m_scaleX * m_seriesScaleX,
item.height(),
m_scaleZ * m_seriesScaleZ));
@@ -1063,6 +1103,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
float seriesPos = m_seriesStart;
for (int series = 0; series < seriesCount; series++) {
const SeriesRenderCache &currentSeries = m_visibleSeriesList.at(series);
+ QQuaternion seriesRotation(currentSeries.meshRotation());
ObjectHelper *barObj = currentSeries.object();
Q3DTheme::ColorStyle colorStyle = currentSeries.colorStyle();
bool colorStyleIsUniform = (colorStyle == Q3DTheme::ColorStyleUniform);
@@ -1123,6 +1164,11 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
item.height(),
(m_columnDepth - rowPos) / m_scaleFactor);
modelScaler.setY(item.height());
+ if (!seriesRotation.isIdentity() || !item.rotation().isIdentity()) {
+ QQuaternion totalRotation = seriesRotation * item.rotation();
+ modelMatrix.rotate(totalRotation);
+ itModelMatrix.rotate(totalRotation);
+ }
modelMatrix.scale(modelScaler);
itModelMatrix.scale(modelScaler);
#ifdef SHOW_DEPTH_TEXTURE_SCENE
@@ -1388,7 +1434,7 @@ void Bars3DRenderer::drawScene(GLuint defaultFboHandle)
// Draw grid lines
if (m_cachedTheme->isGridEnabled() && m_heightNormalizer) {
ShaderHelper *lineShader = m_backgroundShader;
- QQuaternion lineRotation = QQuaternion();
+ QQuaternion lineRotation;
// Bind bar shader
lineShader->bind();
@@ -2021,7 +2067,7 @@ void Bars3DRenderer::fixMeshFileName(QString &fileName, QAbstract3DSeries::Mesh
{
if (!m_cachedTheme->isBackgroundEnabled()) {
// Load full version of meshes that have it available
- // Note: Minimal and Point not supported in bar charts
+ // Note: Minimal, Point, and Arrow not supported in bar charts
if (mesh != QAbstract3DSeries::MeshSphere)
fileName.append(QStringLiteral("Full"));
}
diff --git a/src/datavisualization/engine/bars3drenderer_p.h b/src/datavisualization/engine/bars3drenderer_p.h
index 04e2a1ac..46227aed 100644
--- a/src/datavisualization/engine/bars3drenderer_p.h
+++ b/src/datavisualization/engine/bars3drenderer_p.h
@@ -114,6 +114,7 @@ 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/engine.qrc b/src/datavisualization/engine/engine.qrc
index 073c7450..18cba7fe 100644
--- a/src/datavisualization/engine/engine.qrc
+++ b/src/datavisualization/engine/engine.qrc
@@ -27,8 +27,8 @@
<file alias="negativeBackground">meshes/backgroundNegatives.obj</file>
<file alias="minimal">meshes/minimalFlat.obj</file>
<file alias="minimalSmooth">meshes/minimalSmooth.obj</file>
- <file alias="arrowFull">meshes/arrowFlat.obj</file>
- <file alias="arrowSmoothFull">meshes/arrowSmooth.obj</file>
+ <file alias="arrow">meshes/arrowFlat.obj</file>
+ <file alias="arrowSmooth">meshes/arrowSmooth.obj</file>
</qresource>
<qresource prefix="/shaders">
<file alias="fragment">shaders/default.frag</file>
diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp
index 9cbffcdb..7a2bf568 100644
--- a/src/datavisualization/engine/scatter3drenderer.cpp
+++ b/src/datavisualization/engine/scatter3drenderer.cpp
@@ -204,15 +204,16 @@ void Scatter3DRenderer::updateData()
for (int i = 0; i < dataSize; i++) {
QVector3D dotPos = dataArray.at(i).position();
+ ScatterRenderItem &renderItem = m_renderingArrays[series][i];
if ((dotPos.x() >= minX && dotPos.x() <= maxX )
&& (dotPos.y() >= minY && dotPos.y() <= maxY)
&& (dotPos.z() >= minZ && dotPos.z() <= maxZ)) {
- m_renderingArrays[series][i].setPosition(dotPos);
- m_renderingArrays[series][i].setVisible(true);
- m_renderingArrays[series][i].setRotation(dataArray.at(i).rotation());
- calculateTranslation(m_renderingArrays[series][i]);
+ renderItem.setPosition(dotPos);
+ renderItem.setVisible(true);
+ renderItem.setRotation(dataArray.at(i).rotation());
+ calculateTranslation(renderItem);
} else {
- m_renderingArrays[series][i].setVisible(false);
+ renderItem.setVisible(false);
}
}
}
@@ -372,6 +373,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
// Draw dots to depth buffer
for (int series = 0; series < seriesCount; series++) {
ObjectHelper *dotObj = m_visibleSeriesList.at(series).object();
+ QQuaternion seriesRotation = m_visibleSeriesList.at(series).meshRotation();
bool drawingPoints = (m_visibleSeriesList.at(series).mesh() == QAbstract3DSeries::MeshPoint);
float itemSize = m_cachedItemSize.at(series) / itemScaler;
@@ -393,7 +395,8 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
modelMatrix.translate(item.translation());
if (!drawingPoints) {
- modelMatrix.rotate(item.rotation());
+ if (!seriesRotation.isIdentity() || !item.rotation().isIdentity())
+ modelMatrix.rotate(seriesRotation * item.rotation());
modelMatrix.scale(modelScaler);
}
@@ -467,6 +470,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
bool previousDrawingPoints = (m_visibleSeriesList.at(0).mesh() != QAbstract3DSeries::MeshPoint);
for (int series = 0; series < seriesCount; series++) {
ObjectHelper *dotObj = m_visibleSeriesList.at(series).object();
+ QQuaternion seriesRotation = m_visibleSeriesList.at(series).meshRotation();
bool drawingPoints = (m_visibleSeriesList.at(series).mesh() == QAbstract3DSeries::MeshPoint);
float itemSize = m_cachedItemSize.at(series) / itemScaler;
@@ -504,7 +508,8 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
modelMatrix.translate(item.translation());
if (!drawingPoints) {
- modelMatrix.rotate(item.rotation());
+ if (!seriesRotation.isIdentity() || !item.rotation().isIdentity())
+ modelMatrix.rotate(seriesRotation * item.rotation());
modelMatrix.scale(modelScaler);
}
@@ -601,6 +606,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
for (int series = 0; series < seriesCount; series++) {
const SeriesRenderCache &currentSeries = m_visibleSeriesList.at(series);
+ QQuaternion seriesRotation = currentSeries.meshRotation();
ObjectHelper *dotObj = currentSeries.object();
bool drawingPoints = (currentSeries.mesh() == QAbstract3DSeries::MeshPoint);
Q3DTheme::ColorStyle colorStyle = currentSeries.colorStyle();
@@ -662,10 +668,13 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
modelMatrix.translate(item.translation());
if (!drawingPoints) {
- modelMatrix.rotate(item.rotation());
+ if (!seriesRotation.isIdentity() || !item.rotation().isIdentity()) {
+ QQuaternion totalRotation = seriesRotation * item.rotation();
+ modelMatrix.rotate(totalRotation);
+ itModelMatrix.rotate(totalRotation);
+ }
modelMatrix.scale(modelScaler);
itModelMatrix.scale(modelScaler);
- itModelMatrix.rotate(item.rotation());
}
#ifdef SHOW_DEPTH_TEXTURE_SCENE
MVPMatrix = depthProjectionViewMatrix * modelMatrix;
@@ -862,8 +871,8 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle)
m_cachedTheme->lightStrength() / 2.5f);
}
- QQuaternion lineYRotation = QQuaternion();
- QQuaternion lineXRotation = QQuaternion();
+ QQuaternion lineYRotation;
+ QQuaternion lineXRotation;
if (m_xFlipped)
lineYRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, -90.0f);
@@ -1618,7 +1627,8 @@ void Scatter3DRenderer::fixMeshFileName(QString &fileName, QAbstract3DSeries::Me
// Load full version of meshes that have it available
if (mesh != QAbstract3DSeries::MeshSphere
&& mesh != QAbstract3DSeries::MeshMinimal
- && mesh != QAbstract3DSeries::MeshPoint) {
+ && mesh != QAbstract3DSeries::MeshPoint
+ && mesh != QAbstract3DSeries::MeshArrow) {
fileName.append(QStringLiteral("Full"));
}
}
diff --git a/src/datavisualization/engine/selectionpointer.cpp b/src/datavisualization/engine/selectionpointer.cpp
index 85fb2b71..2dd23930 100644
--- a/src/datavisualization/engine/selectionpointer.cpp
+++ b/src/datavisualization/engine/selectionpointer.cpp
@@ -110,8 +110,15 @@ void SelectionPointer::render(GLuint defaultFboHandle)
// Position the pointer ball
modelMatrix.translate(m_position);
+ if (!m_rotation.isIdentity()) {
+ modelMatrix.rotate(m_rotation);
+ itModelMatrix.rotate(m_rotation);
+ }
+
// Scale the point with fixed values (at this point)
- modelMatrix.scale(QVector3D(0.05f, 0.05f, 0.05f));
+ QVector3D scaleVector(0.05f, 0.05f, 0.05f);
+ modelMatrix.scale(scaleVector);
+ itModelMatrix.scale(scaleVector);
MVPMatrix = projectionMatrix * viewMatrix * modelMatrix;
@@ -189,7 +196,7 @@ void SelectionPointer::render(GLuint defaultFboHandle)
glEnable(GL_DEPTH_TEST);
}
-void SelectionPointer::setPosition(QVector3D position)
+void SelectionPointer::setPosition(const QVector3D &position)
{
m_position = position;
}
@@ -200,11 +207,16 @@ void SelectionPointer::updateSliceData(bool sliceActivated, GLfloat autoScaleAdj
m_autoScaleAdjustment = autoScaleAdjustment;
}
-void SelectionPointer::setHighlightColor(QVector3D colorVector)
+void SelectionPointer::setHighlightColor(const QVector3D &colorVector)
{
m_highlightColor = colorVector;
}
+void SelectionPointer::setRotation(const QQuaternion &rotation)
+{
+ m_rotation = rotation;
+}
+
void SelectionPointer::setLabel(const QString &label)
{
m_label = label;
@@ -222,7 +234,7 @@ void SelectionPointer::handleDrawerChange()
setLabel(m_label);
}
-void SelectionPointer::updateBoundingRect(QRect rect)
+void SelectionPointer::updateBoundingRect(const QRect &rect)
{
m_mainViewPort = rect;
}
diff --git a/src/datavisualization/engine/selectionpointer_p.h b/src/datavisualization/engine/selectionpointer_p.h
index 12317943..5d901caa 100644
--- a/src/datavisualization/engine/selectionpointer_p.h
+++ b/src/datavisualization/engine/selectionpointer_p.h
@@ -52,14 +52,15 @@ public:
~SelectionPointer();
void render(GLuint defaultFboHandle = 0);
- void setPosition(QVector3D position);
+ void setPosition(const QVector3D &position);
void setLabel(const QString &label);
void setPointerObject(ObjectHelper *object);
void handleDrawerChange();
- void updateBoundingRect(QRect rect);
+ void updateBoundingRect(const QRect &rect);
void updateScene(Q3DScene *scene);
void updateSliceData(bool sliceActivated, GLfloat autoScaleAdjustment);
- void setHighlightColor(QVector3D colorVector);
+ void setHighlightColor(const QVector3D &colorVector);
+ void setRotation(const QQuaternion &rotation);
private:
void initializeOpenGL();
@@ -83,6 +84,7 @@ private:
bool m_cachedIsSlicingActivated;
GLfloat m_autoScaleAdjustment;
QVector3D m_highlightColor;
+ QQuaternion m_rotation;
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/engine/seriesrendercache.cpp b/src/datavisualization/engine/seriesrendercache.cpp
index f1165cb7..f13fc2ca 100644
--- a/src/datavisualization/engine/seriesrendercache.cpp
+++ b/src/datavisualization/engine/seriesrendercache.cpp
@@ -126,6 +126,11 @@ void SeriesRenderCache::populate(QAbstract3DSeries *series, Abstract3DRenderer *
}
}
+ if (seriesChanged || changeTracker.meshRotationChanged) {
+ m_meshRotation = series->meshRotation();
+ changeTracker.meshRotationChanged = false;
+ }
+
if (seriesChanged || changeTracker.colorStyleChanged) {
m_colorStyle = series->colorStyle();
changeTracker.colorStyleChanged = false;
diff --git a/src/datavisualization/engine/seriesrendercache_p.h b/src/datavisualization/engine/seriesrendercache_p.h
index 81eaacbc..ec6ef0ad 100644
--- a/src/datavisualization/engine/seriesrendercache_p.h
+++ b/src/datavisualization/engine/seriesrendercache_p.h
@@ -53,6 +53,8 @@ public:
inline const QString &itemLabelFormat() const { return m_itemLabelFormat; }
inline const QAbstract3DSeries::Mesh &mesh() const { return m_mesh; }
+ inline const QQuaternion &meshRotation() const { return m_meshRotation; }
+ inline void setMeshRotation(const QQuaternion &rotation) { m_meshRotation = rotation; }
inline ObjectHelper *object() const { return m_object; }
inline const Q3DTheme::ColorStyle &colorStyle() const { return m_colorStyle; }
inline const QVector3D &baseColor() const { return m_baseColor; }
@@ -68,6 +70,7 @@ protected:
QString m_itemLabelFormat;
ObjectHelper *m_object;
QAbstract3DSeries::Mesh m_mesh;
+ QQuaternion m_meshRotation;
Q3DTheme::ColorStyle m_colorStyle;
QVector3D m_baseColor;
diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp
index 286477df..2ef5ea5d 100644
--- a/src/datavisualization/engine/surface3drenderer.cpp
+++ b/src/datavisualization/engine/surface3drenderer.cpp
@@ -301,6 +301,7 @@ void Surface3DRenderer::updateSeries(const QList<QAbstract3DSeries *> &seriesLis
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());
}
}
}
@@ -1222,8 +1223,8 @@ void Surface3DRenderer::drawScene(GLuint defaultFboHandle)
m_cachedTheme->lightStrength() / 2.5f);
}
- QQuaternion lineYRotation = QQuaternion();
- QQuaternion lineXRotation = QQuaternion();
+ QQuaternion lineYRotation;
+ QQuaternion lineXRotation;
if (m_xFlipped)
lineYRotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, -90.0f);
@@ -1934,6 +1935,7 @@ void Surface3DRenderer::surfacePointSelected(const QPoint &point)
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());
}
// Maps selection Id to surface point in data array
diff --git a/tests/barstest/chart.cpp b/tests/barstest/chart.cpp
index 6b0345ad..187f4886 100644
--- a/tests/barstest/chart.cpp
+++ b/tests/barstest/chart.cpp
@@ -47,6 +47,7 @@ GraphModifier::GraphModifier(Q3DBars *barchart, QColorDialog *colorDialog)
m_minval(-16.0f),
m_maxval(20.0f),
m_selectedBar(-1, -1),
+ m_selectedSeries(0),
m_autoAdjustingAxis(new QValue3DAxis),
m_fixedRangeAxis(new QValue3DAxis),
m_temperatureAxis(new QValue3DAxis),
@@ -229,6 +230,8 @@ GraphModifier::GraphModifier(Q3DBars *barchart, QColorDialog *colorDialog)
QObject::connect(&m_selectionTimer, &QTimer::timeout, this,
&GraphModifier::triggerSelection);
+ QObject::connect(&m_rotationTimer, &QTimer::timeout, this,
+ &GraphModifier::triggerRotation);
resetTemperatureData();
}
@@ -702,11 +705,17 @@ void GraphModifier::handleSelectionChange(const QPoint &position)
m_selectedBar = position;
int index = 0;
foreach (QBar3DSeries *series, m_graph->seriesList()) {
- if (series == sender())
+ if (series == sender()) {
+ if (series->selectedBar() != QBar3DSeries::invalidSelectionPosition())
+ m_selectedSeries = series;
break;
+ }
index++;
}
+ if (m_selectedSeries->selectedBar() == QBar3DSeries::invalidSelectionPosition())
+ m_selectedSeries = 0;
+
qDebug() << "Selected bar position:" << position << "series:" << index;
}
@@ -1027,6 +1036,14 @@ void GraphModifier::insertRemoveTestToggle()
}
}
+void GraphModifier::toggleRotation()
+{
+ if (m_rotationTimer.isActive())
+ m_rotationTimer.stop();
+ else
+ m_rotationTimer.start(20);
+}
+
void GraphModifier::insertRemoveTimerTimeout()
{
if (m_insertRemoveStep < 32) {
@@ -1066,6 +1083,25 @@ void GraphModifier::triggerSelection()
m_graph->scene()->setSelectionQueryPosition(m_customInputHandler->inputPosition());
}
+void GraphModifier::triggerRotation()
+{
+ if (m_selectedSeries) {
+ QPoint selectedBar = m_selectedSeries->selectedBar();
+ if (selectedBar != QBar3DSeries::invalidSelectionPosition()) {
+ QBarDataItem item(*(m_selectedSeries->dataProxy()->itemAt(selectedBar.x(), selectedBar.y())));
+ item.setRotation(item.rotation() + 1.0f);
+ m_selectedSeries->dataProxy()->setItem(selectedBar.x(), selectedBar.y(), item);
+ }
+ } else {
+ // Rotate the first series instead
+ static float seriesAngle = 0.0f;
+ if (m_graph->seriesList().size()) {
+ QQuaternion rotation = QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, seriesAngle++);
+ m_graph->seriesList().at(0)->setMeshRotation(rotation);
+ }
+ }
+}
+
void GraphModifier::setBackgroundEnabled(int enabled)
{
m_graph->activeTheme()->setBackgroundEnabled(bool(enabled));
diff --git a/tests/barstest/chart.h b/tests/barstest/chart.h
index 8e3271cc..c9d2ca9e 100644
--- a/tests/barstest/chart.h
+++ b/tests/barstest/chart.h
@@ -84,6 +84,7 @@ public:
QBarDataArray *makeDummyData();
void primarySeriesTest();
void insertRemoveTestToggle();
+ void toggleRotation();
public slots:
void flipViews();
@@ -101,6 +102,7 @@ public slots:
void insertRemoveTimerTimeout();
void triggerSelection();
+ void triggerRotation();
signals:
void shadowQualityChanged(int quality);
@@ -123,6 +125,7 @@ private:
QStringList m_months;
QStringList m_years;
QPoint m_selectedBar;
+ QBar3DSeries *m_selectedSeries;
QValue3DAxis *m_autoAdjustingAxis;
QValue3DAxis *m_fixedRangeAxis;
QValue3DAxis *m_temperatureAxis;
@@ -148,6 +151,7 @@ private:
int m_insertRemoveStep;
QAbstract3DInputHandler *m_customInputHandler;
QTimer m_selectionTimer;
+ QTimer m_rotationTimer;
};
#endif
diff --git a/tests/barstest/main.cpp b/tests/barstest/main.cpp
index 52d79468..a57d4aca 100644
--- a/tests/barstest/main.cpp
+++ b/tests/barstest/main.cpp
@@ -161,6 +161,10 @@ int main(int argc, char **argv)
primarySeriesTestsButton->setText(QStringLiteral("Test primary series"));
primarySeriesTestsButton->setEnabled(true);
+ QPushButton *toggleRotationButton = new QPushButton(widget);
+ toggleRotationButton->setText(QStringLiteral("Toggle rotation"));
+ toggleRotationButton->setEnabled(true);
+
QColorDialog *colorDialog = new QColorDialog(widget);
QLinearGradient grBtoY(0, 0, 100, 0);
@@ -308,6 +312,7 @@ int main(int argc, char **argv)
vLayout->addWidget(changeColorStyleButton, 0, Qt::AlignTop);
vLayout->addWidget(ownThemeButton, 0, Qt::AlignTop);
vLayout->addWidget(primarySeriesTestsButton, 0, Qt::AlignTop);
+ vLayout->addWidget(toggleRotationButton, 0, Qt::AlignTop);
vLayout->addWidget(gradientBtoYPB, 1, Qt::AlignTop);
vLayout2->addWidget(staticCheckBox, 0, Qt::AlignTop);
@@ -411,6 +416,8 @@ int main(int argc, char **argv)
&GraphModifier::useOwnTheme);
QObject::connect(primarySeriesTestsButton, &QPushButton::clicked, modifier,
&GraphModifier::primarySeriesTest);
+ QObject::connect(toggleRotationButton, &QPushButton::clicked, modifier,
+ &GraphModifier::toggleRotation);
QObject::connect(colorDialog, &QColorDialog::currentColorChanged, modifier,
&GraphModifier::changeBaseColor);
QObject::connect(gradientBtoYPB, &QPushButton::clicked, modifier,
diff --git a/tests/directional/main.cpp b/tests/directional/main.cpp
index 359868cc..34d2e4a1 100644
--- a/tests/directional/main.cpp
+++ b/tests/directional/main.cpp
@@ -78,6 +78,9 @@ int main(int argc, char **argv)
QPushButton *cameraButton = new QPushButton(widget);
cameraButton->setText(QStringLiteral("Change camera preset"));
+ QPushButton *toggleRotationButton = new QPushButton(widget);
+ toggleRotationButton->setText(QStringLiteral("Toggle rotation"));
+
QCheckBox *backgroundCheckBox = new QCheckBox(widget);
backgroundCheckBox->setText(QStringLiteral("Show background"));
backgroundCheckBox->setChecked(true);
@@ -103,6 +106,7 @@ int main(int argc, char **argv)
//! [5]
vLayout->addWidget(labelButton, 0, Qt::AlignTop);
vLayout->addWidget(cameraButton, 0, Qt::AlignTop);
+ vLayout->addWidget(toggleRotationButton, 0, Qt::AlignTop);
vLayout->addWidget(backgroundCheckBox);
vLayout->addWidget(gridCheckBox);
vLayout->addWidget(new QLabel(QStringLiteral("Change dot style")));
@@ -122,6 +126,8 @@ int main(int argc, char **argv)
//! [6]
QObject::connect(cameraButton, &QPushButton::clicked, modifier,
&ScatterDataModifier::changePresetCamera);
+ QObject::connect(toggleRotationButton, &QPushButton::clicked, modifier,
+ &ScatterDataModifier::toggleRotation);
QObject::connect(labelButton, &QPushButton::clicked, modifier,
&ScatterDataModifier::changeLabelStyle);
diff --git a/tests/directional/scatterdatamodifier.cpp b/tests/directional/scatterdatamodifier.cpp
index f7089ae4..5da48483 100644
--- a/tests/directional/scatterdatamodifier.cpp
+++ b/tests/directional/scatterdatamodifier.cpp
@@ -56,6 +56,9 @@ ScatterDataModifier::ScatterDataModifier(Q3DScatter *scatter)
series->setItemLabelFormat("@xTitle: @xLabel @yTitle: @yLabel @zTitle: @zLabel");
m_graph->addSeries(series);
+ QObject::connect(&m_rotationTimer, &QTimer::timeout, this,
+ &ScatterDataModifier::triggerRotation);
+
addData();
}
@@ -164,6 +167,24 @@ void ScatterDataModifier::shadowQualityUpdatedByVisual(QAbstract3DGraph::ShadowQ
emit shadowQualityChanged(quality); // connected to a checkbox in main.cpp
}
+void ScatterDataModifier::triggerRotation()
+{
+ if (m_graph->seriesList().size()) {
+ int selectedIndex = m_graph->seriesList().at(0)->selectedItem();
+ if (selectedIndex != QScatter3DSeries::invalidSelectionIndex()) {
+ static float itemAngle = 0.0f;
+ QScatterDataItem item(*(m_graph->seriesList().at(0)->dataProxy()->itemAt(selectedIndex)));
+ QQuaternion itemRotation = QQuaternion::fromAxisAndAngle(0.0f, 0.0f, 1.0f, itemAngle++);
+ item.setRotation(itemRotation);
+ m_graph->seriesList().at(0)->dataProxy()->setItem(selectedIndex, item);
+ } else {
+ static float seriesAngle = 0.0f;
+ QQuaternion rotation = QQuaternion::fromAxisAndAngle(1.0f, 1.0f, 1.0f, seriesAngle++);
+ m_graph->seriesList().at(0)->setMeshRotation(rotation);
+ }
+ }
+}
+
void ScatterDataModifier::changeShadowQuality(int quality)
{
QAbstract3DGraph::ShadowQuality sq = QAbstract3DGraph::ShadowQuality(quality);
@@ -179,3 +200,11 @@ void ScatterDataModifier::setGridEnabled(int enabled)
{
m_graph->activeTheme()->setGridEnabled((bool)enabled);
}
+
+void ScatterDataModifier::toggleRotation()
+{
+ if (m_rotationTimer.isActive())
+ m_rotationTimer.stop();
+ else
+ m_rotationTimer.start(20);
+}
diff --git a/tests/directional/scatterdatamodifier.h b/tests/directional/scatterdatamodifier.h
index e3979818..f920d43f 100644
--- a/tests/directional/scatterdatamodifier.h
+++ b/tests/directional/scatterdatamodifier.h
@@ -22,6 +22,7 @@
#include <QtDataVisualization/q3dscatter.h>
#include <QtDataVisualization/qabstract3dseries.h>
#include <QtGui/QFont>
+#include <QtCore/QTimer>
using namespace QtDataVisualization;
@@ -40,6 +41,7 @@ public:
void changeFontSize(int fontsize);
void setBackgroundEnabled(int enabled);
void setGridEnabled(int enabled);
+ void toggleRotation();
void start();
public slots:
@@ -47,6 +49,7 @@ public slots:
void changeTheme(int theme);
void changeShadowQuality(int quality);
void shadowQualityUpdatedByVisual(QAbstract3DGraph::ShadowQuality shadowQuality);
+ void triggerRotation();
signals:
void backgroundEnabledChanged(bool enabled);
@@ -59,6 +62,7 @@ private:
int m_fontSize;
QAbstract3DSeries::Mesh m_style;
bool m_smooth;
+ QTimer m_rotationTimer;
};
#endif