summaryrefslogtreecommitdiffstats
path: root/src/render/geometry
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire350@gmail.com>2015-08-30 18:30:51 +0200
committerPaul Lemire <paul.lemire@kdab.com>2015-10-14 21:47:11 +0000
commite8557e086eb476df77fc05b31dd2de3ac5bfd1be (patch)
tree625beaa5aa1823c34443cbe44cca5eeea5cb996e /src/render/geometry
parent7758f05f986c514998d7814fa8241b537a3dcab4 (diff)
QSphereGeometry refactored into a public class
Change-Id: I546ec48312aa9c966d79a50529dd70d8b5430cab Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
Diffstat (limited to 'src/render/geometry')
-rw-r--r--src/render/geometry/geometry.pri7
-rw-r--r--src/render/geometry/qspheregeometry.cpp422
-rw-r--r--src/render/geometry/qspheregeometry.h89
-rw-r--r--src/render/geometry/qspheregeometry_p.h75
-rw-r--r--src/render/geometry/qspheremesh.cpp377
5 files changed, 605 insertions, 365 deletions
diff --git a/src/render/geometry/geometry.pri b/src/render/geometry/geometry.pri
index 9efbe44f1..8cfc0ca71 100644
--- a/src/render/geometry/geometry.pri
+++ b/src/render/geometry/geometry.pri
@@ -27,7 +27,9 @@ HEADERS += \
$$PWD/qspheremesh.h \
$$PWD/qtorusmesh.h \
$$PWD/qtorusgeometry.h \
- $$PWD/qtorusgeometry_p.h
+ $$PWD/qtorusgeometry_p.h \
+ $$PWD/qspheregeometry.h \
+ $$PWD/qspheregeometry_p.h
SOURCES += \
$$PWD/attribute.cpp \
@@ -47,4 +49,5 @@ SOURCES += \
$$PWD/qplanemesh.cpp \
$$PWD/qspheremesh.cpp \
$$PWD/qtorusmesh.cpp \
- $$PWD/qtorusgeometry.cpp
+ $$PWD/qtorusgeometry.cpp \
+ $$PWD/qspheregeometry.cpp
diff --git a/src/render/geometry/qspheregeometry.cpp b/src/render/geometry/qspheregeometry.cpp
new file mode 100644
index 000000000..4cc655d98
--- /dev/null
+++ b/src/render/geometry/qspheregeometry.cpp
@@ -0,0 +1,422 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qspheregeometry.h"
+#include "qspheregeometry_p.h"
+#include <Qt3DRenderer/qbufferfunctor.h>
+#include <Qt3DRenderer/qbuffer.h>
+#include <Qt3DRenderer/qattribute.h>
+
+#ifndef _USE_MATH_DEFINES
+# define _USE_MATH_DEFINES // For MSVC
+#endif
+
+#include <qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace {
+
+QByteArray createSphereMeshVertexData(float radius, int rings, int slices)
+{
+ QByteArray bufferBytes;
+ // vec3 pos, vec2 texCoord, vec3 normal, vec4 tangent
+ const quint32 elementSize = 3 + 2 + 3 + 4;
+ const quint32 stride = elementSize * sizeof(float);
+ const int nVerts = (slices + 1) * (rings + 1);
+ bufferBytes.resize(stride * nVerts);
+
+ float* fptr = reinterpret_cast<float*>(bufferBytes.data());
+
+ const float dTheta = (M_PI * 2) / static_cast<float>( slices );
+ const float dPhi = M_PI / static_cast<float>( rings );
+ const float du = 1.0f / static_cast<float>( slices );
+ const float dv = 1.0f / static_cast<float>( rings );
+
+ // Iterate over latitudes (rings)
+ for ( int lat = 0; lat < rings + 1; ++lat )
+ {
+ const float phi = M_PI_2 - static_cast<float>( lat ) * dPhi;
+ const float cosPhi = qCos( phi );
+ const float sinPhi = qSin( phi );
+ const float v = 1.0f - static_cast<float>( lat ) * dv;
+
+ // Iterate over longitudes (slices)
+ for ( int lon = 0; lon < slices + 1; ++lon )
+ {
+ const float theta = static_cast<float>( lon ) * dTheta;
+ const float cosTheta = qCos( theta );
+ const float sinTheta = qSin( theta );
+ const float u = static_cast<float>( lon ) * du;
+
+ *fptr++ = radius * cosTheta * cosPhi;
+ *fptr++ = radius * sinPhi;
+ *fptr++ = radius * sinTheta * cosPhi;
+
+ *fptr++ = u;
+ *fptr++ = v;
+
+ *fptr++ = cosTheta * cosPhi;
+ *fptr++ = sinPhi;
+ *fptr++ = sinTheta * cosPhi;
+
+ *fptr++ = sinTheta;
+ *fptr++ = 0.0;
+ *fptr++ = -cosTheta;
+ *fptr++ = 1.0;
+ }
+ }
+ return bufferBytes;
+}
+
+QByteArray createSphereMeshIndexData(int rings, int slices)
+{
+ int faces = (slices * 2) * (rings - 2); // two tris per slice, for all middle rings
+ faces += 2 * slices; // tri per slice for both top and bottom
+
+ QByteArray indexBytes;
+ const int indices = faces * 3;
+ Q_ASSERT(indices < 65536);
+ indexBytes.resize(indices * sizeof(quint16));
+ quint16 *indexPtr = reinterpret_cast<quint16*>(indexBytes.data());
+
+ // top cap
+ {
+ const int nextRingStartIndex = slices + 1;
+ for ( int j = 0; j < slices; ++j )
+ {
+ *indexPtr++ = nextRingStartIndex + j;
+ *indexPtr++ = 0;
+ *indexPtr++ = nextRingStartIndex + j + 1;
+ }
+ }
+
+ for ( int i = 1; i < (rings - 1); ++i )
+ {
+ const int ringStartIndex = i * ( slices + 1 );
+ const int nextRingStartIndex = ( i + 1 ) * ( slices + 1 );
+
+ for ( int j = 0; j < slices; ++j )
+ {
+ // Split the quad into two triangles
+ *indexPtr++ = ringStartIndex + j;
+ *indexPtr++ = ringStartIndex + j + 1;
+ *indexPtr++ = nextRingStartIndex + j;
+ *indexPtr++ = nextRingStartIndex + j;
+ *indexPtr++ = ringStartIndex + j + 1;
+ *indexPtr++ = nextRingStartIndex + j + 1;
+ }
+ }
+
+ // bottom cap
+ {
+ const int ringStartIndex = (rings - 1) * ( slices + 1);
+ const int nextRingStartIndex = (rings) * ( slices + 1);
+ for ( int j = 0; j < slices; ++j )
+ {
+ *indexPtr++ = ringStartIndex + j + 1;
+ *indexPtr++ = nextRingStartIndex;
+ *indexPtr++ = ringStartIndex + j;
+ }
+ }
+
+ return indexBytes;
+}
+
+} // anonymous
+
+class SphereVertexDataFunctor : public QBufferFunctor
+{
+public:
+ SphereVertexDataFunctor(int rings, int slices, float radius)
+ : m_rings(rings)
+ , m_slices(slices)
+ , m_radius(radius)
+ {
+ }
+
+ QByteArray operator ()() Q_DECL_OVERRIDE
+ {
+ return createSphereMeshVertexData(m_radius, m_rings, m_slices);
+ }
+
+ bool operator ==(const QBufferFunctor &other) const Q_DECL_OVERRIDE
+ {
+ const SphereVertexDataFunctor *otherFunctor = functor_cast<SphereVertexDataFunctor>(&other);
+ if (otherFunctor != Q_NULLPTR)
+ return (otherFunctor->m_rings == m_rings &&
+ otherFunctor->m_slices == m_slices &&
+ otherFunctor->m_radius == m_radius);
+ return false;
+ }
+
+ QT3D_FUNCTOR(SphereVertexDataFunctor)
+
+private:
+ int m_rings;
+ int m_slices;
+ float m_radius;
+};
+
+class SphereIndexDataFunctor : public QBufferFunctor
+{
+public:
+ SphereIndexDataFunctor(int rings, int slices)
+ : m_rings(rings)
+ , m_slices(slices)
+ {
+ }
+
+ QByteArray operator ()() Q_DECL_OVERRIDE
+ {
+ return createSphereMeshIndexData(m_rings, m_slices);
+ }
+
+ bool operator ==(const QBufferFunctor &other) const Q_DECL_OVERRIDE
+ {
+ const SphereIndexDataFunctor *otherFunctor = functor_cast<SphereIndexDataFunctor>(&other);
+ if (otherFunctor != Q_NULLPTR)
+ return (otherFunctor->m_rings == m_rings &&
+ otherFunctor->m_slices == m_slices);
+ return false;
+ }
+
+ QT3D_FUNCTOR(SphereIndexDataFunctor)
+
+private:
+ int m_rings;
+ int m_slices;
+};
+
+QSphereGeometryPrivate::QSphereGeometryPrivate()
+ : QGeometryPrivate()
+ , m_generateTangents(false)
+ , m_rings(16)
+ , m_slices(16)
+ , m_radius(1.0f)
+ , m_positionAttribute(Q_NULLPTR)
+ , m_normalAttribute(Q_NULLPTR)
+ , m_texCoordAttribute(Q_NULLPTR)
+ , m_tangentAttribute(Q_NULLPTR)
+ , m_indexAttribute(Q_NULLPTR)
+ , m_vertexBuffer(Q_NULLPTR)
+ , m_indexBuffer(Q_NULLPTR)
+{
+}
+
+void QSphereGeometryPrivate::init()
+{
+ Q_Q(QSphereGeometry);
+ m_positionAttribute = new QAttribute(q);
+ m_normalAttribute = new QAttribute(q);
+ m_texCoordAttribute = new QAttribute(q);
+ m_tangentAttribute = new QAttribute(q);
+ m_indexAttribute = new QAttribute(q);
+ m_vertexBuffer = new QBuffer(QBuffer::VertexBuffer, q);
+ m_indexBuffer = new QBuffer(QBuffer::IndexBuffer, q);
+
+ // vec3 pos, vec2 tex, vec3 normal, vec4 tangent
+ const quint32 elementSize = 3 + 2 + 3 + 4;
+ const quint32 stride = elementSize * sizeof(float);
+ const int nVerts = (m_slices + 1) * (m_rings + 1);
+ const int faces = (m_slices * 2) * (m_rings - 2) + (2 * m_slices);
+
+ m_positionAttribute->setName(QAttribute::defaultPositionAttributeName());
+ m_positionAttribute->setDataType(QAttribute::Float);
+ m_positionAttribute->setDataSize(3);
+ m_positionAttribute->setAttributeType(QAttribute::VertexAttribute);
+ m_positionAttribute->setBuffer(m_vertexBuffer);
+ m_positionAttribute->setByteStride(stride);
+ m_positionAttribute->setCount(nVerts);
+
+ m_texCoordAttribute->setName(QAttribute::defaultTextureCoordinateAttributeName());
+ m_texCoordAttribute->setDataType(QAttribute::Float);
+ m_texCoordAttribute->setDataSize(2);
+ m_texCoordAttribute->setAttributeType(QAttribute::VertexAttribute);
+ m_texCoordAttribute->setBuffer(m_vertexBuffer);
+ m_texCoordAttribute->setByteStride(stride);
+ m_texCoordAttribute->setByteOffset(3 * sizeof(float));
+ m_texCoordAttribute->setCount(nVerts);
+
+ m_normalAttribute->setName(QAttribute::defaultNormalAttributeName());
+ m_normalAttribute->setDataType(QAttribute::Float);
+ m_normalAttribute->setDataSize(3);
+ m_normalAttribute->setAttributeType(QAttribute::VertexAttribute);
+ m_normalAttribute->setBuffer(m_vertexBuffer);
+ m_normalAttribute->setByteStride(stride);
+ m_normalAttribute->setByteOffset(5 * sizeof(float));
+ m_normalAttribute->setCount(nVerts);
+
+ m_tangentAttribute->setName(QAttribute::defaultTangentAttributeName());
+ m_tangentAttribute->setDataType(QAttribute::Float);
+ m_tangentAttribute->setDataSize(4);
+ m_tangentAttribute->setAttributeType(QAttribute::VertexAttribute);
+ m_tangentAttribute->setBuffer(m_vertexBuffer);
+ m_tangentAttribute->setByteStride(stride);
+ m_tangentAttribute->setByteOffset(8 * sizeof(float));
+ m_tangentAttribute->setCount(nVerts);
+
+ m_indexAttribute->setAttributeType(QAttribute::IndexAttribute);
+ m_indexAttribute->setDataType(QAttribute::UnsignedShort);
+ m_indexAttribute->setBuffer(m_indexBuffer);
+
+ m_indexAttribute->setCount(faces * 3);
+
+ m_vertexBuffer->setBufferFunctor(QBufferFunctorPtr(new SphereVertexDataFunctor(m_rings, m_slices, m_radius)));
+ m_indexBuffer->setBufferFunctor(QBufferFunctorPtr(new SphereIndexDataFunctor(m_rings, m_slices)));
+
+ q->addAttribute(m_positionAttribute);
+ q->addAttribute(m_texCoordAttribute);
+ q->addAttribute(m_normalAttribute);
+ if (m_generateTangents)
+ q->addAttribute(m_tangentAttribute);
+ q->addAttribute(m_indexAttribute);
+}
+
+QSphereGeometry::QSphereGeometry(QNode *parent)
+ : QGeometry(*new QSphereGeometryPrivate(), parent)
+{
+ Q_D(QSphereGeometry);
+ d->init();
+}
+
+QSphereGeometry::QSphereGeometry(QSphereGeometryPrivate &dd, QNode *parent)
+ : QGeometry(dd, parent)
+{
+ Q_D(QSphereGeometry);
+ d->init();
+}
+
+QSphereGeometry::~QSphereGeometry()
+{
+ QGeometry::cleanup();
+}
+
+void QSphereGeometry::updateVertices()
+{
+ Q_D(QSphereGeometry);
+ const int nVerts = (d->m_slices + 1) * (d->m_rings + 1);
+ d->m_positionAttribute->setCount(nVerts);
+ d->m_texCoordAttribute->setCount(nVerts);
+ d->m_normalAttribute->setCount(nVerts);
+ d->m_tangentAttribute->setCount(nVerts);
+ d->m_vertexBuffer->setBufferFunctor(QBufferFunctorPtr(new SphereVertexDataFunctor(d->m_rings, d->m_slices, d->m_radius)));
+}
+
+void QSphereGeometry::updateIndices()
+{
+ Q_D(QSphereGeometry);
+ const int faces = (d->m_slices * 2) * (d->m_rings - 2) + (2 * d->m_slices);
+ d->m_indexAttribute->setCount(faces * 3);
+ d->m_indexBuffer->setBufferFunctor(QBufferFunctorPtr(new SphereIndexDataFunctor(d->m_rings, d->m_slices)));
+
+}
+
+void QSphereGeometry::setRings(int rings)
+{
+ Q_D(QSphereGeometry);
+ if (rings != d->m_rings) {
+ d->m_rings = rings;
+ updateVertices();
+ updateIndices();
+ emit ringsChanged();
+ }
+}
+
+void QSphereGeometry::setSlices(int slices)
+{
+ Q_D(QSphereGeometry);
+ if (slices != d->m_slices) {
+ d->m_slices = slices;
+ updateVertices();
+ updateIndices();
+ emit slicesChanged();
+ }
+}
+
+void QSphereGeometry::setRadius(float radius)
+{
+ Q_D(QSphereGeometry);
+ if (radius != d->m_radius) {
+ d->m_radius = radius;
+ updateVertices();
+ emit radiusChanged();
+ }
+}
+
+void QSphereGeometry::setGenerateTangents(bool gen)
+{
+ Q_D(QSphereGeometry);
+ if (d->m_generateTangents != gen) {
+ if (d->m_generateTangents)
+ removeAttribute(d->m_tangentAttribute);
+ d->m_generateTangents = gen;
+ if (d->m_generateTangents)
+ addAttribute(d->m_tangentAttribute);
+ emit generateTangentsChanged();
+ }
+}
+
+bool QSphereGeometry::generateTangents() const
+{
+ Q_D(const QSphereGeometry);
+ return d->m_generateTangents;
+}
+
+int QSphereGeometry::rings() const
+{
+ Q_D(const QSphereGeometry);
+ return d->m_rings;
+}
+
+int QSphereGeometry::slices() const
+{
+ Q_D(const QSphereGeometry);
+ return d->m_slices;
+}
+
+float QSphereGeometry::radius() const
+{
+ Q_D(const QSphereGeometry);
+ return d->m_radius;
+}
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
diff --git a/src/render/geometry/qspheregeometry.h b/src/render/geometry/qspheregeometry.h
new file mode 100644
index 000000000..c836d9e07
--- /dev/null
+++ b/src/render/geometry/qspheregeometry.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QSPHEREGEOMETRY_H
+#define QT3DRENDER_QSPHEREGEOMETRY_H
+
+#include <Qt3DRenderer/qgeometry.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class QSphereGeometryPrivate;
+
+class QT3DRENDERERSHARED_EXPORT QSphereGeometry : public QGeometry
+{
+ Q_OBJECT
+ Q_PROPERTY(int rings READ rings WRITE setRings NOTIFY ringsChanged)
+ Q_PROPERTY(int slices READ slices WRITE setSlices NOTIFY slicesChanged)
+ Q_PROPERTY(float radius READ radius WRITE setRadius NOTIFY radiusChanged)
+ Q_PROPERTY(bool generateTangents READ generateTangents WRITE setGenerateTangents NOTIFY generateTangentsChanged)
+public:
+ explicit QSphereGeometry(QNode *parent = Q_NULLPTR);
+ ~QSphereGeometry();
+
+ void updateVertices();
+ void updateIndices();
+ void setRings(int rings);
+ void setSlices(int slices);
+ void setRadius(float radius);
+ void setGenerateTangents(bool gen);
+
+ bool generateTangents() const;
+ int rings() const;
+ int slices() const;
+ float radius() const;
+
+Q_SIGNALS:
+ void radiusChanged();
+ void ringsChanged();
+ void slicesChanged();
+ void generateTangentsChanged();
+
+protected:
+ QSphereGeometry(QSphereGeometryPrivate &dd, QNode *parent = Q_NULLPTR);
+
+private:
+ Q_DECLARE_PRIVATE(QSphereGeometry)
+ QT3D_CLONEABLE(QSphereGeometry)
+};
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QSPHEREGEOMETRY_H
diff --git a/src/render/geometry/qspheregeometry_p.h b/src/render/geometry/qspheregeometry_p.h
new file mode 100644
index 000000000..5696ec216
--- /dev/null
+++ b/src/render/geometry/qspheregeometry_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Paul Lemire
+** Contact: paul.lemire350@gmail.com
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QSPHEREGEOMETRY_P_H
+#define QT3DRENDER_QSPHEREGEOMETRY_P_H
+
+#include <Qt3DRenderer/private/qgeometry_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class QAttribute;
+class QBuffer;
+
+class QSphereGeometryPrivate : public QGeometryPrivate
+{
+public:
+ QSphereGeometryPrivate();
+ void init();
+
+ bool m_generateTangents;
+ int m_rings;
+ int m_slices;
+ float m_radius;
+ QAttribute *m_positionAttribute;
+ QAttribute *m_normalAttribute;
+ QAttribute *m_texCoordAttribute;
+ QAttribute *m_tangentAttribute;
+ QAttribute *m_indexAttribute;
+ QBuffer *m_vertexBuffer;
+ QBuffer *m_indexBuffer;
+
+ Q_DECLARE_PUBLIC(QSphereGeometry);
+};
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QSPHEREGEOMETRY_P_H
+
diff --git a/src/render/geometry/qspheremesh.cpp b/src/render/geometry/qspheremesh.cpp
index 6e5b6ce4f..bd93c0ab6 100644
--- a/src/render/geometry/qspheremesh.cpp
+++ b/src/render/geometry/qspheremesh.cpp
@@ -35,368 +35,21 @@
**
****************************************************************************/
-#ifndef _USE_MATH_DEFINES
-# define _USE_MATH_DEFINES // For MSVC
-#endif
-
#include "qspheremesh.h"
-#include <Qt3DRenderer/private/renderlogging_p.h>
-#include <Qt3DRenderer/qbufferfunctor.h>
-#include <Qt3DRenderer/qbuffer.h>
-#include <Qt3DRenderer/qattribute.h>
-
-#include <qmath.h>
+#include "qspheregeometry.h"
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-namespace {
-
-QByteArray createSphereMeshVertexData(float radius, int rings, int slices)
-{
- QByteArray bufferBytes;
- // vec3 pos, vec2 texCoord, vec3 normal, vec4 tangent
- const quint32 elementSize = 3 + 2 + 3 + 4;
- const quint32 stride = elementSize * sizeof(float);
- const int nVerts = (slices + 1) * (rings + 1);
- bufferBytes.resize(stride * nVerts);
-
- float* fptr = reinterpret_cast<float*>(bufferBytes.data());
-
- const float dTheta = (M_PI * 2) / static_cast<float>( slices );
- const float dPhi = M_PI / static_cast<float>( rings );
- const float du = 1.0f / static_cast<float>( slices );
- const float dv = 1.0f / static_cast<float>( rings );
-
- // Iterate over latitudes (rings)
- for ( int lat = 0; lat < rings + 1; ++lat )
- {
- const float phi = M_PI_2 - static_cast<float>( lat ) * dPhi;
- const float cosPhi = qCos( phi );
- const float sinPhi = qSin( phi );
- const float v = 1.0f - static_cast<float>( lat ) * dv;
-
- // Iterate over longitudes (slices)
- for ( int lon = 0; lon < slices + 1; ++lon )
- {
- const float theta = static_cast<float>( lon ) * dTheta;
- const float cosTheta = qCos( theta );
- const float sinTheta = qSin( theta );
- const float u = static_cast<float>( lon ) * du;
-
- *fptr++ = radius * cosTheta * cosPhi;
- *fptr++ = radius * sinPhi;
- *fptr++ = radius * sinTheta * cosPhi;
-
- *fptr++ = u;
- *fptr++ = v;
-
- *fptr++ = cosTheta * cosPhi;
- *fptr++ = sinPhi;
- *fptr++ = sinTheta * cosPhi;
-
- *fptr++ = sinTheta;
- *fptr++ = 0.0;
- *fptr++ = -cosTheta;
- *fptr++ = 1.0;
- }
- }
- return bufferBytes;
-}
-
-QByteArray createSphereMeshIndexData(int rings, int slices)
-{
- int faces = (slices * 2) * (rings - 2); // two tris per slice, for all middle rings
- faces += 2 * slices; // tri per slice for both top and bottom
-
- QByteArray indexBytes;
- const int indices = faces * 3;
- Q_ASSERT(indices < 65536);
- indexBytes.resize(indices * sizeof(quint16));
- quint16 *indexPtr = reinterpret_cast<quint16*>(indexBytes.data());
-
- // top cap
- {
- const int nextRingStartIndex = slices + 1;
- for ( int j = 0; j < slices; ++j )
- {
- *indexPtr++ = nextRingStartIndex + j;
- *indexPtr++ = 0;
- *indexPtr++ = nextRingStartIndex + j + 1;
- }
- }
-
- for ( int i = 1; i < (rings - 1); ++i )
- {
- const int ringStartIndex = i * ( slices + 1 );
- const int nextRingStartIndex = ( i + 1 ) * ( slices + 1 );
-
- for ( int j = 0; j < slices; ++j )
- {
- // Split the quad into two triangles
- *indexPtr++ = ringStartIndex + j;
- *indexPtr++ = ringStartIndex + j + 1;
- *indexPtr++ = nextRingStartIndex + j;
- *indexPtr++ = nextRingStartIndex + j;
- *indexPtr++ = ringStartIndex + j + 1;
- *indexPtr++ = nextRingStartIndex + j + 1;
- }
- }
-
- // bottom cap
- {
- const int ringStartIndex = (rings - 1) * ( slices + 1);
- const int nextRingStartIndex = (rings) * ( slices + 1);
- for ( int j = 0; j < slices; ++j )
- {
- *indexPtr++ = ringStartIndex + j + 1;
- *indexPtr++ = nextRingStartIndex;
- *indexPtr++ = ringStartIndex + j;
- }
- }
-
- return indexBytes;
-}
-
-} // anonymous
-
-class SphereVertexDataFunctor : public QBufferFunctor
-{
-public:
- SphereVertexDataFunctor(int rings, int slices, float radius)
- : m_rings(rings)
- , m_slices(slices)
- , m_radius(radius)
- {
- }
-
- QByteArray operator ()() Q_DECL_OVERRIDE
- {
- return createSphereMeshVertexData(m_radius, m_rings, m_slices);
- }
-
- bool operator ==(const QBufferFunctor &other) const Q_DECL_OVERRIDE
- {
- const SphereVertexDataFunctor *otherFunctor = functor_cast<SphereVertexDataFunctor>(&other);
- if (otherFunctor != Q_NULLPTR)
- return (otherFunctor->m_rings == m_rings &&
- otherFunctor->m_slices == m_slices &&
- otherFunctor->m_radius == m_radius);
- return false;
- }
-
- QT3D_FUNCTOR(SphereVertexDataFunctor)
-
-private:
- int m_rings;
- int m_slices;
- float m_radius;
-};
-
-class SphereIndexDataFunctor : public QBufferFunctor
-{
-public:
- SphereIndexDataFunctor(int rings, int slices)
- : m_rings(rings)
- , m_slices(slices)
- {
- }
-
- QByteArray operator ()() Q_DECL_OVERRIDE
- {
- return createSphereMeshIndexData(m_rings, m_slices);
- }
-
- bool operator ==(const QBufferFunctor &other) const Q_DECL_OVERRIDE
- {
- const SphereIndexDataFunctor *otherFunctor = functor_cast<SphereIndexDataFunctor>(&other);
- if (otherFunctor != Q_NULLPTR)
- return (otherFunctor->m_rings == m_rings &&
- otherFunctor->m_slices == m_slices);
- return false;
- }
-
- QT3D_FUNCTOR(SphereIndexDataFunctor)
-
-private:
- int m_rings;
- int m_slices;
-};
-
-class SphereGeometry : public QGeometry
-{
- Q_OBJECT
-public:
- explicit SphereGeometry(QNode *parent = 0)
- : QGeometry(parent)
- , m_generateTangents(false)
- , m_rings(16)
- , m_slices(16)
- , m_radius(1.0f)
- , m_positionAttribute(new QAttribute(this))
- , m_normalAttribute(new QAttribute(this))
- , m_texCoordAttribute(new QAttribute(this))
- , m_tangentAttribute(new QAttribute(this))
- , m_indexAttribute(new QAttribute(this))
- , m_vertexBuffer(new QBuffer(QBuffer::VertexBuffer, this))
- , m_indexBuffer(new QBuffer(QBuffer::IndexBuffer, this))
- {
- // vec3 pos, vec2 tex, vec3 normal, vec4 tangent
- const quint32 elementSize = 3 + 2 + 3 + 4;
- const quint32 stride = elementSize * sizeof(float);
- const int nVerts = (m_slices + 1) * (m_rings + 1);
- const int faces = (m_slices * 2) * (m_rings - 2) + (2 * m_slices);
-
- m_positionAttribute->setName(QAttribute::defaultPositionAttributeName());
- m_positionAttribute->setDataType(QAttribute::Float);
- m_positionAttribute->setDataSize(3);
- m_positionAttribute->setAttributeType(QAttribute::VertexAttribute);
- m_positionAttribute->setBuffer(m_vertexBuffer);
- m_positionAttribute->setByteStride(stride);
- m_positionAttribute->setCount(nVerts);
-
- m_texCoordAttribute->setName(QAttribute::defaultTextureCoordinateAttributeName());
- m_texCoordAttribute->setDataType(QAttribute::Float);
- m_texCoordAttribute->setDataSize(2);
- m_texCoordAttribute->setAttributeType(QAttribute::VertexAttribute);
- m_texCoordAttribute->setBuffer(m_vertexBuffer);
- m_texCoordAttribute->setByteStride(stride);
- m_texCoordAttribute->setByteOffset(3 * sizeof(float));
- m_texCoordAttribute->setCount(nVerts);
-
- m_normalAttribute->setName(QAttribute::defaultNormalAttributeName());
- m_normalAttribute->setDataType(QAttribute::Float);
- m_normalAttribute->setDataSize(3);
- m_normalAttribute->setAttributeType(QAttribute::VertexAttribute);
- m_normalAttribute->setBuffer(m_vertexBuffer);
- m_normalAttribute->setByteStride(stride);
- m_normalAttribute->setByteOffset(5 * sizeof(float));
- m_normalAttribute->setCount(nVerts);
-
- m_tangentAttribute->setName(QAttribute::defaultTangentAttributeName());
- m_tangentAttribute->setDataType(QAttribute::Float);
- m_tangentAttribute->setDataSize(4);
- m_tangentAttribute->setAttributeType(QAttribute::VertexAttribute);
- m_tangentAttribute->setBuffer(m_vertexBuffer);
- m_tangentAttribute->setByteStride(stride);
- m_tangentAttribute->setByteOffset(8 * sizeof(float));
- m_tangentAttribute->setCount(nVerts);
-
- m_indexAttribute->setAttributeType(QAttribute::IndexAttribute);
- m_indexAttribute->setDataType(QAttribute::UnsignedShort);
- m_indexAttribute->setBuffer(m_indexBuffer);
-
- m_indexAttribute->setCount(faces * 3);
-
- m_vertexBuffer->setBufferFunctor(QBufferFunctorPtr(new SphereVertexDataFunctor(m_rings, m_slices, m_radius)));
- m_indexBuffer->setBufferFunctor(QBufferFunctorPtr(new SphereIndexDataFunctor(m_rings, m_slices)));
-
- addAttribute(m_positionAttribute);
- addAttribute(m_texCoordAttribute);
- addAttribute(m_normalAttribute);
- if (m_generateTangents)
- addAttribute(m_tangentAttribute);
- addAttribute(m_indexAttribute);
- }
-
- ~SphereGeometry()
- {
- QGeometry::cleanup();
- }
-
- void updateVertices()
- {
- const int nVerts = (m_slices + 1) * (m_rings + 1);
- m_positionAttribute->setCount(nVerts);
- m_texCoordAttribute->setCount(nVerts);
- m_normalAttribute->setCount(nVerts);
- m_tangentAttribute->setCount(nVerts);
-
- m_vertexBuffer->setBufferFunctor(QBufferFunctorPtr(new SphereVertexDataFunctor(m_rings, m_slices, m_radius)));
- }
-
- void updateIndices()
- {
- const int faces = (m_slices * 2) * (m_rings - 2) + (2 * m_slices);
- m_indexAttribute->setCount(faces * 3);
- m_indexBuffer->setBufferFunctor(QBufferFunctorPtr(new SphereIndexDataFunctor(m_rings, m_slices)));
- }
-
- void setRings(int rings)
- {
- if (rings != m_rings) {
- m_rings = rings;
- updateVertices();
- updateIndices();
- emit ringsChanged();
- }
- }
-
- void setSlices(int slices)
- {
- if (slices != m_slices) {
- m_slices = slices;
- updateVertices();
- updateIndices();
- emit slicesChanged();
- }
- }
-
- void setRadius(float radius)
- {
- if (radius != m_radius) {
- m_radius = radius;
- updateVertices();
- emit radiusChanged();
- }
- }
-
- void setGenerateTangents(bool gen)
- {
- if (m_generateTangents != gen) {
- if (m_generateTangents)
- removeAttribute(m_tangentAttribute);
- m_generateTangents = gen;
- if (m_generateTangents)
- addAttribute(m_tangentAttribute);
- emit generateTangentsChanged();
- }
- }
-
- bool generateTangents() const { return m_generateTangents; }
- int rings() const { return m_rings; }
- int slices() const { return m_slices; }
- float radius() const { return m_radius; }
-
-Q_SIGNALS:
- void radiusChanged();
- void ringsChanged();
- void slicesChanged();
- void generateTangentsChanged();
-
-private:
- bool m_generateTangents;
- int m_rings;
- int m_slices;
- float m_radius;
- QAttribute *m_positionAttribute;
- QAttribute *m_normalAttribute;
- QAttribute *m_texCoordAttribute;
- QAttribute *m_tangentAttribute;
- QAttribute *m_indexAttribute;
- QBuffer *m_vertexBuffer;
- QBuffer *m_indexBuffer;
-};
-
QSphereMesh::QSphereMesh(QNode *parent)
: QGeometryRenderer(parent)
{
- SphereGeometry *geometry = new SphereGeometry(this);
- QObject::connect(geometry, &SphereGeometry::radiusChanged, this, &QSphereMesh::radiusChanged);
- QObject::connect(geometry, &SphereGeometry::ringsChanged, this, &QSphereMesh::ringsChanged);
- QObject::connect(geometry, &SphereGeometry::slicesChanged, this, &QSphereMesh::slicesChanged);
- QObject::connect(geometry, &SphereGeometry::generateTangentsChanged, this, &QSphereMesh::generateTangentsChanged);
+ QSphereGeometry *geometry = new QSphereGeometry(this);
+ QObject::connect(geometry, &QSphereGeometry::radiusChanged, this, &QSphereMesh::radiusChanged);
+ QObject::connect(geometry, &QSphereGeometry::ringsChanged, this, &QSphereMesh::ringsChanged);
+ QObject::connect(geometry, &QSphereGeometry::slicesChanged, this, &QSphereMesh::slicesChanged);
+ QObject::connect(geometry, &QSphereGeometry::generateTangentsChanged, this, &QSphereMesh::generateTangentsChanged);
QGeometryRenderer::setGeometry(geometry);
}
@@ -407,46 +60,44 @@ QSphereMesh::~QSphereMesh()
void QSphereMesh::setRings(int rings)
{
- static_cast<SphereGeometry *>(geometry())->setRings(rings);
+ static_cast<QSphereGeometry *>(geometry())->setRings(rings);
}
void QSphereMesh::setSlices(int slices)
{
- static_cast<SphereGeometry *>(geometry())->setSlices(slices);
+ static_cast<QSphereGeometry *>(geometry())->setSlices(slices);
}
void QSphereMesh::setRadius(float radius)
{
- static_cast<SphereGeometry *>(geometry())->setRadius(radius);
+ static_cast<QSphereGeometry *>(geometry())->setRadius(radius);
}
void QSphereMesh::setGenerateTangents(bool gen)
{
- static_cast<SphereGeometry *>(geometry())->setGenerateTangents(gen);
+ static_cast<QSphereGeometry *>(geometry())->setGenerateTangents(gen);
}
bool QSphereMesh::generateTangents() const
{
- return static_cast<SphereGeometry *>(geometry())->generateTangents();
+ return static_cast<QSphereGeometry *>(geometry())->generateTangents();
}
int QSphereMesh::rings() const
{
- return static_cast<SphereGeometry *>(geometry())->rings();
+ return static_cast<QSphereGeometry *>(geometry())->rings();
}
int QSphereMesh::slices() const
{
- return static_cast<SphereGeometry *>(geometry())->slices();
+ return static_cast<QSphereGeometry *>(geometry())->slices();
}
float QSphereMesh::radius() const
{
- return static_cast<SphereGeometry *>(geometry())->radius();
+ return static_cast<QSphereGeometry *>(geometry())->radius();
}
} //Qt3D
QT_END_NAMESPACE
-
-#include "qspheremesh.moc"