diff options
-rw-r--r-- | examples/cylinder-cpp/cylinder-cpp.pro | 7 | ||||
-rw-r--r-- | examples/cylinder-cpp/main.cpp | 155 | ||||
-rw-r--r-- | examples/cylinder-qml/ForwardRenderer.qml | 73 | ||||
-rw-r--r-- | examples/cylinder-qml/cylinder-qml.pro | 13 | ||||
-rw-r--r-- | examples/cylinder-qml/cylinder-qml.qrc | 6 | ||||
-rw-r--r-- | examples/cylinder-qml/main.cpp | 63 | ||||
-rw-r--r-- | examples/cylinder-qml/main.qml | 115 | ||||
-rw-r--r-- | examples/examples.pro | 10 | ||||
-rw-r--r-- | src/quick3d/imports/render/qt3dquick3drenderplugin.cpp | 2 | ||||
-rw-r--r-- | src/render/frontend/qcylindermesh.cpp | 356 | ||||
-rw-r--r-- | src/render/frontend/qcylindermesh.h | 94 | ||||
-rw-r--r-- | src/render/frontend/render-frontend.pri | 2 |
12 files changed, 896 insertions, 0 deletions
diff --git a/examples/cylinder-cpp/cylinder-cpp.pro b/examples/cylinder-cpp/cylinder-cpp.pro new file mode 100644 index 000000000..2bee5ff07 --- /dev/null +++ b/examples/cylinder-cpp/cylinder-cpp.pro @@ -0,0 +1,7 @@ +TEMPLATE = app + +QT += 3dcore 3drenderer + +SOURCES += main.cpp + + diff --git a/examples/cylinder-cpp/main.cpp b/examples/cylinder-cpp/main.cpp new file mode 100644 index 000000000..ed7f8ca10 --- /dev/null +++ b/examples/cylinder-cpp/main.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE: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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QGuiApplication> + +#include <Qt3DCore/window.h> +#include <Qt3DCore/qcamera.h> +#include <Qt3DCore/qentity.h> +#include <Qt3DCore/qcameralens.h> + +#include <Qt3DRenderer/qcylindermesh.h> +#include <Qt3DRenderer/qmesh.h> +#include <Qt3DRenderer/qtechnique.h> +#include <Qt3DRenderer/qmaterial.h> +#include <Qt3DCore/qabstracteffect.h> +#include <Qt3DRenderer/qtexture.h> +#include <Qt3DRenderer/qrenderpass.h> +#include <Qt3DRenderer/qscene.h> + +#include <Qt3DCore/qscaletransform.h> +#include <Qt3DCore/qrotatetransform.h> +#include <Qt3DCore/qlookattransform.h> +#include <Qt3DCore/qtransform.h> + +#include <Qt3DRenderer/qcameraselector.h> +#include <Qt3DRenderer/qrenderpassfilter.h> +#include <Qt3DRenderer/qtechniquefilter.h> +#include <Qt3DRenderer/qviewport.h> +#include <Qt3DRenderer/rendereraspect.h> +#include <Qt3DRenderer/qframegraph.h> +#include <Qt3DRenderer/qclearbuffer.h> + +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + + Qt3D::Window view; + view.registerAspect(new Qt3D::RendererAspect()); + + // Root entity + Qt3D::QEntity *rootEntity = new Qt3D::QEntity(); + + // Camera + Qt3D::QCamera *cameraEntity = new Qt3D::QCamera(); + cameraEntity->setObjectName(QStringLiteral("cameraEntity")); + Qt3D::QCameraLens *cameraLens = new Qt3D::QCameraLens(); + Qt3D::QTransform *cameraTransform = new Qt3D::QTransform(); + Qt3D::QLookAtTransform *cameraLookAtTransform = new Qt3D::QLookAtTransform(); + + cameraLens->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f); + cameraLookAtTransform->setPosition(QVector3D(0, 0, -20.0f)); + cameraLookAtTransform->setUpVector(QVector3D(0, 1, 0)); + cameraLookAtTransform->setViewCenter(QVector3D(0, 0, 0)); + cameraTransform->appendTransform(cameraLookAtTransform); + cameraEntity->setTransform(cameraTransform); + cameraEntity->setLens(cameraLens); + view.setCamera(cameraEntity); + + // FrameGraph + Qt3D::QFrameGraph *frameGraph = new Qt3D::QFrameGraph(); + Qt3D::QTechniqueFilter *techniqueFilter = new Qt3D::QTechniqueFilter(); + Qt3D::QCameraSelector *cameraSelector = new Qt3D::QCameraSelector(); + Qt3D::QRenderPassFilter *defaultRenderPassFilter = new Qt3D::QRenderPassFilter(); + Qt3D::QViewport *viewport = new Qt3D::QViewport(); + Qt3D::QClearBuffer *clearBuffer = new Qt3D::QClearBuffer(); + + // TechiqueFilter and renderPassFilter are not implement yet + + viewport->setRect(QRectF(0, 0, 1, 1)); + viewport->addChild(clearBuffer); + clearBuffer->setBuffers(Qt3D::QClearBuffer::ColorDepthBuffer); + clearBuffer->addChild(cameraSelector); + cameraSelector->setCamera(cameraEntity); + cameraSelector->addChild(defaultRenderPassFilter); + techniqueFilter->addChild(viewport); + + frameGraph->setActiveFrameGraph(techniqueFilter); + + + // Cylinder shape data + Qt3D::QCylinderMesh *cylinder = new Qt3D::QCylinderMesh(); + cylinder->setRadius(1); + cylinder->setLength(3); + cylinder->setRings(100); + cylinder->setSlices(20); + + // CylinderMesh Transform + Qt3D::QScaleTransform *cylinderScale = new Qt3D::QScaleTransform(); + Qt3D::QRotateTransform *cylinderRotation = new Qt3D::QRotateTransform(); + Qt3D::QTransform *cylinderTransforms = new Qt3D::QTransform(); + + cylinderScale->setScale3D(QVector3D(1.5f, 1.5f, 1.5f)); + cylinderRotation->setAngleDeg(45.0f); + cylinderRotation->setAxis(QVector3D(1, 0, 0)); + + cylinderTransforms->appendTransform(cylinderScale); + cylinderTransforms->appendTransform(cylinderRotation); + + // Cylinder + Qt3D::QEntity *cylinderEntity = new Qt3D::QEntity(); + cylinderEntity->addComponent(cylinder); + cylinderEntity->addComponent(cylinderTransforms); + + // Setting the FrameGraph + rootEntity->addComponent(frameGraph); + + // Build Node Tree + rootEntity->addChild(cameraEntity); + rootEntity->addChild(cylinderEntity); + + // Set root object of the scene + view.setRootObject(rootEntity); + // Show window + view.show(); + + return app.exec(); +} diff --git a/examples/cylinder-qml/ForwardRenderer.qml b/examples/cylinder-qml/ForwardRenderer.qml new file mode 100644 index 000000000..e2d1537b3 --- /dev/null +++ b/examples/cylinder-qml/ForwardRenderer.qml @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE: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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt3D 2.0 +import Qt3D.Render 2.0 + +TechniqueFilter { + id: root + + // Expose the viewport rect and camera. This allows users of this + // forward rendering framegraph to decide which camera in the + // scene renders to a given viewport region. + // + // Using this as a building block for a larger framegraph would + // allow a scene to be rendered multiple times f.i. to different + // viewports using different cameras + property alias viewportRect: viewport.rect + property alias camera: cameraSelector.camera + + criteria : [ + Criterion { name : "RenderingStyle"; value : "forward"} + ] + + Viewport { + id: viewport + rect: Qt.rect(0.0, 0.0, 1.0, 1.0) // From Top Left + + ClearBuffer { + buffers : ClearBuffer.ColorDepthBuffer + CameraSelector { + id : cameraSelector + } + } + } +} diff --git a/examples/cylinder-qml/cylinder-qml.pro b/examples/cylinder-qml/cylinder-qml.pro new file mode 100644 index 000000000..8392eaa7e --- /dev/null +++ b/examples/cylinder-qml/cylinder-qml.pro @@ -0,0 +1,13 @@ +TEMPLATE = app + +QT += 3dcore 3drenderer 3dquick qml quick + +SOURCES += \ + main.cpp + +OTHER_FILES += \ + main.qml \ + ForwardRenderer.qml + +RESOURCES += \ + cylinder-qml.qrc diff --git a/examples/cylinder-qml/cylinder-qml.qrc b/examples/cylinder-qml/cylinder-qml.qrc new file mode 100644 index 000000000..fedae75c1 --- /dev/null +++ b/examples/cylinder-qml/cylinder-qml.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + <file>ForwardRenderer.qml</file> + </qresource> +</RCC> diff --git a/examples/cylinder-qml/main.cpp b/examples/cylinder-qml/main.cpp new file mode 100644 index 000000000..1efee589c --- /dev/null +++ b/examples/cylinder-qml/main.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE: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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <Qt3DQuick/quickwindow.h> +#include <Qt3DRenderer/rendereraspect.h> + + +#include <QGuiApplication> +#include <QtQml> + +int main(int argc, char* argv[]) +{ + QGuiApplication app(argc, argv); + + Qt3D::Quick::QuickWindow view; + view.registerAspect(new Qt3D::RendererAspect()); + // There should be some synchronising mechanism to make sure + // the source is set after alll aspects have been completely initialized + // Otherwise we might encounter cases where an Aspect's QML elements have + // not yet been registered + view.setSource(QUrl("qrc:/main.qml")); + view.show(); + + return app.exec(); +} diff --git a/examples/cylinder-qml/main.qml b/examples/cylinder-qml/main.qml new file mode 100644 index 000000000..bdf262238 --- /dev/null +++ b/examples/cylinder-qml/main.qml @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE: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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt3D 2.0 +import Qt3D.Render 2.0 + +// For Qt.vector3d() and friends. For some reason this is provided by +// QQuickValueTypeProvider in QtQuick rather than the default value +// type provider in QtQml. So we will need to replicate this in Qt3D +// for the types that we wish to support. Otherwise we'll have to import +// QtQuick 2.1 all over the place. +import QtQuick 2.1 as QQ2 + +Entity { + id: sceneRoot + + Camera { + id: camera + lens : CameraLens { + projectionType: CameraLens.PerspectiveProjection + fieldOfView: 45 + aspectRatio: 16/9 + nearPlane : 0.1 + farPlane : 1000.0 + } + + transform : Transform { + LookAt { + position: Qt.vector3d( 0.0, 0.0, -20.0 ) + upVector: Qt.vector3d( 0.0, 1.0, 0.0 ) + viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 ) + } + } + } + + Configuration { + controlledCamera: camera + } + + FrameGraph { + id : external_forward_renderer + activeFrameGraph : ForwardRenderer { + camera: camera + } + } + + components: [external_forward_renderer] + + CylinderMesh { + id: mesh + radius: 1 + length: 3 + rings: 100 + slices: 20 + } + + Transform { + id: transform + Scale { scale3D: Qt.vector3d(1.5, 1.5, 1.5) } + Rotate { + angle: 45 + axis: Qt.vector3d(1, 0, 0) + } + } + + Material { + id: material + effect : Effect { + } + } + + Entity { + id: mainEntity + objectName: "mainEntity" + components: [ mesh, material, transform ] + } +} diff --git a/examples/examples.pro b/examples/examples.pro index 6a1703e48..cb97d9f84 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -31,6 +31,14 @@ src_toruscpp.subdir = $$PWD/torus-cpp src_toruscpp.target = sub-toruscpp src_toruscpp.depends = src_exampleresources +src_cylinderqml.subdir = $$PWD/cylinder-qml +src_cylinderqml.target = sub-cylinderqml +src_cylinderqml.depends = src_exampleresources + +src_cylindercpp.subdir = $$PWD/cylinder-cpp +src_cylindercpp.target = sub-cylindercpp +src_cylindercpp.depends = src_exampleresources + src_bigmodelqml.subdir = $$PWD/bigmodel-qml src_bigmodelqml.target = sub-bigmodelqml src_bigmodelqml.depends = src_exampleresources @@ -60,6 +68,8 @@ SUBDIRS += \ src_multiviewport \ src_torusqml \ src_toruscpp \ + src_cylinderqml \ + src_cylindercpp \ src_bigmodelqml \ src_deferredrenderer \ src_wireframe \ diff --git a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp index 63b889a11..7d52753d1 100644 --- a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp +++ b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp @@ -62,6 +62,7 @@ #include <Qt3DRenderer/qcriterion.h> #include <Qt3DRenderer/qparametermapper.h> #include <Qt3DRenderer/qcuboidmesh.h> +#include <Qt3DRenderer/qcylindermesh.h> #include <Qt3DRenderer/qplanemesh.h> #include <Qt3DRenderer/qspheremesh.h> #include <Qt3DRenderer/qtorusmesh.h> @@ -121,6 +122,7 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri) qmlRegisterType<Qt3D::QMesh>(uri, 2, 0, "Mesh"); qmlRegisterUncreatableType<Qt3D::QAbstractShapeMesh>(uri, 2, 0, "QAbstractShapeMesh", QStringLiteral("Shape is an abstract base class")); qmlRegisterType<Qt3D::QCuboidMesh>(uri, 2, 0, "CuboidMesh"); + qmlRegisterType<Qt3D::QCylinderMesh>(uri, 2, 0, "CylinderMesh"); qmlRegisterType<Qt3D::QPlaneMesh>(uri, 2, 0, "PlaneMesh"); qmlRegisterType<Qt3D::QTorusMesh>(uri, 2, 0, "TorusMesh"); qmlRegisterType<Qt3D::QSphereMesh>(uri, 2, 0, "SphereMesh"); diff --git a/src/render/frontend/qcylindermesh.cpp b/src/render/frontend/qcylindermesh.cpp new file mode 100644 index 000000000..da917c808 --- /dev/null +++ b/src/render/frontend/qcylindermesh.cpp @@ -0,0 +1,356 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _USE_MATH_DEFINES +# define _USE_MATH_DEFINES // For MSVC +#endif + +#include "qcylindermesh.h" +#include "qabstractshapemesh_p.h" +#include "qbuffer.h" +#include "qattribute.h" + +#include <cmath> + +QT_BEGIN_NAMESPACE + +namespace Qt3D { + +class CylinderMeshFunctor : public QAbstractMeshFunctor +{ +public: + CylinderMeshFunctor(int rings, int slices, float radius, float length); + QAbstractMeshDataPtr operator ()() Q_DECL_OVERRIDE; + +private: + int m_rings; + int m_slices; + float m_radius; + float m_length; +}; + +class QCylinderMeshPrivate : public QAbstractShapeMeshPrivate +{ + QCylinderMeshPrivate(QCylinderMesh *qq) + : QAbstractShapeMeshPrivate(qq) + , m_rings(16) + , m_slices(16) + , m_radius(1.0) + , m_length(1.0) + {} + + Q_DECLARE_PUBLIC(QCylinderMesh) + int m_rings; + int m_slices; + float m_radius; + float m_length; +}; + +QCylinderMesh::QCylinderMesh(QNode *parent) + : QAbstractShapeMesh(*new QCylinderMeshPrivate(this), parent) +{ + setDirty(true); +} + +void QCylinderMesh::copy(const QNode *ref) +{ + Q_D(QCylinderMesh); + QAbstractShapeMesh::copy(ref); + const QCylinderMesh *mesh = qobject_cast<const QCylinderMesh *>(ref); + if (mesh != Q_NULLPTR) { + d->m_rings = mesh->rings(); + d->m_slices = mesh->slices(); + d->m_radius = mesh->radius(); + d->m_length = mesh->length(); + } +} + +void QCylinderMesh::setRings(int rings) +{ + Q_D(QCylinderMesh); + if (rings != d->m_rings) { + d->m_rings = rings; + emit ringsChanged(rings); + setDirty(true); + } +} + +void QCylinderMesh::setSlices(int slices) +{ + Q_D(QCylinderMesh); + if (slices != d->m_slices) { + d->m_slices = slices; + emit slicesChanged(slices); + setDirty(true); + } +} + +void QCylinderMesh::setRadius(float radius) +{ + Q_D(QCylinderMesh); + if (radius != d->m_radius) { + d->m_radius = radius; + emit radiusChanged(radius); + setDirty(true); + } +} + +void QCylinderMesh::setLength(float length) +{ + Q_D(QCylinderMesh); + if (length != d->m_length) { + d->m_length = length; + emit lengthChanged(length); + setDirty(true); + } +} + +int QCylinderMesh::rings() const +{ + Q_D(const QCylinderMesh); + return d->m_rings; +} + +int QCylinderMesh::slices() const +{ + Q_D(const QCylinderMesh); + return d->m_slices; +} + +float QCylinderMesh::radius() const +{ + Q_D(const QCylinderMesh); + return d->m_radius; +} + +float QCylinderMesh::length() const +{ + Q_D(const QCylinderMesh); + return d->m_length; +} + +QAbstractMeshDataPtr assembleMesh(const QByteArray &verticesBytes, quint32 vertexSize, int verticesCount, + const QByteArray &indicesBytes, int indicesCount) +{ + QAbstractMeshDataPtr mesh(new QMeshData(GL_TRIANGLES)); + + BufferPtr verticesBuffer(new Buffer(QOpenGLBuffer::VertexBuffer)); + verticesBuffer->setUsage(QOpenGLBuffer::StaticDraw); + verticesBuffer->setData(verticesBytes); + + mesh->addAttribute(QAbstractMeshData::defaultPositionAttributeName(), + QAbstractAttributePtr(new Attribute(verticesBuffer, GL_FLOAT_VEC3, + verticesCount, 0, vertexSize))); + quint32 offset = sizeof(float) * 3; + + mesh->addAttribute(QAbstractMeshData::defaultTextureCoordinateAttributeName(), + QAbstractAttributePtr(new Attribute(verticesBuffer, GL_FLOAT_VEC2, + verticesCount, offset, vertexSize))); + offset += sizeof(float) * 2; + + mesh->addAttribute(QAbstractMeshData::defaultNormalAttributeName(), + QAbstractAttributePtr(new Attribute(verticesBuffer, GL_FLOAT_VEC3, + verticesCount, offset, vertexSize))); + offset += sizeof(float) * 3; + + BufferPtr indicesBuffer(new Buffer(QOpenGLBuffer::IndexBuffer)); + indicesBuffer->setUsage(QOpenGLBuffer::StaticDraw); + indicesBuffer->setData(indicesBytes); + mesh->setIndexAttribute(AttributePtr(new Attribute(indicesBuffer, GL_UNSIGNED_SHORT, indicesCount, 0, 0))); + + mesh->computeBoundsFromAttribute(QAbstractMeshData::defaultPositionAttributeName()); + + return mesh; +} + +void createSides(float *&verticesPtr, quint16 *&indicesPtr, + 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; + const int ringIndexStart = ring * (slices + 1); + const int nextRingIndexStart = (ring + 1) * (slices + 1); + + for (int slice = 0; slice <= slices; slice++) { + const float theta = static_cast<float>(slice) * dTheta; + const float ct = cos(theta); + const float st = sin(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(); + + 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 createDisc(float *&verticesPtr, quint16 *&indicesPtr, + int discCenterIndex, 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 = cos(theta); + const float st = sin(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; + + if (slice == slices) + continue; + + const int nextSlice = slice + 1; + + *indicesPtr++ = discCenterIndex; + *indicesPtr++ = (discCenterIndex + 1 + nextSlice); + *indicesPtr++ = (discCenterIndex + 1 + slice); + + if (yNormal < 0.0f) + qSwap(*(indicesPtr -1), *(indicesPtr - 2)); + } +} + +QAbstractMeshDataPtr createCylinderMesh(double radius, double length, + int rings, int slices) +{ + const int verticesCount = (slices + 1) * rings + 2 * (slices + 1) + 2; + // vec3 pos, vec2 texCoord, vec3 normal + const quint32 vertexSize = (3 + 2 + 3) * sizeof(float); + + QByteArray verticesBytes; + verticesBytes.resize(verticesCount * vertexSize); + float *verticesPtr = reinterpret_cast<float*>(verticesBytes.data()); + + const int facesCount = (slices * 2) * rings // two tris per side, for all rings + + 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()); + + createSides(verticesPtr, indicesPtr, rings, slices, radius, length); + createDisc(verticesPtr, indicesPtr, rings * (slices + 1), + slices, radius, -length / 2.0f); + createDisc(verticesPtr, indicesPtr, rings * (slices + 1) + slices + 2, + slices, radius, length / 2.0f); + return assembleMesh(verticesBytes, vertexSize, verticesCount, + indicesBytes, indicesCount); +} + +QAbstractMeshFunctorPtr QCylinderMesh::meshFunctor() const +{ + Q_D(const QCylinderMesh); + return QAbstractMeshFunctorPtr(new CylinderMeshFunctor(d->m_rings, d->m_slices, d->m_radius, d->m_length)); +} + +QCylinderMesh *QCylinderMesh::doClone(QNode *clonedParent) const +{ + return new QCylinderMesh(clonedParent); +} + +CylinderMeshFunctor::CylinderMeshFunctor(int rings, int slices, float radius, float length) + : QAbstractMeshFunctor() + , m_rings(rings) + , m_slices(slices) + , m_radius(radius) + , m_length(length) +{ +} + +QAbstractMeshDataPtr CylinderMeshFunctor::operator ()() +{ + return createCylinderMesh(m_radius, m_length, m_rings, m_slices); +} + +} // Qt3D + +QT_END_NAMESPACE diff --git a/src/render/frontend/qcylindermesh.h b/src/render/frontend/qcylindermesh.h new file mode 100644 index 000000000..dd6ff05f5 --- /dev/null +++ b/src/render/frontend/qcylindermesh.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE: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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3D_QCYLINDERMESH_H +#define QT3D_QCYLINDERMESH_H + +#include <Qt3DRenderer/qt3drenderer_global.h> +#include <Qt3DRenderer/qabstractshapemesh.h> + +QT_BEGIN_NAMESPACE + + +namespace Qt3D { + +class QCylinderMeshPrivate; + +class QT3DRENDERERSHARED_EXPORT QCylinderMesh : public Qt3D::QAbstractShapeMesh +{ + 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(QNode *parent = 0); + + void copy(const QNode *ref) Q_DECL_OVERRIDE; + + void setRings(int rings); + void setSlices(int slices); + void setRadius(float radius); + void setLength(float length); + + int rings() const; + int slices() const; + float radius() const; + float length() const; + + QAbstractMeshFunctorPtr meshFunctor() const Q_DECL_OVERRIDE; + +Q_SIGNALS: + void ringsChanged(int rings); + void slicesChanged(int slices); + void radiusChanged(float radius); + void lengthChanged(float length); + +private: + Q_DECLARE_PRIVATE(QCylinderMesh) + QCylinderMesh *doClone(QNode *clonedParent) const Q_DECL_OVERRIDE; +}; + +} // Qt3D + +QT_END_NAMESPACE + +#endif // QT3D_QCYLINDERMESH_H diff --git a/src/render/frontend/render-frontend.pri b/src/render/frontend/render-frontend.pri index b593a47b6..e99fc0cc3 100644 --- a/src/render/frontend/render-frontend.pri +++ b/src/render/frontend/render-frontend.pri @@ -21,6 +21,7 @@ HEADERS += \ $$PWD/qparameter.h \ $$PWD/qparameter_p.h \ $$PWD/qparametermapper.h \ + $$PWD/qcylindermesh.h \ $$PWD/qtorusmesh.h \ $$PWD/qspheremesh.h \ $$PWD/qabstractshapemesh_p.h \ @@ -78,6 +79,7 @@ SOURCES += \ $$PWD/qcriterion.cpp \ $$PWD/qparameter.cpp \ $$PWD/qparametermapper.cpp \ + $$PWD/qcylindermesh.cpp \ $$PWD/qtorusmesh.cpp \ $$PWD/qspheremesh.cpp \ $$PWD/qabstractlight.cpp \ |