From bb30ea555c71604de9a2bc5096fa35c9532b26bd Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 4 Sep 2014 15:00:28 +0300 Subject: Add possibility to scale custom items according to data ranges MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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ää --- src/datavisualization/data/customrenderitem.cpp | 4 +- src/datavisualization/data/customrenderitem_p.h | 15 +++- src/datavisualization/data/qcustom3ditem.cpp | 85 +++++++++++++++++++--- src/datavisualization/data/qcustom3ditem.h | 5 ++ src/datavisualization/data/qcustom3ditem_p.h | 4 +- src/datavisualization/data/qcustom3dvolume.cpp | 4 +- .../engine/abstract3drenderer.cpp | 60 +++++++++++---- .../engine/abstract3drenderer_p.h | 2 + .../datavisualizationqml2_plugin.cpp | 1 + 9 files changed, 148 insertions(+), 32 deletions(-) (limited to 'src') 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(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(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(uri, 1, 2, "Surface3D"); qmlRegisterType(uri, 1, 2, "Camera3D"); + qmlRegisterType(uri, 1, 2, "Custom3DItem"); // New types qmlRegisterType(uri, 1, 2, "InputHandler3D"); -- cgit v1.2.3