summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSarah Smith <sarah.j.smith@nokia.com>2011-12-03 10:11:39 -0800
committerQt by Nokia <qt-info@nokia.com>2011-12-06 05:31:19 +0100
commit904f3a7181e6b4761c6cc6b21bc66936ef46c52d (patch)
tree6add69388e66fe38202bb3cc0b2ace1c733586f3
parent960b6e36fcd1e03b7c704c9139ca2ec182161f7a (diff)
Mesh conversion on Cylinder and Capsule.
Follow the example of the Sphere and convert Cylinder and Capsule to being meshes as well. Add some useful doc to the three classes showing the performance and other considerations for each. Add a basic manual test, with a README. Slightly improve the warning message from QDeclarativeMesh. Fix a bug with Sphere where nothing would display if the default values for a sphere were used. This was because the createGeometry() function was only triggered when properties changed. Now also trigger it if draw is called and the scenegraph for the object has not yet been created. Same code was also required on the new shape meshes. Change-Id: I475e34e31741ba8583587961fc3d0ee3d03bcb9d Reviewed-by: Sarah Jane Smith <sarah.j.smith@nokia.com>
-rw-r--r--src/imports/shapes/Capsule.qml55
-rw-r--r--src/imports/shapes/Cylinder.qml55
-rw-r--r--src/imports/shapes/Sphere.qml3
-rw-r--r--src/imports/shapes/capsule.cpp218
-rw-r--r--src/imports/shapes/capsulemesh.cpp352
-rw-r--r--src/imports/shapes/capsulemesh.h (renamed from src/imports/shapes/capsule.h)34
-rw-r--r--src/imports/shapes/capsulemesh_p.h83
-rw-r--r--src/imports/shapes/cylinder.cpp210
-rw-r--r--src/imports/shapes/cylindermesh.cpp348
-rw-r--r--src/imports/shapes/cylindermesh.h (renamed from src/imports/shapes/cylinder.h)34
-rw-r--r--src/imports/shapes/cylindermesh_p.h85
-rw-r--r--src/imports/shapes/line.cpp3
-rw-r--r--src/imports/shapes/point.cpp4
-rw-r--r--src/imports/shapes/qmldir2
-rw-r--r--src/imports/shapes/shapes.cpp8
-rw-r--r--src/imports/shapes/shapes.pro28
-rw-r--r--src/imports/shapes/spheremesh.cpp60
-rw-r--r--src/imports/shapes/spheremesh.h8
-rw-r--r--src/imports/shapes/spheremesh_p.h14
-rw-r--r--src/quick3d/qdeclarativemesh.cpp2
-rw-r--r--tests/manual/manual.pro3
-rw-r--r--tests/manual/shapes/README6
-rw-r--r--tests/manual/shapes/main.cpp63
-rw-r--r--tests/manual/shapes/qml/tst_shapes.qml98
-rw-r--r--tests/manual/shapes/qtquick3d.pngbin0 -> 4050 bytes
-rw-r--r--tests/manual/shapes/shapes.pro10
-rw-r--r--tests/manual/shapes/tst_shapes_qml.desktop7
27 files changed, 1300 insertions, 493 deletions
diff --git a/src/imports/shapes/Capsule.qml b/src/imports/shapes/Capsule.qml
new file mode 100644
index 00000000..6997e76d
--- /dev/null
+++ b/src/imports/shapes/Capsule.qml
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+import Qt3D 1.0
+import Qt3D.Shapes 1.0
+
+Item3D {
+ id: capsule
+ property alias name: capsuleMesh.objectName
+ property alias radius: capsuleMesh.radius
+ property alias length: capsuleMesh.length
+ property alias levelOfDetail: capsuleMesh.levelOfDetail
+ mesh: CapsuleMesh {
+ id: capsuleMesh
+ }
+}
diff --git a/src/imports/shapes/Cylinder.qml b/src/imports/shapes/Cylinder.qml
new file mode 100644
index 00000000..0323f425
--- /dev/null
+++ b/src/imports/shapes/Cylinder.qml
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+import Qt3D 1.0
+import Qt3D.Shapes 1.0
+
+Item3D {
+ id: cylinder
+ property alias name: cylinderMesh.objectName
+ property alias radius: cylinderMesh.radius
+ property alias length: cylinderMesh.length
+ property alias levelOfDetail: cylinderMesh.levelOfDetail
+ mesh: CylinderMesh {
+ id: cylinderMesh
+ }
+}
diff --git a/src/imports/shapes/Sphere.qml b/src/imports/shapes/Sphere.qml
index a53ced6c..15a9f020 100644
--- a/src/imports/shapes/Sphere.qml
+++ b/src/imports/shapes/Sphere.qml
@@ -41,9 +41,10 @@
import QtQuick 1.0
import Qt3D 1.0
+import Qt3D.Shapes 1.0
Item3D {
- id: cube
+ id: sphere
property alias name: sphereMesh.objectName
property alias radius: sphereMesh.radius
property alias levelOfDetail: sphereMesh.levelOfDetail
diff --git a/src/imports/shapes/capsule.cpp b/src/imports/shapes/capsule.cpp
deleted file mode 100644
index 868598bd..00000000
--- a/src/imports/shapes/capsule.cpp
+++ /dev/null
@@ -1,218 +0,0 @@
-/****************************************************************************
-**
-** 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 "capsule.h"
-#include "qglbuilder.h"
-#include "qglcylinder.h"
-#include "qgldome.h"
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmlclass Capsule Capsule
- \brief The Capsule item represents a simple capsule in 3D space.
- \since 4.8
- \ingroup qt3d::qml3d::shapes
- \inherits Item3D
-
- The Capsule element in QML provides a simple way to create a capsule
- object, usually for testing material effects. For example,
- the following QML code displays a green cylinder of with a uniform
- diameter of 0.5, and a length of 3.0, centered vertically on the
- origin:
-
- \code
- Capsule {
- radius: 0.5
- length: 3.0
- effect: Effect {
- color: "#aaca00"
- }
- }
- \endcode
-
- The Capsule element is part of the \c{Qt3D.Shapes} namespace,
- so the following must appear at the top of any QML file that
- references it:
-
- \code
- import Qt3D.Shapes 1.0
- \endcode
-
- The capsule shape can have differing levels of detail, allowing
- for additional slices and layers to be drawn if more detailed meshes
- are required.
-
- Note that the length of the capsule should always exceed its
- diameter to be considered valid.
-
- \sa Item3D
-*/
-/*!
- \internal
-*/
-Capsule::Capsule(QObject *parent) :
- QDeclarativeItem3D(parent)
- , m_radius(1.0)
- , m_length(4.0)
- , m_lod(1)
-{
-}
-
-/*!
- \qmlproperty real Capsule::radius
-
- This property defines the radius of the capsule.
- The default value is 1.
-*/
-void Capsule::setRadius(qreal radius)
-{
- if (m_radius != radius) {
- m_radius = radius;
- emit radiusChanged();
- update();
- }
-}
-
-/*!
- \qmlproperty real Capsule::length
-
- This property defines the length of the capsule.
- The default value is 1.
-*/
-void Capsule::setLength(qreal length)
-{
- if (m_length != length) {
- m_length = length;
- emit lengthChanged();
- update();
- }
-}
-
-/*!
- \qmlproperty int Capsule::levelOfDetail
-
- This property defines the level of detail, between 1 and 10,
- which controls the number of slices and layers that are used
- to generate the capsule's mesh.
-
- Values outside the range 1 to 10 will be clamped to the range
- when the capsule is generated.
-
- The exact number of facets generated is consistent with the
- level of detail as specified in the Cylinder and Sphere
- objects.
-
- \sa Sphere, Cylinder
-*/
-void Capsule::setLevelOfDetail(int lod)
-{
- if (m_lod != lod) {
- m_lod = lod;
- emit levelOfDetailChanged();
- update();
- }
-}
-
-/*!
- \internal
-*/
-void Capsule::drawItem(QGLPainter *painter)
-{
- // Convert the level of detail into a depth value for the object.
- // We cache a maximum of 5 levels of detail for lod animations.
- int lod = m_lod;
- if (lod < 1)
- lod = 1;
- else if (lod > 10)
- lod = 10;
-
- // Create a new geometry node for this level of detail if necessary.
- QGLSceneNode *geometry = m_lodGeometry.value(lod, 0);
- if (!geometry) {
- QGLBuilder builder;
-
- //For the cylinder
- int facets = 4 * 1<<lod;
- int layers = 1<<lod;
-
- //For the spheres
- int divisions = lod;
-
- //sanity check - the height of the capsule must exceed its diameter. A minimal capsule is
- //a sphere - a capsule where diameter = height.
- if (m_length<2.0*m_radius) {
- qWarning() << "Length of capsule must exceed its diameter - correcting height.";
- m_length = 2*m_radius;
- }
-
- qreal diameter = m_radius+m_radius;
- qreal cylinderHeight = m_length - diameter;
- qreal offset = cylinderHeight/2.0;
-
- builder << QGL::Faceted;
- builder.newNode();
- builder << QGLCylinder(diameter, diameter, cylinderHeight, facets, layers, false, false);
- QMatrix4x4 translateMatrix;
- translateMatrix.translate(0, 0, -offset);
- builder.currentNode()->setLocalTransform(translateMatrix);
-
- builder.newNode();
- builder << QGLDome(diameter, divisions, false);
- translateMatrix.setToIdentity();
- translateMatrix.rotate(180, 0, 1,0);
- translateMatrix.translate(0, 0, offset);
- builder.currentNode()->setLocalTransform(translateMatrix);
-
- builder.newNode();
- builder << QGLDome(diameter, divisions, false);
- translateMatrix.setToIdentity();
- translateMatrix.translate(0, 0, offset);
- builder.currentNode()->setLocalTransform(translateMatrix);
-
- geometry = builder.finalizedSceneNode();
-
- m_lodGeometry.insert(lod, geometry);
- }
-
- // Draw the geometry.
- geometry->draw(painter);
-}
diff --git a/src/imports/shapes/capsulemesh.cpp b/src/imports/shapes/capsulemesh.cpp
new file mode 100644
index 00000000..5b0c068d
--- /dev/null
+++ b/src/imports/shapes/capsulemesh.cpp
@@ -0,0 +1,352 @@
+/****************************************************************************
+**
+** 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 "capsulemesh.h"
+#include "qglbuilder.h"
+#include "qglcylinder.h"
+#include "qgldome.h"
+#include "qglabstractscene.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass CapsuleMesh CapsuleMesh
+ \brief The CapsuleMesh item represents a simple capsule in 3D space.
+ \since 4.8
+ \ingroup qt3d::qml3d::shapes
+ \inherits Item3D
+
+ The CapsuleMesh element in QML provides a simple way to create a capsule
+ object, usually for testing material effects. For example,
+ the following QML code displays a green capsule of with a uniform
+ diameter of 0.5, and a length of 3.0, centered vertically on the
+ origin:
+
+ \code
+ Item3D {
+ mesh: CapsuleMesh {
+ radius: 0.5
+ length: 3.0
+ }
+ effect: Effect {
+ color: "#aaca00"
+ }
+ }
+ \endcode
+
+ The CapsuleMesh element is part of the \c{Qt3D.Shapes} namespace,
+ so the following must appear at the top of any QML file that
+ references it:
+
+ \code
+ import Qt3D.Shapes 1.0
+ \endcode
+
+ The capsule shape can have differing levels of detail, allowing
+ for additional slices and layers to be drawn if more detailed meshes
+ are required.
+
+ Note that the length of the capsule should always exceed its
+ diameter to be considered valid.
+
+ To display the capsule mesh you can create your own Item3D as shown
+ above, or use the convenience Capsule QML Component.
+
+ \code
+ Capsule {
+ radius: 0.5
+ length: 3.0
+ effect: Effect {
+ color: "#aaca00"
+ }
+ }
+ \endcode
+
+ \section1 Performance Hints for Larger Scenes
+
+ The convenience Capsule QML component will create a new mesh each
+ time is instantiated.
+
+ If you have a scene with a number of similar capsules use your own
+ Item3D elements to all refer to the same mesh. See the Performance
+ Hints section of the SphereMesh documentation for more details on
+ this important technique.
+
+ \section1 Performance Hints for Animation
+
+ Because of the need to maintain the relative proportions of the
+ cylinders components, the length and radius are implemented directly
+ in the construction of the mesh. This differs from the approach
+ used in the SphereMesh where a scale is used.
+
+ For this reason avoid animating the length and radius properties
+ of a CapsuleMesh, as it will give poor results due to the mesh
+ being recreated every frame.
+
+ Since the capules components are created with named sections in
+ the mesh, one approach would be to individually apply scales to
+ these sections using the meshNode property. This is an
+ advanced topic, and future tutorials may cover it in more depth.
+
+ \sa Item3D, SphereMesh
+*/
+
+CapsuleMeshPrivate::CapsuleMeshPrivate()
+ : topNode(new QGLSceneNode)
+ , currentCapsule(0)
+ , radius(1.0f)
+ , length(1.0f)
+ , lod(5)
+ , sceneSet(false)
+{
+ topNode->setObjectName("CapsuleMesh");
+}
+
+CapsuleMeshPrivate::~CapsuleMeshPrivate()
+{
+ topNode->removeNode(currentCapsule);
+ delete topNode;
+ QList<QGLSceneNode*> lods = lodGeometry.values();
+ qDeleteAll(lods);
+}
+
+class CapsuleScene : public QGLAbstractScene
+{
+public:
+ explicit CapsuleScene(QGLSceneNode *s) : m_s(s) {}
+ ~CapsuleScene() {}
+ QList<QObject *> objects() const
+ {
+ QList<QObject *> s;
+ s.append(m_s);
+ return s;
+ }
+ QGLSceneNode *mainNode() const
+ {
+ return m_s;
+ }
+private:
+ QGLSceneNode *m_s;
+};
+
+/*!
+ \internal
+*/
+CapsuleMesh::CapsuleMesh(QObject *parent)
+ : QDeclarativeMesh(parent)
+ , d_ptr(new CapsuleMeshPrivate)
+{
+}
+
+/*!
+ \qmlproperty real CapsuleMesh::radius
+
+ This property defines the radius of the capsule.
+ The default value is 1.
+*/
+qreal CapsuleMesh::radius() const
+{
+ Q_D(const CapsuleMesh);
+ return d->radius;
+}
+
+void CapsuleMesh::setRadius(qreal radius)
+{
+ Q_D(CapsuleMesh);
+ if (qFuzzyCompare(radius, 1))
+ radius = 1.0f;
+ if (d->radius != radius) {
+ d->radius = radius;
+ createGeometry();
+ emit radiusChanged();
+ emit dataChanged();
+ }
+}
+
+/*!
+ \qmlproperty real CapsuleMesh::length
+
+ This property defines the length of the capsule.
+ The default value is 1.
+*/
+qreal CapsuleMesh::length() const
+{
+ Q_D(const CapsuleMesh);
+ return d->length;
+}
+
+void CapsuleMesh::setLength(qreal length)
+{
+ Q_D(CapsuleMesh);
+ if (qFuzzyCompare(length, 1))
+ length = 1.0f;
+ if (d->length != length) {
+ d->length = length;
+ createGeometry();
+ emit lengthChanged();
+ emit dataChanged();
+ }
+}
+
+/*!
+ \qmlproperty int CapsuleMesh::levelOfDetail
+
+ This property defines the level of detail, between 1 and 10,
+ which controls the number of slices and layers that are used
+ to generate the capsule's mesh.
+
+ Values outside the range 1 to 10 will be clamped to the range
+ when the capsule is generated.
+
+ The exact number of facets generated is consistent with the
+ level of detail as specified in the Cylinder and Sphere
+ objects.
+
+ \sa Sphere, Cylinder
+*/
+int CapsuleMesh::levelOfDetail() const
+{
+ Q_D(const CapsuleMesh);
+ return d->lod;
+}
+
+void CapsuleMesh::setLevelOfDetail(int lod)
+{
+ Q_D(CapsuleMesh);
+ lod = qBound(1, lod, 10);
+ if (d->lod != lod) {
+ d->lod = lod;
+ createGeometry();
+ emit levelOfDetailChanged();
+ emit dataChanged();
+ }
+}
+
+/*!
+ \internal
+*/
+void CapsuleMesh::draw(QGLPainter *painter, int branchId)
+{
+ Q_D(CapsuleMesh);
+ if (!d->currentCapsule)
+ createGeometry();
+ QDeclarativeMesh::draw(painter, branchId);
+}
+
+/*!
+ \internal
+*/
+void CapsuleMesh::createGeometry()
+{
+ Q_D(CapsuleMesh);
+
+ // Create a new geometry node for this level of detail if necessary.
+ QGLSceneNode *geometry = d->lodGeometry.value(d->lod, 0);
+ if (!geometry) {
+ QGLBuilder builder;
+
+ // For the cylinder
+ int facets = 4 * 1 << d->lod;
+ int layers = 1 << d->lod;
+
+ // For the spheres
+ int divisions = d->lod;
+
+ // Sanity check - the height of the capsule must not be less than its
+ // diameter. A minimal capsule is a sphere - where diameter == height.
+ if (d->length < 2.0 * d->radius)
+ {
+ qWarning() << "Length of capsule must exceed its diameter"
+ << " - correcting height.";
+ d->length = 2 * d->radius;
+ }
+
+ qreal diameter = d->radius+d->radius;
+ qreal cylinderHeight = d->length - diameter;
+ qreal offset = cylinderHeight/2.0;
+
+ builder << QGL::Faceted;
+ QGLSceneNode *s = 0;
+ s = builder.newNode();
+ s->setObjectName("Cylinder");
+ builder << QGLCylinder(diameter, diameter, cylinderHeight,
+ facets, layers, false, false);
+ QMatrix4x4 translateMatrix;
+ translateMatrix.translate(0, 0, -offset);
+ builder.currentNode()->setLocalTransform(translateMatrix);
+
+ s = builder.newNode();
+ s->setObjectName("LeftEndCap");
+ builder << QGLDome(diameter, divisions, false);
+ translateMatrix.setToIdentity();
+ translateMatrix.rotate(180, 0, 1,0);
+ translateMatrix.translate(0, 0, offset);
+ builder.currentNode()->setLocalTransform(translateMatrix);
+
+ s = builder.newNode();
+ s->setObjectName("RightEndCap");
+ builder << QGLDome(diameter, divisions, false);
+ translateMatrix.setToIdentity();
+ translateMatrix.translate(0, 0, offset);
+ builder.currentNode()->setLocalTransform(translateMatrix);
+
+ geometry = builder.finalizedSceneNode();
+
+ d->lodGeometry.insert(d->lod, geometry);
+ }
+ Q_ASSERT_X(geometry != 0, Q_FUNC_INFO, "Could not create/find geometry!");
+ if (d->currentCapsule != geometry)
+ {
+ if (d->currentCapsule)
+ d->topNode->removeNode(d->currentCapsule);
+ d->topNode->addNode(geometry);
+ d->currentCapsule = geometry;
+ }
+
+ if (!d->sceneSet)
+ {
+ setScene(new CapsuleScene(d->topNode));
+ d->sceneSet = true;
+ }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/imports/shapes/capsule.h b/src/imports/shapes/capsulemesh.h
index b4f6a6d6..e065d936 100644
--- a/src/imports/shapes/capsule.h
+++ b/src/imports/shapes/capsulemesh.h
@@ -42,15 +42,14 @@
#ifndef CAPSULE_H
#define CAPSULE_H
-#include "qdeclarativeitem3d.h"
-#include "qglscenenode.h"
-#include <QtCore/qmap.h>
+#include "qdeclarativemesh.h"
+#include "capsulemesh_p.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
-class Capsule : public QDeclarativeItem3D
+class CapsuleMesh : public QDeclarativeMesh
{
Q_OBJECT
Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged)
@@ -58,34 +57,35 @@ class Capsule : public QDeclarativeItem3D
Q_PROPERTY(int levelOfDetail READ levelOfDetail WRITE setLevelOfDetail NOTIFY levelOfDetailChanged)
public:
- explicit Capsule(QObject *parent = 0);
- ~Capsule() {}
+ explicit CapsuleMesh(QObject *parent = 0);
+ ~CapsuleMesh() {}
- qreal radius() const { return m_radius; }
+ qreal radius() const;
void setRadius(qreal radius);
- qreal length() const {return m_length;}
+ qreal length() const;
void setLength(qreal length);
- int levelOfDetail() const {return m_lod;}
+ int levelOfDetail() const;
void setLevelOfDetail(int lod);
+ void draw(QGLPainter *painter, int branchId);
+
Q_SIGNALS:
void radiusChanged();
void lengthChanged();
void levelOfDetailChanged();
-protected:
- void drawItem(QGLPainter *painter);
-
private:
- qreal m_radius;
- qreal m_length;
- int m_lod;
- QMap<int, QGLSceneNode *> m_lodGeometry;
+ void createGeometry();
+
+ Q_DISABLE_COPY(CapsuleMesh)
+ Q_DECLARE_PRIVATE(CapsuleMesh)
+
+ QScopedPointer<CapsuleMeshPrivate> d_ptr;
};
-QML_DECLARE_TYPE(Capsule)
+QML_DECLARE_TYPE(CapsuleMesh)
QT_END_NAMESPACE
diff --git a/src/imports/shapes/capsulemesh_p.h b/src/imports/shapes/capsulemesh_p.h
new file mode 100644
index 00000000..2cff15fd
--- /dev/null
+++ b/src/imports/shapes/capsulemesh_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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 CAPSULEMESH_P_H
+#define CAPSULEMESH_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QMap>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QGLSceneNode;
+
+class CapsuleMeshPrivate
+{
+public:
+ CapsuleMeshPrivate();
+ ~CapsuleMeshPrivate();
+
+ QMap<int, QGLSceneNode *> lodGeometry;
+ QGLSceneNode *topNode;
+ QGLSceneNode *currentCapsule;
+ qreal radius;
+ qreal length;
+ int lod;
+ bool sceneSet;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // CAPSULEMESH_P_H
diff --git a/src/imports/shapes/cylinder.cpp b/src/imports/shapes/cylinder.cpp
deleted file mode 100644
index a1a32362..00000000
--- a/src/imports/shapes/cylinder.cpp
+++ /dev/null
@@ -1,210 +0,0 @@
-/****************************************************************************
-**
-** 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 "cylinder.h"
-#include "qglbuilder.h"
-#include "qglcylinder.h"
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmlclass Cylinder Cylinder
- \brief The Cylinder item represents a simple cylinder in 3D space.
- \since 4.8
- \ingroup qt3d::qml3d::shapes
- \inherits Item3D
-
- The Cylinder element in QML provides a way to create a simple cylinder
- object, usually for testing material effects. For example, the
- following QML code displays a green cylinder of with a uniform
- diameter of 0.5, and a length of 3.0, centered with its base on the
- origin:
-
- \code
- Cylinder {
- radius: 0.5
- length: 3.0
- effect: Effect {
- color: "#aaca00"
- }
- }
- \endcode
-
- The Cylinder element is part of the \c{Qt3D.Shapes} namespace,
- so the following must appear at the top of any QML file that
- references it:
-
- \code
- import Qt3D.Shapes 1.0
- \endcode
-
- The cylinder shape can have differing levels of detail, allowing
- for additional slices and layers to be drawn if more detailed meshes
- are required.
-
- \sa Item3D
-*/
-/*!
- \internal
-*/
-Cylinder::Cylinder(QObject *parent) :
- QDeclarativeItem3D(parent)
- , m_radius(1.0)
- , m_length(1.0)
- , m_lod(1)
-{
-
-}
-
-/*!
- \qmlproperty real Cylinder::radius
-
- This property defines the radius of the cylinder.
- The default value is 1.
-*/
-void Cylinder::setRadius(qreal radius)
-{
- if (m_radius != radius) {
- m_radius = radius;
- emit radiusChanged();
- update();
- }
-}
-
-/*!
- \qmlproperty real Cylinder::length
-
- This property defines the length of the cylinder.
- The default value is 1.
-*/
-void Cylinder::setLength(qreal length)
-{
- if (m_length != length) {
- m_length = length;
- emit lengthChanged();
- update();
- }
-}
-
-/*!
- \qmlproperty int Cylinder::levelOfDetail
-
- This property defines the level of detail, between 1 and 10,
- which controls the number of slices and layers that are used
- to generate the cylinder's mesh.
-
- Values outside the range 1 to 10 will be clamped to the range
- when the cylinder is generated.
-
- The default value is 1, which produces a cylinder with 8
- slices/facets and 2 layers. Each successive increase in this
- level of detail doubles the number of facets and layers. The
- following table provides information for these level of detail
- values
-
- \table
- \header \o Level of Detail \o Facets \o Layers
- \row \o 1 \o 8 \o 2
- \row \o 2 \o 16 \o 4
- \row \o 3 \o 32 \o 8
- \row \o 4 \o 64 \o 16
- \row \o 5 \o 128 \o 32
- \row \o 6 \o 256 \o 64
- \row \o 7 \o 512 \o 128
- \row \o 8 \o 1024 \o 256
- \row \o 9 \o 2048 \o 512
- \row \o 10 \o 4096 \o 1024
- \endtable
-*/
-void Cylinder::setLevelOfDetail(int lod)
-{
- if (m_lod != lod) {
- m_lod = lod;
- emit levelOfDetailChanged();
- update();
- }
-}
-
-/*!
- \internal
-*/
-void Cylinder::drawItem(QGLPainter *painter)
-{
- // Convert the level of detail into a depth value for cylinder.
- // We cache a maximum of 5 levels of detail for lod animations.
- int lod = m_lod;
- if (lod < 1)
- lod = 1;
- else if (lod > 10)
- lod = 10;
-
- int facets = 4 * 1<<lod;
- int layers = 1<<lod;
-
- // Create a new geometry node for this level of detail if necessary.
- QGLSceneNode *geometry = m_lodGeometry.value(lod, 0);
- if (!geometry) {
- QGLBuilder builder;
- builder << QGL::Faceted << QGLCylinder(2.0, 2.0, 1.0, facets, layers, true, true);
- geometry = builder.finalizedSceneNode();
- geometry->setParent(this);
- m_lodGeometry.insert(lod, geometry);
- }
-
- // Set the length as a scale on the modelview transformation.
- // This way, we don't have to regenerate the geometry every
- // frame if the height is being animated.
- if (m_length != 1.0f || m_radius!=1.0) {
- painter->modelViewMatrix().push();
- //We could do the scales separately if either height or radius
- //were !=1.0f, but the same amount of maths is required, so
- //we can just scale appropriately on the axes.
- painter->modelViewMatrix().scale(m_radius,m_radius, m_length);
- }
-
- // Draw the geometry.
- geometry->draw(painter);
-
- // Restore the original modelview if necessary
- if (m_length != 1.0f || m_radius!=1.0)
- painter->modelViewMatrix().pop();
-}
-
diff --git a/src/imports/shapes/cylindermesh.cpp b/src/imports/shapes/cylindermesh.cpp
new file mode 100644
index 00000000..ee814009
--- /dev/null
+++ b/src/imports/shapes/cylindermesh.cpp
@@ -0,0 +1,348 @@
+/****************************************************************************
+**
+** 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 "cylindermesh.h"
+#include "qglbuilder.h"
+#include "qglcylinder.h"
+#include "qgraphicsscale3d.h"
+#include "qglabstractscene.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass CylinderMesh CylinderMesh
+ \brief The CylinderMesh item represents a simple cylinder in 3D space.
+ \since 4.8
+ \ingroup qt3d::qml3d::shapes
+ \inherits Item3D
+
+ The CylinderMesh element in QML provides a way to create a simple cylinder
+ object, usually for testing material effects. For example, the
+ following QML code displays a green cylinder of with a uniform
+ diameter of 0.5, and a length of 3.0, centered with its base on the
+ origin:
+
+ \code
+ Item3D {
+ mesh: CylinderMesh {
+ radius: 0.5
+ length: 3.0
+ }
+ effect: Effect {
+ color: "#aaca00"
+ }
+ }
+ \endcode
+
+ The CylinderMesh element is part of the \c{Qt3D.Shapes} namespace,
+ so the following must appear at the top of any QML file that
+ references it:
+
+ \code
+ import Qt3D.Shapes 1.0
+ \endcode
+
+ The cylinder shape can have differing levels of detail, allowing
+ for additional slices and layers to be drawn if more detailed meshes
+ are required.
+
+ To display the cylinder mesh you can create your own Item3D as shown
+ above, or use the convenience Cylinder QML Component.
+
+ \code
+ Cylinder {
+ radius: 0.5
+ length: 3.0
+ effect: Effect {
+ color: "#aaca00"
+ }
+ }
+ \endcode
+
+ \section1 Performance Hints for Larger Scenes
+
+ The convenience Cylinder QML component will create a new mesh each
+ time is instantiated.
+
+ If you have a scene with a number of similar capsules use your own
+ Item3D elements to all refer to the same mesh. See the Performance
+ Hints section of the SphereMesh documentation for more details on
+ this important technique.
+
+ \section1 Performance Hints for Animation
+
+ Some support for animation of the CylinderMesh properties is provided
+ by utilizing a QGraphicsScale3D to implement the length & radius
+ properties, and by caching levels of detail.
+
+ So within limits animation of these items should provide reasonable
+ results. Be aware that on constrained devices animation of the
+ level of detail for many cylinders could cause problems with memory
+ usage due to the caching.
+
+ \sa Item3D, SphereMesh
+*/
+
+CylinderMeshPrivate::CylinderMeshPrivate()
+ : topNode(new QGLSceneNode)
+ , currentCylinder(0)
+ , scale(0)
+ , radius(1.0f)
+ , length(1.0f)
+ , lod(5)
+ , sceneSet(false)
+{
+ topNode->setObjectName("CylinderMesh");
+}
+
+CylinderMeshPrivate::~CylinderMeshPrivate()
+{
+ topNode->removeNode(currentCylinder);
+ delete topNode;
+ QList<QGLSceneNode*> lods = lodGeometry.values();
+ qDeleteAll(lods);
+}
+
+class CylinderScene : public QGLAbstractScene
+{
+public:
+ explicit CylinderScene(QGLSceneNode *s) : m_s(s) {}
+ ~CylinderScene() {}
+ QList<QObject *> objects() const
+ {
+ QList<QObject *> s;
+ s.append(m_s);
+ return s;
+ }
+ QGLSceneNode *mainNode() const
+ {
+ return m_s;
+ }
+private:
+ QGLSceneNode *m_s;
+};
+
+/*!
+ \internal
+*/
+CylinderMesh::CylinderMesh(QObject *parent)
+ : QDeclarativeMesh(parent)
+ , d_ptr(new CylinderMeshPrivate)
+{
+}
+
+/*!
+ \qmlproperty real CylinderMesh::radius
+
+ This property defines the radius of the cylinder.
+ The default value is 1.
+*/
+qreal CylinderMesh::radius() const
+{
+ Q_D(const CylinderMesh);
+ return d->radius;
+}
+
+void CylinderMesh::setRadius(qreal radius)
+{
+ Q_D(CylinderMesh);
+ if (qFuzzyCompare(radius, 1))
+ radius = 1.0f;
+ if (d->radius != radius) {
+ d->radius = radius;
+ createGeometry();
+ emit radiusChanged();
+ emit dataChanged();
+ }
+}
+
+/*!
+ \qmlproperty real CylinderMesh::length
+
+ This property defines the length of the cylinder.
+ The default value is 1.
+*/
+qreal CylinderMesh::length() const
+{
+ Q_D(const CylinderMesh);
+ return d->length;
+}
+
+void CylinderMesh::setLength(qreal length)
+{
+ Q_D(CylinderMesh);
+ if (qFuzzyCompare(length, 1))
+ length = 1.0f;
+ if (d->length != length) {
+ d->length = length;
+ createGeometry();
+ emit lengthChanged();
+ emit dataChanged();
+ }
+}
+
+/*!
+ \qmlproperty int CylinderMesh::levelOfDetail
+
+ This property defines the level of detail, between 1 and 10,
+ which controls the number of slices and layers that are used
+ to generate the cylinder's mesh.
+
+ Values outside the range 1 to 10 will be clamped to the range
+ when the cylinder is generated.
+
+ The default value is 1, which produces a cylinder with 8
+ slices/facets and 2 layers. Each successive increase in this
+ level of detail doubles the number of facets and layers. The
+ following table provides information for these level of detail
+ values
+
+ \table
+ \header \o Level of Detail \o Facets \o Layers
+ \row \o 1 \o 8 \o 2
+ \row \o 2 \o 16 \o 4
+ \row \o 3 \o 32 \o 8
+ \row \o 4 \o 64 \o 16
+ \row \o 5 \o 128 \o 32
+ \row \o 6 \o 256 \o 64
+ \row \o 7 \o 512 \o 128
+ \row \o 8 \o 1024 \o 256
+ \row \o 9 \o 2048 \o 512
+ \row \o 10 \o 4096 \o 1024
+ \endtable
+*/
+int CylinderMesh::levelOfDetail() const
+{
+ Q_D(const CylinderMesh);
+ return d->lod;
+}
+
+void CylinderMesh::setLevelOfDetail(int lod)
+{
+ Q_D(CylinderMesh);
+ lod = qBound(1, lod, 10);
+ if (d->lod != lod) {
+ d->lod = lod;
+ createGeometry();
+ emit levelOfDetailChanged();
+ emit dataChanged();
+ }
+}
+
+/*!
+ \internal
+*/
+void CylinderMesh::draw(QGLPainter *painter, int branchId)
+{
+ Q_D(CylinderMesh);
+ if (!d->currentCylinder)
+ createGeometry();
+ QDeclarativeMesh::draw(painter, branchId);
+}
+
+/*!
+ \internal
+*/
+void CylinderMesh::createGeometry()
+{
+ Q_D(CylinderMesh);
+
+ int facets = 4 * 1 << d->lod;
+ int layers = 1 << d->lod;
+
+ // Create a new geometry node for this level of detail if necessary.
+ QGLSceneNode *geometry = d->lodGeometry.value(d->lod, 0);
+ if (!geometry) {
+ QGLBuilder builder;
+ builder << QGL::Faceted << QGLCylinder(2.0, 2.0, 1.0, facets,
+ layers, true, true);
+ geometry = builder.finalizedSceneNode();
+ geometry->setParent(this);
+ d->lodGeometry.insert(d->lod, geometry);
+ }
+ Q_ASSERT_X(geometry != 0, Q_FUNC_INFO, "Could not create/find geometry!");
+ if (d->currentCylinder != geometry)
+ {
+ if (d->currentCylinder)
+ d->topNode->removeNode(d->currentCylinder);
+ d->topNode->addNode(geometry);
+ d->currentCylinder = geometry;
+ }
+
+ // Set the length as a scale on the modelview transformation.
+ // This way, we don't have to regenerate the geometry every
+ // frame if the height is being animated.
+ //
+ // We could do the scales separately if either height or radius
+ // were != 1.0f, but the same amount of maths is required, so
+ // we can just scale appropriately on the axes.
+ if (d->radius != 1.0f || d->length != 1.0)
+ {
+ if (!d->scale)
+ {
+ d->scale = new QGraphicsScale3D(d->topNode);
+ d->topNode->addTransform(d->scale);
+ }
+ if (d->scale->scale().x() != d->radius ||
+ d->scale->scale().z() != d->length)
+ {
+ d->scale->setScale(QVector3D(d->radius, d->radius, d->length));
+ }
+ }
+ else
+ {
+ // If there is already a scale set it to be the identity scale.
+ // This case is optimised for in QGraphicsScale. Removing it from
+ // the transform list is too expensive, especially if the size is
+ // being animated, and the next frame will recreate it.
+ if (d->scale)
+ d->scale->setScale(QVector3D(1, 1, 1));
+ }
+
+ if (!d->sceneSet)
+ {
+ setScene(new CylinderScene(d->topNode));
+ d->sceneSet = true;
+ }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/imports/shapes/cylinder.h b/src/imports/shapes/cylindermesh.h
index 30014801..181ee0ad 100644
--- a/src/imports/shapes/cylinder.h
+++ b/src/imports/shapes/cylindermesh.h
@@ -42,15 +42,14 @@
#ifndef CYLINDER_H
#define CYLINDER_H
-#include "qdeclarativeitem3d.h"
-#include "qglscenenode.h"
-#include <QtCore/qmap.h>
+#include "qdeclarativemesh.h"
+#include "cylindermesh_p.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
-class Cylinder : public QDeclarativeItem3D
+class CylinderMesh : public QDeclarativeMesh
{
Q_OBJECT
Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged)
@@ -58,34 +57,35 @@ class Cylinder : public QDeclarativeItem3D
Q_PROPERTY(int levelOfDetail READ levelOfDetail WRITE setLevelOfDetail NOTIFY levelOfDetailChanged)
public:
- explicit Cylinder(QObject *parent = 0);
- ~Cylinder() {}
+ explicit CylinderMesh(QObject *parent = 0);
+ ~CylinderMesh() {}
- qreal radius() const { return m_radius; }
+ qreal radius() const;
void setRadius(qreal radius);
- qreal length() const {return m_length;}
+ qreal length() const;
void setLength(qreal length);
- int levelOfDetail() const {return m_lod;}
+ int levelOfDetail() const;
void setLevelOfDetail(int lod);
+ void draw(QGLPainter *painter, int branchId);
+
Q_SIGNALS:
void radiusChanged();
void lengthChanged();
void levelOfDetailChanged();
-protected:
- void drawItem(QGLPainter *painter);
-
private:
- qreal m_radius;
- qreal m_length;
- int m_lod;
- QMap<int, QGLSceneNode *> m_lodGeometry;
+ void createGeometry();
+
+ Q_DISABLE_COPY(CylinderMesh)
+ Q_DECLARE_PRIVATE(CylinderMesh)
+
+ QScopedPointer<CylinderMeshPrivate> d_ptr;
};
-QML_DECLARE_TYPE(Cylinder)
+QML_DECLARE_TYPE(CylinderMesh)
QT_END_NAMESPACE
diff --git a/src/imports/shapes/cylindermesh_p.h b/src/imports/shapes/cylindermesh_p.h
new file mode 100644
index 00000000..a5ad562f
--- /dev/null
+++ b/src/imports/shapes/cylindermesh_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** 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 CYLINDERMESH_P_H
+#define CYLINDERMESH_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QMap>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsScale3D;
+class QGLSceneNode;
+
+class CylinderMeshPrivate
+{
+public:
+ CylinderMeshPrivate();
+ ~CylinderMeshPrivate();
+
+ QMap<int, QGLSceneNode *> lodGeometry;
+ QGLSceneNode *topNode;
+ QGLSceneNode *currentCylinder;
+ QGraphicsScale3D *scale;
+ qreal radius;
+ qreal length;
+ int lod;
+ bool sceneSet;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // CYLINDERMESH_P_H
diff --git a/src/imports/shapes/line.cpp b/src/imports/shapes/line.cpp
index 5d51e4f1..0091aaff 100644
--- a/src/imports/shapes/line.cpp
+++ b/src/imports/shapes/line.cpp
@@ -162,3 +162,6 @@ void Line::drawItem(QGLPainter *painter)
// Draw the geometry.
m_geometry->draw(painter);
}
+
+QT_END_NAMESPACE
+
diff --git a/src/imports/shapes/point.cpp b/src/imports/shapes/point.cpp
index 29b18707..93595b7a 100644
--- a/src/imports/shapes/point.cpp
+++ b/src/imports/shapes/point.cpp
@@ -165,3 +165,7 @@ void Point::drawItem(QGLPainter *painter)
// Draw the geometry.
m_geometry->draw(painter);
}
+
+QT_END_NAMESPACE
+
+
diff --git a/src/imports/shapes/qmldir b/src/imports/shapes/qmldir
index 430fa1b1..dd4f575d 100644
--- a/src/imports/shapes/qmldir
+++ b/src/imports/shapes/qmldir
@@ -3,3 +3,5 @@ Cube 1.0 Cube.qml
Teapot 1.0 Teapot.qml
Quad 1.0 Quad.qml
Sphere 1.0 Sphere.qml
+Capsule 1.0 Capsule.qml
+Cylinder 1.0 Cylinder.qml
diff --git a/src/imports/shapes/shapes.cpp b/src/imports/shapes/shapes.cpp
index 0f71aa85..7c1958c6 100644
--- a/src/imports/shapes/shapes.cpp
+++ b/src/imports/shapes/shapes.cpp
@@ -42,8 +42,8 @@
#include <QtDeclarative/qdeclarativeextensionplugin.h>
#include "spheremesh.h"
-#include "cylinder.h"
-#include "capsule.h"
+#include "cylindermesh.h"
+#include "capsulemesh.h"
#include "line.h"
#include "point.h"
@@ -57,8 +57,8 @@ public:
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("Qt3D.Shapes"));
qmlRegisterType<SphereMesh>(uri,1,0,"SphereMesh");
- qmlRegisterType<Cylinder>(uri,1,0,"Cylinder");
- qmlRegisterType<Capsule>(uri,1,0,"Capsule");
+ qmlRegisterType<CylinderMesh>(uri,1,0,"CylinderMesh");
+ qmlRegisterType<CapsuleMesh>(uri,1,0,"CapsuleMesh");
qmlRegisterType<Line>(uri,1,0,"Line");
qmlRegisterType<Point>(uri,1,0,"Point");
diff --git a/src/imports/shapes/shapes.pro b/src/imports/shapes/shapes.pro
index dbfe27b1..002446d4 100644
--- a/src/imports/shapes/shapes.pro
+++ b/src/imports/shapes/shapes.pro
@@ -32,24 +32,28 @@ symbian {
SOURCES += \
shapes.cpp \
- cylinder.cpp \
- capsule.cpp \
line.cpp \
point.cpp \
- spheremesh.cpp
+ spheremesh.cpp \
+ capsulemesh.cpp \
+ cylindermesh.cpp
HEADERS += \
- cylinder.h \
- capsule.h \
line.h \
point.h \
spheremesh.h \
- spheremesh_p.h
+ spheremesh_p.h \
+ capsulemesh.h \
+ cylindermesh.h \
+ capsulemesh_p.h \
+ cylindermesh_p.h
QML_FILES = \
Cube.qml \
Sphere.qml \
Quad.qml \
- Teapot.qml
+ Teapot.qml \
+ Capsule.qml \
+ Cylinder.qml
QML_INFRA_FILES += \
$$QML_FILES \
@@ -85,3 +89,13 @@ OTHER_FILES += $$QML_FILES
+
+
+
+
+
+
+
+
+
+
diff --git a/src/imports/shapes/spheremesh.cpp b/src/imports/shapes/spheremesh.cpp
index 6d8620f8..72bf1dee 100644
--- a/src/imports/shapes/spheremesh.cpp
+++ b/src/imports/shapes/spheremesh.cpp
@@ -57,18 +57,19 @@ QT_BEGIN_NAMESPACE
The SphereMesh element in QML provides a simple way to create a sphere
object, usually for testing material effects. For example,
- the following QML code creates a green sphere mesh of radius 1.5,
+ the following QML code displays a green sphere mesh of radius 1.5,
centered on the origin:
\code
- SphereMesh {
- radius: 1.5
- effect: Effect {
- color: "#aaca00"
- }
+ Item3D {
+ mesh: SphereMesh { radius: 1.5 }
+ effect: Effect { color: "#aaca00" }
}
\endcode
+ As shown, the mesh is only displayed when it is set as the target of
+ a mesh property on an Item3D.
+
The SphereMesh element is part of the \c{Qt3D.Shapes} namespace,
so the following must appear at the top of any QML file that
references it:
@@ -83,17 +84,17 @@ QT_BEGIN_NAMESPACE
\code
SphereMesh {
- scale: 1.5
+ radius: 1.5
axis: Qt.YAxis
}
\endcode
- To display the sphere mesh you can create your own Item3D or use
- the convenience Sphere QML component:
+ To display the sphere mesh you can create your own Item3D as shown
+ above, or use the convenience Sphere QML component:
\code
Sphere {
- scale: 1.5
+ radius: 1.5
levelOfDetail: 6
axis: Qt.YAxis
effect: Effect { texture: "moon-texture.jpg" }
@@ -102,7 +103,12 @@ QT_BEGIN_NAMESPACE
\image moon-screenshot.png
- If you have a scene with a number of identical spheres use your own
+ \section1 Performance Hints for Larger Scenes
+
+ The convenience Sphere QML component will create a new mesh each
+ time it is instantiated.
+
+ If you have a scene with a number of similar spheres use your own
Item3D elements to all refer to the same mesh - this will save on
graphics memory and improve the performance of your application since
there is no need to recreate many copies of the same geometry. This
@@ -120,6 +126,24 @@ QT_BEGIN_NAMESPACE
\snippet quick3d/solarsystem_qml/qml/solarsystem_qml.qml 1
+ In this case since only one copy of the triangle data for the mesh is
+ sent to the GPU performance will generally be better.
+
+ \section1 Performance Hints for Animation
+
+ Some support for animation of the SphereMesh properties is provided
+ by utilizing a QGraphicsScale3D to implement the radius property,
+ and by caching levels of detail.
+
+ So within limits animation of these items should provide reasonable
+ results. Be aware that on constrained devices animation of the
+ level of detail for many spheres could cause problems with memory
+ usage due to the caching.
+
+ The other shapes primitives are implemented differently with respect
+ to radius, length and so on, so read the performance notes there, as
+ they will differ from the sphere case.
+
\sa Item3D
*/
@@ -274,6 +298,17 @@ void SphereMesh::setAxis(Qt::Axis axis)
/*!
\internal
*/
+void SphereMesh::draw(QGLPainter *painter, int branchId)
+{
+ Q_D(SphereMesh);
+ if (!d->currentSphere)
+ createGeometry();
+ QDeclarativeMesh::draw(painter, branchId);
+}
+
+/*!
+ \internal
+*/
void SphereMesh::createGeometry()
{
Q_D(SphereMesh);
@@ -353,3 +388,6 @@ void SphereMesh::createGeometry()
d->sceneSet = true;
}
}
+
+QT_END_NAMESPACE
+
diff --git a/src/imports/shapes/spheremesh.h b/src/imports/shapes/spheremesh.h
index 7e4b8603..1d324fc8 100644
--- a/src/imports/shapes/spheremesh.h
+++ b/src/imports/shapes/spheremesh.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef SPHERE_H
-#define SPHERE_H
+#ifndef SPHEREMESH_H
+#define SPHEREMESH_H
#include "qglscenenode.h"
#include "qdeclarativemesh.h"
@@ -74,6 +74,8 @@ public:
Qt::Axis axis() const;
void setAxis(Qt::Axis axis);
+ void draw(QGLPainter *painter, int branchId);
+
Q_SIGNALS:
void radiusChanged();
void levelOfDetailChanged();
@@ -94,4 +96,4 @@ QT_END_NAMESPACE
QT_END_HEADER
-#endif
+#endif // SPHEREMESH_H
diff --git a/src/imports/shapes/spheremesh_p.h b/src/imports/shapes/spheremesh_p.h
index 90adc3fc..3d407421 100644
--- a/src/imports/shapes/spheremesh_p.h
+++ b/src/imports/shapes/spheremesh_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef SPHERE_P_H
-#define SPHERE_P_H
+#ifndef SPHEREMESH_P_H
+#define SPHEREMESH_P_H
//
// W A R N I N G
@@ -55,6 +55,10 @@
#include <QtCore/QMap>
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
class QGraphicsRotation3D;
class QGraphicsScale3D;
class QGLSceneNode;
@@ -76,4 +80,8 @@ public:
bool sceneSet;
};
-#endif // SPHERE_P_H
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // SPHEREMESH_P_H
diff --git a/src/quick3d/qdeclarativemesh.cpp b/src/quick3d/qdeclarativemesh.cpp
index bbd36598..25b405b2 100644
--- a/src/quick3d/qdeclarativemesh.cpp
+++ b/src/quick3d/qdeclarativemesh.cpp
@@ -623,7 +623,7 @@ void QDeclarativeMesh::resetSceneBranches()
void QDeclarativeMesh::draw(QGLPainter *painter, int branchId)
{
if (!d->sceneBranches.contains(branchId)) {
- qWarning() << "Unable to find valid scene object with ID: " << branchId;
+ qWarning() << "No scene object with ID: " << branchId << "for" << this;
} else {
QDeclarativeMeshPrivate::branchObject targetBranch = d->sceneBranches.value(branchId);
targetBranch.rootSceneObject->draw(painter);
diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro
index cdeb40e6..8200a5da 100644
--- a/tests/manual/manual.pro
+++ b/tests/manual/manual.pro
@@ -9,4 +9,5 @@ SUBDIRS += displaymodel \
translation \
transformations \
animations \
- qrc
+ qrc \
+ shapes
diff --git a/tests/manual/shapes/README b/tests/manual/shapes/README
new file mode 100644
index 00000000..0d2d97a3
--- /dev/null
+++ b/tests/manual/shapes/README
@@ -0,0 +1,6 @@
+This is a basic manual test for the shapes classes in QML.
+It needs to be extended greatly to deal with level-of-detail, and the
+other properties which can be changed, such as radius and length,
+also checking on the animations of these, and creation of larger
+numbers of shapes. This last item is to confirm that only one copy
+of the geometry is created in this case.
diff --git a/tests/manual/shapes/main.cpp b/tests/manual/shapes/main.cpp
new file mode 100644
index 00000000..374b7c73
--- /dev/null
+++ b/tests/manual/shapes/main.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** 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 <QtGui/QApplication>
+#include "qdeclarativeview3d.h"
+
+#include "../../shared/qmlres.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ QDeclarativeView3D view;
+ QString qml = q_get_qmldir(QLatin1String("qml/tst_shapes.qml"));
+ view.setSource(QUrl::fromLocalFile(qml));
+
+ if (QApplication::arguments().contains(QLatin1String("-maximize")))
+ view.showMaximized();
+ else if (QApplication::arguments().contains(QLatin1String("-fullscreen")))
+ view.showFullScreen();
+ else
+ view.show();
+
+ return app.exec();
+}
diff --git a/tests/manual/shapes/qml/tst_shapes.qml b/tests/manual/shapes/qml/tst_shapes.qml
new file mode 100644
index 00000000..e402e90d
--- /dev/null
+++ b/tests/manual/shapes/qml/tst_shapes.qml
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+import Qt3D 1.0
+import Qt3D.Shapes 1.0
+
+Item {
+ id: screen
+ width: 720
+ height: 480
+ Rectangle {
+ id: description
+ border.width: 3
+ radius: 5
+ width: parent.width
+ height: text.height + 10
+ Text {
+ id: text
+ width: parent.width
+ wrapMode: "WordWrap"
+ text: "There should be a green cylinder on the left, a beige sphere in the middle,\n" +
+ "and a red capsule on the right hand side.\n\n" +
+ "They should be the same diameter, but the capsule & cylinder twice the height.\n" +
+ "The capsule and cylinder should be oriented with their length vertically.\n" +
+ "Click & drag in the window to rotate the objects to confirm."
+ anchors.centerIn: parent
+ }
+ }
+ Rectangle {
+ width: parent.width
+ anchors.top: description.bottom
+ anchors.bottom: screen.bottom
+ anchors.left: screen.left
+ anchors.right: screen.right
+ color: "#aaccee"
+
+ Viewport {
+ id: view
+ anchors.fill: parent
+ showSceneGraph: true
+ Cylinder {
+ x: -2.2
+ y: 1.5
+ transform: Rotation3D { axis: "1, 0, 0"; angle: 90 }
+ length: 3
+ effect: Effect { color: "green" }
+ }
+ Sphere {
+ effect: Effect { color: "burlywood" }
+ }
+ Capsule {
+ x: 2.2
+ length: 3
+ transform: Rotation3D { axis: "1, 0, 0"; angle: 90 }
+ effect: Effect { color: "red" }
+ }
+ }
+ }
+}
diff --git a/tests/manual/shapes/qtquick3d.png b/tests/manual/shapes/qtquick3d.png
new file mode 100644
index 00000000..8351083e
--- /dev/null
+++ b/tests/manual/shapes/qtquick3d.png
Binary files differ
diff --git a/tests/manual/shapes/shapes.pro b/tests/manual/shapes/shapes.pro
new file mode 100644
index 00000000..d4950ff5
--- /dev/null
+++ b/tests/manual/shapes/shapes.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+TARGET = tst_shapes
+CONFIG += qt warn_on
+
+INSTALL_DIRS = qml
+CONFIG += qt3d_deploy_qml qt3dquick_deploy_pkg
+include(../../../pkg.pri)
+qtcAddDeployment()
+
+SOURCES += main.cpp
diff --git a/tests/manual/shapes/tst_shapes_qml.desktop b/tests/manual/shapes/tst_shapes_qml.desktop
new file mode 100644
index 00000000..7bd7fd92
--- /dev/null
+++ b/tests/manual/shapes/tst_shapes_qml.desktop
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Type=Application
+Name=tst_submesh
+Icon=/usr/share/icons/hicolor/80x80/apps/qtquick3d.png
+Exec=/usr/bin/invoker --type=e -s /usr/bin/tst_submesh -fullscreen
+OnlyShowIn=X-MeeGo;
+X-MeeGo-Logical-Id=qtn_comm_appname_tst_submesh_qml