summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2015-08-05 12:37:17 +0200
committerPaul Lemire <paul.lemire@kdab.com>2015-08-07 14:32:21 +0000
commitac98340d29ce050651b14004abc9269705f631b9 (patch)
tree0d9ef59ef8452398e7b29ab1dc64d8784bcf25af /src
parent0a37465495645d9ac2277726b043ecf9f3fb012a (diff)
QTorusMesh converted to QGeometryRenderer subclass
Change-Id: I19ae5dc944de3eab3081eda4b4ad95863c182e4d Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src')
-rw-r--r--src/render/frontend/qtorusmesh.cpp477
-rw-r--r--src/render/frontend/qtorusmesh.h26
2 files changed, 305 insertions, 198 deletions
diff --git a/src/render/frontend/qtorusmesh.cpp b/src/render/frontend/qtorusmesh.cpp
index 241553f8d..cb0f8c536 100644
--- a/src/render/frontend/qtorusmesh.cpp
+++ b/src/render/frontend/qtorusmesh.cpp
@@ -40,257 +40,364 @@
#endif
#include "qtorusmesh.h"
-#include "qbuffer.h"
-#include "qattribute.h"
-#include "qmeshdata.h"
-#include <Qt3DRenderer/private/qabstractmesh_p.h>
-
+#include <Qt3DRenderer/qbuffer.h>
+#include <Qt3DRenderer/qbufferfunctor.h>
+#include <Qt3DRenderer/qattribute.h>
+#include <QVector3D>
#include <qmath.h>
QT_BEGIN_NAMESPACE
namespace Qt3D {
-class TorusMeshFunctor : public QAbstractMeshFunctor
-{
-public:
- TorusMeshFunctor(int rings, int slices, float radius, float minorRadius);
- QMeshDataPtr operator ()() Q_DECL_OVERRIDE;
- bool operator ==(const QAbstractMeshFunctor &other) const Q_DECL_OVERRIDE;
- QT3D_FUNCTOR(TorusMeshFunctor)
-private:
- int m_rings;
- int m_slices;
- float m_radius;
- float m_minorRadius;
-};
+namespace {
-class QTorusMeshPrivate : public QAbstractMeshPrivate
+QByteArray createTorusVertexData(double radius, double minorRadius,
+ int rings, int sides)
{
- QTorusMeshPrivate()
- : QAbstractMeshPrivate()
- , m_rings(16)
- , m_slices(16)
- , m_radius(1.0)
- , m_minorRadius(1.0)
- {}
+ const int nVerts = sides * (rings + 1);
+ QByteArray bufferBytes;
+ // vec3 pos, vec2 texCoord, vec3 normal
+ const quint32 elementSize = 3 + 2 + 3;
+ const quint32 stride = elementSize * sizeof(float);
+ bufferBytes.resize(stride * nVerts);
- Q_DECLARE_PUBLIC(QTorusMesh)
- int m_rings;
- int m_slices;
- float m_radius;
- float m_minorRadius;
-};
+ float* fptr = reinterpret_cast<float*>(bufferBytes.data());
-void QTorusMesh::copy(const QNode *ref)
-{
- QAbstractMesh::copy(ref);
- const QTorusMesh *mesh = static_cast<const QTorusMesh*>(ref);
- d_func()->m_rings = mesh->d_func()->m_rings;
- d_func()->m_slices = mesh->d_func()->m_slices;
- d_func()->m_radius = mesh->d_func()->m_radius;
- d_func()->m_minorRadius = mesh->d_func()->m_minorRadius;
-}
+ const float ringFactor = (M_PI * 2) / static_cast<float>( rings );
+ const float sideFactor = (M_PI * 2) / static_cast<float>( sides );
+ for (int ring = 0; ring <= rings; ++ring) {
+ const float u = ring * ringFactor;
+ const float cu = qCos( u );
+ const float su = qSin( u );
-QTorusMesh::QTorusMesh(QNode *parent)
- : QAbstractMesh(*new QTorusMeshPrivate, parent)
-{
- update();
-}
+ for (int side = 0; side < sides; ++side) {
+ const float v = side * sideFactor;
+ const float cv = qCos( v );
+ const float sv = qSin( v );
+ const float r = (radius + minorRadius * cv);
-QTorusMesh::~QTorusMesh()
-{
- QNode::cleanup();
-}
+ *fptr++ = r * cu;
+ *fptr++ = r * su;
+ *fptr++ = minorRadius * sv;
-void QTorusMesh::setRings(int rings)
-{
- Q_D(QTorusMesh);
- if (rings != d->m_rings) {
- d->m_rings = rings;
- emit ringsChanged();
- QAbstractMesh::update();
+ *fptr++ = u / (M_PI * 2);
+ *fptr++ = v / (M_PI * 2);
+
+ QVector3D n(cv * cu * r, cv * su * r, sv * r);
+ n.normalize();
+ *fptr++ = n.x();
+ *fptr++ = n.y();
+ *fptr++ = n.z();
+ }
}
+
+ return bufferBytes;
}
-void QTorusMesh::setSlices(int slices)
+QByteArray createTorusIndexData(int rings, int sides)
{
- Q_D(QTorusMesh);
- if (slices != d->m_slices) {
- d->m_slices = slices;
- emit slicesChanged();
- QAbstractMesh::update();
+ QByteArray indexBytes;
+ int faces = (sides * 2) * rings; // two tris per side, for all rings
+ int indices = faces * 3;
+ Q_ASSERT(indices < 65536);
+ indexBytes.resize(indices * sizeof(quint16));
+ quint16* indexPtr = reinterpret_cast<quint16*>(indexBytes.data());
+
+ for (int ring = 0; ring < rings; ++ring) {
+ const int ringStart = ring * sides;
+ const int nextRingStart = (ring + 1) * sides;
+ for (int side = 0; side < sides; ++side) {
+ const int nextSide = (side + 1) % sides;
+ *indexPtr++ = (ringStart + side);
+ *indexPtr++ = (nextRingStart + side);
+ *indexPtr++ = (nextRingStart + nextSide);
+ *indexPtr++ = ringStart + side;
+ *indexPtr++ = nextRingStart + nextSide;
+ *indexPtr++ = (ringStart + nextSide);
+ }
}
+
+ return indexBytes;
}
-void QTorusMesh::setRadius(float radius)
+} // anonymous
+
+class TorusVertexDataFunctor : public QBufferFunctor
{
- Q_D(QTorusMesh);
- if (radius != d->m_radius) {
- d->m_radius = radius;
- emit radiusChanged();
- QAbstractMesh::update();
+public:
+ TorusVertexDataFunctor(int rings, int slices, float radius, float minorRadius)
+ : m_rings(rings)
+ , m_sides(slices)
+ , m_radius(radius)
+ , m_minorRadius(minorRadius)
+ {
}
-}
-void QTorusMesh::setMinorRadius(float minorRadius)
-{
- Q_D(QTorusMesh);
- if (minorRadius != d->m_minorRadius) {
- d->m_minorRadius = minorRadius;
- emit minorRadiusChanged();
- QAbstractMesh::update();
+ QByteArray operator ()() Q_DECL_OVERRIDE
+ {
+ return createTorusVertexData(m_radius, m_minorRadius, m_rings, m_sides);
}
-}
-int QTorusMesh::rings() const
-{
- Q_D(const QTorusMesh);
- return d->m_rings;
-}
+ bool operator ==(const QBufferFunctor &other) const Q_DECL_OVERRIDE
+ {
+ const TorusVertexDataFunctor *otherFunctor = functor_cast<TorusVertexDataFunctor>(&other);
+ if (otherFunctor != Q_NULLPTR)
+ return (otherFunctor->m_rings == m_rings &&
+ otherFunctor->m_sides == m_sides &&
+ otherFunctor->m_radius == m_radius &&
+ otherFunctor->m_minorRadius == m_minorRadius);
+ return false;
+ }
-int QTorusMesh::slices() const
-{
- Q_D(const QTorusMesh);
- return d->m_slices;
-}
+ QT3D_FUNCTOR(TorusVertexDataFunctor)
-float QTorusMesh::radius() const
-{
- Q_D(const QTorusMesh);
- return d->m_radius;
-}
+private:
+ int m_rings;
+ int m_sides;
+ float m_radius;
+ float m_minorRadius;
+};
-float QTorusMesh::minorRadius() const
+class TorusIndexDataFunctor : public QBufferFunctor
{
- Q_D(const QTorusMesh);
- return d->m_minorRadius;
-}
+public:
+ TorusIndexDataFunctor(int rings, int slices)
+ : m_rings(rings)
+ , m_sides(slices)
+ {
+ }
-QMeshDataPtr createTorusMesh(double radius, double minorRadius,
- int rings, int sides)
-{
- QMeshDataPtr mesh(new QMeshData(QMeshData::Triangles));
+ QByteArray operator ()() Q_DECL_OVERRIDE
+ {
+ return createTorusIndexData(m_rings, m_sides);
+ }
- int nVerts = sides * ( rings + 1 );
- QByteArray bufferBytes;
- // vec3 pos, vec2 texCoord, vec3 normal
- quint32 elementSize = 3 + 2 + 3;
- quint32 stride = elementSize * sizeof(float);
- bufferBytes.resize(stride * nVerts);
+ bool operator ==(const QBufferFunctor &other) const Q_DECL_OVERRIDE
+ {
+ const TorusIndexDataFunctor *otherFunctor = functor_cast<TorusIndexDataFunctor>(&other);
+ if (otherFunctor != Q_NULLPTR)
+ return (otherFunctor->m_rings == m_rings &&
+ otherFunctor->m_sides == m_sides);
+ return false;
+ }
- float* fptr = reinterpret_cast<float*>(bufferBytes.data());
+ QT3D_FUNCTOR(TorusIndexDataFunctor)
- float ringFactor = (M_PI * 2) / static_cast<float>( rings );
- float sideFactor = (M_PI * 2) / static_cast<float>( sides );
+private:
+ int m_rings;
+ int m_sides;
+};
- for ( int ring = 0; ring <= rings; ring++ )
+class TorusGeometry : public QGeometry
+{
+ Q_OBJECT
+public:
+ explicit TorusGeometry(QNode *parent = 0)
+ : QGeometry(parent)
+ , m_rings(16)
+ , m_slices(16)
+ , m_radius(1.0f)
+ , m_minorRadius(1.0f)
+ , m_positionAttribute(new QAttribute(this))
+ , m_normalAttribute(new QAttribute(this))
+ , m_texCoordAttribute(new QAttribute(this))
+ , m_indexAttribute(new QAttribute(this))
+ , m_vertexBuffer(new QBuffer(QBuffer::VertexBuffer, this))
+ , m_indexBuffer(new QBuffer(QBuffer::IndexBuffer, this))
{
- float u = ring * ringFactor;
- float cu = qCos( u );
- float su = qSin( u );
+ // vec3 pos, vec2 tex, vec3 normal
+ const quint32 elementSize = 3 + 2 + 3;
+ const quint32 stride = elementSize * sizeof(float);
+ const int nVerts = (m_slices + 1) * (m_rings + 1);
+ const int faces = (m_slices * 2) * m_rings;
+
+ 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_indexAttribute->setAttributeType(QAttribute::IndexAttribute);
+ m_indexAttribute->setDataType(QAttribute::UnsignedShort);
+ m_indexAttribute->setBuffer(m_indexBuffer);
+
+ m_indexAttribute->setCount(faces * 3);
+
+ m_vertexBuffer->setBufferFunctor(QBufferFunctorPtr(new TorusVertexDataFunctor(m_rings, m_slices, m_radius, m_minorRadius)));
+ m_indexBuffer->setBufferFunctor(QBufferFunctorPtr(new TorusIndexDataFunctor(m_rings, m_slices)));
+
+ addAttribute(m_positionAttribute);
+ addAttribute(m_texCoordAttribute);
+ addAttribute(m_normalAttribute);
+ addAttribute(m_indexAttribute);
+ }
- for ( int side = 0; side < sides; side++ )
- {
- float v = side * sideFactor;
- float cv = qCos( v );
- float sv = qSin( v );
- float r = ( radius + minorRadius * cv );
+ ~TorusGeometry()
+ {
+ QGeometry::cleanup();
+ }
- *fptr++ = r * cu;
- *fptr++ = r * su;
- *fptr++ = minorRadius * sv;
+ void updateVertices()
+ {
+ const int nVerts = (m_slices + 1) * (m_rings + 1);
+ m_positionAttribute->setCount(nVerts);
+ m_texCoordAttribute->setCount(nVerts);
+ m_normalAttribute->setCount(nVerts);
+ m_vertexBuffer->setBufferFunctor(QBufferFunctorPtr(new TorusVertexDataFunctor(m_rings, m_slices, m_radius, m_minorRadius)));
+ }
- *fptr++ = u / (M_PI * 2);
- *fptr++ = v / (M_PI * 2);
+ void updateIndices()
+ {
+ const int faces = (m_slices * 2) * m_rings;
+ m_indexAttribute->setCount(faces * 3);
+ m_indexBuffer->setBufferFunctor(QBufferFunctorPtr(new TorusIndexDataFunctor(m_rings, m_slices)));
+ }
- QVector3D n(cv * cu * r, cv * su * r, sv * r);
- n.normalize();
- *fptr++ = n.x();
- *fptr++ = n.y();
- *fptr++ = n.z();
+ void setRings(int rings)
+ {
+ if (rings != m_rings) {
+ m_rings = rings;
+ updateVertices();
+ updateIndices();
+ emit ringsChanged();
}
}
- QBuffer *buf(new QBuffer(QBuffer::VertexBuffer));
- buf->setUsage(QBuffer::StaticDraw);
- buf->setData(bufferBytes);
-
- mesh->addAttribute(QMeshData::defaultPositionAttributeName(), new QAttribute(buf, QAttribute::Float, 3, nVerts, 0, stride));
- quint32 offset = sizeof(float) * 3;
-
- mesh->addAttribute(QMeshData::defaultTextureCoordinateAttributeName(), new QAttribute(buf, QAttribute::Float, 2, nVerts, offset, stride));
- offset += sizeof(float) * 2;
-
- mesh->addAttribute(QMeshData::defaultNormalAttributeName(), new QAttribute(buf, QAttribute::Float, 3, nVerts, offset, stride));
- offset += sizeof(float) * 3;
+ void setSlices(int slices)
+ {
+ if (slices != m_slices) {
+ m_slices = slices;
+ updateVertices();
+ updateIndices();
+ emit slicesChanged();
+ }
+ }
- QByteArray indexBytes;
- int faces = (sides * 2) * rings; // two tris per side, for all rings
- int indices = faces * 3;
- Q_ASSERT(indices < 65536);
- indexBytes.resize(indices * sizeof(quint16));
- quint16* indexPtr = reinterpret_cast<quint16*>(indexBytes.data());
+ void setRadius(float radius)
+ {
+ if (radius != m_radius) {
+ m_radius = radius;
+ updateVertices();
+ emit radiusChanged();
+ }
+ }
- for ( int ring = 0; ring < rings; ring++ )
+ void setMinorRadius(float minorRadius)
{
- int ringStart = ring * sides;
- int nextRingStart = ( ring + 1 ) * sides;
- for ( int side = 0; side < sides; side++ )
- {
- int nextSide = ( side + 1 ) % sides;
- *indexPtr++ = ( ringStart + side );
- *indexPtr++ = ( nextRingStart + side );
- *indexPtr++ = ( nextRingStart + nextSide );
- *indexPtr++ = ringStart + side;
- *indexPtr++ = nextRingStart + nextSide;
- *indexPtr++ = ( ringStart + nextSide );
+ if (minorRadius != m_minorRadius) {
+ m_minorRadius = minorRadius;
+ updateVertices();
+ emit minorRadiusChanged();
}
}
- QBuffer *indexBuffer(new QBuffer(QBuffer::IndexBuffer));
- indexBuffer->setUsage(QBuffer::StaticDraw);
- indexBuffer->setData(indexBytes);
- mesh->setIndexAttribute(new QAttribute(indexBuffer, QAttribute::UnsignedShort, 1, indices, 0, 0));
+ int rings() const { return m_rings; }
+ int slices() const { return m_slices; }
+ float radius() const { return m_radius; }
+ float minorRadius() const { return m_minorRadius; }
+
+Q_SIGNALS:
+ void radiusChanged();
+ void ringsChanged();
+ void slicesChanged();
+ void minorRadiusChanged();
+
+private:
+ int m_rings;
+ int m_slices;
+ float m_radius;
+ float m_minorRadius;
+ QAttribute *m_positionAttribute;
+ QAttribute *m_normalAttribute;
+ QAttribute *m_texCoordAttribute;
+ QAttribute *m_indexAttribute;
+ QBuffer *m_vertexBuffer;
+ QBuffer *m_indexBuffer;
+};
+
- mesh->computeBoundsFromAttribute(QMeshData::defaultPositionAttributeName());
+QTorusMesh::QTorusMesh(QNode *parent)
+ : QGeometryRenderer(parent)
+{
+ TorusGeometry *geometry = new TorusGeometry(this);
+ QObject::connect(geometry, &TorusGeometry::radiusChanged, this, &QTorusMesh::radiusChanged);
+ QObject::connect(geometry, &TorusGeometry::ringsChanged, this, &QTorusMesh::ringsChanged);
+ QObject::connect(geometry, &TorusGeometry::slicesChanged, this, &QTorusMesh::slicesChanged);
+ QObject::connect(geometry, &TorusGeometry::minorRadiusChanged, this, &QTorusMesh::minorRadiusChanged);
- return mesh;
+ QGeometryRenderer::setGeometry(geometry);
}
-QAbstractMeshFunctorPtr QTorusMesh::meshFunctor() const
+QTorusMesh::~QTorusMesh()
{
- Q_D(const QTorusMesh);
- return QAbstractMeshFunctorPtr(new TorusMeshFunctor(d->m_rings, d->m_slices, d->m_radius, d->m_minorRadius));
+ QGeometryRenderer::cleanup();
}
-TorusMeshFunctor::TorusMeshFunctor(int rings, int slices, float radius, float minorRadius)
- : QAbstractMeshFunctor()
- , m_rings(rings)
- , m_slices(slices)
- , m_radius(radius)
- , m_minorRadius(minorRadius)
+void QTorusMesh::setRings(int rings)
{
+ static_cast<TorusGeometry *>(geometry())->setRings(rings);
}
-QMeshDataPtr TorusMeshFunctor::operator ()()
+void QTorusMesh::setSlices(int slices)
{
- return createTorusMesh(m_radius, m_minorRadius, m_rings, m_slices);
+ static_cast<TorusGeometry *>(geometry())->setSlices(slices);
}
-bool TorusMeshFunctor::operator ==(const QAbstractMeshFunctor &other) const
+void QTorusMesh::setRadius(float radius)
{
- const TorusMeshFunctor *otherFunctor = functor_cast<TorusMeshFunctor>(&other);
- if (otherFunctor != Q_NULLPTR)
- return (otherFunctor->m_radius == m_radius &&
- otherFunctor->m_slices == m_slices &&
- otherFunctor->m_rings == m_rings &&
- otherFunctor->m_minorRadius == m_minorRadius);
- return false;
+ static_cast<TorusGeometry *>(geometry())->setRadius(radius);
+}
+
+void QTorusMesh::setMinorRadius(float minorRadius)
+{
+ static_cast<TorusGeometry *>(geometry())->setMinorRadius(minorRadius);
+}
+
+int QTorusMesh::rings() const
+{
+ return static_cast<TorusGeometry *>(geometry())->rings();
+}
+
+int QTorusMesh::slices() const
+{
+ return static_cast<TorusGeometry *>(geometry())->slices();
+}
+
+float QTorusMesh::radius() const
+{
+ return static_cast<TorusGeometry *>(geometry())->radius();
+}
+
+float QTorusMesh::minorRadius() const
+{
+ return static_cast<TorusGeometry *>(geometry())->minorRadius();
}
} // Qt3D
QT_END_NAMESPACE
+
+#include "qtorusmesh.moc"
diff --git a/src/render/frontend/qtorusmesh.h b/src/render/frontend/qtorusmesh.h
index a434008b5..746951266 100644
--- a/src/render/frontend/qtorusmesh.h
+++ b/src/render/frontend/qtorusmesh.h
@@ -38,16 +38,13 @@
#define QT3D_QTORUSMESH_H
#include <Qt3DRenderer/qt3drenderer_global.h>
-#include <Qt3DRenderer/qabstractmesh.h>
+#include <Qt3DRenderer/qgeometryrenderer.h>
QT_BEGIN_NAMESPACE
-
namespace Qt3D {
-class QTorusMeshPrivate;
-
-class QT3DRENDERERSHARED_EXPORT QTorusMesh : public QAbstractMesh
+class QT3DRENDERERSHARED_EXPORT QTorusMesh : public QGeometryRenderer
{
Q_OBJECT
Q_PROPERTY(int rings READ rings WRITE setRings NOTIFY ringsChanged)
@@ -68,21 +65,24 @@ public:
float radius() const;
float minorRadius() const;
- QAbstractMeshFunctorPtr meshFunctor() const Q_DECL_OVERRIDE;
-
Q_SIGNALS:
-
void radiusChanged();
void minorRadiusChanged();
void ringsChanged();
void slicesChanged();
-protected:
- void copy(const QNode *ref) Q_DECL_OVERRIDE;
-
private:
- Q_DECLARE_PRIVATE(QTorusMesh)
- QT3D_CLONEABLE(QTorusMesh)
+ // As this is a default provided geometry renderer, no one should be able
+ // to modify the QGeometryRenderer's properties
+
+ void setInstanceCount(int instanceCount);
+ void setPrimitiveCount(int primitiveCount);
+ void setBaseVertex(int baseVertex);
+ void setBaseInstance(int baseInstance);
+ void setRestartIndex(int index);
+ void setPrimitiveRestart(bool enabled);
+ void setGeometry(QGeometry *geometry);
+ void setPrimitiveType(PrimitiveType primitiveType);
};
} // Qt3D