diff options
Diffstat (limited to 'src/extras/geometries')
31 files changed, 6558 insertions, 0 deletions
diff --git a/src/extras/geometries/geometries.pri b/src/extras/geometries/geometries.pri new file mode 100644 index 000000000..7a2932cb7 --- /dev/null +++ b/src/extras/geometries/geometries.pri @@ -0,0 +1,35 @@ +HEADERS += \ + $$PWD/qconegeometry.h \ + $$PWD/qconegeometry_p.h \ + $$PWD/qconemesh.h \ + $$PWD/qcuboidmesh.h \ + $$PWD/qcylindergeometry.h \ + $$PWD/qcylindergeometry_p.h \ + $$PWD/qcylindermesh.h \ + $$PWD/qplanemesh.h \ + $$PWD/qspheremesh.h \ + $$PWD/qtorusmesh.h \ + $$PWD/qtorusgeometry.h \ + $$PWD/qtorusgeometry_p.h \ + $$PWD/qspheregeometry.h \ + $$PWD/qspheregeometry_p.h \ + $$PWD/qcuboidgeometry.h \ + $$PWD/qcuboidgeometry_p.h \ + $$PWD/qplanegeometry.h \ + $$PWD/qplanegeometry_p.h + +SOURCES += \ + $$PWD/qconegeometry.cpp \ + $$PWD/qconemesh.cpp \ + $$PWD/qcuboidmesh.cpp \ + $$PWD/qcylindergeometry.cpp \ + $$PWD/qcylindermesh.cpp \ + $$PWD/qplanemesh.cpp \ + $$PWD/qspheremesh.cpp \ + $$PWD/qtorusmesh.cpp \ + $$PWD/qtorusgeometry.cpp \ + $$PWD/qspheregeometry.cpp \ + $$PWD/qcuboidgeometry.cpp \ + $$PWD/qplanegeometry.cpp + +INCLUDEPATH += $$PWD diff --git a/src/extras/geometries/qconegeometry.cpp b/src/extras/geometries/qconegeometry.cpp new file mode 100644 index 000000000..4d1c4ce17 --- /dev/null +++ b/src/extras/geometries/qconegeometry.cpp @@ -0,0 +1,589 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _USE_MATH_DEFINES +# define _USE_MATH_DEFINES // For MSVC +#endif + +#include "qconegeometry.h" +#include "qconegeometry_p.h" +#include <Qt3DRender/qbuffer.h> +#include <Qt3DRender/qbufferdatagenerator.h> +#include <Qt3DRender/qattribute.h> +#include <QVector3D> +#include <cmath> + +QT_BEGIN_NAMESPACE + +using namespace Qt3DRender; + +namespace Qt3DExtras { + +namespace { + +void createSidesVertices(float *&verticesPtr, + int rings, + int slices, + double topRadius, + double bottomRadius, + double length) +{ + const float dY = length / static_cast<float>(rings - 1); + const float dTheta = (M_PI * 2) / static_cast<float>(slices); + + for (int ring = 0; ring < rings; ++ring) { + const float y = -length / 2.0f + static_cast<float>(ring) * dY; + + const float t = (y + length / 2) / length; + const float radius = (bottomRadius * (1 - t)) + (t * topRadius); + + for (int slice = 0; slice <= slices; ++slice) { + const float theta = static_cast<float>(slice) * dTheta; + const float ta = std::tan((M_PI/2) - std::atan(length / (bottomRadius - topRadius))); + const float ct = std::cos(theta); + const float st = std::sin(theta); + + *verticesPtr++ = radius * ct; + *verticesPtr++ = y; + *verticesPtr++ = radius * st; + + *verticesPtr++ = (y + length / 2.0) / length; + *verticesPtr++ = theta / (M_PI * 2); + + QVector3D n(ct, ta, st); + n.normalize(); + *verticesPtr++ = n.x(); + *verticesPtr++ = n.y(); + *verticesPtr++ = n.z(); + } + } +} + +void createSidesIndices(quint16 *&indicesPtr, int rings, int slices) +{ + for (int ring = 0; ring < rings-1; ++ring) { + const int ringIndexStart = ring * (slices + 1); + const int nextRingIndexStart = (ring + 1) * (slices + 1); + + for (int slice = 0; slice <= slices; ++slice) { + if (slice == slices) + continue; + + const int nextSlice = slice + 1; + + *indicesPtr++ = (ringIndexStart + slice); + *indicesPtr++ = (nextRingIndexStart + slice); + *indicesPtr++ = (ringIndexStart + nextSlice); + *indicesPtr++ = (ringIndexStart + nextSlice); + *indicesPtr++ = (nextRingIndexStart + slice); + *indicesPtr++ = (nextRingIndexStart + nextSlice); + } + } +} + +void createDiscVertices(float *&verticesPtr, + int slices, + double topRadius, + double bottomRadius, + double length, + double yPosition) +{ + const float dTheta = (M_PI * 2) / static_cast<float>(slices); + const double yNormal = (yPosition < 0.0f) ? -1.0f : 1.0f; + + *verticesPtr++ = 0.0f; + *verticesPtr++ = yPosition; + *verticesPtr++ = 0.0f; + + *verticesPtr++ = 1.0f; + *verticesPtr++ = 0.0f; + + *verticesPtr++ = 0.0f; + *verticesPtr++ = yNormal; + *verticesPtr++ = 0.0f; + + + for (int slice = 0; slice <= slices; ++slice) + { + const float theta = static_cast<float>(slice) * dTheta; + const float ct = std::cos(theta); + const float st = std::sin(theta); + + const float t = (yPosition + length / 2) / length; + const float radius = (bottomRadius * (1 - t)) + (t * topRadius); + + *verticesPtr++ = radius * ct; + *verticesPtr++ = yPosition; + *verticesPtr++ = radius * st; + + *verticesPtr++ = 1.0f; + *verticesPtr++ = theta / (M_PI * 2); + + *verticesPtr++ = 0.0f; + *verticesPtr++ = yNormal; + *verticesPtr++ = 0.0f; + } +} + +void createDiscIndices(quint16 *&indicesPtr, + int discCenterIndex, + int slices, + bool isTopCap) +{ + if ( !isTopCap ) { + for ( int i = slices - 1 ; i >= 0 ; --i ) + { + if ( i != 0 ) { + *indicesPtr++ = discCenterIndex; + *indicesPtr++ = discCenterIndex + i + 1; + *indicesPtr++ = discCenterIndex + i; + } else { + *indicesPtr++ = discCenterIndex; + *indicesPtr++ = discCenterIndex + i + 1; + *indicesPtr++ = discCenterIndex + slices; + } + } + } else { + for ( int i = 0 ; i < slices; ++i ) + { + if ( i != slices - 1 ) { + *indicesPtr++ = discCenterIndex; + *indicesPtr++ = discCenterIndex + i + 1; + *indicesPtr++ = discCenterIndex + i + 2; + } else { + *indicesPtr++ = discCenterIndex; + *indicesPtr++ = discCenterIndex + i + 1; + *indicesPtr++ = discCenterIndex + 1; + } + } + } +} + +} // anonymous + + +class ConeVertexDataFunctor : public QBufferDataGenerator +{ +public: + ConeVertexDataFunctor(bool hasTopEndcap, bool hasBottomEndcap, int rings, int slices, + float topRadius, float bottomRadius, float length) + : m_hasTopEndcap(hasTopEndcap) + , m_hasBottomEndcap(hasBottomEndcap) + , m_rings(rings) + , m_slices(slices) + , m_topRadius(topRadius) + , m_bottomRadius(bottomRadius) + , m_length(length) + {} + + QByteArray operator ()() Q_DECL_OVERRIDE + { + int verticesCount = 0; + + verticesCount = ( m_slices + 1 ) * m_rings // Sides + + (m_hasTopEndcap + m_hasBottomEndcap) * (m_slices + 1) + 2; // endcaps + + // vec3 pos, vec2 texCoord, vec3 normal + const quint32 vertexSize = (3 + 2 + 3) * sizeof(float); + + QByteArray verticesData; + verticesData.resize(vertexSize * verticesCount); + float *verticesPtr = reinterpret_cast<float*>(verticesData.data()); + + createSidesVertices(verticesPtr, m_rings, m_slices, m_topRadius, m_bottomRadius, m_length); + if ( m_hasTopEndcap ) + createDiscVertices(verticesPtr, m_slices, m_topRadius, m_bottomRadius, m_length, m_length * 0.5f); + if ( m_hasBottomEndcap ) + createDiscVertices(verticesPtr, m_slices, m_topRadius, m_bottomRadius, m_length, -m_length * 0.5f); + + return verticesData; + } + + bool operator ==(const QBufferDataGenerator &other) const Q_DECL_OVERRIDE + { + const ConeVertexDataFunctor *otherFunctor = functor_cast<ConeVertexDataFunctor>(&other); + if (otherFunctor != Q_NULLPTR) + return (otherFunctor->m_hasTopEndcap == m_hasTopEndcap && + otherFunctor->m_hasBottomEndcap == m_hasBottomEndcap && + otherFunctor->m_rings == m_rings && + otherFunctor->m_slices == m_slices && + otherFunctor->m_topRadius == m_topRadius && + otherFunctor->m_bottomRadius == m_bottomRadius && + otherFunctor->m_length == m_length); + return false; + } + + QT3D_FUNCTOR(ConeVertexDataFunctor) + +private: + bool m_hasTopEndcap; + bool m_hasBottomEndcap; + int m_rings; + int m_slices; + float m_topRadius; + float m_bottomRadius; + float m_length; +}; + +class ConeIndexDataFunctor : public QBufferDataGenerator +{ +public: + ConeIndexDataFunctor(bool hasTopEndcap, bool hasBottomEndcap, int rings, int slices, + float length) + : m_hasTopEndcap(hasTopEndcap) + , m_hasBottomEndcap(hasBottomEndcap) + , m_rings(rings) + , m_slices(slices) + , m_length(length) + { + } + + QByteArray operator ()() Q_DECL_OVERRIDE + { + int facesCount = 0; + + facesCount = (m_slices * 2) * m_rings // 2 x tris per side, for all rings + + m_slices * (m_hasTopEndcap + m_hasBottomEndcap); // endcaps + + const int indicesCount = facesCount * 3; + const int indexSize = sizeof(quint16); + Q_ASSERT(indicesCount < 65536); + + QByteArray indicesBytes; + indicesBytes.resize(indicesCount * indexSize); + quint16 *indicesPtr = reinterpret_cast<quint16*>(indicesBytes.data()); + + createSidesIndices(indicesPtr, m_rings, m_slices); + if ( m_hasTopEndcap ) + createDiscIndices(indicesPtr, m_rings * (m_slices + 1) + m_slices + 2, m_slices, true); + if ( m_hasBottomEndcap ) + createDiscIndices(indicesPtr, m_rings * (m_slices + 1), m_slices, false); + + return indicesBytes; + } + + bool operator ==(const QBufferDataGenerator &other) const Q_DECL_OVERRIDE + { + const ConeIndexDataFunctor *otherFunctor = functor_cast<ConeIndexDataFunctor>(&other); + if (otherFunctor != Q_NULLPTR) + return (otherFunctor->m_hasTopEndcap == m_hasTopEndcap && + otherFunctor->m_hasBottomEndcap == m_hasBottomEndcap && + otherFunctor->m_rings == m_rings && + otherFunctor->m_slices == m_slices && + otherFunctor->m_length == m_length); + return false; + } + + QT3D_FUNCTOR(ConeIndexDataFunctor) + +private: + bool m_hasTopEndcap; + bool m_hasBottomEndcap; + int m_rings; + int m_slices; + float m_length; +}; + + +QConeGeometryPrivate::QConeGeometryPrivate() + : QGeometryPrivate() + , m_hasTopEndcap(true) + , m_hasBottomEndcap(true) + , m_rings(16) + , m_slices(16) + , m_topRadius(0.0f) + , m_bottomRadius(1.0f) + , m_length(1.0f) + , m_positionAttribute(Q_NULLPTR) + , m_normalAttribute(Q_NULLPTR) + , m_texCoordAttribute(Q_NULLPTR) + , m_indexAttribute(Q_NULLPTR) + , m_vertexBuffer(Q_NULLPTR) + , m_indexBuffer(Q_NULLPTR) +{ +} + +void QConeGeometryPrivate::init() +{ + Q_Q(QConeGeometry); + m_positionAttribute = new QAttribute(q); + m_normalAttribute = new QAttribute(q); + m_texCoordAttribute = new QAttribute(q); + m_indexAttribute = new QAttribute(q); + m_vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, q); + m_indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, q); + + // vec3 pos, vec2 tex, vec3 normal + const quint32 elementSize = 3 + 2 + 3; + const quint32 stride = elementSize * sizeof(float); + const int faces = (m_slices + 1) * (m_rings + 1); + int nVerts = 0; + + nVerts = (m_slices * 2) * m_rings // Sides + + m_slices * (m_hasTopEndcap + m_hasBottomEndcap); // endcaps + + 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->setDataGenerator(QBufferDataGeneratorPtr(new ConeVertexDataFunctor(m_hasTopEndcap, m_hasBottomEndcap, m_rings, m_slices, + m_topRadius, m_bottomRadius, m_length))); + m_indexBuffer->setDataGenerator(QBufferDataGeneratorPtr(new ConeIndexDataFunctor(m_hasTopEndcap, m_hasBottomEndcap, m_rings, m_slices, + m_length))); + + q->addAttribute(m_positionAttribute); + q->addAttribute(m_texCoordAttribute); + q->addAttribute(m_normalAttribute); + q->addAttribute(m_indexAttribute); +} + +QConeGeometry::QConeGeometry(QNode *parent) + : QGeometry(*new QConeGeometryPrivate, parent) +{ + Q_D(QConeGeometry); + d->init(); +} + +QConeGeometry::QConeGeometry(QConeGeometryPrivate &dd, QNode *parent) + :QGeometry(dd, parent) +{ + Q_D(QConeGeometry); + d->init(); +} + +QConeGeometry::~QConeGeometry() +{ + QGeometry::cleanup(); +} + +void QConeGeometry::updateVertices() +{ + Q_D(QConeGeometry); + 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_vertexBuffer->setDataGenerator(QBufferDataGeneratorPtr(new ConeVertexDataFunctor(d->m_hasTopEndcap, d->m_hasBottomEndcap, d->m_rings, d->m_slices, + d->m_topRadius, d->m_bottomRadius, d->m_length))); +} + +void QConeGeometry::updateIndices() +{ + Q_D(QConeGeometry); + int faces = 0; + + faces = (d->m_slices * 2) * d->m_rings // 2 x tris per side, for all rings + + d->m_slices * (d->m_hasTopEndcap + d->m_hasBottomEndcap); // 2 x endcaps + + d->m_indexAttribute->setCount(faces * 3); + d->m_indexBuffer->setDataGenerator(QBufferDataGeneratorPtr(new ConeIndexDataFunctor(d->m_hasTopEndcap, d->m_hasBottomEndcap, d->m_rings, d->m_slices, + d->m_length))); +} + +void QConeGeometry::setHasTopEndcap(bool hasTopEndcap) +{ + Q_D(QConeGeometry); + if (hasTopEndcap != d->m_hasTopEndcap) { + d->m_hasTopEndcap = hasTopEndcap; + updateVertices(); + emit hasTopEndcapChanged(hasTopEndcap); + } +} + + +void QConeGeometry::setHasBottomEndcap(bool hasBottomEndcap) +{ + Q_D(QConeGeometry); + if (hasBottomEndcap != d->m_hasBottomEndcap) { + d->m_hasBottomEndcap = hasBottomEndcap; + updateVertices(); + emit hasBottomEndcapChanged(hasBottomEndcap); + } +} + +void QConeGeometry::setRings(int rings) +{ + Q_D(QConeGeometry); + if (rings != d->m_rings) { + d->m_rings = rings; + updateVertices(); + updateIndices(); + emit ringsChanged(rings); + } +} + +void QConeGeometry::setSlices(int slices) +{ + Q_D(QConeGeometry); + if (slices != d->m_slices) { + d->m_slices = slices; + updateVertices(); + updateIndices(); + emit slicesChanged(slices); + } +} + +void QConeGeometry::setTopRadius(float topRadius) +{ + Q_D(QConeGeometry); + if (topRadius != d->m_topRadius) { + d->m_topRadius = topRadius; + updateVertices(); + emit topRadiusChanged(topRadius); + } +} + +void QConeGeometry::setBottomRadius(float bottomRadius) +{ + Q_D(QConeGeometry); + if (bottomRadius != d->m_bottomRadius) { + d->m_bottomRadius = bottomRadius; + updateVertices(); + emit bottomRadiusChanged(bottomRadius); + } +} + +void QConeGeometry::setLength(float length) +{ + Q_D(QConeGeometry); + if (length != d->m_length) { + d->m_length = length; + updateVertices(); + updateIndices(); + emit lengthChanged(length); + } +} + +bool QConeGeometry::hasTopEndcap() const +{ + Q_D(const QConeGeometry); + return d->m_hasTopEndcap; +} + +bool QConeGeometry::hasBottomEndcap() const +{ + Q_D(const QConeGeometry); + return d->m_hasBottomEndcap; +} + +float QConeGeometry::topRadius() const +{ + Q_D(const QConeGeometry); + return d->m_topRadius; +} + +float QConeGeometry::bottomRadius() const +{ + Q_D(const QConeGeometry); + return d->m_bottomRadius; +} + +int QConeGeometry::rings() const +{ + Q_D(const QConeGeometry); + return d->m_rings; +} + +int QConeGeometry::slices() const +{ + Q_D(const QConeGeometry); + return d->m_slices; +} + +float QConeGeometry::length() const +{ + Q_D(const QConeGeometry); + return d->m_length; +} + +QAttribute *QConeGeometry::positionAttribute() const +{ + Q_D(const QConeGeometry); + return d->m_positionAttribute; +} + +QAttribute *QConeGeometry::normalAttribute() const +{ + Q_D(const QConeGeometry); + return d->m_normalAttribute; +} + +QAttribute *QConeGeometry::texCoordAttribute() const +{ + Q_D(const QConeGeometry); + return d->m_texCoordAttribute; +} + +QAttribute *QConeGeometry::indexAttribute() const +{ + Q_D(const QConeGeometry); + return d->m_indexAttribute; +} + +} // namespace Qt3DExtras + +QT_END_NAMESPACE diff --git a/src/extras/geometries/qconegeometry.h b/src/extras/geometries/qconegeometry.h new file mode 100644 index 000000000..4f1dc944a --- /dev/null +++ b/src/extras/geometries/qconegeometry.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QCONEGEOMETRY_H +#define QT3DEXTRAS_QCONEGEOMETRY_H + +#include <Qt3DExtras/qt3dextras_global.h> +#include <Qt3DRender/qgeometry.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { +class QAttribute; +} // Render + +namespace Qt3DExtras { + +class QConeGeometryPrivate; + +class QT3DEXTRASSHARED_EXPORT QConeGeometry : public Qt3DRender::QGeometry +{ + Q_OBJECT + Q_PROPERTY( bool hasTopEndcap READ hasTopEndcap WRITE setHasTopEndcap NOTIFY hasTopEndcapChanged ) + Q_PROPERTY( bool hasBottomEndcap READ hasBottomEndcap WRITE setHasBottomEndcap NOTIFY hasBottomEndcapChanged ) + Q_PROPERTY(int rings READ rings WRITE setRings NOTIFY ringsChanged) + Q_PROPERTY(int slices READ slices WRITE setSlices NOTIFY slicesChanged) + Q_PROPERTY( float topRadius READ topRadius WRITE setTopRadius NOTIFY topRadiusChanged ) + Q_PROPERTY( float bottomRadius READ bottomRadius WRITE setBottomRadius NOTIFY bottomRadiusChanged ) + Q_PROPERTY(float length READ length WRITE setLength NOTIFY lengthChanged) + Q_PROPERTY(Qt3DRender::QAttribute *positionAttribute READ positionAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *normalAttribute READ normalAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *texCoordAttribute READ texCoordAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *indexAttribute READ indexAttribute CONSTANT) + +public: + explicit QConeGeometry(QNode *parent = nullptr); + ~QConeGeometry(); + + void updateVertices(); + void updateIndices(); + + bool hasTopEndcap() const; + bool hasBottomEndcap() const; + float topRadius() const; + float bottomRadius() const; + int rings() const; + int slices() const; + float length() const; + + Qt3DRender::QAttribute *positionAttribute() const; + Qt3DRender::QAttribute *normalAttribute() const; + Qt3DRender::QAttribute *texCoordAttribute() const; + Qt3DRender::QAttribute *indexAttribute() const; + +public Q_SLOTS: + void setHasTopEndcap( bool hasTopEndcap ); + void setHasBottomEndcap( bool hasBottomEndcap ); + void setTopRadius( float topRadius ); + void setBottomRadius( float bottomRadius ); + void setRings( int rings ); + void setSlices( int slices ); + void setLength( float length ); + +Q_SIGNALS: + void hasTopEndcapChanged( bool hasTopEndcap ); + void hasBottomEndcapChanged( bool hasBottomEndcap ); + void topRadiusChanged( float topRadius ); + void bottomRadiusChanged( float bottomRadius ); + void ringsChanged( int rings ); + void slicesChanged( int slices ); + void lengthChanged( float length ); + +protected: + QConeGeometry(QConeGeometryPrivate &dd, QNode *parent = nullptr); + +private: + Q_DECLARE_PRIVATE(QConeGeometry) +}; + +} // namespace Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QCONEGEOMETRY_H diff --git a/src/extras/geometries/qconegeometry_p.h b/src/extras/geometries/qconegeometry_p.h new file mode 100644 index 000000000..3987b4315 --- /dev/null +++ b/src/extras/geometries/qconegeometry_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QCONEGEOMETRY_P_H +#define QT3DEXTRAS_QCONEGEOMETRY_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <Qt3DRender/private/qgeometry_p.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QAttribute; +class QBuffer; + +} // namespace Qt3DRender + +namespace Qt3DExtras { + +class QConeGeometryPrivate : public Qt3DRender::QGeometryPrivate +{ +public: + QConeGeometryPrivate(); + + void init(); + + Q_DECLARE_PUBLIC(QConeGeometry) + + bool m_hasTopEndcap; + bool m_hasBottomEndcap; + int m_rings; + int m_slices; + float m_topRadius; + float m_bottomRadius; + float m_length; + Qt3DRender::QAttribute *m_positionAttribute; + Qt3DRender::QAttribute *m_normalAttribute; + Qt3DRender::QAttribute *m_texCoordAttribute; + Qt3DRender::QAttribute *m_indexAttribute; + Qt3DRender::QBuffer *m_positionBuffer; + Qt3DRender::QBuffer *m_vertexBuffer; + Qt3DRender::QBuffer *m_indexBuffer; +}; + +} // Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QCONEGEOMETRY_P_H + diff --git a/src/extras/geometries/qconemesh.cpp b/src/extras/geometries/qconemesh.cpp new file mode 100644 index 000000000..621e06046 --- /dev/null +++ b/src/extras/geometries/qconemesh.cpp @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _USE_MATH_DEFINES +# define _USE_MATH_DEFINES // For MSVC +#endif + +#include "qconemesh.h" +#include "qconegeometry.h" +#include <Qt3DRender/qbuffer.h> +#include <Qt3DRender/qbufferdatagenerator.h> +#include <Qt3DRender/qattribute.h> +#include <qmath.h> +#include <QVector3D> + +QT_BEGIN_NAMESPACE + +namespace Qt3DExtras { + +QConeMesh::QConeMesh(QNode *parent) + : QGeometryRenderer(parent) +{ + QConeGeometry *geometry = new QConeGeometry(this); + QObject::connect(geometry, &QConeGeometry::hasTopEndcapChanged, this, &QConeMesh::hasTopEndcapChanged); + QObject::connect(geometry, &QConeGeometry::hasBottomEndcapChanged, this, &QConeMesh::hasBottomEndcapChanged); + QObject::connect(geometry, &QConeGeometry::topRadiusChanged, this, &QConeMesh::topRadiusChanged); + QObject::connect(geometry, &QConeGeometry::bottomRadiusChanged, this, &QConeMesh::bottomRadiusChanged); + QObject::connect(geometry, &QConeGeometry::ringsChanged, this, &QConeMesh::ringsChanged); + QObject::connect(geometry, &QConeGeometry::slicesChanged, this, &QConeMesh::slicesChanged); + QObject::connect(geometry, &QConeGeometry::lengthChanged, this, &QConeMesh::lengthChanged); + + QGeometryRenderer::setGeometry(geometry); +} + +QConeMesh::~QConeMesh() +{ + QNode::cleanup(); +} + +void QConeMesh::setHasTopEndcap(bool hasTopEndcap) +{ + static_cast<QConeGeometry *>(geometry())->setHasTopEndcap(hasTopEndcap); +} + +void QConeMesh::setHasBottomEndcap(bool hasBottomEndcap) +{ + static_cast<QConeGeometry *>(geometry())->setHasBottomEndcap(hasBottomEndcap); +} + +void QConeMesh::setTopRadius(float topRadius) +{ + static_cast<QConeGeometry *>(geometry())->setTopRadius(topRadius); +} + +void QConeMesh::setBottomRadius(float bottomRadius) +{ + static_cast<QConeGeometry *>(geometry())->setBottomRadius(bottomRadius); +} + +void QConeMesh::setRings(int rings) +{ + static_cast<QConeGeometry *>(geometry())->setRings(rings); +} + +void QConeMesh::setSlices(int slices) +{ + static_cast<QConeGeometry *>(geometry())->setSlices(slices); +} + +void QConeMesh::setLength(float length) +{ + static_cast<QConeGeometry *>(geometry())->setLength(length); +} + +bool QConeMesh::hasTopEndcap() const +{ + return static_cast<QConeGeometry *>(geometry())->hasTopEndcap(); +} + +bool QConeMesh::hasBottomEndcap() const +{ + return static_cast<QConeGeometry *>(geometry())->hasBottomEndcap(); +} + +float QConeMesh::topRadius() const +{ + return static_cast<QConeGeometry *>(geometry())->topRadius(); +} + +float QConeMesh::bottomRadius() const +{ + return static_cast<QConeGeometry *>(geometry())->bottomRadius(); +} + +int QConeMesh::rings() const +{ + return static_cast<QConeGeometry *>(geometry())->rings(); +} + +int QConeMesh::slices() const +{ + return static_cast<QConeGeometry *>(geometry())->slices(); +} + +float QConeMesh::length() const +{ + return static_cast<QConeGeometry *>(geometry())->length(); +} + +} // namespace Qt3DExtras + +QT_END_NAMESPACE diff --git a/src/extras/geometries/qconemesh.h b/src/extras/geometries/qconemesh.h new file mode 100644 index 000000000..c32070e5c --- /dev/null +++ b/src/extras/geometries/qconemesh.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QCONEMESH_H +#define QT3DEXTRAS_QCONEMESH_H + +#include <Qt3DExtras/qt3dextras_global.h> +#include <Qt3DRender/qgeometryrenderer.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DExtras { + +class QT3DEXTRASSHARED_EXPORT QConeMesh : public Qt3DRender::QGeometryRenderer +{ + Q_OBJECT + Q_PROPERTY(int rings READ rings WRITE setRings NOTIFY ringsChanged) + Q_PROPERTY(int slices READ slices WRITE setSlices NOTIFY slicesChanged) + Q_PROPERTY( bool hasTopEndcap READ hasTopEndcap WRITE setHasTopEndcap NOTIFY hasTopEndcapChanged ) + Q_PROPERTY( bool hasBottomEndcap READ hasBottomEndcap WRITE setHasBottomEndcap NOTIFY hasBottomEndcapChanged ) + Q_PROPERTY( float topRadius READ topRadius WRITE setTopRadius NOTIFY topRadiusChanged ) + Q_PROPERTY( float bottomRadius READ bottomRadius WRITE setBottomRadius NOTIFY bottomRadiusChanged ) + Q_PROPERTY(float length READ length WRITE setLength NOTIFY lengthChanged) +public: + explicit QConeMesh(Qt3DCore::QNode *parent = nullptr); + ~QConeMesh(); + + int rings() const; + int slices() const; + bool hasTopEndcap() const; + bool hasBottomEndcap() const; + float topRadius() const; + float bottomRadius() const; + float length() const; + +public Q_SLOTS: + void setHasTopEndcap( bool hasTopEndcap ); + void setHasBottomEndcap( bool hasBottomEndcap ); + void setTopRadius( float topRadius ); + void setBottomRadius( float bottomRadius ); + void setRings( int rings ); + void setSlices( int slices ); + void setLength( float length ); + +Q_SIGNALS: + void hasTopEndcapChanged( bool hasTopEndcap ); + void hasBottomEndcapChanged( bool hasBottomEndcap ); + void topRadiusChanged( float topRadius ); + void bottomRadiusChanged( float bottomRadius ); + void ringsChanged( int rings ); + void slicesChanged( int slices ); + void lengthChanged( float length ); + +private: + // As this is a default provided geometry renderer, no one should be able + // to modify the QGeometryRenderer's properties + + void setInstanceCount(int instanceCount); + void setVertexCount(int vertexCount); + void setIndexOffset(int indexOffset); + void setFirstInstance(int firstInstance); + void setRestartIndexValue(int index); + void setPrimitiveRestartEnabled(bool enabled); + void setGeometry(Qt3DRender::QGeometry *geometry); + void setPrimitiveType(PrimitiveType primitiveType); +}; + +} // namespace Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QCONEMESH_H diff --git a/src/extras/geometries/qcuboidgeometry.cpp b/src/extras/geometries/qcuboidgeometry.cpp new file mode 100644 index 000000000..b62ae0022 --- /dev/null +++ b/src/extras/geometries/qcuboidgeometry.cpp @@ -0,0 +1,827 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcuboidgeometry.h" +#include "qcuboidgeometry_p.h" +#include <Qt3DRender/qattribute.h> +#include <Qt3DRender/qbuffer.h> +#include <Qt3DRender/qbufferdatagenerator.h> +#include <Qt3DRender/private/renderlogging_p.h> +#include <limits> + +QT_BEGIN_NAMESPACE + +using namespace Qt3DRender; + +namespace Qt3DExtras { + +namespace { + +enum PlaneNormal { + PositiveX, + NegativeX, + PositiveY, + NegativeY, + PositiveZ, + NegativeZ +}; + +void createPlaneVertexData(float w, float h, const QSize &resolution, + PlaneNormal normal, float planeDistance, + float *vertices) +{ + const float a0 = -w / 2.0f; + const float b0 = -h / 2.0f; + const float da = w / (resolution.width() - 1); + const float db = h / (resolution.height() - 1); + const float du = 1.0 / (resolution.width() - 1); + const float dv = 1.0 / (resolution.height() - 1); + float n = 1.0f; + + switch (normal) { + case NegativeX: + n = -1.0f; // fall through + case PositiveX: { + // Iterate over z + for (int j = 0; j < resolution.height(); ++j) { + const float b = b0 + static_cast<float>(j) * db; + const float v = static_cast<float>(j) * dv; + + // Iterate over y + for (int i = 0; i < resolution.width(); ++i) { + const float a = a0 + static_cast<float>(i) * da; + const float u = static_cast<float>(i) * du; + + // position + *vertices++ = planeDistance; + *vertices++ = a; + *vertices++ = b; + + // texture coordinates + *vertices++ = u; + *vertices++ = v; + + // normal + *vertices++ = n; + *vertices++ = 0.0f; + *vertices++ = 0.0f; + + // tangent + *vertices++ = 0.0f; + *vertices++ = 0.0f; + *vertices++ = 1.0f; + *vertices++ = 1.0f; + } + } + break; + } + + case NegativeY: + n = -1.0f; + case PositiveY: { + // Iterate over z + for (int j = 0; j < resolution.height(); ++j) { + const float b = b0 + static_cast<float>(j) * db; + const float v = static_cast<float>(j) * dv; + + // Iterate over x + // This iterates in the opposite sense to the other directions + // so that the winding order is correct + for (int i = resolution.width() - 1; i >= 0; --i) { + const float a = a0 + static_cast<float>(i) * da; + const float u = static_cast<float>(i) * du; + + // position + *vertices++ = a; + *vertices++ = planeDistance; + *vertices++ = b; + + // texture coordinates + *vertices++ = u; + *vertices++ = v; + + // normal + *vertices++ = 0.0f; + *vertices++ = n; + *vertices++ = 0.0f; + + // tangent + *vertices++ = 1.0f; + *vertices++ = 0.0f; + *vertices++ = 0.0f; + *vertices++ = 1.0f; + } + } + break; + } + + case NegativeZ: + n = -1.0f; + case PositiveZ: { + // Iterate over y + for (int j = 0; j < resolution.height(); ++j) { + const float b = b0 + static_cast<float>(j) * db; + const float v = static_cast<float>(j) * dv; + + // Iterate over x + for (int i = 0; i < resolution.width(); ++i) { + const float a = a0 + static_cast<float>(i) * da; + const float u = static_cast<float>(i) * du; + + // position + *vertices++ = a; + *vertices++ = b; + *vertices++ = planeDistance; + + // texture coordinates + *vertices++ = u; + *vertices++ = v; + + // normal + *vertices++ = 0.0f; + *vertices++ = 0.0f; + *vertices++ = n; + + // tangent + *vertices++ = 1.0f; + *vertices++ = 0.0f; + *vertices++ = 0.0f; + *vertices++ = 1.0f; + } + } + break; + } + } // switch (normal) +} + +void createPlaneIndexData(PlaneNormal normal, const QSize &resolution, quint16 *indices, quint16 &baseVertex) +{ + float n = 1.0f; + + switch (normal) { + case NegativeX: + case NegativeY: + case NegativeZ: + n = -1.0f; + break; + default: + break; + } + + // Populate indices taking care to get correct CCW winding on all faces + if (n > 0.0f) { + for (int j = 0; j < resolution.height() - 1; ++j) { + const int rowStartIndex = j * resolution.width() + baseVertex; + const int nextRowStartIndex = (j + 1) * resolution.width() + baseVertex; + + // Iterate over x + for (int i = 0; i < resolution.width() - 1; ++i) { + // Split quad into two triangles + *indices++ = rowStartIndex + i; + *indices++ = rowStartIndex + i + 1; + *indices++ = nextRowStartIndex + i; + + *indices++ = nextRowStartIndex + i; + *indices++ = rowStartIndex + i + 1; + *indices++ = nextRowStartIndex + i + 1; + } + } + } else { + for (int j = 0; j < resolution.height() - 1; ++j) { + const int rowStartIndex = j * resolution.width() + baseVertex; + const int nextRowStartIndex = (j + 1) * resolution.width() + baseVertex; + + // Iterate over x + for (int i = 0; i < resolution.width() - 1; ++i) { + // Split quad into two triangles + *indices++ = rowStartIndex + i; + *indices++ = nextRowStartIndex + i; + *indices++ = rowStartIndex + i + 1; + + *indices++ = nextRowStartIndex + i; + *indices++ = nextRowStartIndex + i + 1; + *indices++ = rowStartIndex + i + 1; + } + } + } + baseVertex += resolution.width() * resolution.height(); +} + +QByteArray createCuboidVertexData(float xExtent, + float yExtent, + float zExtent, + const QSize &yzResolution, + const QSize &xzResolution, + const QSize &xyResolution) +{ + Q_ASSERT(xExtent > 0.0f && yExtent > 0.0f && zExtent > 0.0); + Q_ASSERT(yzResolution.width() >= 2 && yzResolution.height() >=2); + Q_ASSERT(xzResolution.width() >= 2 && xzResolution.height() >=2); + Q_ASSERT(xyResolution.width() >= 2 && xyResolution.height() >=2); + + const int yzVerts = yzResolution.width() * yzResolution.height(); + const int xzVerts = xzResolution.width() * xzResolution.height(); + const int xyVerts = xyResolution.width() * xyResolution.height(); + const int nVerts = 2 * (yzVerts + xzVerts + xyVerts); + + const quint32 elementSize = 3 + 3 + 2 + 4; + const quint32 stride = elementSize * sizeof(float); + QByteArray vertexBytes; + vertexBytes.resize(stride * nVerts); + float* vertices = reinterpret_cast<float*>(vertexBytes.data()); + + createPlaneVertexData(yExtent, zExtent, yzResolution, PositiveX, xExtent * 0.5f, vertices); + vertices += yzVerts * elementSize; + createPlaneVertexData(yExtent, zExtent, yzResolution, NegativeX, -xExtent * 0.5f, vertices); + vertices += yzVerts * elementSize; + createPlaneVertexData(xExtent, zExtent, xzResolution, PositiveY, yExtent * 0.5f, vertices); + vertices += xzVerts * elementSize; + createPlaneVertexData(xExtent, zExtent, xzResolution, NegativeY, -yExtent * 0.5f, vertices); + vertices += xzVerts * elementSize; + createPlaneVertexData(xExtent, yExtent, xyResolution, PositiveZ, zExtent * 0.5f, vertices); + vertices += xyVerts * elementSize; + createPlaneVertexData(xExtent, yExtent, xyResolution, NegativeZ, -zExtent * 0.5f, vertices); + + return vertexBytes; +} + +QByteArray createCuboidIndexData(const QSize &yzResolution, + const QSize &xzResolution, + const QSize &xyResolution) +{ + Q_ASSERT(yzResolution.width() >= 2 && yzResolution.height() >= 2); + Q_ASSERT(xzResolution.width() >= 2 && xzResolution.height() >= 2); + Q_ASSERT(xyResolution.width() >= 2 && xyResolution.height() >= 2); + + const int yzIndices = 2 * 3 * (yzResolution.width() - 1) * (yzResolution.height() - 1); + const int xzIndices = 2 * 3 * (xzResolution.width() - 1) * (xzResolution.height() - 1); + const int xyIndices = 2 * 3 * (xyResolution.width() - 1) * (xyResolution.height() - 1); + const int indexCount = 2 * (yzIndices + xzIndices + xyIndices); + + QByteArray indexData; + indexData.resize(indexCount * sizeof(quint16)); + quint16 *indices = reinterpret_cast<quint16 *>(indexData.data()); + quint16 baseIndex = 0; + + createPlaneIndexData(PositiveX, yzResolution, indices, baseIndex); + indices += yzIndices; + createPlaneIndexData(NegativeX, yzResolution, indices, baseIndex); + indices += yzIndices; + createPlaneIndexData(PositiveY, xzResolution, indices, baseIndex); + indices += xzIndices; + createPlaneIndexData(NegativeY, xzResolution, indices, baseIndex); + indices += xzIndices; + createPlaneIndexData(PositiveZ, xyResolution, indices, baseIndex); + indices += xyIndices; + createPlaneIndexData(NegativeZ, xyResolution, indices, baseIndex); + + return indexData; +} + +} // anonymous + +class CuboidVertexBufferFunctor : public QBufferDataGenerator +{ +public: + explicit CuboidVertexBufferFunctor(float xExtent, + float yExtent, + float zExtent, + const QSize &yzResolution, + const QSize &xzResolution, + const QSize &xyResolution) + : m_xExtent(xExtent) + , m_yExtent(yExtent) + , m_zExtent(zExtent) + , m_yzFaceResolution(yzResolution) + , m_xzFaceResolution(xzResolution) + , m_xyFaceResolution(xyResolution) + {} + + ~CuboidVertexBufferFunctor() {} + + QByteArray operator()() Q_DECL_FINAL + { + return createCuboidVertexData(m_xExtent, m_yExtent, m_zExtent, + m_yzFaceResolution, m_xzFaceResolution, m_xyFaceResolution); + } + + bool operator ==(const QBufferDataGenerator &other) const Q_DECL_FINAL + { + const CuboidVertexBufferFunctor *otherFunctor = functor_cast<CuboidVertexBufferFunctor>(&other); + if (otherFunctor != Q_NULLPTR) + return (otherFunctor->m_xExtent == m_xExtent && + otherFunctor->m_yExtent == m_yExtent && + otherFunctor->m_zExtent == m_zExtent && + otherFunctor->m_yzFaceResolution == m_yzFaceResolution && + otherFunctor->m_xzFaceResolution == m_xzFaceResolution && + otherFunctor->m_xyFaceResolution == m_xyFaceResolution); + return false; + } + + QT3D_FUNCTOR(CuboidVertexBufferFunctor) + +private: + float m_xExtent; + float m_yExtent; + float m_zExtent; + QSize m_yzFaceResolution; + QSize m_xzFaceResolution; + QSize m_xyFaceResolution; +}; + +class CuboidIndexBufferFunctor : public QBufferDataGenerator +{ +public: + explicit CuboidIndexBufferFunctor(const QSize &yzResolution, + const QSize &xzResolution, + const QSize &xyResolution) + : m_yzFaceResolution(yzResolution) + , m_xzFaceResolution(xzResolution) + , m_xyFaceResolution(xyResolution) + {} + + ~CuboidIndexBufferFunctor() {} + + QByteArray operator()() Q_DECL_FINAL + { + return createCuboidIndexData(m_yzFaceResolution, m_xzFaceResolution, m_xyFaceResolution); + } + + bool operator ==(const QBufferDataGenerator &other) const Q_DECL_FINAL + { + const CuboidIndexBufferFunctor *otherFunctor = functor_cast<CuboidIndexBufferFunctor>(&other); + if (otherFunctor != Q_NULLPTR) + return (otherFunctor->m_yzFaceResolution == m_yzFaceResolution && + otherFunctor->m_xzFaceResolution == m_xzFaceResolution && + otherFunctor->m_xyFaceResolution == m_xyFaceResolution); + return false; + } + + QT3D_FUNCTOR(CuboidIndexBufferFunctor) + +private: + QSize m_yzFaceResolution; + QSize m_xzFaceResolution; + QSize m_xyFaceResolution; +}; + +QCuboidGeometryPrivate::QCuboidGeometryPrivate() + : QGeometryPrivate() + , m_xExtent(1.0f) + , m_yExtent(1.0f) + , m_zExtent(1.0f) + , m_yzFaceResolution(2, 2) + , m_xzFaceResolution(2, 2) + , m_xyFaceResolution(2, 2) + , 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 QCuboidGeometryPrivate::init() +{ + Q_Q(QCuboidGeometry); + m_positionAttribute = new Qt3DRender::QAttribute(q); + m_normalAttribute = new Qt3DRender::QAttribute(q); + m_texCoordAttribute = new Qt3DRender::QAttribute(q); + m_tangentAttribute = new Qt3DRender::QAttribute(q); + m_indexAttribute = new Qt3DRender::QAttribute(q); + m_vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, q); + m_indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, q); + + // vec3 pos vec2 tex vec3 normal vec4 tangent + const quint32 stride = (3 + 2 + 3 + 4) * sizeof(float); + const int yzIndices = 2 * 3 * (m_yzFaceResolution.width() - 1) * (m_yzFaceResolution.height() - 1); + const int xzIndices = 2 * 3 * (m_xzFaceResolution.width() - 1) * (m_xzFaceResolution.height() - 1); + const int xyIndices = 2 * 3 * (m_xyFaceResolution.width() - 1) * (m_xyFaceResolution.height() - 1); + const int yzVerts = m_yzFaceResolution.width() * m_yzFaceResolution.height(); + const int xzVerts = m_xzFaceResolution.width() * m_xzFaceResolution.height(); + const int xyVerts = m_xyFaceResolution.width() * m_xyFaceResolution.height(); + + const int nVerts = 2 * (yzVerts + xzVerts + xyVerts); + const int indexCount = 2 * (yzIndices + xzIndices + xyIndices); + + 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(indexCount); + + m_vertexBuffer->setDataGenerator(QBufferDataGeneratorPtr(new CuboidVertexBufferFunctor(m_xExtent, m_yExtent, m_zExtent, + m_yzFaceResolution, m_xzFaceResolution, m_xyFaceResolution))); + m_indexBuffer->setDataGenerator(QBufferDataGeneratorPtr(new CuboidIndexBufferFunctor(m_yzFaceResolution, m_xzFaceResolution, m_xyFaceResolution))); + + q->addAttribute(m_positionAttribute); + q->addAttribute(m_texCoordAttribute); + q->addAttribute(m_normalAttribute); + q->addAttribute(m_tangentAttribute); + q->addAttribute(m_indexAttribute); +} + +/*! + * \qmltype CuboidGeometry + * \instantiates Qt3DRender::QCuboidGeometry + * \inqmlmodule Qt3D.Render + */ + +/*! + * \qmlproperty float CuboidGeometry::xExtent + * + * Holds the x extent. + */ + +/*! + * \qmlproperty float CuboidGeometry::yExtent + * + * Holds the y extent. + */ + +/*! + * \qmlproperty float CuboidGeometry::zExtent + * + * Holds the z extent. + */ + +/*! + * \qmlproperty size CuboidGeometry::yzMeshResolution + * + * Holds the y-z resolution. + */ + +/*! + * \qmlproperty size CuboidGeometry::xzMeshResolution + * + * Holds the x-z resolution. + */ + +/*! + * \qmlproperty size CuboidGeometry::xyMeshResolution + * + * Holds the x-y resolution. + */ + +/*! + * \qmlproperty Attribute CuboidGeometry::positionAttribute + * + * Holds the geometry position attribute. + */ + +/*! + * \qmlproperty Attribute CuboidGeometry::normalAttribute + * + * Holds the geometry normal attribute. + */ + +/*! + * \qmlproperty Attribute CuboidGeometry::texCoordAttribute + * + * Holds the geometry texture coordinate attribute. + */ + +/*! + * \qmlproperty Attribute CuboidGeometry::tangentAttribute + * + * Holds the geometry tangent attribute. + */ + +/*! + * \qmlproperty Attribute CuboidGeometry::indexAttribute + * + * Holds the geometry index attribute. + */ + +/*! + * \class Qt3DRender::QCuboidGeometry + * \inmodule Qt3DRender + * + * \inherits Qt3DRender::QGeometry + * + */ + +/*! + * Constructs a new QCuboidGeometry with \a parent. + */ +QCuboidGeometry::QCuboidGeometry(QNode *parent) + : QGeometry(*new QCuboidGeometryPrivate(), parent) +{ + Q_D(QCuboidGeometry); + d->init(); +} + +/*! + * \internal + */ +QCuboidGeometry::QCuboidGeometry(QCuboidGeometryPrivate &dd, QNode *parent) + : QGeometry(dd, parent) +{ + Q_D(QCuboidGeometry); + d->init(); +} + +/*! + * Destroys this geometry. + */ +QCuboidGeometry::~QCuboidGeometry() +{ + QGeometry::cleanup(); +} + +/*! + * Updates indices based on mesh resolutions. + */ +void QCuboidGeometry::updateIndices() +{ + Q_D(QCuboidGeometry); + const int yzIndices = 2 * 3 * (d->m_yzFaceResolution.width() - 1) * (d->m_yzFaceResolution.height() - 1); + const int xzIndices = 2 * 3 * (d->m_xzFaceResolution.width() - 1) * (d->m_xzFaceResolution.height() - 1); + const int xyIndices = 2 * 3 * (d->m_xyFaceResolution.width() - 1) * (d->m_xyFaceResolution.height() - 1); + const int indexCount = 2 * (yzIndices + xzIndices + xyIndices); + + d->m_indexAttribute->setCount(indexCount); + d->m_indexBuffer->setDataGenerator(QBufferDataGeneratorPtr(new CuboidIndexBufferFunctor(d->m_yzFaceResolution, d->m_xzFaceResolution, d->m_xyFaceResolution))); + +} + +/*! + * Updates vertices based on mesh resolutions. + */ +void QCuboidGeometry::updateVertices() +{ + Q_D(QCuboidGeometry); + const int yzVerts = d->m_yzFaceResolution.width() * d->m_yzFaceResolution.height(); + const int xzVerts = d->m_xzFaceResolution.width() * d->m_xzFaceResolution.height(); + const int xyVerts = d->m_xyFaceResolution.width() * d->m_xyFaceResolution.height(); + const int nVerts = 2 * (yzVerts + xzVerts + xyVerts); + + d->m_positionAttribute->setCount(nVerts); + d->m_normalAttribute->setCount(nVerts); + d->m_texCoordAttribute->setCount(nVerts); + d->m_tangentAttribute->setCount(nVerts); + + d->m_vertexBuffer->setDataGenerator(QBufferDataGeneratorPtr(new CuboidVertexBufferFunctor(d->m_xExtent, d->m_yExtent, d->m_zExtent, + d->m_yzFaceResolution, d->m_xzFaceResolution, d->m_xyFaceResolution))); +} + +void QCuboidGeometry::setXExtent(float xExtent) +{ + Q_D(QCuboidGeometry); + if (d->m_xExtent != xExtent) { + d->m_xExtent = xExtent; + updateVertices(); + emit xExtentChanged(xExtent); + } +} + +void QCuboidGeometry::setYExtent(float yExtent) +{ + Q_D(QCuboidGeometry); + if (d->m_yExtent != yExtent) { + d->m_yExtent = yExtent; + updateVertices(); + emit yExtentChanged(yExtent); + } +} + +void QCuboidGeometry::setZExtent(float zExtent) +{ + Q_D(QCuboidGeometry); + if (d->m_zExtent != zExtent) { + d->m_zExtent = zExtent; + updateVertices(); + emit zExtentChanged(zExtent); + } +} + +void QCuboidGeometry::setYZMeshResolution(const QSize &resolution) +{ + Q_D(QCuboidGeometry); + if (d->m_yzFaceResolution != resolution) { + d->m_yzFaceResolution = resolution; + updateVertices(); + updateIndices(); + emit yzMeshResolutionChanged(resolution); + } +} + +void QCuboidGeometry::setXZMeshResolution(const QSize &resolution) +{ + Q_D(QCuboidGeometry); + if (d->m_xzFaceResolution != resolution) { + d->m_xzFaceResolution = resolution; + updateVertices(); + updateIndices(); + emit xzMeshResolutionChanged(resolution); + } +} + +void QCuboidGeometry::setXYMeshResolution(const QSize &resolution) +{ + Q_D(QCuboidGeometry); + if (d->m_xyFaceResolution != resolution) { + d->m_xyFaceResolution = resolution; + updateVertices(); + updateIndices(); + emit xyMeshResolutionChanged(resolution); + } +} + +/*! + * \property QCuboidGeometry::xExtent + * + * Holds the x extent. + */ +float QCuboidGeometry::xExtent() const +{ + Q_D(const QCuboidGeometry); + return d->m_xExtent; +} + +/*! + * \property QCuboidGeometry::yExtent + * + * Holds the y extent. + */ +float QCuboidGeometry::yExtent() const +{ + Q_D(const QCuboidGeometry); + return d->m_yExtent; +} + +/*! + * \property QCuboidGeometry::zExtent + * + * Holds the z extent. + */ +float QCuboidGeometry::zExtent() const +{ + Q_D(const QCuboidGeometry); + return d->m_zExtent; +} + +/*! + * \property QCuboidGeometry::yzMeshResolution + * + * Holds the y-z resolution. + */ +QSize QCuboidGeometry::yzMeshResolution() const +{ + Q_D(const QCuboidGeometry); + return d->m_yzFaceResolution; +} + +/*! + * \property QCuboidGeometry::xzMeshResolution + * + * Holds the x-z resolution. + */ +QSize QCuboidGeometry::xyMeshResolution() const +{ + Q_D(const QCuboidGeometry); + return d->m_xyFaceResolution; +} + +/*! + * \property QCuboidGeometry::xyMeshResolution + * + * Holds the x-y resolution. + */ +QSize QCuboidGeometry::xzMeshResolution() const +{ + Q_D(const QCuboidGeometry); + return d->m_xzFaceResolution; +} + +/*! + * \property QCuboidGeometry::positionAttribute + * + * Holds the geometry position attribute. + */ +QAttribute *QCuboidGeometry::positionAttribute() const +{ + Q_D(const QCuboidGeometry); + return d->m_positionAttribute; +} + +/*! + * \property QCuboidGeometry::normalAttribute + * + * Holds the geometry normal attribute. + */ +QAttribute *QCuboidGeometry::normalAttribute() const +{ + Q_D(const QCuboidGeometry); + return d->m_normalAttribute; +} + +/*! + * \property QCuboidGeometry::texCoordAttribute + * + * Holds the geometry texture coordinate attribute. + */ +QAttribute *QCuboidGeometry::texCoordAttribute() const +{ + Q_D(const QCuboidGeometry); + return d->m_texCoordAttribute; +} + +/*! + * \property QCuboidGeometry::tangentAttribute + * + * Holds the geometry tangent attribute. + */ +QAttribute *QCuboidGeometry::tangentAttribute() const +{ + Q_D(const QCuboidGeometry); + return d->m_tangentAttribute; +} + +/*! + * \property QCuboidGeometry::indexAttribute + * + * Holds the geometry index attribute. + */ +QAttribute *QCuboidGeometry::indexAttribute() const +{ + Q_D(const QCuboidGeometry); + return d->m_indexAttribute; +} + +} // Qt3DExtras + +QT_END_NAMESPACE diff --git a/src/extras/geometries/qcuboidgeometry.h b/src/extras/geometries/qcuboidgeometry.h new file mode 100644 index 000000000..7fa5f58ff --- /dev/null +++ b/src/extras/geometries/qcuboidgeometry.h @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QCUBOIDGEOMETRY_H +#define QT3DEXTRAS_QCUBOIDGEOMETRY_H + +#include <Qt3DExtras/qt3dextras_global.h> +#include <Qt3DRender/qgeometry.h> +#include <QSize> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QAttribute; + +} // Qt3DRender + +namespace Qt3DExtras { + +class QCuboidGeometryPrivate; + +class QT3DEXTRASSHARED_EXPORT QCuboidGeometry : public Qt3DRender::QGeometry +{ + Q_OBJECT + Q_PROPERTY(float xExtent READ xExtent WRITE setXExtent NOTIFY xExtentChanged) + Q_PROPERTY(float yExtent READ yExtent WRITE setYExtent NOTIFY yExtentChanged) + Q_PROPERTY(float zExtent READ zExtent WRITE setZExtent NOTIFY zExtentChanged) + Q_PROPERTY(QSize xyMeshResolution READ xyMeshResolution WRITE setXYMeshResolution NOTIFY xyMeshResolutionChanged) + Q_PROPERTY(QSize yzMeshResolution READ yzMeshResolution WRITE setYZMeshResolution NOTIFY yzMeshResolutionChanged) + Q_PROPERTY(QSize xzMeshResolution READ xzMeshResolution WRITE setXZMeshResolution NOTIFY xzMeshResolutionChanged) + Q_PROPERTY(Qt3DRender::QAttribute *positionAttribute READ positionAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *normalAttribute READ normalAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *texCoordAttribute READ texCoordAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *tangentAttribute READ tangentAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *indexAttribute READ indexAttribute CONSTANT) + +public: + explicit QCuboidGeometry(QNode *parent = Q_NULLPTR); + ~QCuboidGeometry(); + + void updateIndices(); + void updateVertices(); + + float xExtent() const; + float yExtent() const; + float zExtent() const; + QSize yzMeshResolution() const; + QSize xyMeshResolution() const; + QSize xzMeshResolution() const; + + Qt3DRender::QAttribute *positionAttribute() const; + Qt3DRender::QAttribute *normalAttribute() const; + Qt3DRender::QAttribute *texCoordAttribute() const; + Qt3DRender::QAttribute *tangentAttribute() const; + Qt3DRender::QAttribute *indexAttribute() const; + +public Q_SLOTS: + void setXExtent(float xExtent); + void setYExtent(float yExtent); + void setZExtent(float zExtent); + void setYZMeshResolution(const QSize &resolution); + void setXZMeshResolution(const QSize &resolution); + void setXYMeshResolution(const QSize &resolution); + +Q_SIGNALS: + void xExtentChanged(float xExtent); + void yExtentChanged(float yExtent); + void zExtentChanged(float zExtent); + + void yzMeshResolutionChanged(const QSize &yzMeshResolution); + void xzMeshResolutionChanged(const QSize &xzMeshResolution); + void xyMeshResolutionChanged(const QSize &xyMeshResolution); + +protected: + QCuboidGeometry(QCuboidGeometryPrivate &dd, QNode *parent = Q_NULLPTR); + +private: + Q_DECLARE_PRIVATE(QCuboidGeometry) +}; + +} // Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QCUBOIDGEOMETRY_H diff --git a/src/extras/geometries/qcuboidgeometry_p.h b/src/extras/geometries/qcuboidgeometry_p.h new file mode 100644 index 000000000..212be19b4 --- /dev/null +++ b/src/extras/geometries/qcuboidgeometry_p.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QCUBOIDGEOMETRY_P_H +#define QT3DEXTRAS_QCUBOIDGEOMETRY_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 <Qt3DRender/private/qgeometry_p.h> +#include <QSize> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QAttribute; +class QBuffer; + +} // Qt3DRender + +namespace Qt3DExtras { + +class QCuboidGeometryPrivate : public Qt3DRender::QGeometryPrivate +{ +public: + QCuboidGeometryPrivate(); + void init(); + + // Dimensions + float m_xExtent; + float m_yExtent; + float m_zExtent; + + // Resolutions of faces with normal x, y, and z + QSize m_yzFaceResolution; + QSize m_xzFaceResolution; + QSize m_xyFaceResolution; + + Qt3DRender::QAttribute *m_positionAttribute; + Qt3DRender::QAttribute *m_normalAttribute; + Qt3DRender::QAttribute *m_texCoordAttribute; + Qt3DRender::QAttribute *m_tangentAttribute; + Qt3DRender::QAttribute *m_indexAttribute; + Qt3DRender::QBuffer *m_vertexBuffer; + Qt3DRender::QBuffer *m_indexBuffer; + + Q_DECLARE_PUBLIC(QCuboidGeometry) +}; + +} // Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QCUBOIDGEOMETRY_P_H + diff --git a/src/extras/geometries/qcuboidmesh.cpp b/src/extras/geometries/qcuboidmesh.cpp new file mode 100644 index 000000000..99cfa4733 --- /dev/null +++ b/src/extras/geometries/qcuboidmesh.cpp @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcuboidmesh.h" +#include "qcuboidgeometry.h" + +QT_BEGIN_NAMESPACE + +namespace Qt3DExtras { + +/*! + * \qmltype QCuboidMesh + * \instantiates Qt3DRender::QCuboidMesh + * \inqmlmodule Qt3D.Render + * \brief A cube mesh. + */ + +/*! + * \qmlproperty float CuboidMesh::xExtent + * + * Holds the x extent. + */ + +/*! + * \qmlproperty float CuboidMesh::yExtent + * + * Holds the y extent. + */ + +/*! + * \qmlproperty float CuboidMesh::zExtent + * + * Holds the z extent. + */ + +/*! + * \qmlproperty size CuboidMesh::yzMeshResolution + * + * Holds the y-z resolution. + */ + +/*! + * \qmlproperty size CuboidMesh::xzMeshResolution + * + * Holds the x-z resolution. + */ + +/*! + * \qmlproperty size CuboidMesh::xyMeshResolution + * + * Holds the x-y resolution. + */ + +/*! + * \class Qt3DRender::QCuboidMesh + * \inmodule Qt3DRender + * + * \inherits Qt3DRender::QGeometryRenderer + * + * \brief A cube mesh. + */ + +/*! + * Constructs a new QCuboidMedh with \a parent. + */ +QCuboidMesh::QCuboidMesh(QNode *parent) + : QGeometryRenderer(parent) +{ + QCuboidGeometry *geometry = new QCuboidGeometry(this); + QObject::connect(geometry, &QCuboidGeometry::xExtentChanged, this, &QCuboidMesh::xExtentChanged); + QObject::connect(geometry, &QCuboidGeometry::yExtentChanged, this, &QCuboidMesh::yExtentChanged); + QObject::connect(geometry, &QCuboidGeometry::zExtentChanged, this, &QCuboidMesh::zExtentChanged); + QObject::connect(geometry, &QCuboidGeometry::xyMeshResolutionChanged, this, &QCuboidMesh::xyMeshResolutionChanged); + QObject::connect(geometry, &QCuboidGeometry::xzMeshResolutionChanged, this, &QCuboidMesh::xzMeshResolutionChanged); + QObject::connect(geometry, &QCuboidGeometry::yzMeshResolutionChanged, this, &QCuboidMesh::yzMeshResolutionChanged); + QGeometryRenderer::setGeometry(geometry); +} + +/*! + * Destroys this cube mesh. + */ +QCuboidMesh::~QCuboidMesh() +{ + QNode::cleanup(); +} + +void QCuboidMesh::setXExtent(float xExtent) +{ + static_cast<QCuboidGeometry *>(geometry())->setXExtent(xExtent); +} + +/*! + * \property QCuboidMesh::xExtent + * + * Holds the x extent. + */ +float QCuboidMesh::xExtent() const +{ + return static_cast<QCuboidGeometry *>(geometry())->xExtent(); +} + +void QCuboidMesh::setYExtent(float yExtent) +{ + static_cast<QCuboidGeometry *>(geometry())->setYExtent(yExtent); +} + +/*! + * \property QCuboidMesh::yExtent + * + * Holds the y extent. + */ +float QCuboidMesh::yExtent() const +{ + return static_cast<QCuboidGeometry *>(geometry())->yExtent(); +} + +void QCuboidMesh::setZExtent(float zExtent) +{ + static_cast<QCuboidGeometry *>(geometry())->setZExtent(zExtent); +} + +/*! + * \property QCuboidMesh::zExtent + * + * Holds the z extent. + */ +float QCuboidMesh::zExtent() const +{ + return static_cast<QCuboidGeometry *>(geometry())->zExtent(); +} + +void QCuboidMesh::setYZMeshResolution(const QSize &resolution) +{ + static_cast<QCuboidGeometry *>(geometry())->setYZMeshResolution(resolution); +} + +/*! + * \property QCuboidMesh::yzMeshResolution + * + * Holds the y-z resolution. + */ +QSize QCuboidMesh::yzMeshResolution() const +{ + return static_cast<QCuboidGeometry *>(geometry())->yzMeshResolution(); +} + +void QCuboidMesh::setXZMeshResolution(const QSize &resolution) +{ + static_cast<QCuboidGeometry *>(geometry())->setXZMeshResolution(resolution); +} + +/*! + * \property QCuboidMesh::xzMeshResolution + * + * Holds the x-z resolution. + */ +QSize QCuboidMesh::xzMeshResolution() const +{ + return static_cast<QCuboidGeometry *>(geometry())->xzMeshResolution(); +} + +void QCuboidMesh::setXYMeshResolution(const QSize &resolution) +{ + static_cast<QCuboidGeometry *>(geometry())->setXYMeshResolution(resolution); +} + +/*! + * \property QCuboidMesh::xyMeshResolution + * + * Holds the x-y resolution. + */ +QSize QCuboidMesh::xyMeshResolution() const +{ + return static_cast<QCuboidGeometry *>(geometry())->xyMeshResolution(); +} + +} // namespace Qt3DExtras + +QT_END_NAMESPACE diff --git a/src/extras/geometries/qcuboidmesh.h b/src/extras/geometries/qcuboidmesh.h new file mode 100644 index 000000000..72f6a007d --- /dev/null +++ b/src/extras/geometries/qcuboidmesh.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_CUBOIDMESH_H +#define QT3DEXTRAS_CUBOIDMESH_H + +#include <Qt3DExtras/qt3dextras_global.h> +#include <Qt3DRender/qgeometryrenderer.h> +#include <QSize> + +QT_BEGIN_NAMESPACE + +namespace Qt3DExtras { + +class QT3DEXTRASSHARED_EXPORT QCuboidMesh : public Qt3DRender::QGeometryRenderer +{ + Q_OBJECT + + Q_PROPERTY(float xExtent READ xExtent WRITE setXExtent NOTIFY xExtentChanged) + Q_PROPERTY(float yExtent READ yExtent WRITE setYExtent NOTIFY yExtentChanged) + Q_PROPERTY(float zExtent READ zExtent WRITE setZExtent NOTIFY zExtentChanged) + Q_PROPERTY(QSize yzMeshResolution READ yzMeshResolution WRITE setYZMeshResolution NOTIFY yzMeshResolutionChanged) + Q_PROPERTY(QSize xzMeshResolution READ xzMeshResolution WRITE setXZMeshResolution NOTIFY xzMeshResolutionChanged) + Q_PROPERTY(QSize xyMeshResolution READ xyMeshResolution WRITE setXYMeshResolution NOTIFY xyMeshResolutionChanged) + +public: + explicit QCuboidMesh(Qt3DCore::QNode *parent = Q_NULLPTR); + ~QCuboidMesh(); + + float xExtent() const; + float yExtent() const; + float zExtent() const; + QSize yzMeshResolution() const; + QSize xzMeshResolution() const; + QSize xyMeshResolution() const; + +public Q_SLOTS: + void setXExtent(float xExtent); + void setYExtent(float yExtent); + void setZExtent(float zExtent); + void setYZMeshResolution(const QSize &resolution); + void setXZMeshResolution(const QSize &resolution); + void setXYMeshResolution(const QSize &resolution); + +Q_SIGNALS: + void xExtentChanged(float xExtent); + void yExtentChanged(float yExtent); + void zExtentChanged(float zExtent); + + void yzMeshResolutionChanged(const QSize &yzMeshResolution); + void xzMeshResolutionChanged(const QSize &xzMeshResolution); + void xyMeshResolutionChanged(const QSize &xyMeshResolution); + +private: + // As this is a default provided geometry renderer, no one should be able + // to modify the QGeometryRenderer's properties + + void setInstanceCount(int instanceCount); + void setVertexCount(int vertexCount); + void setIndexOffset(int indexOffset); + void setFirstInstance(int firstInstance); + void setRestartIndexValue(int index); + void setPrimitiveRestartEnabled(bool enabled); + void setGeometry(Qt3DRender::QGeometry *geometry); + void setPrimitiveType(PrimitiveType primitiveType); +}; + +} // namespace Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_CUBOIDMESH_H diff --git a/src/extras/geometries/qcylindergeometry.cpp b/src/extras/geometries/qcylindergeometry.cpp new file mode 100644 index 000000000..f514d0dc9 --- /dev/null +++ b/src/extras/geometries/qcylindergeometry.cpp @@ -0,0 +1,585 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _USE_MATH_DEFINES +# define _USE_MATH_DEFINES // For MSVC +#endif + +#include "qcylindergeometry.h" +#include "qcylindergeometry_p.h" +#include <Qt3DRender/qbuffer.h> +#include <Qt3DRender/qbufferdatagenerator.h> +#include <Qt3DRender/qattribute.h> +#include <qmath.h> +#include <QVector3D> + +QT_BEGIN_NAMESPACE + +using namespace Qt3DRender; + +namespace Qt3DExtras { + +namespace { + +void createSidesVertices(float *&verticesPtr, + int rings, + int slices, + double radius, + double length) +{ + const float dY = length / static_cast<float>(rings - 1); + const float dTheta = (M_PI * 2) / static_cast<float>(slices); + + for (int ring = 0; ring < rings; ++ring) { + const float y = -length / 2.0f + static_cast<float>(ring) * dY; + + for (int slice = 0; slice <= slices; ++slice) { + const float theta = static_cast<float>(slice) * dTheta; + const float ct = qCos(theta); + const float st = qSin(theta); + + *verticesPtr++ = radius * ct; + *verticesPtr++ = y; + *verticesPtr++ = radius * st; + + *verticesPtr++ = (y + length / 2.0) / length; + *verticesPtr++ = theta / (M_PI * 2); + + QVector3D n(ct, 0.0f, st); + n.normalize(); + *verticesPtr++ = n.x(); + *verticesPtr++ = n.y(); + *verticesPtr++ = n.z(); + } + } +} + +void createSidesIndices(quint16 *&indicesPtr, int rings, int slices) +{ + for (int ring = 0; ring < rings - 1; ++ring) { + const int ringIndexStart = ring * (slices + 1); + const int nextRingIndexStart = (ring + 1) * (slices + 1); + + for (int slice = 0; slice < slices; ++slice) { + const int nextSlice = slice + 1; + + *indicesPtr++ = (ringIndexStart + slice); + *indicesPtr++ = (nextRingIndexStart + slice); + *indicesPtr++ = (ringIndexStart + nextSlice); + *indicesPtr++ = (ringIndexStart + nextSlice); + *indicesPtr++ = (nextRingIndexStart + slice); + *indicesPtr++ = (nextRingIndexStart + nextSlice); + } + } +} + +void createDiscVertices(float *&verticesPtr, + int slices, + double radius, + double yPosition) +{ + const float dTheta = (M_PI * 2) / static_cast<float>(slices); + const double yNormal = (yPosition < 0.0f) ? -1.0f : 1.0f; + + *verticesPtr++ = 0.0f; + *verticesPtr++ = yPosition; + *verticesPtr++ = 0.0f; + + *verticesPtr++ = 1.0f; + *verticesPtr++ = 0.0f; + + *verticesPtr++ = 0.0f; + *verticesPtr++ = yNormal; + *verticesPtr++ = 0.0f; + + for (int slice = 0; slice <= slices; ++slice) { + const float theta = static_cast<float>(slice) * dTheta; + const float ct = qCos(theta); + const float st = qSin(theta); + + *verticesPtr++ = radius * ct; + *verticesPtr++ = yPosition; + *verticesPtr++ = radius * st; + + *verticesPtr++ = 1.0f; + *verticesPtr++ = theta / (M_PI * 2); + + *verticesPtr++ = 0.0f; + *verticesPtr++ = yNormal; + *verticesPtr++ = 0.0f; + } +} + +void createDiscIndices(quint16 *&indicesPtr, + int discCenterIndex, + int slices, + double yPosition) +{ + const double yNormal = (yPosition < 0.0f) ? -1.0f : 1.0f; + + for (int slice = 0; slice < slices; ++slice) { + const int nextSlice = slice + 1; + + *indicesPtr++ = discCenterIndex; + *indicesPtr++ = (discCenterIndex + 1 + nextSlice); + *indicesPtr++ = (discCenterIndex + 1 + slice); + + if (yNormal < 0.0f) + qSwap(*(indicesPtr -1), *(indicesPtr - 2)); + } +} + +} // anonymous + + +class CylinderVertexDataFunctor : public QBufferDataGenerator +{ +public: + CylinderVertexDataFunctor(int rings, int slices, float radius, float length) + : m_rings(rings) + , m_slices(slices) + , m_radius(radius) + , m_length(length) + {} + + QByteArray operator ()() Q_DECL_OVERRIDE + { + const int verticesCount = (m_slices + 1) * m_rings + 2 * (m_slices + 1) + 2; + // vec3 pos, vec2 texCoord, vec3 normal + const quint32 vertexSize = (3 + 2 + 3) * sizeof(float); + + QByteArray verticesData; + verticesData.resize(vertexSize * verticesCount); + float *verticesPtr = reinterpret_cast<float*>(verticesData.data()); + + createSidesVertices(verticesPtr, m_rings, m_slices, m_radius, m_length); + createDiscVertices(verticesPtr, m_slices, m_radius, -m_length * 0.5f); + createDiscVertices(verticesPtr, m_slices, m_radius, m_length * 0.5f); + + return verticesData; + } + + bool operator ==(const QBufferDataGenerator &other) const Q_DECL_OVERRIDE + { + const CylinderVertexDataFunctor *otherFunctor = functor_cast<CylinderVertexDataFunctor>(&other); + if (otherFunctor != Q_NULLPTR) + return (otherFunctor->m_rings == m_rings && + otherFunctor->m_slices == m_slices && + otherFunctor->m_radius == m_radius && + otherFunctor->m_length == m_length); + return false; + } + + QT3D_FUNCTOR(CylinderVertexDataFunctor) + +private: + int m_rings; + int m_slices; + float m_radius; + float m_length; +}; + +class CylinderIndexDataFunctor : public QBufferDataGenerator +{ +public: + CylinderIndexDataFunctor(int rings, int slices, float length) + : m_rings(rings) + , m_slices(slices) + , m_length(length) + { + } + + QByteArray operator ()() Q_DECL_OVERRIDE + { + const int facesCount = (m_slices * 2) * (m_rings - 1) // two tris per side, for each pair of adjacent rings + + m_slices * 2; // two caps + const int indicesCount = facesCount * 3; + const int indexSize = sizeof(quint16); + Q_ASSERT(indicesCount < 65536); + + QByteArray indicesBytes; + indicesBytes.resize(indicesCount * indexSize); + quint16 *indicesPtr = reinterpret_cast<quint16*>(indicesBytes.data()); + + createSidesIndices(indicesPtr, m_rings, m_slices); + createDiscIndices(indicesPtr, m_rings * (m_slices + 1), m_slices, -m_length * 0.5); + createDiscIndices(indicesPtr, m_rings * (m_slices + 1) + m_slices + 2, m_slices, m_length * 0.5); + + return indicesBytes; + } + + bool operator ==(const QBufferDataGenerator &other) const Q_DECL_OVERRIDE + { + const CylinderIndexDataFunctor *otherFunctor = functor_cast<CylinderIndexDataFunctor>(&other); + if (otherFunctor != Q_NULLPTR) + return (otherFunctor->m_rings == m_rings && + otherFunctor->m_slices == m_slices && + otherFunctor->m_length == m_length); + return false; + } + + QT3D_FUNCTOR(CylinderIndexDataFunctor) + +private: + int m_rings; + int m_slices; + float m_length; +}; + + +QCylinderGeometryPrivate::QCylinderGeometryPrivate() + : QGeometryPrivate() + , m_rings(16) + , m_slices(16) + , m_radius(1.0f) + , m_length(1.0f) + , m_positionAttribute(Q_NULLPTR) + , m_normalAttribute(Q_NULLPTR) + , m_texCoordAttribute(Q_NULLPTR) + , m_indexAttribute(Q_NULLPTR) + , m_vertexBuffer(Q_NULLPTR) + , m_indexBuffer(Q_NULLPTR) +{ +} + +void QCylinderGeometryPrivate::init() +{ + Q_Q(QCylinderGeometry); + m_positionAttribute = new QAttribute(q); + m_normalAttribute = new QAttribute(q); + m_texCoordAttribute = new QAttribute(q); + m_indexAttribute = new QAttribute(q); + m_vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, q); + m_indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, q); + + // 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 + 2 * (m_slices + 1) + 2; + const int faces = (m_slices * 2) * (m_rings - 1) + (m_slices * 2); + + 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->setDataGenerator(QBufferDataGeneratorPtr(new CylinderVertexDataFunctor(m_rings, m_slices, m_radius, m_length))); + m_indexBuffer->setDataGenerator(QBufferDataGeneratorPtr(new CylinderIndexDataFunctor(m_rings, m_slices, m_length))); + + q->addAttribute(m_positionAttribute); + q->addAttribute(m_texCoordAttribute); + q->addAttribute(m_normalAttribute); + q->addAttribute(m_indexAttribute); +} + +/*! + * \qmltype CylinderGeometry + * \instantiates Qt3DRender::QCylinderGeometry + * \inqmlmodule Qt3D.Render + */ + +/*! + * \qmlproperty int CylinderGeometry::rings + * + * Holds the number of rings in the cylinder. + */ + +/*! + * \qmlproperty int CylinderGeometry::slices + * + * Holds the number of slices in the cylinder. + */ + +/*! + * \qmlproperty float CylinderGeometry::radius + * + * Holds the radius of the cylinder. + */ + +/*! + * \qmlproperty float CylinderGeometry::length + * + * Holds the length of the cylinder. + */ + +/*! + * \qmlproperty Attribute CylinderGeometry::positionAttribute + * + * Holds the geometry position attribute. + */ + +/*! + * \qmlproperty Attribute CylinderGeometry::normalAttribute + * + * Holds the geometry normal attribute. + */ + +/*! + * \qmlproperty Attribute CylinderGeometry::texCoordAttribute + * + * Holds the geometry texture coordinate attribute. + */ + +/*! + * \qmlproperty Attribute CylinderGeometry::indexAttribute + * + * Holds the geometry index attribute. + */ + +/*! + * \class Qt3DRender::QCylinderGeometry + * \inmodule Qt3DRender + * + * \inherits Qt3DRender::QGeometry + */ + +/*! + * Constructs a new QCylinderMesh with \a parent. + */ +QCylinderGeometry::QCylinderGeometry(QNode *parent) + : QGeometry(*new QCylinderGeometryPrivate, parent) +{ + Q_D(QCylinderGeometry); + d->init(); +} + +/*! + * \internal + */ +QCylinderGeometry::QCylinderGeometry(QCylinderGeometryPrivate &dd, QNode *parent) + :QGeometry(dd, parent) +{ + Q_D(QCylinderGeometry); + d->init(); +} + +/*! + * Destroys the geometry. + */ +QCylinderGeometry::~QCylinderGeometry() +{ + QGeometry::cleanup(); +} + +/*! + * Updates the vertices based on rings and slices. + */ +void QCylinderGeometry::updateVertices() +{ + Q_D(QCylinderGeometry); + 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_vertexBuffer->setDataGenerator(QBufferDataGeneratorPtr(new CylinderVertexDataFunctor(d->m_rings, d->m_slices, d->m_radius, d->m_length))); +} + +/*! + * Updates the indices based on rings and slices. + */ +void QCylinderGeometry::updateIndices() +{ + Q_D(QCylinderGeometry); + const int faces = (d->m_slices * 2) * d->m_rings + (2 * d->m_slices); + d->m_indexAttribute->setCount(faces * 3); + d->m_indexBuffer->setDataGenerator(QBufferDataGeneratorPtr(new CylinderIndexDataFunctor(d->m_rings, d->m_slices, d->m_length))); +} + +void QCylinderGeometry::setRings(int rings) +{ + Q_D(QCylinderGeometry); + if (rings != d->m_rings) { + d->m_rings = rings; + updateVertices(); + updateIndices(); + emit ringsChanged(rings); + } +} + +void QCylinderGeometry::setSlices(int slices) +{ + Q_D(QCylinderGeometry); + if (slices != d->m_slices) { + d->m_slices = slices; + updateVertices(); + updateIndices(); + emit slicesChanged(slices); + } +} + +void QCylinderGeometry::setRadius(float radius) +{ + Q_D(QCylinderGeometry); + if (radius != d->m_radius) { + d->m_radius = radius; + updateVertices(); + emit radiusChanged(radius); + } +} + +void QCylinderGeometry::setLength(float length) +{ + Q_D(QCylinderGeometry); + if (length != d->m_length) { + d->m_length = length; + updateVertices(); + updateIndices(); + emit lengthChanged(length); + } +} + +/*! + * \property QCylinderGeometry::rings + * + * Holds the number of rings in the cylinder. + */ +int QCylinderGeometry::rings() const +{ + Q_D(const QCylinderGeometry); + return d->m_rings; +} + +/*! + * \property QCylinderGeometry::slices + * + * Holds the number of slices in the cylinder. + */ +int QCylinderGeometry::slices() const +{ + Q_D(const QCylinderGeometry); + return d->m_slices; +} + +/*! + * \property QCylinderGeometry::radius + * + * Holds the radius of the cylinder. + */ +float QCylinderGeometry::radius() const +{ + Q_D(const QCylinderGeometry); + return d->m_radius; +} + +/*! + * \property QCylinderGeometry::length + * + * Holds the length of the cylinder. + */ +float QCylinderGeometry::length() const +{ + Q_D(const QCylinderGeometry); + return d->m_length; +} + +/*! + * \property QCylinderGeometry::positionAttribute + * + * Holds the geometry position attribute. + */ +QAttribute *QCylinderGeometry::positionAttribute() const +{ + Q_D(const QCylinderGeometry); + return d->m_positionAttribute; +} + +/*! + * \property QCylinderGeometry::normalAttribute + * + * Holds the geometry normal attribute. + */ +QAttribute *QCylinderGeometry::normalAttribute() const +{ + Q_D(const QCylinderGeometry); + return d->m_normalAttribute; +} + +/*! + * \property QCylinderGeometry::texCoordAttribute + * + * Holds the geometry texture coordinate attribute. + */ +QAttribute *QCylinderGeometry::texCoordAttribute() const +{ + Q_D(const QCylinderGeometry); + return d->m_texCoordAttribute; +} + +/*! + * \property QCylinderGeometry::indexAttribute + * + * Holds the geometry index attribute. + */ +QAttribute *QCylinderGeometry::indexAttribute() const +{ + Q_D(const QCylinderGeometry); + return d->m_indexAttribute; +} + +} // namespace Qt3DExtras + +QT_END_NAMESPACE diff --git a/src/extras/geometries/qcylindergeometry.h b/src/extras/geometries/qcylindergeometry.h new file mode 100644 index 000000000..570b2b25d --- /dev/null +++ b/src/extras/geometries/qcylindergeometry.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QCYLINDERGEOMETRY_H +#define QT3DEXTRAS_QCYLINDERGEOMETRY_H + +#include <Qt3DExtras/qt3dextras_global.h> +#include <Qt3DRender/qgeometry.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QAttribute; + +} // namespace Qt3DRender + +namespace Qt3DExtras { + +class QCylinderGeometryPrivate; +class QT3DEXTRASSHARED_EXPORT QCylinderGeometry : public Qt3DRender::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(float length READ length WRITE setLength NOTIFY lengthChanged) + Q_PROPERTY(Qt3DRender::QAttribute *positionAttribute READ positionAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *normalAttribute READ normalAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *texCoordAttribute READ texCoordAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *indexAttribute READ indexAttribute CONSTANT) + +public: + explicit QCylinderGeometry(QNode *parent = Q_NULLPTR); + ~QCylinderGeometry(); + + void updateVertices(); + void updateIndices(); + + int rings() const; + int slices() const; + float radius() const; + float length() const; + + Qt3DRender::QAttribute *positionAttribute() const; + Qt3DRender::QAttribute *normalAttribute() const; + Qt3DRender::QAttribute *texCoordAttribute() const; + Qt3DRender::QAttribute *indexAttribute() const; + +public Q_SLOTS: + void setRings(int rings); + void setSlices(int slices); + void setRadius(float radius); + void setLength(float length); + +Q_SIGNALS: + void radiusChanged(float radius); + void ringsChanged(int rings); + void slicesChanged(int slices); + void lengthChanged(float length); + +protected: + QCylinderGeometry(QCylinderGeometryPrivate &dd, QNode *parent = Q_NULLPTR); + +private: + Q_DECLARE_PRIVATE(QCylinderGeometry) +}; + +} // Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QCYLINDERGEOMETRY_H diff --git a/src/extras/geometries/qcylindergeometry_p.h b/src/extras/geometries/qcylindergeometry_p.h new file mode 100644 index 000000000..50c37cb62 --- /dev/null +++ b/src/extras/geometries/qcylindergeometry_p.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QCYLINDERGEOMETRY_P_H +#define QT3DEXTRAS_QCYLINDERGEOMETRY_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <Qt3DRender/private/qgeometry_p.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QAttribute; +class QBuffer; + +} // namespace Qt3DRender + +namespace Qt3DExtras { + +class QCylinderGeometryPrivate : public Qt3DRender::QGeometryPrivate +{ +public: + QCylinderGeometryPrivate(); + + void init(); + + Q_DECLARE_PUBLIC(QCylinderGeometry) + + int m_rings; + int m_slices; + float m_radius; + float m_length; + Qt3DRender::QAttribute *m_positionAttribute; + Qt3DRender::QAttribute *m_normalAttribute; + Qt3DRender::QAttribute *m_texCoordAttribute; + Qt3DRender::QAttribute *m_indexAttribute; + Qt3DRender::QBuffer *m_vertexBuffer; + Qt3DRender::QBuffer *m_indexBuffer; +}; + +} // Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QCYLINDERGEOMETRY_P_H + diff --git a/src/extras/geometries/qcylindermesh.cpp b/src/extras/geometries/qcylindermesh.cpp new file mode 100644 index 000000000..9cbf729a6 --- /dev/null +++ b/src/extras/geometries/qcylindermesh.cpp @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _USE_MATH_DEFINES +# define _USE_MATH_DEFINES // For MSVC +#endif + +#include "qcylindermesh.h" +#include "qcylindergeometry.h" +#include <Qt3DRender/qbuffer.h> +#include <Qt3DRender/qbufferdatagenerator.h> +#include <Qt3DRender/qattribute.h> +#include <qmath.h> +#include <QVector3D> + +QT_BEGIN_NAMESPACE + +using namespace Qt3DRender; + +namespace Qt3DExtras { + +/*! + * \qmltype CylinderMesh + * \instantiates Qt3DRender::QCylinderMesh + * \inqmlmodule Qt3D.Render + * \brief A cylindrical mesh. + */ + +/*! + * \qmlproperty int CylinderMesh::rings + * + * Holds the number of rings in the mesh. + */ + +/*! + * \qmlproperty int CylinderMesh::slices + * + * Holds the number of slices in the mesh. + */ + +/*! + * \qmlproperty float CylinderMesh::radius + * + * Holds the radius of the cylinder. + */ + +/*! + * \qmlproperty float CylinderMesh::length + * + * Holds the length of the cylinder. + */ + +/*! + * \class Qt3DRender::QCylinderMesh + * \inmodule Qt3DRender + * + * \inherits Qt3DRender::QGeometryRenderer + * + * \brief A cylindrical mesh. + */ + +/*! + * Constructs a new QCylinderMesh with \a parent. + */ +QCylinderMesh::QCylinderMesh(QNode *parent) + : QGeometryRenderer(parent) +{ + QCylinderGeometry *geometry = new QCylinderGeometry(this); + QObject::connect(geometry, &QCylinderGeometry::radiusChanged, this, &QCylinderMesh::radiusChanged); + QObject::connect(geometry, &QCylinderGeometry::ringsChanged, this, &QCylinderMesh::ringsChanged); + QObject::connect(geometry, &QCylinderGeometry::slicesChanged, this, &QCylinderMesh::slicesChanged); + QObject::connect(geometry, &QCylinderGeometry::lengthChanged, this, &QCylinderMesh::lengthChanged); + + QGeometryRenderer::setGeometry(geometry); +} + +/*! + * Destroys this cylinder mesh. + */ +QCylinderMesh::~QCylinderMesh() +{ + QNode::cleanup(); +} + +void QCylinderMesh::setRings(int rings) +{ + static_cast<QCylinderGeometry *>(geometry())->setRings(rings); +} + +void QCylinderMesh::setSlices(int slices) +{ + static_cast<QCylinderGeometry *>(geometry())->setSlices(slices); +} + +void QCylinderMesh::setRadius(float radius) +{ + static_cast<QCylinderGeometry *>(geometry())->setRadius(radius); +} + +void QCylinderMesh::setLength(float length) +{ + static_cast<QCylinderGeometry *>(geometry())->setLength(length); +} + +/*! + * \property QCylinderMesh::rings + * + * Holds the number of rings in the mesh. + */ +int QCylinderMesh::rings() const +{ + return static_cast<QCylinderGeometry *>(geometry())->rings(); +} + +/*! + * \property QCylinderMesh::slices + * + * Holds the number of slices in the mesh. + */ +int QCylinderMesh::slices() const +{ + return static_cast<QCylinderGeometry *>(geometry())->slices(); +} + +/*! + * \property QCylinderMesh::radius + * + * Holds the radius of the cylinder. + */ +float QCylinderMesh::radius() const +{ + return static_cast<QCylinderGeometry *>(geometry())->radius(); +} + +/*! + * \property QCylinderMesh::length + * + * Holds the length of the cylinder. + */ +float QCylinderMesh::length() const +{ + return static_cast<QCylinderGeometry *>(geometry())->length(); +} + +} // namespace Qt3DExtras + +QT_END_NAMESPACE diff --git a/src/extras/geometries/qcylindermesh.h b/src/extras/geometries/qcylindermesh.h new file mode 100644 index 000000000..256508576 --- /dev/null +++ b/src/extras/geometries/qcylindermesh.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QCYLINDERMESH_H +#define QT3DEXTRAS_QCYLINDERMESH_H + +#include <Qt3DExtras/qt3dextras_global.h> +#include <Qt3DRender/qgeometryrenderer.h> + +QT_BEGIN_NAMESPACE + + +namespace Qt3DExtras { + +class QT3DEXTRASSHARED_EXPORT QCylinderMesh : public Qt3DRender::QGeometryRenderer +{ + 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(float length READ length WRITE setLength NOTIFY lengthChanged) +public: + explicit QCylinderMesh(Qt3DCore::QNode *parent = Q_NULLPTR); + ~QCylinderMesh(); + + int rings() const; + int slices() const; + float radius() const; + float length() const; + +public Q_SLOTS: + void setRings(int rings); + void setSlices(int slices); + void setRadius(float radius); + void setLength(float length); + +Q_SIGNALS: + void radiusChanged(float radius); + void ringsChanged(int rings); + void slicesChanged(int slices); + void lengthChanged(float length); + +private: + // As this is a default provided geometry renderer, no one should be able + // to modify the QGeometryRenderer's properties + + void setInstanceCount(int instanceCount); + void setVertexCount(int vertexCount); + void setIndexOffset(int indexOffset); + void setFirstInstance(int firstInstance); + void setRestartIndexValue(int index); + void setPrimitiveRestartEnabled(bool enabled); + void setGeometry(Qt3DRender::QGeometry *geometry); + void setPrimitiveType(PrimitiveType primitiveType); +}; + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QCYLINDERMESH_H diff --git a/src/extras/geometries/qplanegeometry.cpp b/src/extras/geometries/qplanegeometry.cpp new file mode 100644 index 000000000..a0c0ffbc0 --- /dev/null +++ b/src/extras/geometries/qplanegeometry.cpp @@ -0,0 +1,529 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplanegeometry.h" +#include "qplanegeometry_p.h" +#include <Qt3DRender/qattribute.h> +#include <Qt3DRender/qbuffer.h> +#include <Qt3DRender/qbufferdatagenerator.h> +#include <limits> + +QT_BEGIN_NAMESPACE + +using namespace Qt3DRender; + +namespace Qt3DExtras { + +namespace { + +QByteArray createPlaneVertexData(float w, float h, const QSize &resolution) +{ + Q_ASSERT(w > 0.0f); + Q_ASSERT(h > 0.0f); + Q_ASSERT(resolution.width() >= 2); + Q_ASSERT(resolution.height() >= 2); + + const int nVerts = resolution.width() * resolution.height(); + + // Populate a buffer with the interleaved per-vertex data with + // vec3 pos, vec2 texCoord, vec3 normal, vec4 tangent + const quint32 elementSize = 3 + 2 + 3 + 4; + const quint32 stride = elementSize * sizeof(float); + QByteArray bufferBytes; + bufferBytes.resize(stride * nVerts); + float* fptr = reinterpret_cast<float*>(bufferBytes.data()); + + const float x0 = -w / 2.0f; + const float z0 = -h / 2.0f; + const float dx = w / (resolution.width() - 1); + const float dz = h / (resolution.height() - 1); + const float du = 1.0 / (resolution.width() - 1); + const float dv = 1.0 / (resolution.height() - 1); + + // Iterate over z + for (int j = 0; j < resolution.height(); ++j) { + const float z = z0 + static_cast<float>(j) * dz; + const float v = static_cast<float>(j) * dv; + + // Iterate over x + for (int i = 0; i < resolution.width(); ++i) { + const float x = x0 + static_cast<float>(i) * dx; + const float u = static_cast<float>(i) * du; + + // position + *fptr++ = x; + *fptr++ = 0.0; + *fptr++ = z; + + // texture coordinates + *fptr++ = u; + *fptr++ = v; + + // normal + *fptr++ = 0.0f; + *fptr++ = 1.0f; + *fptr++ = 0.0f; + + // tangent + *fptr++ = 1.0f; + *fptr++ = 0.0f; + *fptr++ = 0.0f; + *fptr++ = 1.0f; + } + } + + return bufferBytes; +} + +QByteArray createPlaneIndexData(const QSize &resolution) +{ + // Create the index data. 2 triangles per rectangular face + const int faces = 2 * (resolution.width() - 1) * (resolution.height() - 1); + const int indices = 3 * faces; + Q_ASSERT(indices < std::numeric_limits<quint16>::max()); + QByteArray indexBytes; + indexBytes.resize(indices * sizeof(quint16)); + quint16* indexPtr = reinterpret_cast<quint16*>(indexBytes.data()); + + // Iterate over z + for (int j = 0; j < resolution.height() - 1; ++j) { + const int rowStartIndex = j * resolution.width(); + const int nextRowStartIndex = (j + 1) * resolution.width(); + + // Iterate over x + for (int i = 0; i < resolution.width() - 1; ++i) { + // Split quad into two triangles + *indexPtr++ = rowStartIndex + i; + *indexPtr++ = nextRowStartIndex + i; + *indexPtr++ = rowStartIndex + i + 1; + + *indexPtr++ = nextRowStartIndex + i; + *indexPtr++ = nextRowStartIndex + i + 1; + *indexPtr++ = rowStartIndex + i + 1; + } + } + + return indexBytes; +} + +} // anonymous + +class PlaneVertexBufferFunctor : public QBufferDataGenerator +{ +public: + explicit PlaneVertexBufferFunctor(float w, float h, const QSize &resolution) + : m_width(w) + , m_height(h) + , m_resolution(resolution) + {} + + ~PlaneVertexBufferFunctor() {} + + QByteArray operator()() Q_DECL_FINAL + { + return createPlaneVertexData(m_width, m_height, m_resolution); + } + + bool operator ==(const QBufferDataGenerator &other) const Q_DECL_FINAL + { + const PlaneVertexBufferFunctor *otherFunctor = functor_cast<PlaneVertexBufferFunctor>(&other); + if (otherFunctor != Q_NULLPTR) + return (otherFunctor->m_width == m_width && + otherFunctor->m_height == m_height && + otherFunctor->m_resolution == m_resolution); + return false; + } + + QT3D_FUNCTOR(PlaneVertexBufferFunctor) + + private: + float m_width; + float m_height; + QSize m_resolution; +}; + +class PlaneIndexBufferFunctor : public QBufferDataGenerator +{ +public: + explicit PlaneIndexBufferFunctor(const QSize &resolution) + : m_resolution(resolution) + {} + + ~PlaneIndexBufferFunctor() {} + + QByteArray operator()() Q_DECL_FINAL + { + return createPlaneIndexData(m_resolution); + } + + bool operator ==(const QBufferDataGenerator &other) const Q_DECL_FINAL + { + const PlaneIndexBufferFunctor *otherFunctor = functor_cast<PlaneIndexBufferFunctor>(&other); + if (otherFunctor != Q_NULLPTR) + return (otherFunctor->m_resolution == m_resolution); + return false; + } + + QT3D_FUNCTOR(PlaneIndexBufferFunctor) + + private: + QSize m_resolution; +}; + +/*! + * \qmltype PlaneGeometry + * \instantiates Qt3DRender::QPlaneGeometry + * \inqmlmodule Qt3D.Render + */ + +/*! + * \qmlproperty float PlaneGeometry::width + * + * Holds the plane width. + */ + +/*! + * \qmlproperty float PlaneGeometry::height + * + * Holds the plane height. + */ + +/*! + * \qmlproperty size PlaneGeometry::resolution + * + * Holds the plane resolution. + */ + +/*! + * \qmlproperty Attribute PlaneGeometry::positionAttribute + * + * Holds the geometry position attribute. + */ + +/*! + * \qmlproperty Attribute PlaneGeometry::normalAttribute + * + * Holds the geometry normal attribute. + */ + +/*! + * \qmlproperty Attribute PlaneGeometry::texCoordAttribute + * + * Holds the geometry texture coordinate attribute. + */ + +/*! + * \qmlproperty Attribute PlaneGeometry::tangentAttribute + * + * Holds the geometry tangent attribute. + */ + +/*! + * \qmlproperty Attribute PlaneGeometry::indexAttribute + * + * Holds the geometry index attribute. + */ + +/*! + * \class Qt3DRender::QPlaneGeometry + * \inmodule Qt3DRender + * + * \inherits Qt3DRender::QGeometry + */ + +/*! + * Constructs a new QPlaneGeometry with \a parent. + */ +QPlaneGeometry::QPlaneGeometry(QPlaneGeometry::QNode *parent) + : QGeometry(*new QPlaneGeometryPrivate(), parent) +{ + Q_D(QPlaneGeometry); + d->init(); +} + +/*! + * \internal + */ +QPlaneGeometry::QPlaneGeometry(QPlaneGeometryPrivate &dd, QNode *parent) + : QGeometry(dd, parent) +{ + Q_D(QPlaneGeometry); + d->init(); +} + +/*! + * Destroys this geometry. + */ +QPlaneGeometry::~QPlaneGeometry() +{ + QGeometry::cleanup(); +} + +/*! + * Updates vertices based on resolution. + */ +void QPlaneGeometry::updateVertices() +{ + Q_D(QPlaneGeometry); + const int nVerts = d->m_meshResolution.width() * d->m_meshResolution.height(); + + d->m_positionAttribute->setCount(nVerts); + d->m_normalAttribute->setCount(nVerts); + d->m_texCoordAttribute->setCount(nVerts); + d->m_tangentAttribute->setCount(nVerts); + d->m_vertexBuffer->setDataGenerator(QBufferDataGeneratorPtr(new PlaneVertexBufferFunctor(d->m_width, d->m_height, d->m_meshResolution))); +} + +/*! + * Updates indices based on resolution. + */ +void QPlaneGeometry::updateIndices() +{ + Q_D(QPlaneGeometry); + const int faces = 2 * (d->m_meshResolution.width() - 1) * (d->m_meshResolution.height() - 1); + // Each primitive has 3 vertices + d->m_indexAttribute->setCount(faces * 3); + d->m_indexBuffer->setDataGenerator(QBufferDataGeneratorPtr(new PlaneIndexBufferFunctor(d->m_meshResolution))); + +} + +void QPlaneGeometry::setResolution(const QSize &resolution) +{ + Q_D(QPlaneGeometry); + if (d->m_meshResolution == resolution) + return; + d->m_meshResolution = resolution; + updateVertices(); + updateIndices(); + emit resolutionChanged(resolution); +} + +void QPlaneGeometry::setWidth(float width) +{ + Q_D(QPlaneGeometry); + if (width == d->m_width) + return; + d->m_width = width; + updateVertices(); + emit widthChanged(width); +} + +void QPlaneGeometry::setHeight(float height) +{ + Q_D(QPlaneGeometry); + if (height == d->m_height) + return; + d->m_height = height; + updateVertices(); + emit heightChanged(height); +} + +/*! + * \property QPlaneGeometry::resolution + * + * Holds the plane resolution. + */ +QSize QPlaneGeometry::resolution() const +{ + Q_D(const QPlaneGeometry); + return d->m_meshResolution; +} + +/*! + * \property QPlaneGeometry::width + * + * Holds the plane width. + */ +float QPlaneGeometry::width() const +{ + Q_D(const QPlaneGeometry); + return d->m_width; +} + +/*! + * \property QPlaneGeometry::height + * + * Holds the plane height. + */ +float QPlaneGeometry::height() const +{ + Q_D(const QPlaneGeometry); + return d->m_height; +} + +/*! + * \property QPlaneGeometry::positionAttribute + * + * Holds the geometry position attribute. + */ +QAttribute *QPlaneGeometry::positionAttribute() const +{ + Q_D(const QPlaneGeometry); + return d->m_positionAttribute; +} + +/*! + * \property QPlaneGeometry::normalAttribute + * + * Holds the geometry normal attribute. + */ +QAttribute *QPlaneGeometry::normalAttribute() const +{ + Q_D(const QPlaneGeometry); + return d->m_normalAttribute; +} + +/*! + * \property QPlaneGeometry::texCoordAttribute + * + * Holds the geometry texture coordinate attribute. + */ +QAttribute *QPlaneGeometry::texCoordAttribute() const +{ + Q_D(const QPlaneGeometry); + return d->m_texCoordAttribute; +} + +/*! + * \property QPlaneGeometry::tangentAttribute + * + * Holds the geometry tangent attribute. + */ +QAttribute *QPlaneGeometry::tangentAttribute() const +{ + Q_D(const QPlaneGeometry); + return d->m_tangentAttribute; +} + +/*! + * \property QPlaneGeometry::indexAttribute + * + * Holds the geometry index attribute. + */ +QAttribute *QPlaneGeometry::indexAttribute() const +{ + Q_D(const QPlaneGeometry); + return d->m_indexAttribute; +} + +QPlaneGeometryPrivate::QPlaneGeometryPrivate() + : QGeometryPrivate() + , m_width(1.0f) + , m_height(1.0f) + , m_meshResolution(QSize(2, 2)) + , 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 QPlaneGeometryPrivate::init() +{ + Q_Q(QPlaneGeometry); + 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 Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, q); + m_indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, q); + + const int nVerts = m_meshResolution.width() * m_meshResolution.height(); + const int stride = (3 + 2 + 3 + 4) * sizeof(float); + const int faces = 2 * (m_meshResolution.width() - 1) * (m_meshResolution.height() - 1); + + 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); + + // Each primitive has 3 vertives + m_indexAttribute->setCount(faces * 3); + + m_vertexBuffer->setDataGenerator(QBufferDataGeneratorPtr(new PlaneVertexBufferFunctor(m_width, m_height, m_meshResolution))); + m_indexBuffer->setDataGenerator(QBufferDataGeneratorPtr(new PlaneIndexBufferFunctor(m_meshResolution))); + + q->addAttribute(m_positionAttribute); + q->addAttribute(m_texCoordAttribute); + q->addAttribute(m_normalAttribute); + q->addAttribute(m_tangentAttribute); + q->addAttribute(m_indexAttribute); +} + +} // Qt3DExtras + +QT_END_NAMESPACE diff --git a/src/extras/geometries/qplanegeometry.h b/src/extras/geometries/qplanegeometry.h new file mode 100644 index 000000000..708ea931d --- /dev/null +++ b/src/extras/geometries/qplanegeometry.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QPLANEGEOMETRY_H +#define QT3DEXTRAS_QPLANEGEOMETRY_H + +#include <Qt3DExtras/qt3dextras_global.h> +#include <Qt3DRender/qgeometry.h> +#include <QSize> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QAttribute; + +} // Qt3DRender + +namespace Qt3DExtras { + +class QPlaneGeometryPrivate; + +class QT3DEXTRASSHARED_EXPORT QPlaneGeometry : public Qt3DRender::QGeometry +{ + Q_OBJECT + Q_PROPERTY(float width READ width WRITE setWidth NOTIFY widthChanged) + Q_PROPERTY(float height READ height WRITE setHeight NOTIFY heightChanged) + Q_PROPERTY(QSize resolution READ resolution WRITE setResolution NOTIFY resolutionChanged) + Q_PROPERTY(Qt3DRender::QAttribute *positionAttribute READ positionAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *normalAttribute READ normalAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *texCoordAttribute READ texCoordAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *tangentAttribute READ tangentAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *indexAttribute READ indexAttribute CONSTANT) + +public: + explicit QPlaneGeometry(QNode *parent = Q_NULLPTR); + ~QPlaneGeometry(); + + void updateVertices(); + void updateIndices(); + + QSize resolution() const; + float width() const; + float height() const; + + Qt3DRender::QAttribute *positionAttribute() const; + Qt3DRender::QAttribute *normalAttribute() const; + Qt3DRender::QAttribute *texCoordAttribute() const; + Qt3DRender::QAttribute *tangentAttribute() const; + Qt3DRender::QAttribute *indexAttribute() const; + +public Q_SLOTS: + void setResolution(const QSize &resolution); + void setWidth(float width); + void setHeight(float height); + +Q_SIGNALS: + void resolutionChanged(const QSize &resolution); + void widthChanged(float width); + void heightChanged(float height); + +protected: + QPlaneGeometry(QPlaneGeometryPrivate &dd, QNode *parent = Q_NULLPTR); + +private: + Q_DECLARE_PRIVATE(QPlaneGeometry) +}; + +} // Qt3DExpoerimental + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QPLANEGEOMETRY_H diff --git a/src/extras/geometries/qplanegeometry_p.h b/src/extras/geometries/qplanegeometry_p.h new file mode 100644 index 000000000..d0a4e88e4 --- /dev/null +++ b/src/extras/geometries/qplanegeometry_p.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QPLANEGEOMETRY_P_H +#define QT3DEXTRAS_QPLANEGEOMETRY_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 <Qt3DRender/private/qgeometry_p.h> +#include <QSize> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QAttribute; +class QBuffer; + +} // Qt3DRender + +namespace Qt3DExtras { + +class QPlaneGeometryPrivate : public Qt3DRender::QGeometryPrivate +{ +public: + QPlaneGeometryPrivate(); + void init(); + + float m_width; + float m_height; + QSize m_meshResolution; + Qt3DRender::QAttribute *m_positionAttribute; + Qt3DRender::QAttribute *m_normalAttribute; + Qt3DRender::QAttribute *m_texCoordAttribute; + Qt3DRender::QAttribute *m_tangentAttribute; + Qt3DRender::QAttribute *m_indexAttribute; + Qt3DRender::QBuffer *m_vertexBuffer; + Qt3DRender::QBuffer *m_indexBuffer; + + Q_DECLARE_PUBLIC(QPlaneGeometry) +}; + +} // Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QPLANEGEOMETRY_P_H + diff --git a/src/extras/geometries/qplanemesh.cpp b/src/extras/geometries/qplanemesh.cpp new file mode 100644 index 000000000..4c6cc914d --- /dev/null +++ b/src/extras/geometries/qplanemesh.cpp @@ -0,0 +1,149 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplanemesh.h" +#include "qplanegeometry.h" + +QT_BEGIN_NAMESPACE + +namespace Qt3DExtras { + +/*! + * \qmltype PlaneMesh + * \instantiates Qt3DRender::QPlaneMesh + * \inqmlmodule Qt3D.Render + * \brief A square planar mesh. + */ + +/*! + * \qmlproperty float PlaneMesh::width + * + * Holds the plane width. + */ + +/*! + * \qmlproperty float PlaneMesh::height + * + * Holds the plane height. + */ + +/*! + * \qmlproperty size PlaneMesh::meshResolution + * + * Holds the plane resolution. + */ + +/*! + * \class Qt3DRender::QPlaneMesh + * \inmodule Qt3DRender + * + * \inherits Qt3DRender::QGeometryRenderer + * + * \brief A square planar mesh. + */ + +/*! + * Constructs a new QPlaneMesh with \a parent. + */ +QPlaneMesh::QPlaneMesh(QNode *parent) + : QGeometryRenderer(parent) +{ + QPlaneGeometry *geometry = new QPlaneGeometry(this); + QObject::connect(geometry, &QPlaneGeometry::widthChanged, this, &QPlaneMesh::widthChanged); + QObject::connect(geometry, &QPlaneGeometry::heightChanged, this, &QPlaneMesh::heightChanged); + QObject::connect(geometry, &QPlaneGeometry::resolutionChanged, this, &QPlaneMesh::meshResolutionChanged); + QGeometryRenderer::setGeometry(geometry); +} + +/*! + * Destroys this plane mesh. + */ +QPlaneMesh::~QPlaneMesh() +{ + QNode::cleanup(); +} + +void QPlaneMesh::setWidth(float width) +{ + static_cast<QPlaneGeometry *>(geometry())->setWidth(width); +} + +/*! + * \property QPlaneMesh::width + * + * Holds the plane width. + */ +float QPlaneMesh::width() const +{ + return static_cast<QPlaneGeometry *>(geometry())->width(); +} + +void QPlaneMesh::setHeight(float height) +{ + static_cast<QPlaneGeometry *>(geometry())->setHeight(height); +} + +/*! + * \property QPlaneMesh::height + * + * Holds the plane height. + */ +float QPlaneMesh::height() const +{ + return static_cast<QPlaneGeometry *>(geometry())->height(); +} + +void QPlaneMesh::setMeshResolution(const QSize &resolution) +{ + static_cast<QPlaneGeometry *>(geometry())->setResolution(resolution); +} + +/*! + * \property QPlaneMesh::meshResolution + * + * Holds the plane resolution. + */ +QSize QPlaneMesh::meshResolution() const +{ + return static_cast<QPlaneGeometry *>(geometry())->resolution(); +} + +} // namespace Qt3DExtras + +QT_END_NAMESPACE diff --git a/src/extras/geometries/qplanemesh.h b/src/extras/geometries/qplanemesh.h new file mode 100644 index 000000000..45edbdf45 --- /dev/null +++ b/src/extras/geometries/qplanemesh.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QPLANEMESH_H +#define QT3DEXTRAS_QPLANEMESH_H + +#include <Qt3DExtras/qt3dextras_global.h> +#include <Qt3DRender/qgeometryrenderer.h> +#include <QSize> + +QT_BEGIN_NAMESPACE + +namespace Qt3DExtras { + +class QT3DEXTRASSHARED_EXPORT QPlaneMesh : public Qt3DRender::QGeometryRenderer +{ + Q_OBJECT + Q_PROPERTY(float width READ width WRITE setWidth NOTIFY widthChanged) + Q_PROPERTY(float height READ height WRITE setHeight NOTIFY heightChanged) + Q_PROPERTY(QSize meshResolution READ meshResolution WRITE setMeshResolution NOTIFY meshResolutionChanged) + +public: + explicit QPlaneMesh(Qt3DCore::QNode *parent = Q_NULLPTR); + ~QPlaneMesh(); + + float width() const; + float height() const; + QSize meshResolution() const; + +public Q_SLOTS: + void setWidth(float width); + void setHeight(float height); + void setMeshResolution(const QSize &resolution); + +Q_SIGNALS: + void meshResolutionChanged(const QSize &meshResolution); + void widthChanged(float width); + void heightChanged(float height); + +private: + // As this is a default provided geometry renderer, no one should be able + // to modify the QGeometryRenderer's properties + + void setInstanceCount(int instanceCount); + void setVertexCount(int vertexCount); + void setIndexOffset(int indexOffset); + void setFirstInstance(int firstInstance); + void setRestartIndexValue(int index); + void setPrimitiveRestartEnabled(bool enabled); + void setGeometry(Qt3DRender::QGeometry *geometry); + void setPrimitiveType(PrimitiveType primitiveType); +}; + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QPLANEMESH_H diff --git a/src/extras/geometries/qspheregeometry.cpp b/src/extras/geometries/qspheregeometry.cpp new file mode 100644 index 000000000..0e610346c --- /dev/null +++ b/src/extras/geometries/qspheregeometry.cpp @@ -0,0 +1,584 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qspheregeometry.h" +#include "qspheregeometry_p.h" +#include <Qt3DRender/qbufferdatagenerator.h> +#include <Qt3DRender/qbuffer.h> +#include <Qt3DRender/qattribute.h> + +#ifndef _USE_MATH_DEFINES +# define _USE_MATH_DEFINES // For MSVC +#endif + +#include <qmath.h> + +QT_BEGIN_NAMESPACE + +using namespace Qt3DRender; + +namespace Qt3DExtras { + +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 QBufferDataGenerator +{ +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 QBufferDataGenerator &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 QBufferDataGenerator +{ +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 QBufferDataGenerator &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 Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, q); + m_indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::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->setDataGenerator(QBufferDataGeneratorPtr(new SphereVertexDataFunctor(m_rings, m_slices, m_radius))); + m_indexBuffer->setDataGenerator(QBufferDataGeneratorPtr(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); +} + +/*! + * \qmltype SphereGeometry + * \instantiates QSphereGeometry + * \inqmlmodule Qt3D.Render + */ + +/*! + * \qmlproperty int SphereGeometry::rings + * + * Holds the number of rings in the sphere. + */ + +/*! + * \qmlproperty int SphereGeometry::slices + * + * Holds the number of slices in the sphere. + */ + +/*! + * \qmlproperty float SphereGeometry::radius + * + * Holds the radius of the sphere. + */ + +/*! + * \qmlproperty bool SphereGeometry::generateTangents + * + * Holds the value of the automatic tangent generation flag. + */ + +/*! + * \qmlproperty Attribute SphereGeometry::positionAttribute + * + * Holds the geometry position attribute. + */ + +/*! + * \qmlproperty Attribute SphereGeometry::normalAttribute + * + * Holds the geometry normal attribute. + */ + +/*! + * \qmlproperty Attribute SphereGeometry::texCoordAttribute + * + * Holds the geometry texture coordinate attribute. + */ + +/*! + * \qmlproperty Attribute SphereGeometry::tangentAttribute + * + * Holds the geometry tangent attribute. + */ + +/*! + * \qmlproperty Attribute SphereGeometry::indexAttribute + * + * Holds the geometry index attribute. + */ + +/*! + * \class QSphereGeometry + * \inmodule Qt3DRender + * + * \inherits QGeometry + */ + +/*! + * Constructs a new QSphereGeometry with \a parent. + */ +QSphereGeometry::QSphereGeometry(QNode *parent) + : QGeometry(*new QSphereGeometryPrivate(), parent) +{ + Q_D(QSphereGeometry); + d->init(); +} + +/*! + * \internal + */ +QSphereGeometry::QSphereGeometry(QSphereGeometryPrivate &dd, QNode *parent) + : QGeometry(dd, parent) +{ + Q_D(QSphereGeometry); + d->init(); +} + +/*! + * Destroys this geometry. + */ +QSphereGeometry::~QSphereGeometry() +{ + QGeometry::cleanup(); +} + +/*! + * Updates vertices based on rings and slices. + */ +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->setDataGenerator(QBufferDataGeneratorPtr(new SphereVertexDataFunctor(d->m_rings, d->m_slices, d->m_radius))); +} + +/*! + * Updates indices based on rings and slices. + */ +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->setDataGenerator(QBufferDataGeneratorPtr(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(rings); + } +} + +void QSphereGeometry::setSlices(int slices) +{ + Q_D(QSphereGeometry); + if (slices != d->m_slices) { + d->m_slices = slices; + updateVertices(); + updateIndices(); + emit slicesChanged(slices); + } +} + +void QSphereGeometry::setRadius(float radius) +{ + Q_D(QSphereGeometry); + if (radius != d->m_radius) { + d->m_radius = radius; + updateVertices(); + emit radiusChanged(radius); + } +} + +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(gen); + } +} + +/*! + * \property QSphereGeometry::generateTangents + * + * Holds the value of the automatic tangent generation flag. + */ +bool QSphereGeometry::generateTangents() const +{ + Q_D(const QSphereGeometry); + return d->m_generateTangents; +} + +/*! + * \property QSphereGeometry::rings + * + * Holds the number of rings in the sphere. + */ +int QSphereGeometry::rings() const +{ + Q_D(const QSphereGeometry); + return d->m_rings; +} + +/*! + * \property QSphereGeometry::slices + * + * Holds the number of slices in the sphere. + */ +int QSphereGeometry::slices() const +{ + Q_D(const QSphereGeometry); + return d->m_slices; +} + +/*! + * \property QSphereGeometry::radius + * + * Holds the radius of the sphere. + */ +float QSphereGeometry::radius() const +{ + Q_D(const QSphereGeometry); + return d->m_radius; +} + +/*! + * \property QSphereGeometry::positionAttribute + * + * Holds the geometry position attribute. + */ +QAttribute *QSphereGeometry::positionAttribute() const +{ + Q_D(const QSphereGeometry); + return d->m_positionAttribute; +} + +/*! + * \property QSphereGeometry::normalAttribute + * + * Holds the geometry normal attribute. + */ +QAttribute *QSphereGeometry::normalAttribute() const +{ + Q_D(const QSphereGeometry); + return d->m_normalAttribute; +} + +/*! + * \property QSphereGeometry::texCoordAttribute + * + * Holds the geometry texture coordinate attribute. + */ +QAttribute *QSphereGeometry::texCoordAttribute() const +{ + Q_D(const QSphereGeometry); + return d->m_texCoordAttribute; +} + +/*! + * \property QSphereGeometry::tangentAttribute + * + * Holds the geometry tangent attribute. + */ +QAttribute *QSphereGeometry::tangentAttribute() const +{ + Q_D(const QSphereGeometry); + return d->m_tangentAttribute; +} + +/*! + * \property QSphereGeometry::indexAttribute + * + * Holds the geometry index attribute. + */ +QAttribute *QSphereGeometry::indexAttribute() const +{ + Q_D(const QSphereGeometry); + return d->m_indexAttribute; +} + +} // Qt3DExtras + +QT_END_NAMESPACE + diff --git a/src/extras/geometries/qspheregeometry.h b/src/extras/geometries/qspheregeometry.h new file mode 100644 index 000000000..acc908d35 --- /dev/null +++ b/src/extras/geometries/qspheregeometry.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QSPHEREGEOMETRY_H +#define QT3DEXTRAS_QSPHEREGEOMETRY_H + +#include <Qt3DRender/qgeometry.h> +#include <Qt3DExtras/qt3dextras_global.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QAttribute; + +} // Qt3DRender + +namespace Qt3DExtras { + +class QSphereGeometryPrivate; + +class QT3DEXTRASSHARED_EXPORT QSphereGeometry : public Qt3DRender::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) + Q_PROPERTY(Qt3DRender::QAttribute *positionAttribute READ positionAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *normalAttribute READ normalAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *texCoordAttribute READ texCoordAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *tangentAttribute READ tangentAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *indexAttribute READ indexAttribute CONSTANT) + +public: + explicit QSphereGeometry(QNode *parent = Q_NULLPTR); + ~QSphereGeometry(); + + void updateVertices(); + void updateIndices(); + + bool generateTangents() const; + int rings() const; + int slices() const; + float radius() const; + + Qt3DRender::QAttribute *positionAttribute() const; + Qt3DRender::QAttribute *normalAttribute() const; + Qt3DRender::QAttribute *texCoordAttribute() const; + Qt3DRender::QAttribute *tangentAttribute() const; + Qt3DRender::QAttribute *indexAttribute() const; + +public Q_SLOTS: + void setRings(int rings); + void setSlices(int slices); + void setRadius(float radius); + void setGenerateTangents(bool gen); + +Q_SIGNALS: + void radiusChanged(float radius); + void ringsChanged(int rings); + void slicesChanged(int slices); + void generateTangentsChanged(bool generateTangents); + +protected: + QSphereGeometry(QSphereGeometryPrivate &dd, QNode *parent = Q_NULLPTR); + +private: + Q_DECLARE_PRIVATE(QSphereGeometry) +}; + +} // Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QSPHEREGEOMETRY_H diff --git a/src/extras/geometries/qspheregeometry_p.h b/src/extras/geometries/qspheregeometry_p.h new file mode 100644 index 000000000..dc96766e1 --- /dev/null +++ b/src/extras/geometries/qspheregeometry_p.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Paul Lemire paul.lemire350@gmail.com +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QSPHEREGEOMETRY_P_H +#define QT3DEXTRAS_QSPHEREGEOMETRY_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 <Qt3DRender/private/qgeometry_p.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QAttribute; +class QBuffer; + +} // Qt3DRender + +namespace Qt3DExtras { + +class QSphereGeometryPrivate : public Qt3DRender::QGeometryPrivate +{ +public: + QSphereGeometryPrivate(); + void init(); + + bool m_generateTangents; + int m_rings; + int m_slices; + float m_radius; + Qt3DRender::QAttribute *m_positionAttribute; + Qt3DRender::QAttribute *m_normalAttribute; + Qt3DRender::QAttribute *m_texCoordAttribute; + Qt3DRender::QAttribute *m_tangentAttribute; + Qt3DRender::QAttribute *m_indexAttribute; + Qt3DRender::QBuffer *m_vertexBuffer; + Qt3DRender::QBuffer *m_indexBuffer; + + Q_DECLARE_PUBLIC(QSphereGeometry); +}; + +} // Qt3DExtras + +QT_END_NAMESPACE + +#endif //QT3DEXTRAS_QSPHEREGEOMETRY_P_H + diff --git a/src/extras/geometries/qspheremesh.cpp b/src/extras/geometries/qspheremesh.cpp new file mode 100644 index 000000000..d5c4a1317 --- /dev/null +++ b/src/extras/geometries/qspheremesh.cpp @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qspheremesh.h" +#include "qspheregeometry.h" + +QT_BEGIN_NAMESPACE + +namespace Qt3DExtras { + +/*! + * \qmltype SphereMesh + * \instantiates Qt3DRender::QSphereMesh + * \inqmlmodule Qt3D.Render + * \brief A spherical mesh. + */ + +/*! + * \qmlproperty int SphereMesh::rings + * + * Holds the number of rings in the mesh. + */ + +/*! + * \qmlproperty int SphereMesh::slices + * + * Holds the number of slices in the mesh. + */ + +/*! + * \qmlproperty float SphereMesh::radius + * + * Holds the radius of the sphere. + */ + +/*! + * \qmlproperty bool SphereMesh::generateTangents + * + * Holds the value of the automatic tangent generation flag. + */ + +/*! + * \class Qt3DRender::QSphereMesh + * \inmodule Qt3DRender + * + * \inherits Qt3DRender::QGeometryRenderer + * + * \brief A spherical mesh. + */ + +/*! + * Constructs a new QSphereMesh with \a parent. + */ +QSphereMesh::QSphereMesh(QNode *parent) + : QGeometryRenderer(parent) +{ + 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); +} + +/*! + * Destroys this sphere mesh. + */ +QSphereMesh::~QSphereMesh() +{ + QNode::cleanup(); +} + +void QSphereMesh::setRings(int rings) +{ + static_cast<QSphereGeometry *>(geometry())->setRings(rings); +} + +void QSphereMesh::setSlices(int slices) +{ + static_cast<QSphereGeometry *>(geometry())->setSlices(slices); +} + +void QSphereMesh::setRadius(float radius) +{ + static_cast<QSphereGeometry *>(geometry())->setRadius(radius); +} + +void QSphereMesh::setGenerateTangents(bool gen) +{ + static_cast<QSphereGeometry *>(geometry())->setGenerateTangents(gen); +} + +/*! + * \property QSphereMesh::generateTangents + * + * Holds the value of the automatic tangent generation flag. + */ +bool QSphereMesh::generateTangents() const +{ + return static_cast<QSphereGeometry *>(geometry())->generateTangents(); +} + +/*! + * \property QSphereMesh::rings + * + * Holds the number of rings in the mesh. + */ +int QSphereMesh::rings() const +{ + return static_cast<QSphereGeometry *>(geometry())->rings(); +} + +/*! + * \property QSphereMesh::slices + * + * Holds the number of slices in the mesh. + */ +int QSphereMesh::slices() const +{ + return static_cast<QSphereGeometry *>(geometry())->slices(); +} + +/*! + * \property QSphereMesh::radius + * + * Holds the radius of the sphere. + */ +float QSphereMesh::radius() const +{ + return static_cast<QSphereGeometry *>(geometry())->radius(); +} + +} // Qt3DExtras + +QT_END_NAMESPACE diff --git a/src/extras/geometries/qspheremesh.h b/src/extras/geometries/qspheremesh.h new file mode 100644 index 000000000..7fe346e41 --- /dev/null +++ b/src/extras/geometries/qspheremesh.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QSPHEREMESH_H +#define QT3DEXTRAS_QSPHEREMESH_H + +#include <Qt3DExtras/qt3dextras_global.h> +#include <Qt3DRender/qgeometryrenderer.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DExtras { + +class QSphereMeshPrivate; + +class QT3DEXTRASSHARED_EXPORT QSphereMesh : public Qt3DRender::QGeometryRenderer +{ + 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 QSphereMesh(Qt3DCore::QNode *parent = Q_NULLPTR); + ~QSphereMesh(); + + int rings() const; + int slices() const; + float radius() const; + bool generateTangents() const; + +public Q_SLOTS: + void setRings(int rings); + void setSlices(int slices); + void setRadius(float radius); + void setGenerateTangents(bool gen); + +Q_SIGNALS: + void radiusChanged(float radius); + void ringsChanged(int rings); + void slicesChanged(int slices); + void generateTangentsChanged(bool generateTangents); + +private: + // As this is a default provided geometry renderer, no one should be able + // to modify the QGeometryRenderer's properties + + void setVertexCount(int vertexCount); + void setIndexOffset(int indexOffset); + void setFirstInstance(int firstInstance); + void setRestartIndexValue(int index); + void setPrimitiveRestartEnabled(bool enabled); + void setGeometry(Qt3DRender::QGeometry *geometry); + void setPrimitiveType(PrimitiveType primitiveType); +}; + +} // namespace Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QSPHEREMESH_H diff --git a/src/extras/geometries/qtorusgeometry.cpp b/src/extras/geometries/qtorusgeometry.cpp new file mode 100644 index 000000000..fe9ac7821 --- /dev/null +++ b/src/extras/geometries/qtorusgeometry.cpp @@ -0,0 +1,511 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtorusgeometry.h" +#include "qtorusgeometry_p.h" +#include <Qt3DRender/qbuffer.h> +#include <Qt3DRender/qbufferdatagenerator.h> +#include <Qt3DRender/qattribute.h> +#include <qmath.h> +#include <QVector3D> + +QT_BEGIN_NAMESPACE + +using namespace Qt3DRender; + +namespace Qt3DExtras { + +namespace { + +QByteArray createTorusVertexData(double radius, double minorRadius, + int rings, int sides) +{ + 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); + + float* fptr = reinterpret_cast<float*>(bufferBytes.data()); + + 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 ); + + 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); + + *fptr++ = r * cu; + *fptr++ = r * su; + *fptr++ = minorRadius * sv; + + *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; +} + +QByteArray createTorusIndexData(int rings, int sides) +{ + 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; +} + +} // anonymous + +class TorusVertexDataFunctor : public QBufferDataGenerator +{ +public: + TorusVertexDataFunctor(int rings, int slices, float radius, float minorRadius) + : m_rings(rings) + , m_sides(slices) + , m_radius(radius) + , m_minorRadius(minorRadius) + { + } + + QByteArray operator ()() Q_DECL_OVERRIDE + { + return createTorusVertexData(m_radius, m_minorRadius, m_rings, m_sides); + } + + bool operator ==(const QBufferDataGenerator &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; + } + + QT3D_FUNCTOR(TorusVertexDataFunctor) + +private: + int m_rings; + int m_sides; + float m_radius; + float m_minorRadius; +}; + +class TorusIndexDataFunctor : public QBufferDataGenerator +{ +public: + TorusIndexDataFunctor(int rings, int slices) + : m_rings(rings) + , m_sides(slices) + { + } + + QByteArray operator ()() Q_DECL_OVERRIDE + { + return createTorusIndexData(m_rings, m_sides); + } + + bool operator ==(const QBufferDataGenerator &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; + } + + QT3D_FUNCTOR(TorusIndexDataFunctor) + +private: + int m_rings; + int m_sides; +}; + +QTorusGeometryPrivate::QTorusGeometryPrivate() + : QGeometryPrivate() + , m_rings(16) + , m_slices(16) + , m_radius(1.0f) + , m_minorRadius(1.0f) + , m_positionAttribute(Q_NULLPTR) + , m_normalAttribute(Q_NULLPTR) + , m_texCoordAttribute(Q_NULLPTR) + , m_indexAttribute(Q_NULLPTR) + , m_vertexBuffer(Q_NULLPTR) + , m_indexBuffer(Q_NULLPTR) +{ +} + +void QTorusGeometryPrivate::init() +{ + Q_Q(QTorusGeometry); + m_positionAttribute = new QAttribute(q); + m_normalAttribute = new QAttribute(q); + m_texCoordAttribute = new QAttribute(q); + m_indexAttribute = new QAttribute(q); + m_vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, q); + m_indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, q); + // 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->setDataGenerator(QBufferDataGeneratorPtr(new TorusVertexDataFunctor(m_rings, m_slices, m_radius, m_minorRadius))); + m_indexBuffer->setDataGenerator(QBufferDataGeneratorPtr(new TorusIndexDataFunctor(m_rings, m_slices))); + + q->addAttribute(m_positionAttribute); + q->addAttribute(m_texCoordAttribute); + q->addAttribute(m_normalAttribute); + q->addAttribute(m_indexAttribute); +} + +/*! + * \qmltype TorusGeometry + * \instantiates Qt3DRender::QTorusGeometry + * \inqmlmodule Qt3D.Render + */ + +/*! + * \qmlproperty int TorusGeometry::rings + * + * Holds the number of rings in the torus. + */ + +/*! + * \qmlproperty int TorusGeometry::slices + * + * Holds the number of slices in the torus. + */ + +/*! + * \qmlproperty float TorusGeometry::radius + * + * Holds the outer radius of the torus. + */ + +/*! + * \qmlproperty float TorusGeometry::minorRadius + * + * Holds the inner radius of the torus. + */ + +/*! + * \qmlproperty Attribute TorusGeometry::positionAttribute + * + * Holds the geometry position attribute. + */ + +/*! + * \qmlproperty Attribute TorusGeometry::normalAttribute + * + * Holds the geometry normal attribute. + */ + +/*! + * \qmlproperty Attribute TorusGeometry::texCoordAttribute + * + * Holds the geometry texture coordinate attribute. + */ + +/*! + * \qmlproperty Attribute TorusGeometry::indexAttribute + * + * Holds the geometry index attribute. + */ + +/*! + * \class Qt3DRender::QTorusGeometry + * \inmodule Qt3DRender + * + * \inherits Qt3DRender::QGeometry + */ + +/*! + * Constructs a new QTorusGeometry with \a parent. + */ +QTorusGeometry::QTorusGeometry(QNode *parent) + : QGeometry(*new QTorusGeometryPrivate(), parent) +{ + Q_D(QTorusGeometry); + d->init(); +} + +/*! + * \internal + */ +QTorusGeometry::QTorusGeometry(QTorusGeometryPrivate &dd, QNode *parent) + : QGeometry(dd, parent) +{ + Q_D(QTorusGeometry); + d->init(); +} + +/*! + * Destroys this geometry. + */ +QTorusGeometry::~QTorusGeometry() +{ + QGeometry::cleanup(); +} + +/*! + * Updates vertices based on rings and slices. + */ +void QTorusGeometry::updateVertices() +{ + Q_D(QTorusGeometry); + const int nVerts = d->m_slices * (d->m_rings + 1); + d->m_positionAttribute->setCount(nVerts); + d->m_texCoordAttribute->setCount(nVerts); + d->m_normalAttribute->setCount(nVerts); + d->m_vertexBuffer->setDataGenerator(QBufferDataGeneratorPtr(new TorusVertexDataFunctor(d->m_rings, d->m_slices, d->m_radius, d->m_minorRadius))); +} + +/*! + * Updates indices based on rings and slices. + */ +void QTorusGeometry::updateIndices() +{ + Q_D(QTorusGeometry); + const int faces = (d->m_slices * 2) * d->m_rings; + d->m_indexAttribute->setCount(faces * 3); + d->m_indexBuffer->setDataGenerator(QBufferDataGeneratorPtr(new TorusIndexDataFunctor(d->m_rings, d->m_slices))); + +} + +void QTorusGeometry::setRings(int rings) +{ + Q_D(QTorusGeometry); + if (rings != d->m_rings) { + d->m_rings = rings; + updateVertices(); + updateIndices(); + emit ringsChanged(rings); + } +} + +void QTorusGeometry::setSlices(int slices) +{ + Q_D(QTorusGeometry); + if (slices != d->m_slices) { + d->m_slices = slices; + updateVertices(); + updateIndices(); + emit slicesChanged(slices); + } +} + +void QTorusGeometry::setRadius(float radius) +{ + Q_D(QTorusGeometry); + if (radius != d->m_radius) { + d->m_radius = radius; + updateVertices(); + emit radiusChanged(radius); + } +} + +void QTorusGeometry::setMinorRadius(float minorRadius) +{ + Q_D(QTorusGeometry); + if (minorRadius != d->m_minorRadius) { + d->m_minorRadius = minorRadius; + updateVertices(); + emit minorRadiusChanged(minorRadius); + } +} + +/*! + * \property QTorusGeometry::rings + * + * Holds the number of rings in the torus. + */ +int QTorusGeometry::rings() const +{ + Q_D(const QTorusGeometry); + return d->m_rings; +} + +/*! + * \property QTorusGeometry::slices + * + * Holds the number of slices in the torus. + */ +int QTorusGeometry::slices() const +{ + Q_D(const QTorusGeometry); + return d->m_slices; +} + +/*! + * \property QTorusGeometry::radius + * + * Holds the outer radius of the torus. + */ +float QTorusGeometry::radius() const +{ + Q_D(const QTorusGeometry); + return d->m_radius; +} + +/*! + * \property QTorusGeometry::minorRadius + * + * Holds the inner radius of the torus. + */ +float QTorusGeometry::minorRadius() const +{ + Q_D(const QTorusGeometry); + return d->m_minorRadius; +} + +/*! + * \property QTorusGeometry::positionAttribute + * + * Holds the geometry position attribute. + */ +QAttribute *QTorusGeometry::positionAttribute() const +{ + Q_D(const QTorusGeometry); + return d->m_positionAttribute; +} + +/*! + * \property QTorusGeometry::normalAttribute + * + * Holds the geometry normal attribute. + */ +QAttribute *QTorusGeometry::normalAttribute() const +{ + Q_D(const QTorusGeometry); + return d->m_normalAttribute; +} + +/*! + * \property QTorusGeometry::texCoordAttribute + * + * Holds the geometry texture coordinate attribute. + */ +QAttribute *QTorusGeometry::texCoordAttribute() const +{ + Q_D(const QTorusGeometry); + return d->m_texCoordAttribute; +} + +/*! + * \property QTorusGeometry::indexAttribute + * + * Holds the geometry index attribute. + */ +QAttribute *QTorusGeometry::indexAttribute() const +{ + Q_D(const QTorusGeometry); + return d->m_indexAttribute; +} + +} // Qt3DExtras + +QT_END_NAMESPACE diff --git a/src/extras/geometries/qtorusgeometry.h b/src/extras/geometries/qtorusgeometry.h new file mode 100644 index 000000000..99b76acd3 --- /dev/null +++ b/src/extras/geometries/qtorusgeometry.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QTORUSGEOMETRY_H +#define QT3DEXTRAS_QTORUSGEOMETRY_H + +#include <Qt3DExtras/qt3dextras_global.h> +#include <Qt3DRender/qgeometry.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QAttribute; + +} // Qt3DRender + +namespace Qt3DExtras { + +class QTorusGeometryPrivate; + +class QT3DEXTRASSHARED_EXPORT QTorusGeometry : public Qt3DRender::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(float minorRadius READ minorRadius WRITE setMinorRadius NOTIFY minorRadiusChanged) + Q_PROPERTY(Qt3DRender::QAttribute *positionAttribute READ positionAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *normalAttribute READ normalAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *texCoordAttribute READ texCoordAttribute CONSTANT) + Q_PROPERTY(Qt3DRender::QAttribute *indexAttribute READ indexAttribute CONSTANT) + +public: + explicit QTorusGeometry(QNode *parent = Q_NULLPTR); + ~QTorusGeometry(); + + void updateVertices(); + void updateIndices(); + + int rings() const; + int slices() const; + float radius() const; + float minorRadius() const; + + Qt3DRender::QAttribute *positionAttribute() const; + Qt3DRender::QAttribute *normalAttribute() const; + Qt3DRender::QAttribute *texCoordAttribute() const; + Qt3DRender::QAttribute *indexAttribute() const; + +public Q_SLOTS: + void setRings(int rings); + void setSlices(int slices); + void setRadius(float radius); + void setMinorRadius(float minorRadius); + +Q_SIGNALS: + void radiusChanged(float radius); + void ringsChanged(int rings); + void slicesChanged(int slices); + void minorRadiusChanged(float minorRadius); + + +protected: + QTorusGeometry(QTorusGeometryPrivate &dd, QNode *parent = Q_NULLPTR); + +private: + Q_DECLARE_PRIVATE(QTorusGeometry) +}; + +} // Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QTORUSGEOMETRY_H diff --git a/src/extras/geometries/qtorusgeometry_p.h b/src/extras/geometries/qtorusgeometry_p.h new file mode 100644 index 000000000..b4bcbde9f --- /dev/null +++ b/src/extras/geometries/qtorusgeometry_p.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QTORUSGEOMETRY_P_H +#define QT3DEXTRAS_QTORUSGEOMETRY_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 <Qt3DRender/private/qgeometry_p.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QAttribute; +class QBuffer; + +} // Qt3DRender + +namespace Qt3DExtras { + +class QTorusGeometryPrivate : public Qt3DRender::QGeometryPrivate +{ +public: + QTorusGeometryPrivate(); + void init(); + + int m_rings; + int m_slices; + float m_radius; + float m_minorRadius; + Qt3DRender::QAttribute *m_positionAttribute; + Qt3DRender::QAttribute *m_normalAttribute; + Qt3DRender::QAttribute *m_texCoordAttribute; + Qt3DRender::QAttribute *m_indexAttribute; + Qt3DRender::QBuffer *m_vertexBuffer; + Qt3DRender::QBuffer *m_indexBuffer; + + Q_DECLARE_PUBLIC(QTorusGeometry) +}; + +} // Qt3DExtras + + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QTORUSGEOMETRY_P_H + diff --git a/src/extras/geometries/qtorusmesh.cpp b/src/extras/geometries/qtorusmesh.cpp new file mode 100644 index 000000000..0f2143835 --- /dev/null +++ b/src/extras/geometries/qtorusmesh.cpp @@ -0,0 +1,177 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _USE_MATH_DEFINES +# define _USE_MATH_DEFINES // For MSVC +#endif + +#include "qtorusmesh.h" +#include "qtorusgeometry.h" + +QT_BEGIN_NAMESPACE + +namespace Qt3DExtras { + +/*! + * \qmltype TorusMesh + * \instantiates Qt3DRender::QTorusMesh + * \inqmlmodule Qt3D.Render + * \brief A custom mesh. + */ + +/*! + * \qmlproperty int TorusMesh::rings + * + * Holds the number of rings in the mesh. + */ + +/*! + * \qmlproperty int TorusMesh::slices + * + * Holds the number of slices in the mesh. + */ + +/*! + * \qmlproperty float TorusMesh::radius + * + * Holds the outer radius of the torus. + */ + +/*! + * \qmlproperty float TorusMesh::minorRadius + * + * Holds the inner radius of the torus. + */ + +/*! + * \class Qt3DRender::QTorusMesh + * \inmodule Qt3DRender + * + * \inherits Qt3DRender::QGeometryRenderer + * + * \brief A custom mesh. + */ + +/*! + * Constructs a new QTorusMesh with \a parent. + */ +QTorusMesh::QTorusMesh(QNode *parent) + : QGeometryRenderer(parent) +{ + QTorusGeometry *geometry = new QTorusGeometry(this); + QObject::connect(geometry, &QTorusGeometry::radiusChanged, this, &QTorusMesh::radiusChanged); + QObject::connect(geometry, &QTorusGeometry::ringsChanged, this, &QTorusMesh::ringsChanged); + QObject::connect(geometry, &QTorusGeometry::slicesChanged, this, &QTorusMesh::slicesChanged); + QObject::connect(geometry, &QTorusGeometry::minorRadiusChanged, this, &QTorusMesh::minorRadiusChanged); + + QGeometryRenderer::setGeometry(geometry); +} + +/*! + * Destroys this torus mesh. + */ +QTorusMesh::~QTorusMesh() +{ + QGeometryRenderer::cleanup(); +} + +void QTorusMesh::setRings(int rings) +{ + static_cast<QTorusGeometry *>(geometry())->setRings(rings); +} + +void QTorusMesh::setSlices(int slices) +{ + static_cast<QTorusGeometry *>(geometry())->setSlices(slices); +} + +void QTorusMesh::setRadius(float radius) +{ + static_cast<QTorusGeometry *>(geometry())->setRadius(radius); +} + +void QTorusMesh::setMinorRadius(float minorRadius) +{ + static_cast<QTorusGeometry *>(geometry())->setMinorRadius(minorRadius); +} + +/*! + * \property QTorusMesh::rings + * + * Holds the number of rings in the mesh. + */ +int QTorusMesh::rings() const +{ + return static_cast<QTorusGeometry *>(geometry())->rings(); +} + +/*! + * \property QTorusMesh::slices + * + * Holds the number of slices in the mesh. + */ +int QTorusMesh::slices() const +{ + return static_cast<QTorusGeometry *>(geometry())->slices(); +} + +/*! + * \property QTorusMesh::radius + * + * Holds the outer radius of the torus. + */ +float QTorusMesh::radius() const +{ + return static_cast<QTorusGeometry *>(geometry())->radius(); +} + +/*! + * \property QTorusMesh::minorRadius + * + * Holds the inner radius of the torus. + */ +float QTorusMesh::minorRadius() const +{ + return static_cast<QTorusGeometry *>(geometry())->minorRadius(); +} + +} // namespace Qt3DExtras + +QT_END_NAMESPACE diff --git a/src/extras/geometries/qtorusmesh.h b/src/extras/geometries/qtorusmesh.h new file mode 100644 index 000000000..16d1be736 --- /dev/null +++ b/src/extras/geometries/qtorusmesh.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QTORUSMESH_H +#define QT3DEXTRAS_QTORUSMESH_H + +#include <Qt3DExtras/qt3dextras_global.h> +#include <Qt3DRender/qgeometryrenderer.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DExtras { + +class QT3DEXTRASSHARED_EXPORT QTorusMesh : public Qt3DRender::QGeometryRenderer +{ + 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(float minorRadius READ minorRadius WRITE setMinorRadius NOTIFY minorRadiusChanged) +public: + explicit QTorusMesh(Qt3DCore::QNode *parent = Q_NULLPTR); + ~QTorusMesh(); + + int rings() const; + int slices() const; + float radius() const; + float minorRadius() const; + +public Q_SLOTS: + void setRings(int rings); + void setSlices(int slices); + void setRadius(float radius); + void setMinorRadius(float minorRadius); + +Q_SIGNALS: + void radiusChanged(float radius); + void ringsChanged(int rings); + void slicesChanged(int slices); + void minorRadiusChanged(float minorRadius); + +private: + // As this is a default provided geometry renderer, no one should be able + // to modify the QGeometryRenderer's properties + + void setInstanceCount(int instanceCount); + void setVertexCount(int vertexCount); + void setIndexOffset(int indexOffset); + void setFirstInstance(int firstInstance); + void setRestartIndexValue(int index); + void setPrimitiveRestartEnabled(bool enabled); + void setGeometry(Qt3DRender::QGeometry *geometry); + void setPrimitiveType(PrimitiveType primitiveType); +}; + +} // namespace Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QTORUSMESH_H |