summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@digia.com>2014-09-04 15:00:28 +0300
committerMiikka Heikkinen <miikka.heikkinen@digia.com>2014-09-08 09:21:04 +0300
commitbb30ea555c71604de9a2bc5096fa35c9532b26bd (patch)
tree42825d3574e07136e4028f90abb1f719e2c8b6f6
parent18413de96ea907ea5c7defdcb40248fdfbaa4de7 (diff)
Add possibility to scale custom items according to data ranges
Proper behavior of volume objects that are shown only partially will be added in a separate patch later. Change-Id: I1fcd98faa6c4a7d09e3fef1645ed9816ff54654f Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
-rw-r--r--examples/datavisualization/volumetric/volumetric.cpp30
-rw-r--r--src/datavisualization/data/customrenderitem.cpp4
-rw-r--r--src/datavisualization/data/customrenderitem_p.h15
-rw-r--r--src/datavisualization/data/qcustom3ditem.cpp85
-rw-r--r--src/datavisualization/data/qcustom3ditem.h5
-rw-r--r--src/datavisualization/data/qcustom3ditem_p.h4
-rw-r--r--src/datavisualization/data/qcustom3dvolume.cpp4
-rw-r--r--src/datavisualization/engine/abstract3drenderer.cpp60
-rw-r--r--src/datavisualization/engine/abstract3drenderer_p.h2
-rw-r--r--src/datavisualizationqml2/datavisualizationqml2_plugin.cpp1
-rw-r--r--tests/volumetrictest/main.cpp34
-rw-r--r--tests/volumetrictest/volumetrictest.cpp89
-rw-r--r--tests/volumetrictest/volumetrictest.h4
13 files changed, 281 insertions, 56 deletions
diff --git a/examples/datavisualization/volumetric/volumetric.cpp b/examples/datavisualization/volumetric/volumetric.cpp
index 156e0bf4..eb8f2188 100644
--- a/examples/datavisualization/volumetric/volumetric.cpp
+++ b/examples/datavisualization/volumetric/volumetric.cpp
@@ -22,6 +22,7 @@
#include <QtDataVisualization/q3dcamera.h>
#include <QtDataVisualization/q3dtheme.h>
#include <QtDataVisualization/qcustom3dlabel.h>
+#include <QtDataVisualization/q3dscatter.h>
#include <QtCore/qmath.h>
#include <QtWidgets/QLabel>
#include <QtWidgets/QRadioButton>
@@ -40,6 +41,7 @@ const int mineShaftDiameter(1);
const int airColorIndex(254);
const int mineShaftColorIndex(255);
const int layerColorThickness(60);
+const int heightToColorDiv(128);
const int magmaColorsMin(0);
const int magmaColorsMax(layerColorThickness);
const int aboveWaterGroundColorsMin(magmaColorsMax + 1);
@@ -93,7 +95,10 @@ VolumetricModifier::VolumetricModifier(Q3DScatter *scatter)
excavateMineShaft(lowDetailSize, 0, m_mineShaftArray.size(), m_lowDetailData);
m_volumeItem = new QCustom3DVolume;
- m_volumeItem->setScaling(QVector3D(2.0f, 1.0f, 2.0f));
+ m_volumeItem->setScaling(QVector3D(m_graph->axisX()->max() - m_graph->axisX()->min(),
+ m_graph->axisY()->max() - m_graph->axisY()->min(),
+ m_graph->axisZ()->max() - m_graph->axisZ()->min()));
+ m_volumeItem->setScalingAbsolute(false);
m_volumeItem->setTextureWidth(lowDetailSize);
m_volumeItem->setTextureHeight(lowDetailSize / 2);
m_volumeItem->setTextureDepth(lowDetailSize);
@@ -108,11 +113,14 @@ VolumetricModifier::VolumetricModifier(Q3DScatter *scatter)
if (i < magmaColorsMax) {
m_colorTable1[i] = qRgba(130 - (i * 2), 0, 0, 255);
} else if (i < aboveWaterGroundColorsMax) {
- m_colorTable1[i] = qRgba(0, ((i - magmaColorsMax) * 2) + 120, 0, terrainTransparency);
+ m_colorTable1[i] = qRgba((i - magmaColorsMax) * 4,
+ ((i - magmaColorsMax) * 2) + 120,
+ (i - magmaColorsMax) * 5, terrainTransparency);
} else if (i < underWaterGroundColorsMax) {
- m_colorTable1[i] = qRgba(((i - aboveWaterGroundColorsMax) * 2) + 30,
- ((i - aboveWaterGroundColorsMax) * 2) + 100,
- ((i - aboveWaterGroundColorsMax) * 2) + 30, terrainTransparency);
+ m_colorTable1[i] = qRgba(((layerColorThickness - i - aboveWaterGroundColorsMax)) + 70,
+ ((layerColorThickness - i - aboveWaterGroundColorsMax) * 2) + 20,
+ ((layerColorThickness - i - aboveWaterGroundColorsMax)) + 50,
+ terrainTransparency);
} else if (i < waterColorsMax) {
m_colorTable1[i] = qRgba(0, 0, ((i - underWaterGroundColorsMax) * 2) + 120,
terrainTransparency);
@@ -471,19 +479,19 @@ int VolumetricModifier::createVolume(int textureSize, int startIndex, int count,
int height((layerDataSize - (j * 2 * multiplier)) / 2);
if (height < magmaHeights.at(k)) {
// Magma layer
- colorIndex = int((float(height) / colorTableSize)
+ colorIndex = int((float(height) / heightToColorDiv)
* float(layerColorThickness)) + magmaColorsMin;
- } else if (height <= groundHeights.at(k) && height <= waterHeights.at(k)) {
+ } else if (height < groundHeights.at(k) && height < waterHeights.at(k)) {
// Ground layer below water
- colorIndex = int((float(waterHeights.at(k) - height) / colorTableSize)
+ colorIndex = int((float(waterHeights.at(k) - height) / heightToColorDiv)
* float(layerColorThickness)) + underWaterGroundColorsMin;
} else if (height <= waterHeights.at(k)) {
// Water layer where water goes over ground
- colorIndex = int((float(height - magmaHeights.at(k)) / colorTableSize)
+ colorIndex = int((float(height - magmaHeights.at(k)) / heightToColorDiv)
* float(layerColorThickness)) + waterColorsMin;
} else if (height <= groundHeights.at(k)) {
// Ground above water
- colorIndex = int((float(height - waterHeights.at(k)) / colorTableSize)
+ colorIndex = int((float(height - waterHeights.at(k)) / heightToColorDiv)
* float(layerColorThickness)) + aboveWaterGroundColorsMin;
} else {
// Rest is air
@@ -499,7 +507,7 @@ int VolumetricModifier::createVolume(int textureSize, int startIndex, int count,
}
int VolumetricModifier::excavateMineShaft(int textureSize, int startIndex, int count,
- QVector<uchar> *textureData)
+ QVector<uchar> *textureData)
{
int endIndex = startIndex + count;
if (endIndex > m_mineShaftArray.size())
diff --git a/src/datavisualization/data/customrenderitem.cpp b/src/datavisualization/data/customrenderitem.cpp
index 555f48b7..64194bac 100644
--- a/src/datavisualization/data/customrenderitem.cpp
+++ b/src/datavisualization/data/customrenderitem.cpp
@@ -23,7 +23,8 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
CustomRenderItem::CustomRenderItem()
: AbstractRenderItem(),
m_texture(0),
- m_absolute(false),
+ m_positionAbsolute(false),
+ m_scalingAbsolute(true),
m_object(0),
m_needBlend(true),
m_visible(true),
@@ -33,6 +34,7 @@ CustomRenderItem::CustomRenderItem()
m_isFacingCamera(false),
m_item(0),
m_renderer(0),
+ m_labelItem(false),
m_textureWidth(0),
m_textureHeight(0),
m_textureDepth(0),
diff --git a/src/datavisualization/data/customrenderitem_p.h b/src/datavisualization/data/customrenderitem_p.h
index 5024270a..8ea8e894 100644
--- a/src/datavisualization/data/customrenderitem_p.h
+++ b/src/datavisualization/data/customrenderitem_p.h
@@ -51,10 +51,14 @@ public:
inline ObjectHelper *mesh() const { return m_object; }
inline void setScaling(const QVector3D &scaling) { m_scaling = scaling; }
inline QVector3D scaling() const { return m_scaling; }
+ inline void setOrigScaling(const QVector3D &scaling) { m_origScaling = scaling; }
+ inline QVector3D origScaling() const { return m_origScaling; }
inline void setPosition(const QVector3D &position) { m_position = position; }
inline QVector3D position() const { return m_position; }
- inline void setPositionAbsolute(bool absolute) { m_absolute = absolute; }
- inline bool isPositionAbsolute() const { return m_absolute; }
+ inline void setPositionAbsolute(bool absolute) { m_positionAbsolute = absolute; }
+ inline bool isPositionAbsolute() const { return m_positionAbsolute; }
+ inline void setScalingAbsolute(bool absolute) { m_scalingAbsolute = absolute; }
+ inline bool isScalingAbsolute() const { return m_scalingAbsolute; }
inline void setBlendNeeded(bool blend) { m_needBlend = blend; }
inline bool isBlendNeeded() const { return m_needBlend; }
inline void setVisible(bool visible) { m_visible = visible; }
@@ -70,6 +74,8 @@ public:
inline void setFacingCamera(bool facing) { m_isFacingCamera = facing; }
inline bool isFacingCamera() const { return m_isFacingCamera; }
inline void setRenderer(Abstract3DRenderer *renderer) { m_renderer = renderer; }
+ inline void setLabelItem(bool isLabel) { m_labelItem = isLabel; }
+ inline bool isLabel() const { return m_labelItem; }
// Volume specific
inline void setTextureWidth(int width) { m_textureWidth = width; }
@@ -104,8 +110,10 @@ private:
GLuint m_texture;
QVector3D m_scaling;
+ QVector3D m_origScaling;
QVector3D m_position;
- bool m_absolute;
+ bool m_positionAbsolute;
+ bool m_scalingAbsolute;
ObjectHelper *m_object; // shared reference
bool m_needBlend;
bool m_visible;
@@ -115,6 +123,7 @@ private:
bool m_isFacingCamera;
QCustom3DItem *m_item;
Abstract3DRenderer *m_renderer;
+ bool m_labelItem;
// Volume specific
int m_textureWidth;
diff --git a/src/datavisualization/data/qcustom3ditem.cpp b/src/datavisualization/data/qcustom3ditem.cpp
index cb843b62..64cb4531 100644
--- a/src/datavisualization/data/qcustom3ditem.cpp
+++ b/src/datavisualization/data/qcustom3ditem.cpp
@@ -62,11 +62,13 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
*
* Holds the item \a position as a vector3d. Defaults to \c {vector3d(0.0, 0.0, 0.0)}.
*
- * Item position is either in data coordinates or in absolute coordinates, depending on
+ * Item position is either in data coordinates or in absolute coordinates, depending on the
* positionAbsolute property. When using absolute coordinates, values between \c{-1.0...1.0} are
* within axis ranges.
*
- * \note Items positioned outside any axis range are not rendered if positionAbsolute is \c{false}.
+ * \note Items positioned outside any axis range are not rendered if positionAbsolute is \c{false},
+ * unless the item is a Custom3DVolume that would be partially visible. In that case, the visible
+ * portion of the volume will be rendered.
*
* \sa positionAbsolute
*/
@@ -83,8 +85,31 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
/*! \qmlproperty vector3d Custom3DItem::scaling
*
* Holds the item \a scaling as a vector3d. Defaults to \c {vector3d(0.1, 0.1, 0.1)}.
- * The default value sets the item to 10% of the height of the graph, provided the item size is
- * normalized.
+ *
+ * Item scaling is either in data values or in absolute values, depending on the
+ * scalingAbsolute property. The default vector interpreted as absolute values sets the item to
+ * 10% of the height of the graph, provided the item mesh is normalized and the graph aspect ratios
+ * haven't been changed from the defaults.
+ *
+ * \sa scalingAbsolute
+ */
+
+/*! \qmlproperty bool Custom3DItem::scalingAbsolute
+ * \since QtDataVisualization 1.2
+ *
+ * This property dictates if item scaling is to be handled in data values or in absolute
+ * values. Defaults to \c{true}. Items with absolute scaling will be rendered at the same
+ * size, regardless of axis ranges. Items with data scaling will change their apparent size
+ * according to the axis ranges. If positionAbsolute value is \c{true}, this property is ignored
+ * and scaling is interpreted as an absolute value.
+ *
+ * \note: Only absolute scaling is supported for Custom3DLabel items or for custom items used in
+ * \l{AbstractGraph3D::polar}{polar} graphs.
+ *
+ * \note: The custom item's mesh must be normalized to range \c{[-1 ,1]}, or the data
+ * scaling will not be accurate.
+ *
+ * \sa scaling, positionAbsolute
*/
/*! \qmlproperty quaternion Custom3DItem::rotation
@@ -180,7 +205,9 @@ QString QCustom3DItem::meshFile() const
* positionAbsolute property. When using absolute coordinates, values between \c{-1.0...1.0} are
* within axis ranges.
*
- * \note Items positioned outside any axis range are not rendered if positionAbsolute is \c{false}.
+ * \note Items positioned outside any axis range are not rendered if positionAbsolute is \c{false},
+ * unless the item is a QCustom3DVolume that would be partially visible. In that case, the visible
+ * portion of the volume will be rendered.
*
* \sa positionAbsolute
*/
@@ -211,7 +238,7 @@ void QCustom3DItem::setPositionAbsolute(bool positionAbsolute)
{
if (d_ptr->m_positionAbsolute != positionAbsolute) {
d_ptr->m_positionAbsolute = positionAbsolute;
- d_ptr->m_dirtyBits.positionAbsoluteDirty = true;
+ d_ptr->m_dirtyBits.positionDirty = true;
emit positionAbsoluteChanged(positionAbsolute);
emit d_ptr->needUpdate();
}
@@ -225,8 +252,13 @@ bool QCustom3DItem::isPositionAbsolute() const
/*! \property QCustom3DItem::scaling
*
* Holds the item \a scaling as a QVector3D. Defaults to \c {QVector3D(0.1, 0.1, 0.1)}.
- * The default value sets the item to 10% of the height of the graph, provided the item size is
- * normalized.
+ *
+ * Item scaling is either in data values or in absolute values, depending on the
+ * scalingAbsolute property. The default vector interpreted as absolute values sets the item to
+ * 10% of the height of the graph, provided the item mesh is normalized and the graph aspect ratios
+ * haven't been changed from the defaults.
+ *
+ * \sa scalingAbsolute
*/
void QCustom3DItem::setScaling(const QVector3D &scaling)
{
@@ -243,6 +275,40 @@ QVector3D QCustom3DItem::scaling() const
return d_ptr->m_scaling;
}
+/*! \property QCustom3DItem::scalingAbsolute
+ * \since QtDataVisualization 1.2
+ *
+ * This property dictates if item scaling is to be handled in data values or in absolute
+ * values. Defaults to \c{true}. Items with absolute scaling will be rendered at the same
+ * size, regardless of axis ranges. Items with data scaling will change their apparent size
+ * according to the axis ranges. If positionAbsolute value is \c{true}, this property is ignored
+ * and scaling is interpreted as an absolute value.
+ *
+ * \note: Only absolute scaling is supported for QCustom3DLabel items or for custom items used in
+ * \l{QAbstract3DGraph::polar}{polar} graphs.
+ *
+ * \note: The custom item's mesh must be normalized to range \c{[-1 ,1]}, or the data
+ * scaling will not be accurate.
+ *
+ * \sa scaling, positionAbsolute
+ */
+void QCustom3DItem::setScalingAbsolute(bool scalingAbsolute)
+{
+ if (d_ptr->m_isLabelItem && !scalingAbsolute) {
+ qWarning() << __FUNCTION__ << "Data bounds are not supported for label items.";
+ } else if (d_ptr->m_scalingAbsolute != scalingAbsolute) {
+ d_ptr->m_scalingAbsolute = scalingAbsolute;
+ d_ptr->m_dirtyBits.scalingDirty = true;
+ emit scalingAbsoluteChanged(scalingAbsolute);
+ emit d_ptr->needUpdate();
+ }
+}
+
+bool QCustom3DItem::isScalingAbsolute() const
+{
+ return d_ptr->m_scalingAbsolute;
+}
+
/*! \property QCustom3DItem::rotation
*
* Holds the item \a rotation as a QQuaternion. Defaults to \c {QQuaternion(0.0, 0.0, 0.0, 0.0)}.
@@ -371,6 +437,7 @@ QCustom3DItemPrivate::QCustom3DItemPrivate(QCustom3DItem *q) :
m_position(QVector3D(0.0f, 0.0f, 0.0f)),
m_positionAbsolute(false),
m_scaling(QVector3D(0.1f, 0.1f, 0.1f)),
+ m_scalingAbsolute(true),
m_rotation(QQuaternion(0.0f, 0.0f, 0.0f, 0.0f)),
m_visible(true),
m_shadowCasting(true),
@@ -388,6 +455,7 @@ QCustom3DItemPrivate::QCustom3DItemPrivate(QCustom3DItem *q, const QString &mesh
m_position(position),
m_positionAbsolute(false),
m_scaling(scaling),
+ m_scalingAbsolute(true),
m_rotation(rotation),
m_visible(true),
m_shadowCasting(true),
@@ -416,7 +484,6 @@ void QCustom3DItemPrivate::resetDirtyBits()
m_dirtyBits.textureDirty = false;
m_dirtyBits.meshDirty = false;
m_dirtyBits.positionDirty = false;
- m_dirtyBits.positionAbsoluteDirty = false;
m_dirtyBits.scalingDirty = false;
m_dirtyBits.rotationDirty = false;
m_dirtyBits.visibleDirty = false;
diff --git a/src/datavisualization/data/qcustom3ditem.h b/src/datavisualization/data/qcustom3ditem.h
index 2f7f37cf..5c880213 100644
--- a/src/datavisualization/data/qcustom3ditem.h
+++ b/src/datavisualization/data/qcustom3ditem.h
@@ -39,6 +39,7 @@ class QT_DATAVISUALIZATION_EXPORT QCustom3DItem : public QObject
Q_PROPERTY(QQuaternion rotation READ rotation WRITE setRotation NOTIFY rotationChanged)
Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged)
Q_PROPERTY(bool shadowCasting READ isShadowCasting WRITE setShadowCasting NOTIFY shadowCastingChanged)
+ Q_PROPERTY(bool scalingAbsolute READ isScalingAbsolute WRITE setScalingAbsolute NOTIFY scalingAbsoluteChanged REVISION 1)
public:
explicit QCustom3DItem(QObject *parent = 0);
@@ -62,6 +63,9 @@ public:
void setScaling(const QVector3D &scaling);
QVector3D scaling() const;
+ void setScalingAbsolute(bool scalingAbsolute);
+ bool isScalingAbsolute() const;
+
void setRotation(const QQuaternion &rotation);
QQuaternion rotation();
@@ -84,6 +88,7 @@ signals:
void rotationChanged(const QQuaternion &rotation);
void visibleChanged(bool visible);
void shadowCastingChanged(bool shadowCasting);
+ Q_REVISION(1) void scalingAbsoluteChanged(bool scalingAbsolute);
protected:
QCustom3DItem(QCustom3DItemPrivate *d, QObject *parent = 0);
diff --git a/src/datavisualization/data/qcustom3ditem_p.h b/src/datavisualization/data/qcustom3ditem_p.h
index d766bcf3..627bf53f 100644
--- a/src/datavisualization/data/qcustom3ditem_p.h
+++ b/src/datavisualization/data/qcustom3ditem_p.h
@@ -29,6 +29,7 @@
#ifndef QCUSTOM3DITEM_P_H
#define QCUSTOM3DITEM_P_H
+#include "datavisualizationglobal_p.h"
#include "qcustom3ditem.h"
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -37,7 +38,6 @@ struct QCustomItemDirtyBitField {
bool textureDirty : 1;
bool meshDirty : 1;
bool positionDirty : 1;
- bool positionAbsoluteDirty : 1;
bool scalingDirty : 1;
bool rotationDirty : 1;
bool visibleDirty : 1;
@@ -47,7 +47,6 @@ struct QCustomItemDirtyBitField {
: textureDirty(false),
meshDirty(false),
positionDirty(false),
- positionAbsoluteDirty(false),
scalingDirty(false),
rotationDirty(false),
visibleDirty(false),
@@ -77,6 +76,7 @@ public:
QVector3D m_position;
bool m_positionAbsolute;
QVector3D m_scaling;
+ bool m_scalingAbsolute;
QQuaternion m_rotation;
bool m_visible;
bool m_shadowCasting;
diff --git a/src/datavisualization/data/qcustom3dvolume.cpp b/src/datavisualization/data/qcustom3dvolume.cpp
index 393533c0..d0e0c139 100644
--- a/src/datavisualization/data/qcustom3dvolume.cpp
+++ b/src/datavisualization/data/qcustom3dvolume.cpp
@@ -623,7 +623,7 @@ void QCustom3DVolume::setSubTextureData(Qt::Axis axis, int index, const uchar *d
*
* \note Each X-line of the data needs to be 32bit aligned when targeting Y-axis or Z-axis.
* If the textureFormat is QImage::Format_Indexed8 and textureWidth is not divisible by four,
- * padding bytes need to be added to each X-line of the \a data in cases it is not already
+ * padding bytes need to be added to each X-line of the \a image in cases it is not already
* properly aligned. The padding bytes should indicate an fully transparent color to avoid
* rendering artifacts. It is not guaranteed QImage will do this automatically.
*
@@ -893,6 +893,8 @@ void QCustom3DVolumePrivate::resetDirtyBits()
m_dirtyBitsVolume.colorTableDirty = false;
m_dirtyBitsVolume.textureDataDirty = false;
m_dirtyBitsVolume.textureFormatDirty = false;
+ m_dirtyBitsVolume.alphaDirty = false;
+ m_dirtyBitsVolume.shaderDirty = false;
}
QImage QCustom3DVolumePrivate::renderSlice(Qt::Axis axis, int index)
diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp
index 3d5ccba1..18384872 100644
--- a/src/datavisualization/engine/abstract3drenderer.cpp
+++ b/src/datavisualization/engine/abstract3drenderer.cpp
@@ -960,12 +960,16 @@ CustomRenderItem *Abstract3DRenderer::addCustomItem(QCustom3DItem *item)
newItem->setRenderer(this);
newItem->setItemPointer(item); // Store pointer for render item updates
newItem->setMesh(item->meshFile());
- QVector3D scaling = item->scaling();
+ newItem->setPosition(item->position());
+ newItem->setOrigScaling(item->scaling());
+ newItem->setScalingAbsolute(item->isScalingAbsolute());
+ newItem->setPositionAbsolute(item->isPositionAbsolute());
QImage textureImage = item->d_ptr->textureImage();
bool facingCamera = false;
GLuint texture = 0;
if (item->d_ptr->m_isLabelItem) {
QCustom3DLabel *labelItem = static_cast<QCustom3DLabel *>(item);
+ newItem->setLabelItem(true);
float pointSize = labelItem->font().pointSizeF();
// Check do we have custom visuals or need to use theme
if (!labelItem->dptr()->m_customVisuals) {
@@ -979,8 +983,10 @@ CustomRenderItem *Abstract3DRenderer::addCustomItem(QCustom3DItem *item)
}
// Calculate scaling based on text (texture size), font size and asked scaling
float scaledFontSize = (0.05f + pointSize / 500.0f) / float(textureImage.height());
+ QVector3D scaling = newItem->origScaling();
scaling.setX(scaling.x() * textureImage.width() * scaledFontSize);
scaling.setY(scaling.y() * textureImage.height() * scaledFontSize);
+ newItem->setOrigScaling(scaling);
// Check if facing camera
facingCamera = labelItem->isFacingCamera();
#if !defined(QT_OPENGL_ES_2)
@@ -1007,10 +1013,8 @@ CustomRenderItem *Abstract3DRenderer::addCustomItem(QCustom3DItem *item)
newItem->setUseHighDefShader(volumeItem->useHighDefShader());
#endif
}
- newItem->setScaling(scaling);
+ recalculateCustomItemScaling(newItem);
newItem->setRotation(item->rotation());
- newItem->setPosition(item->position());
- newItem->setPositionAbsolute(item->isPositionAbsolute());
#if !defined(QT_OPENGL_ES_2)
// In OpenGL ES we simply draw volumes as regular custom item placeholders.
if (!item->d_ptr->m_isVolumeItem)
@@ -1021,8 +1025,8 @@ CustomRenderItem *Abstract3DRenderer::addCustomItem(QCustom3DItem *item)
}
newItem->setTexture(texture);
item->d_ptr->clearTextureImage();
- QVector3D translation = convertPositionToTranslation(item->position(),
- item->isPositionAbsolute());
+ QVector3D translation = convertPositionToTranslation(newItem->position(),
+ newItem->isPositionAbsolute());
newItem->setTranslation(translation);
newItem->setVisible(item->isVisible());
newItem->setShadowCasting(item->isShadowCasting());
@@ -1031,6 +1035,27 @@ CustomRenderItem *Abstract3DRenderer::addCustomItem(QCustom3DItem *item)
return newItem;
}
+void Abstract3DRenderer::recalculateCustomItemScaling(CustomRenderItem *item)
+{
+ if (!m_polarGraph && !item->isLabel() && !item->isScalingAbsolute()
+ && !item->isPositionAbsolute()) {
+ QVector3D scale = item->origScaling() / 2.0f;
+ QVector3D pos = item->position();
+ QVector3D minBounds(pos.x() - scale.x(),
+ pos.y() - scale.y(),
+ pos.z() - scale.z());
+ QVector3D maxBounds(pos.x() + scale.x(),
+ pos.y() + scale.y(),
+ pos.z() + scale.z());
+ QVector3D min = convertPositionToTranslation(minBounds, false);
+ QVector3D max = convertPositionToTranslation(maxBounds, false);
+ item->setScaling(QVector3D(qAbs(max.x() - min.x()), qAbs(max.y() - min.y()),
+ qAbs(max.z() - min.z())) / 2.0f);
+ } else {
+ item->setScaling(item->origScaling());
+ }
+}
+
void Abstract3DRenderer::updateCustomItem(CustomRenderItem *renderItem)
{
QCustom3DItem *item = renderItem->itemPointer();
@@ -1038,8 +1063,18 @@ void Abstract3DRenderer::updateCustomItem(CustomRenderItem *renderItem)
renderItem->setMesh(item->meshFile());
item->d_ptr->m_dirtyBits.meshDirty = false;
}
+ if (item->d_ptr->m_dirtyBits.positionDirty) {
+ renderItem->setPosition(item->position());
+ renderItem->setPositionAbsolute(item->isPositionAbsolute());
+ QVector3D translation = convertPositionToTranslation(renderItem->position(),
+ renderItem->isPositionAbsolute());
+ renderItem->setTranslation(translation);
+ item->d_ptr->m_dirtyBits.positionDirty = false;
+ }
if (item->d_ptr->m_dirtyBits.scalingDirty) {
QVector3D scaling = item->scaling();
+ renderItem->setOrigScaling(scaling);
+ renderItem->setScalingAbsolute(item->isScalingAbsolute());
// In case we have label item, we need to recreate texture for scaling adjustment
if (item->d_ptr->m_isLabelItem) {
QCustom3DLabel *labelItem = static_cast<QCustom3DLabel *>(item);
@@ -1062,8 +1097,9 @@ void Abstract3DRenderer::updateCustomItem(CustomRenderItem *renderItem)
scaling.setX(scaling.x() * textureImage.width() * scaledFontSize);
scaling.setY(scaling.y() * textureImage.height() * scaledFontSize);
item->d_ptr->clearTextureImage();
+ renderItem->setOrigScaling(scaling);
}
- renderItem->setScaling(scaling);
+ recalculateCustomItemScaling(renderItem);
item->d_ptr->m_dirtyBits.scalingDirty = false;
}
if (item->d_ptr->m_dirtyBits.rotationDirty) {
@@ -1097,15 +1133,6 @@ void Abstract3DRenderer::updateCustomItem(CustomRenderItem *renderItem)
item->d_ptr->clearTextureImage();
item->d_ptr->m_dirtyBits.textureDirty = false;
}
- if (item->d_ptr->m_dirtyBits.positionDirty || item->d_ptr->m_dirtyBits.positionAbsoluteDirty) {
- renderItem->setPosition(item->position());
- renderItem->setPositionAbsolute(item->isPositionAbsolute());
- QVector3D translation = convertPositionToTranslation(item->position(),
- item->isPositionAbsolute());
- renderItem->setTranslation(translation);
- item->d_ptr->m_dirtyBits.positionDirty = false;
- item->d_ptr->m_dirtyBits.positionAbsoluteDirty = false;
- }
if (item->d_ptr->m_dirtyBits.visibleDirty) {
renderItem->setVisible(item->isVisible());
item->d_ptr->m_dirtyBits.visibleDirty = false;
@@ -1168,6 +1195,7 @@ void Abstract3DRenderer::updateCustomItem(CustomRenderItem *renderItem)
void Abstract3DRenderer::updateCustomItemPositions()
{
foreach (CustomRenderItem *renderItem, m_customRenderCache) {
+ recalculateCustomItemScaling(renderItem);
QVector3D translation = convertPositionToTranslation(renderItem->position(),
renderItem->isPositionAbsolute());
renderItem->setTranslation(translation);
diff --git a/src/datavisualization/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h
index 83b4e1c7..8152e0c9 100644
--- a/src/datavisualization/engine/abstract3drenderer_p.h
+++ b/src/datavisualization/engine/abstract3drenderer_p.h
@@ -205,6 +205,8 @@ protected:
virtual void fixCameraTarget(QVector3D &target) = 0;
void updateCameraViewport();
+ void recalculateCustomItemScaling(CustomRenderItem *item);
+
bool m_hasNegativeValues;
Q3DTheme *m_cachedTheme;
Drawer *m_drawer;
diff --git a/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp b/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp
index c0bd4183..ecdd7454 100644
--- a/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp
+++ b/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp
@@ -115,6 +115,7 @@ void QtDataVisualizationQml2Plugin::registerTypes(const char *uri)
QLatin1String("Trying to create uncreatable: AbstractGraph3D."));
qmlRegisterType<DeclarativeSurface, 1>(uri, 1, 2, "Surface3D");
qmlRegisterType<Q3DCamera, 1>(uri, 1, 2, "Camera3D");
+ qmlRegisterType<QCustom3DItem, 1>(uri, 1, 2, "Custom3DItem");
// New types
qmlRegisterType<Q3DInputHandler>(uri, 1, 2, "InputHandler3D");
diff --git a/tests/volumetrictest/main.cpp b/tests/volumetrictest/main.cpp
index ba5ba6d3..02f67d6c 100644
--- a/tests/volumetrictest/main.cpp
+++ b/tests/volumetrictest/main.cpp
@@ -97,6 +97,27 @@ int main(int argc, char **argv)
QPushButton *testSubTextureSetting = new QPushButton(widget);
testSubTextureSetting->setText(QStringLiteral("Test subtexture settings"));
+ QLabel *rangeSliderLabel = new QLabel(QStringLiteral("Adjust ranges:"), widget);
+
+ QSlider *rangeXSlider = new QSlider(Qt::Horizontal, widget);
+ rangeXSlider->setMinimum(0);
+ rangeXSlider->setMaximum(1024);
+ rangeXSlider->setValue(512);
+ rangeXSlider->setEnabled(true);
+ QSlider *rangeYSlider = new QSlider(Qt::Horizontal, widget);
+ rangeYSlider->setMinimum(0);
+ rangeYSlider->setMaximum(1024);
+ rangeYSlider->setValue(512);
+ rangeYSlider->setEnabled(true);
+ QSlider *rangeZSlider = new QSlider(Qt::Horizontal, widget);
+ rangeZSlider->setMinimum(0);
+ rangeZSlider->setMaximum(1024);
+ rangeZSlider->setValue(512);
+ rangeZSlider->setEnabled(true);
+
+ QPushButton *testBoundsSetting = new QPushButton(widget);
+ testBoundsSetting->setText(QStringLiteral("Test data bounds"));
+
vLayout->addWidget(fpsLabel);
vLayout->addWidget(sliceXCheckBox);
vLayout->addWidget(sliceXSlider);
@@ -107,6 +128,11 @@ int main(int argc, char **argv)
vLayout->addWidget(sliceZCheckBox);
vLayout->addWidget(sliceZSlider);
vLayout->addWidget(sliceImageZLabel);
+ vLayout->addWidget(rangeSliderLabel);
+ vLayout->addWidget(rangeXSlider);
+ vLayout->addWidget(rangeYSlider);
+ vLayout->addWidget(rangeZSlider);
+ vLayout->addWidget(testBoundsSetting);
vLayout->addWidget(testSubTextureSetting, 1, Qt::AlignTop);
VolumetricModifier *modifier = new VolumetricModifier(graph);
@@ -127,6 +153,14 @@ int main(int argc, char **argv)
&VolumetricModifier::adjustSliceZ);
QObject::connect(testSubTextureSetting, &QPushButton::clicked, modifier,
&VolumetricModifier::testSubtextureSetting);
+ QObject::connect(rangeXSlider, &QSlider::valueChanged, modifier,
+ &VolumetricModifier::adjustRangeX);
+ QObject::connect(rangeYSlider, &QSlider::valueChanged, modifier,
+ &VolumetricModifier::adjustRangeY);
+ QObject::connect(rangeZSlider, &QSlider::valueChanged, modifier,
+ &VolumetricModifier::adjustRangeZ);
+ QObject::connect(testBoundsSetting, &QPushButton::clicked, modifier,
+ &VolumetricModifier::testBoundsSetting);
widget->show();
return app.exec();
diff --git a/tests/volumetrictest/volumetrictest.cpp b/tests/volumetrictest/volumetrictest.cpp
index 555cc286..6d7da021 100644
--- a/tests/volumetrictest/volumetrictest.cpp
+++ b/tests/volumetrictest/volumetrictest.cpp
@@ -31,6 +31,12 @@
using namespace QtDataVisualization;
const int imageCount = 512;
+const float xMiddle = 10.0f;
+const float yMiddle = 12.5f;
+const float zMiddle = -40.0f;
+const float xRange = 40.0f;
+const float yRange = 7.5f;
+const float zRange = 20.0f;
VolumetricModifier::VolumetricModifier(Q3DScatter *scatter)
: m_graph(scatter),
@@ -47,6 +53,12 @@ VolumetricModifier::VolumetricModifier(Q3DScatter *scatter)
m_graph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetFront);
m_graph->setOrthoProjection(true);
//m_graph->scene()->activeCamera()->setTarget(QVector3D(0.5f, 0.5f, 0.5f));
+ m_graph->axisX()->setRange(xMiddle - xRange, xMiddle + xRange);
+ m_graph->axisX()->setSegmentCount(8);
+ m_graph->axisY()->setRange(yMiddle - yRange, yMiddle + yRange);
+ m_graph->axisY()->setSegmentCount(3);
+ m_graph->axisZ()->setRange(zMiddle - zRange, zMiddle + zRange);
+ m_graph->axisZ()->setSegmentCount(8);
createVolume();
createAnotherVolume();
@@ -55,6 +67,13 @@ VolumetricModifier::VolumetricModifier(Q3DScatter *scatter)
// m_volumeItem->setUseHighDefShader(false);
// m_volumeItem2->setUseHighDefShader(false);
// m_volumeItem3->setUseHighDefShader(false);
+ m_volumeItem->setScalingAbsolute(false);
+ m_volumeItem2->setScalingAbsolute(false);
+ m_volumeItem3->setScalingAbsolute(false);
+ m_volumeItem->setPositionAbsolute(false);
+ m_volumeItem2->setPositionAbsolute(false);
+ m_volumeItem3->setPositionAbsolute(false);
+
m_plainItem = new QCustom3DItem;
QImage texture(2, 2, QImage::Format_ARGB32);
@@ -62,8 +81,9 @@ VolumetricModifier::VolumetricModifier(Q3DScatter *scatter)
m_plainItem->setMeshFile(QStringLiteral(":/mesh"));
m_plainItem->setTextureImage(texture);
m_plainItem->setRotation(m_volumeItem->rotation());
- m_plainItem->setPosition(m_volumeItem->position() + QVector3D(0.8f, 0.0f, 0.0f));
- m_plainItem->setScaling(m_volumeItem->scaling());
+ m_plainItem->setPosition(QVector3D(30.0f, 17.5f, -30.0f));
+ m_plainItem->setScaling(QVector3D(20.0f, 5.0f, 10.0f));
+ m_plainItem->setScalingAbsolute(false);
m_graph->addCustomItem(m_volumeItem);
m_graph->addCustomItem(m_volumeItem2);
@@ -80,7 +100,9 @@ VolumetricModifier::VolumetricModifier(Q3DScatter *scatter)
label->setScaling(QVector3D(2.0f, 2.0f, 0.0f));
label->setRotationAxisAndAngle(QVector3D(0.0f, 1.0f, 0.0f), 45.0f);
label->setPosition(m_volumeItem3->position());
- label->setPositionAbsolute(true);
+ label->setPositionAbsolute(false);
+ label->setScalingAbsolute(true);
+
m_graph->addCustomItem(label);
QObject::connect(m_graph, &QAbstract3DGraph::currentFpsChanged, this,
@@ -218,6 +240,50 @@ void VolumetricModifier::testSubtextureSetting()
m_volumeItem3->setSubTextureData(Qt::ZAxis, 190, slice);
}
+void VolumetricModifier::adjustRangeX(int value)
+{
+ float adjustment = float(value - 512) / 10.0f;
+ m_graph->axisX()->setRange(xMiddle + adjustment - xRange, xMiddle + adjustment + xRange);
+}
+
+void VolumetricModifier::adjustRangeY(int value)
+{
+ float adjustment = float(value - 512) / 10.0f;
+ m_graph->axisY()->setRange(yMiddle + adjustment - yRange, yMiddle + adjustment + yRange);
+}
+
+void VolumetricModifier::adjustRangeZ(int value)
+{
+ float adjustment = float(value - 512) / 10.0f;
+ m_graph->axisZ()->setRange(zMiddle + adjustment - zRange, zMiddle + adjustment + zRange);
+}
+
+void VolumetricModifier::testBoundsSetting()
+{
+ static QVector3D scaling1 = m_volumeItem->scaling();
+ static QVector3D scaling2 = m_volumeItem2->scaling();
+ static QVector3D scaling3 = m_volumeItem3->scaling();
+ static QVector3D scaleVector = QVector3D(0.5f, 0.3f, 0.2f);
+
+ if (m_volumeItem->isScalingAbsolute()) {
+ m_volumeItem->setScalingAbsolute(false);
+ m_volumeItem2->setScalingAbsolute(false);
+ m_volumeItem3->setScalingAbsolute(false);
+
+ m_volumeItem->setScaling(scaling1);
+ m_volumeItem2->setScaling(scaling2);
+ m_volumeItem3->setScaling(scaling3);
+ } else {
+ m_volumeItem->setScalingAbsolute(true);
+ m_volumeItem2->setScalingAbsolute(true);
+ m_volumeItem3->setScalingAbsolute(true);
+
+ m_volumeItem->setScaling(scaleVector);
+ m_volumeItem2->setScaling(scaleVector);
+ m_volumeItem3->setScaling(scaleVector);
+ }
+}
+
void VolumetricModifier::checkRenderCase(int id, Qt::Axis axis, int index,
const QVector<uchar> &dataBefore,
QCustom3DVolume *volumeItem)
@@ -236,7 +302,7 @@ void VolumetricModifier::createVolume()
m_volumeItem = new QCustom3DVolume;
m_volumeItem->setTextureFormat(QImage::Format_ARGB32);
// m_volumeItem->setRotation(QQuaternion::fromAxisAndAngle(1.0f, 1.0f, 0.0f, 10.0f));
- m_volumeItem->setPosition(QVector3D(-0.5f, 0.6f, 0.0f));
+ m_volumeItem->setPosition(QVector3D(xMiddle - (xRange / 2.0f), yMiddle + (yRange / 2.0f), zMiddle));
QImage logo;
logo.load(QStringLiteral(":/logo_no_padding.png"));
@@ -284,10 +350,7 @@ void VolumetricModifier::createVolume()
int depth = m_volumeItem->textureDepth();
int frameSize = width * height;
qDebug() << width << height << depth << m_volumeItem->textureData()->size();
-// m_volumeItem->setScaling(QVector3D(float(width) / float(depth) * 2.0f,
-// float(height) / float(depth) * 2.0f,
-// 2.0f));
- m_volumeItem->setScaling(QVector3D(0.4f, 0.4f, 0.4f));
+ m_volumeItem->setScaling(QVector3D(xRange, yRange, zRange) / 2.0f);
uchar *data = m_volumeItem->textureData()->data();
uchar *p = data;
@@ -389,7 +452,7 @@ void VolumetricModifier::createAnotherVolume()
{
m_volumeItem2 = new QCustom3DVolume;
m_volumeItem2->setTextureFormat(QImage::Format_ARGB32);
- m_volumeItem2->setPosition(QVector3D(0.5f, -0.5f, 0.0f));
+ m_volumeItem2->setPosition(QVector3D(xMiddle + (xRange / 2.0f), yMiddle - (yRange / 2.0f), zMiddle));
QImage logo;
logo.load(QStringLiteral(":/logo_no_padding.png"));
@@ -417,9 +480,9 @@ void VolumetricModifier::createAnotherVolume()
int height = m_volumeItem2->textureHeight();
int depth = m_volumeItem2->textureDepth();
qDebug() << width << height << depth << m_volumeItem2->textureData()->size();
- m_volumeItem2->setScaling(QVector3D(float(width) / float(depth) * 2.0f,
- float(height) / float(depth) * 2.0f,
- 2.0f));
+ m_volumeItem2->setScaling(QVector3D(float(width) / float(depth) * xRange * 2.0f,
+ float(height) / float(depth) * yRange * 2.0f,
+ zRange * 2.0f));
// Change one picture using subtexture replacement
QImage flipped = logo.mirrored();
@@ -433,7 +496,7 @@ void VolumetricModifier::createYetAnotherVolume()
m_volumeItem3 = new QCustom3DVolume;
m_volumeItem3->setTextureFormat(QImage::Format_Indexed8);
// m_volumeItem2->setRotation(QQuaternion::fromAxisAndAngle(1.0f, 1.0f, 0.0f, 10.0f));
- m_volumeItem3->setPosition(QVector3D(-0.5f, -0.6f, 0.0f));
+ m_volumeItem3->setPosition(QVector3D(xMiddle - (xRange / 2.0f), yMiddle - (yRange / 2.0f), zMiddle));
// m_volumeItem3->setTextureDimensions(m_volumeItem->textureDataWidth(),
// m_volumeItem->textureHeight(),
diff --git a/tests/volumetrictest/volumetrictest.h b/tests/volumetrictest/volumetrictest.h
index b1b98455..48c805d4 100644
--- a/tests/volumetrictest/volumetrictest.h
+++ b/tests/volumetrictest/volumetrictest.h
@@ -46,6 +46,10 @@ public slots:
void adjustSliceZ(int value);
void handleFpsChange();
void testSubtextureSetting();
+ void adjustRangeX(int value);
+ void adjustRangeY(int value);
+ void adjustRangeZ(int value);
+ void testBoundsSetting();
private:
void createVolume();