diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2015-08-05 12:37:17 +0200 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2015-08-07 14:32:21 +0000 |
commit | ac98340d29ce050651b14004abc9269705f631b9 (patch) | |
tree | 0d9ef59ef8452398e7b29ab1dc64d8784bcf25af /src | |
parent | 0a37465495645d9ac2277726b043ecf9f3fb012a (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.cpp | 477 | ||||
-rw-r--r-- | src/render/frontend/qtorusmesh.h | 26 |
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 |