diff options
author | Danny Pope <daniel.pope@nokia.com> | 2011-09-23 11:56:20 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-09-23 04:01:52 +0200 |
commit | 9e694b09e7a09430838718f31ff920492adb7ed0 (patch) | |
tree | a35335187dc74156ecefeb62b395490837317873 /src | |
parent | 23b9b3b53a83587a8cad65a24a476f0fc2baff83 (diff) |
QTBUG-20075 & QTBUG-18450 Item3D and Billboarding
Change-Id: I6f71bded8d7f450d929bd57bed62adac4b0e3b47
Reviewed-on: http://codereview.qt-project.org/5361
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Patrick Burke <patrick.burke@nokia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/imports/threed/billboarditem3d.cpp | 170 | ||||
-rw-r--r-- | src/imports/threed/billboarditem3d.h | 73 | ||||
-rw-r--r-- | src/imports/threed/threed.cpp | 3 | ||||
-rw-r--r-- | src/imports/threed/threed.pro | 8 | ||||
-rw-r--r-- | src/quick3d/qdeclarativeitem3d.cpp | 254 | ||||
-rw-r--r-- | src/quick3d/qdeclarativeitem3d.h | 17 |
6 files changed, 463 insertions, 62 deletions
diff --git a/src/imports/threed/billboarditem3d.cpp b/src/imports/threed/billboarditem3d.cpp new file mode 100644 index 00000000..eb94d26f --- /dev/null +++ b/src/imports/threed/billboarditem3d.cpp @@ -0,0 +1,170 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtQuick3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "billboarditem3d.h" +#include "qgraphicsbillboardtransform.h" + +/*! + \qmlclass BillboardItem3D BillboardItem3D + \brief The BillboardItem3D will always face toward the viewer. + \since 4.8 + \ingroup qt3d::qml3d + + Sometimes it is desirable to have objects which always face toward the + camera. For example, a quad with text on it may always face the camera + so as to be readable at all times. + + While this can be achieved with a QGraphicsLookAtTransform on a normal + Item3D, the BillboardItem3D class provides a more efficient "cheat" which + takes advantage of the underlying 3D mathematics. + + To use a BillboardItem3D declare it exactly like a regular Item3D. When + the item is drawn a QGraphicsBillboardTransform will be applied to the item + after all other transforms have been performed. + + For example: + + \code + Viewport { + BillboardItem3D { + mesh: Mesh { source: "model.obj" } + effect: Effect { + blending: true + texture: "texture.png" + } + } + } + \endcode + + For a practical illustration of its use see the forest example. +*/ +BillboardItem3D::BillboardItem3D(QObject *parent) + : QDeclarativeItem3D(parent) +{ + m_preserveUpVector = false; +} + +/*! + \qmlproperty bool BillboardItem3D::preserveUpVector + + This property specifies whether the billboard transform should + preserve the "up vector" so that objects stay at right angles + to the ground plane in the scene. + + The default value for this property is false, which indicates that + the object being transformed should always face directly to the camera + This is also known as a "spherical billboard". + + If the value for this property is true, then the object will have + its up orientation preserved. This is also known as a "cylindrical + billboard". +*/ +bool BillboardItem3D::preserveUpVector() const +{ + return m_preserveUpVector; +} + +void BillboardItem3D::setPreserveUpVector(bool value) +{ + m_preserveUpVector = value; + update(); +} + +/*! + \internal + This replaces the standard draw() as used in Item3D. In this instance all drawing + carried out using \a painter follows the standard sequence. However, after the + transforms for the item have been applied, a QGraphicsBillboardTransform is applied + to the model-view matrix. + + After the current item is drawn the model-view matrix from immediately before the + billboard transform being applied will be restored so child items are not affected by it. +*/ +void BillboardItem3D::draw(QGLPainter *painter) +{ + // Bail out if this item and its children have been disabled. + if (!isEnabled()) + return; + if (!isInitialized()) + initialize(painter); + + //Setup picking + int prevId = painter->objectPickId(); + painter->setObjectPickId(objectPickId()); + + //Setup effect (lighting, culling, effects etc) + const QGLLightParameters *currentLight = 0; + QMatrix4x4 currentLightTransform; + drawLightingSetup(painter, currentLight, currentLightTransform); + bool viewportBlend, effectBlend; + drawEffectSetup(painter, viewportBlend, effectBlend); + drawCullSetup(); + + //Local and Global transforms + drawTransformSetup(painter); + + //After all of the other transforms, apply the billboard transform to + //ensure forward facing. + painter->modelViewMatrix().push(); + QGraphicsBillboardTransform bill; + bill.setPreserveUpVector(m_preserveUpVector); + bill.applyTo(const_cast<QMatrix4x4 *>(&painter->modelViewMatrix().top())); + + //Drawing + drawItem(painter); + + //Pop the billboard transform from the model-view matrix stack so that it + //is not applied to child items. + painter->modelViewMatrix().pop(); + + //Draw children + drawChildren(painter); + + //Cleanup + drawTransformCleanup(painter); + drawLightingCleanup(painter, currentLight, currentLightTransform); + drawEffectCleanup(painter, viewportBlend, effectBlend); + drawCullCleanup(); + + //Reset pick id. + painter->setObjectPickId(prevId); +} + diff --git a/src/imports/threed/billboarditem3d.h b/src/imports/threed/billboarditem3d.h new file mode 100644 index 00000000..ae533201 --- /dev/null +++ b/src/imports/threed/billboarditem3d.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtQuick3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BILLBOARDITEM3D_H +#define BILLBOARDITEM3D_H + +#include "qdeclarativeitem3d.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class BillboardItem3D : public QDeclarativeItem3D +{ + Q_OBJECT + Q_PROPERTY(bool preserveUpVector READ preserveUpVector WRITE setPreserveUpVector) +public: + BillboardItem3D(QObject *parent = 0); + + bool preserveUpVector() const; + void setPreserveUpVector(bool value); + + void draw(QGLPainter *painter); + +private: + bool m_preserveUpVector; +}; + +QML_DECLARE_TYPE(BillboardItem3D) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // BILLBOARDITEM3D_H diff --git a/src/imports/threed/threed.cpp b/src/imports/threed/threed.cpp index a528fbc0..5faf87f0 100644 --- a/src/imports/threed/threed.cpp +++ b/src/imports/threed/threed.cpp @@ -61,6 +61,8 @@ #include "shaderprogram.h" #include "qt3dnamespace.h" +#include "billboarditem3d.h" + QT_BEGIN_NAMESPACE QML_DECLARE_TYPE(QGraphicsTransform3D) @@ -96,6 +98,7 @@ public: qmlRegisterType<QGLMaterial>(uri,1,0,"Material"); qmlRegisterType<ShaderProgram>(uri,1,0,"ShaderProgram"); qmlRegisterType<Skybox>(uri, 1, 0, "Skybox"); + qmlRegisterType<BillboardItem3D>(uri, 1, 0, "BillboardItem3D"); qmlRegisterType<Viewport>(uri,1,0,"Viewport"); diff --git a/src/imports/threed/threed.pro b/src/imports/threed/threed.pro index a8f20f23..3648dfbc 100644 --- a/src/imports/threed/threed.pro +++ b/src/imports/threed/threed.pro @@ -35,7 +35,8 @@ SOURCES += \ viewport.cpp \ qgraphicslookattransform.cpp \ shaderprogram.cpp \ - skybox.cpp + skybox.cpp \ + billboarditem3d.cpp HEADERS += \ qt3dnamespace.h \ @@ -44,7 +45,8 @@ HEADERS += \ qgraphicslookattransform.h \ shaderprogram.h \ shaderprogram_p.h \ - skybox.h + skybox.h \ + billboarditem3d.h # See the file README.library_xml for more on this qdeclarativesources.files += \ @@ -73,3 +75,5 @@ qdeclarativesources.files += \ OTHER_FILES += \ README.plugins_types \ README.library_xml + + diff --git a/src/quick3d/qdeclarativeitem3d.cpp b/src/quick3d/qdeclarativeitem3d.cpp index 8b1c8dbe..97a8f4e1 100644 --- a/src/quick3d/qdeclarativeitem3d.cpp +++ b/src/quick3d/qdeclarativeitem3d.cpp @@ -1014,47 +1014,91 @@ void QDeclarativeItem3D::setSortChildren(QDeclarativeItem3D::SortMode mode) /*! \internal - Performs the actual drawing of the Item3D using \a painter. - - If the item is set to object picking mode this includes all of the infrastructure needed - to support picking of objects. - - The basic premise of the draw function should be familiar to users of OpenGL or similar - graphics libraries. Essentially it is a stepwise progress through the following stages: + Sets the lighting conditions for this item on the \a painter. The parameters \a currentLight and \a currentLightTransform + are used to store the current lighting parameters and transforms so that they can be reset on cleanup. - \list - \i 1. Iterate through the child objects of the item and set all lighting parameters found. - \i 2. Set up culling mode in the painter. - \i 3. Set effects if they exist. - \i 4. Set all local model view transformations for this item. - \i 5. Draw this item. - \i 6. Iterate through the child objects of the item and draw all child items. - \i 7. Unset the appropriate parameters and states. - \endlist + After drawing has finished the drawLightingCleanup() function should be called to restore previous settings. - \sa drawItem() + \sa drawLightingCleanup(), draw() */ - -void QDeclarativeItem3D::draw(QGLPainter *painter) +void QDeclarativeItem3D::drawLightingSetup(QGLPainter *painter, const QGLLightParameters *currentLight, QMatrix4x4 ¤tLightTransform) { - // Bail out if this item and its children have been disabled. - if (!d->isEnabled) - return; - if (!d->isInitialized) - initialize(painter); - - int prevId = painter->objectPickId(); - painter->setObjectPickId(d->objectPickId); - //Lighting - const QGLLightParameters *currentLight = 0; - QMatrix4x4 currentLightTransform; if (d->light) { currentLight = painter->mainLight(); currentLightTransform = painter->mainLightTransform(); painter->setMainLight(d->light); } +} + +/*! + \internal + Restores the lighting conditions for \a painter to the \a currentLight and \a currentLightTransform. These values are usually + provided by an earlier call to drawLightingSetup(). + + \sa drawLightingSetup(), draw() +*/ +void QDeclarativeItem3D::drawLightingCleanup(QGLPainter *painter, const QGLLightParameters *currentLight, QMatrix4x4 ¤tLightTransform) +{ + if (d->light) + painter->setMainLight(currentLight, currentLightTransform); +} + +/*! + \internal + Sets the effects for this item on the \a painter. The parameters \a viewportBlend and \a effectBlend + are used to store the current blending parameters so that they can be reset on cleanup. + After drawing has finished the drawEffectCleanup() function should be called to restore previous settings. + + \sa drawLightingCleanup(), draw() +*/ +void QDeclarativeItem3D::drawEffectSetup(QGLPainter *painter, bool &viewportBlend, bool &effectBlend) +{ + // Blending change for the effect. + viewportBlend = d->viewport ? d->viewport->blending() : false; + effectBlend = d->effect ? d->effect->blending() : viewportBlend; + if (viewportBlend != effectBlend) { + if (effectBlend) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); + } + + //Effects + if (d->effect) + d->effect->enableEffect(painter); +} + +/*! + \internal + Restores the blending settings for \a painter to the \a viewportBlend and \a effectBlend. These values are usually + provided by an earlier call to drawEffectSetup(). + + \sa drawEffectSetup(), draw() +*/ +void QDeclarativeItem3D::drawEffectCleanup(QGLPainter *painter, bool &viewportBlend, bool &effectBlend) +{ + if (d->effect) + d->effect->disableEffect(painter); + if (viewportBlend != effectBlend) { + if (effectBlend) + glDisable(GL_BLEND); + else + glEnable(GL_BLEND); + } +} + +/*! + \internal + Sets the culling settings for this item. + + After drawing has finished the drawCullCleanup() function should be called to restore previous settings. + + \sa drawCullCleanup(), draw() +*/ +void QDeclarativeItem3D::drawCullSetup() +{ //Culling if ((d->cullFaces & ~CullClockwise) == CullDisabled) { glDisable(GL_CULL_FACE); @@ -1067,30 +1111,57 @@ void QDeclarativeItem3D::draw(QGLPainter *painter) glCullFace(GLenum(d->cullFaces)); glEnable(GL_CULL_FACE); } +} - // Blending change for the effect. - bool viewportBlend = d->viewport ? d->viewport->blending() : false; - bool effectBlend = d->effect ? d->effect->blending() : viewportBlend; - if (viewportBlend != effectBlend) { - if (effectBlend) - glEnable(GL_BLEND); - else - glDisable(GL_BLEND); - } +/*! + \internal + Restores the culling settings after an earlier call to drawCullSetup(). - //Effects - if (d->effect) - d->effect->enableEffect(painter); + \sa drawCullSetup(), draw() +*/ +void QDeclarativeItem3D::drawCullCleanup() +{ + if (d->cullFaces != CullDisabled) + glDisable(GL_CULL_FACE); +} - //Local and Global transforms +/*! + \internal + Applies the transforms for this item on the \a painter. + + After drawing has finished the drawTransformCleanup() function should be called to restore previous settings. - //1) Item Transforms + \sa drawTransformCleanup(), draw() +*/ +void QDeclarativeItem3D::drawTransformSetup(QGLPainter *painter) +{ + //Local and Global transforms painter->modelViewMatrix().push(); painter->modelViewMatrix() *= d->localTransforms(); +} - //Drawing - drawItem(painter); +/*! + \internal + Restores the previous model-view matrix settings for \a painter after an earlier call to drawTransformSetup(). + + \sa drawTransformSetup(), draw() +*/ +void QDeclarativeItem3D::drawTransformCleanup(QGLPainter *painter) +{ + //Unset parameters for transforms, effects etc. + painter->modelViewMatrix().pop(); +} + +/*! + \internal + Iterate through all of the child items for the current item and call their drawing functions. Children will + be drawn in the order specified unless specified by sortChildren(), in which case they will be drawn in the + order specified (usually this will be back-to-front, to allow for transparency of objects). + \sa sortMode(), draw() +*/ +void QDeclarativeItem3D::drawChildren(QGLPainter *painter) +{ // Find all 3d children for drawing QList<QDeclarativeItem3D *> list;; foreach (QObject* o, children()) @@ -1122,22 +1193,66 @@ void QDeclarativeItem3D::draw(QGLPainter *painter) } for (int index = 0; index < list.size(); ++index) list.at(index)->draw(painter); +} - //Unset parameters for transforms, effects etc. - painter->modelViewMatrix().pop(); +/*! + \internal + Performs the actual drawing of the Item3D using \a painter. - if (d->effect) - d->effect->disableEffect(painter); - if (viewportBlend != effectBlend) { - if (effectBlend) - glDisable(GL_BLEND); - else - glEnable(GL_BLEND); - } - if (d->cullFaces != CullDisabled) - glDisable(GL_CULL_FACE); - if (d->light) - painter->setMainLight(currentLight, currentLightTransform); + If the item is set to object picking mode this includes all of the infrastructure needed + to support picking of objects. + + The basic premise of the draw function should be familiar to users of OpenGL or similar + graphics libraries. Essentially it is a stepwise progress through the following stages: + + \list + \i 1. Iterate through the child objects of the item and set all lighting parameters found. + \i 2. Set up culling mode in the painter. + \i 3. Set effects if they exist. + \i 4. Set all local model view transformations for this item. + \i 5. Draw this item. + \i 6. Iterate through the child objects of the item and draw all child items. + \i 7. Unset the appropriate parameters and states. + \endlist + + + + \sa drawItem(), drawLightingSetup(), drawCullSetup(), drawEffectSetup(), drawChildren(), drawTransformSetup() +*/ +void QDeclarativeItem3D::draw(QGLPainter *painter) +{ + // Bail out if this item and its children have been disabled. + if (!d->isEnabled) + return; + if (!d->isInitialized) + initialize(painter); + + //Setup picking + int prevId = painter->objectPickId(); + painter->setObjectPickId(d->objectPickId); + + //Setup effect (lighting, culling, effects etc) + const QGLLightParameters *currentLight = 0; + QMatrix4x4 currentLightTransform; + drawLightingSetup(painter, currentLight, currentLightTransform); + bool viewportBlend, effectBlend; + drawEffectSetup(painter, viewportBlend, effectBlend); + drawCullSetup(); + + //Local and Global transforms + drawTransformSetup(painter); + + //Drawing + drawItem(painter); + drawChildren(painter); + + //Cleanup + drawTransformCleanup(painter); + drawLightingCleanup(painter, currentLight, currentLightTransform); + drawEffectCleanup(painter, viewportBlend, effectBlend); + drawCullCleanup(); + + //Reset pick id. painter->setObjectPickId(prevId); } @@ -1204,6 +1319,17 @@ void QDeclarativeItem3D::initialize(QGLPainter *painter) d->isInitialized = true; } +/*! + Returns true if the initialize() has been called, returns false otherwise. + + \sa initialize() +*/ +bool QDeclarativeItem3D::isInitialized() const +{ + return d->isInitialized; +} + + void QDeclarativeItem3D::componentComplete() { QDeclarativeItem::componentComplete(); @@ -1428,6 +1554,14 @@ void QDeclarativeItem3D::setEnabled(bool value) } /*! + Returns the unique pick ID for this item. +*/ +int QDeclarativeItem3D::objectPickId() const +{ + return d->objectPickId; +} + +/*! \qmlsignal Item3D::onClicked() This signal is emitted when the item is clicked. Picking must be enabled for this to have any effect. diff --git a/src/quick3d/qdeclarativeitem3d.h b/src/quick3d/qdeclarativeitem3d.h index 5a490530..edd228e6 100644 --- a/src/quick3d/qdeclarativeitem3d.h +++ b/src/quick3d/qdeclarativeitem3d.h @@ -155,17 +155,34 @@ public: virtual void draw(QGLPainter *painter); virtual void initialize(QGLPainter *painter); + bool isInitialized() const; Q_INVOKABLE QVector3D localToWorld(const QVector3D &point = QVector3D()) const; Q_INVOKABLE QVector3D worldToLocal(const QVector3D &point = QVector3D()) const; void componentComplete(); + int objectPickId() const; + public Q_SLOTS: void update(); protected: + virtual void drawLightingSetup(QGLPainter *painter, const QGLLightParameters *currentLight, QMatrix4x4 ¤tLightTransform); + virtual void drawLightingCleanup(QGLPainter *painter, const QGLLightParameters *currentLight, QMatrix4x4 ¤tLightTransform); + + virtual void drawCullSetup(); + virtual void drawCullCleanup(); + + virtual void drawEffectSetup(QGLPainter *painter, bool &viewportBlend, bool &effectBlend); + virtual void drawEffectCleanup(QGLPainter *painter, bool &viewportBlend, bool &effectBlend); + + virtual void drawChildren(QGLPainter *painter); virtual void drawItem(QGLPainter *painter); + + virtual void drawTransformSetup(QGLPainter *painter); + virtual void drawTransformCleanup(QGLPainter *painter); + bool event(QEvent *e); private Q_SLOTS: |