diff options
44 files changed, 2665 insertions, 1 deletions
diff --git a/src/doc/src/levelofdetailloader.qdoc b/src/doc/src/levelofdetailloader.qdoc new file mode 100644 index 000000000..65fda072a --- /dev/null +++ b/src/doc/src/levelofdetailloader.qdoc @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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$ +** +****************************************************************************/ + +/*! + \qmltype LevelOfDetailLoader + \inqmlmodule Qt3D.Render + \since 5.9 + \brief An entity loader that changes depending on distance to camera or screen size + + A LevelOfDetailLoader will load the entity matching the \l LevelOfDetail::currentIndex. + The source is selected from the \l sources property. + The range is specified using the \l {minimum} and the \l{maximum} values. + + \sa LevelOfDetail +*/ + +/*! + \qmlproperty list<string> LevelOfDetailLoader::sources + + The list of sources (array of strings) to load from. +*/ diff --git a/src/quick3d/imports/extras/defaults/defaults.pri b/src/quick3d/imports/extras/defaults/defaults.pri index 65271afeb..98f542fd6 100644 --- a/src/quick3d/imports/extras/defaults/defaults.pri +++ b/src/quick3d/imports/extras/defaults/defaults.pri @@ -22,4 +22,5 @@ QML_FILES = \ $$PWD/qml/TextureMaterial.qml \ $$PWD/qml/OrbitCameraController.qml \ $$PWD/qml/FirstPersonCameraController.qml \ - $$PWD/qml/NormalDiffuseMapAlphaEffect.qml + $$PWD/qml/NormalDiffuseMapAlphaEffect.qml \ + $$PWD/qml/LevelOfDetailLoader.qml diff --git a/src/quick3d/imports/extras/defaults/qml/LevelOfDetailLoader.qml b/src/quick3d/imports/extras/defaults/qml/LevelOfDetailLoader.qml new file mode 100644 index 000000000..83655a7bc --- /dev/null +++ b/src/quick3d/imports/extras/defaults/qml/LevelOfDetailLoader.qml @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt3D.Core 2.0 +import Qt3D.Render 2.2 + +Entity { + id:root + + property var sources: [] + readonly property alias entity: loader.entity + readonly property alias source: loader.source + + property alias camera: lod.camera + property alias currentIndex: lod.currentIndex + property alias thresholdType: lod.thresholdType + property alias thresholds: lod.thresholds + property alias volumeOverride: lod.volumeOverride + + EntityLoader { + id: loader + components: [ + LevelOfDetail { + id: lod + enabled: root.enabled + currentIndex: -1 + onCurrentIndexChanged: if (currentIndex >= 0 && currentIndex < root.sources.length) + loader.source = root.sources[currentIndex] + } + ] + } +} + diff --git a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp index b20e416c2..7d695ea5b 100644 --- a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp +++ b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp @@ -75,6 +75,8 @@ static const struct { { "DefaultEffect", 2, 0 }, { "DefaultAlphaEffect", 2, 0 }, { "NormalDiffuseMapAlphaEffect", 2, 0 }, + // Scene Graph + { "LevelOfDetailLoader", 2, 2 }, // FrameGraphs { "ForwardRenderer", 2, 0 }, // Entities diff --git a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp index 2e68893d6..5ca889943 100644 --- a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp +++ b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp @@ -55,6 +55,8 @@ #include <Qt3DRender/qparameter.h> #include <Qt3DRender/qfilterkey.h> #include <Qt3DRender/qlayer.h> +#include <Qt3DRender/qlevelofdetail.h> +#include <Qt3DRender/qboundingsphere.h> #include <Qt3DRender/qabstractlight.h> #include <Qt3DRender/qspotlight.h> #include <Qt3DRender/qdirectionallight.h> @@ -191,6 +193,8 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri) qmlRegisterType<Qt3DRender::Render::Quick::Quick3DBuffer>(uri, 2, 0, "Buffer"); Qt3DRender::Quick::registerExtendedType<Qt3DRender::QGeometry, Qt3DRender::Render::Quick::Quick3DGeometry>("QGeometry", "Qt3D.Render/Geometry", uri, 2, 0, "Geometry"); qmlRegisterType<Qt3DRender::QGeometryRenderer>(uri, 2, 0, "GeometryRenderer"); + qmlRegisterType<Qt3DRender::QLevelOfDetail>(uri, 2, 2, "LevelOfDetail"); + qmlRegisterType<Qt3DRender::QBoundingSphere>(uri, 2, 2, "BoundingSphere"); // Mesh qmlRegisterType<Qt3DRender::QMesh>(uri, 2, 0, "Mesh"); diff --git a/src/render/backend/entity.cpp b/src/render/backend/entity.cpp index f4a57fa43..42233c85a 100644 --- a/src/render/backend/entity.cpp +++ b/src/render/backend/entity.cpp @@ -42,6 +42,7 @@ #include <Qt3DRender/private/nodemanagers_p.h> #include <Qt3DRender/qabstractlight.h> #include <Qt3DRender/qlayer.h> +#include <Qt3DRender/qlevelofdetail.h> #include <Qt3DRender/qmaterial.h> #include <Qt3DRender/qmesh.h> #include <Qt3DRender/private/renderlogging_p.h> @@ -114,6 +115,7 @@ void Entity::cleanup() m_computeComponent = QNodeId(); m_childrenHandles.clear(); m_layerComponents.clear(); + m_levelOfDetailComponents.clear(); m_shaderDataComponents.clear(); m_lightComponents.clear(); m_localBoundingVolume.reset(); @@ -169,6 +171,7 @@ void Entity::initializeFromPeer(const QNodeCreatedChangeBasePtr &change) m_boundingVolumeDebugComponent = QNodeId(); m_computeComponent = QNodeId(); m_layerComponents.clear(); + m_levelOfDetailComponents.clear(); m_shaderDataComponents.clear(); m_lightComponents.clear(); m_localBoundingVolume.reset(new Sphere(peerId())); @@ -284,6 +287,8 @@ void Entity::addComponent(Qt3DCore::QComponent *component) m_cameraComponent = component->id(); } else if (qobject_cast<QLayer *>(component) != nullptr) { m_layerComponents.append(component->id()); + } else if (qobject_cast<QLevelOfDetail *>(component) != nullptr) { + m_levelOfDetailComponents.append(component->id()); } else if (qobject_cast<QMaterial *>(component) != nullptr) { m_materialComponent = component->id(); } else if (qobject_cast<QAbstractLight *>(component) != nullptr) { @@ -315,6 +320,8 @@ void Entity::addComponent(Qt3DCore::QNodeIdTypePair idAndType) m_cameraComponent = id; } else if (type->inherits(&QLayer::staticMetaObject)) { m_layerComponents.append(id); + } else if (type->inherits(&QLevelOfDetail::staticMetaObject)) { + m_levelOfDetailComponents.append(id); } else if (type->inherits(&QMaterial::staticMetaObject)) { m_materialComponent = id; } else if (type->inherits(&QAbstractLight::staticMetaObject)) { // QAbstractLight subclasses QShaderData @@ -341,6 +348,8 @@ void Entity::removeComponent(Qt3DCore::QNodeId nodeId) m_cameraComponent = QNodeId(); } else if (m_layerComponents.contains(nodeId)) { m_layerComponents.removeAll(nodeId); + } else if (m_levelOfDetailComponents.contains(nodeId)) { + m_levelOfDetailComponents.removeAll(nodeId); } else if (m_materialComponent == nodeId) { m_materialComponent = QNodeId(); } else if (m_shaderDataComponents.contains(nodeId)) { @@ -412,6 +421,16 @@ QVector<HLayer> Entity::componentsHandle<Layer>() const } template<> +QVector<HLevelOfDetail> Entity::componentsHandle<LevelOfDetail>() const +{ + QVector<HLevelOfDetail> lodHandles; + lodHandles.reserve(m_levelOfDetailComponents.size()); + for (QNodeId id : m_levelOfDetailComponents) + lodHandles.append(m_nodeManagers->levelOfDetailManager()->lookupHandle(id)); + return lodHandles; +} + +template<> QVector<HShaderData> Entity::componentsHandle<ShaderData>() const { QVector<HShaderData> shaderDataHandles; @@ -486,6 +505,16 @@ QVector<Layer *> Entity::renderComponents<Layer>() const } template<> +QVector<LevelOfDetail *> Entity::renderComponents<LevelOfDetail>() const +{ + QVector<LevelOfDetail *> lods; + lods.reserve(m_levelOfDetailComponents.size()); + for (QNodeId id : m_levelOfDetailComponents) + lods.append(m_nodeManagers->levelOfDetailManager()->lookupResource(id)); + return lods; +} + +template<> QVector<ShaderData *> Entity::renderComponents<ShaderData>() const { QVector<ShaderData *> shaderDatas; @@ -532,6 +561,9 @@ template<> QVector<Qt3DCore::QNodeId> Entity::componentsUuid<Layer>() const { return m_layerComponents; } template<> +QVector<Qt3DCore::QNodeId> Entity::componentsUuid<LevelOfDetail>() const { return m_levelOfDetailComponents; } + +template<> QVector<Qt3DCore::QNodeId> Entity::componentsUuid<ShaderData>() const { return m_shaderDataComponents; } template<> diff --git a/src/render/backend/entity_p.h b/src/render/backend/entity_p.h index 213dc041e..fe970d325 100644 --- a/src/render/backend/entity_p.h +++ b/src/render/backend/entity_p.h @@ -190,6 +190,7 @@ private: Qt3DCore::QNodeId m_materialComponent; Qt3DCore::QNodeId m_cameraComponent; QVector<Qt3DCore::QNodeId> m_layerComponents; + QVector<Qt3DCore::QNodeId> m_levelOfDetailComponents; QVector<Qt3DCore::QNodeId> m_shaderDataComponents; QVector<Qt3DCore::QNodeId> m_lightComponents; Qt3DCore::QNodeId m_geometryRendererComponent; @@ -221,6 +222,9 @@ template<> QVector<HLayer> Entity::componentsHandle<Layer>() const; template<> +QVector<HLevelOfDetail> Entity::componentsHandle<LevelOfDetail>() const; + +template<> QVector<HShaderData> Entity::componentsHandle<ShaderData>() const; //template<> @@ -252,6 +256,9 @@ template<> QVector<Layer *> Entity::renderComponents<Layer>() const; template<> +QVector<LevelOfDetail *> Entity::renderComponents<LevelOfDetail>() const; + +template<> QVector<ShaderData *> Entity::renderComponents<ShaderData>() const; //template<> @@ -277,6 +284,9 @@ template<> Q_AUTOTEST_EXPORT QVector<Qt3DCore::QNodeId> Entity::componentsUuid<Layer>() const; template<> +Q_AUTOTEST_EXPORT QVector<Qt3DCore::QNodeId> Entity::componentsUuid<LevelOfDetail>() const; + +template<> Q_AUTOTEST_EXPORT QVector<Qt3DCore::QNodeId> Entity::componentsUuid<ShaderData>() const; template<> diff --git a/src/render/backend/handle_types_p.h b/src/render/backend/handle_types_p.h index e68f0f1c5..c8c73b749 100644 --- a/src/render/backend/handle_types_p.h +++ b/src/render/backend/handle_types_p.h @@ -72,6 +72,7 @@ class Entity; class Shader; class FrameGraphNode; class Layer; +class LevelOfDetail; class Material; class Technique; class Texture; @@ -100,6 +101,7 @@ typedef Qt3DCore::QHandle<Effect, 16> HEffect; typedef Qt3DCore::QHandle<Entity, 16> HEntity; typedef Qt3DCore::QHandle<FrameGraphNode *, 8> HFrameGraphNode; typedef Qt3DCore::QHandle<Layer, 16> HLayer; +typedef Qt3DCore::QHandle<LevelOfDetail, 16> HLevelOfDetail; typedef Qt3DCore::QHandle<Material, 16> HMaterial; typedef Qt3DCore::QHandle<QMatrix4x4, 16> HMatrix; typedef Qt3DCore::QHandle<OpenGLVertexArrayObject, 16> HVao; diff --git a/src/render/backend/levelofdetail.cpp b/src/render/backend/levelofdetail.cpp new file mode 100644 index 000000000..9ff0ef532 --- /dev/null +++ b/src/render/backend/levelofdetail.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "levelofdetail_p.h" +#include <Qt3DRender/QLevelOfDetail> +#include <Qt3DRender/QBoundingSphere> +#include <Qt3DRender/private/qlevelofdetail_p.h> +#include <Qt3DRender/private/stringtoint_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <QVariant> + +QT_BEGIN_NAMESPACE + +using namespace Qt3DCore; + +namespace Qt3DRender { +namespace Render { + +LevelOfDetail::LevelOfDetail() + : BackendNode(BackendNode::ReadWrite) + , m_currentIndex(0) + , m_thresholdType(QLevelOfDetail::DistanceToCamera) + , m_radius(1.f) +{ +} + +LevelOfDetail::~LevelOfDetail() +{ + cleanup(); +} + +void LevelOfDetail::initializeFromPeer(const QNodeCreatedChangeBasePtr &change) +{ + const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QLevelOfDetailData>>(change); + const auto &data = typedChange->data; + m_camera = data.camera; + m_currentIndex = data.currentIndex; + m_thresholdType = data.thresholdType; + m_thresholds = data.thresholds; + m_radius = data.radius; + m_center = data.center; +} + +void LevelOfDetail::cleanup() +{ + QBackendNode::setEnabled(false); +} + +void LevelOfDetail::sceneChangeEvent(const QSceneChangePtr &e) +{ + if (e->type() == PropertyUpdated) { + const QPropertyUpdatedChangePtr &propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); + if (propertyChange->propertyName() == QByteArrayLiteral("currentIndex")) { + m_currentIndex = propertyChange->value().value<int>(); + } else if (propertyChange->propertyName() == QByteArrayLiteral("camera")) { + m_camera = propertyChange->value().value<Qt3DCore::QNodeId>(); + } else if (propertyChange->propertyName() == QByteArrayLiteral("thresholdType")) { + m_thresholdType = propertyChange->value().value<QLevelOfDetail::ThresholdType>(); + } else if (propertyChange->propertyName() == QByteArrayLiteral("thresholds")) { + m_thresholds = propertyChange->value().value<QVector<qreal>>(); + } else if (propertyChange->propertyName() == QByteArrayLiteral("center")) { + m_center = propertyChange->value().value<QVector3D>(); + } else if (propertyChange->propertyName() == QByteArrayLiteral("radius")) { + m_radius = propertyChange->value().value<float>(); + } else if (propertyChange->propertyName() == QByteArrayLiteral("volumeOverride")) { + auto volumeOverride = propertyChange->value().value<Qt3DRender::QBoundingSphere*>(); + m_center = volumeOverride ? volumeOverride->center() : QVector3D(); + m_radius = volumeOverride ? volumeOverride->radius() : -1.f; + } + } + + markDirty(AbstractRenderer::GeometryDirty); + + BackendNode::sceneChangeEvent(e); +} + +void LevelOfDetail::setCurrentIndex(int currentIndex) +{ + if (m_currentIndex != currentIndex) { + m_currentIndex = currentIndex; + auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); + e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); + e->setPropertyName("currentIndex"); + e->setValue(m_currentIndex); + notifyObservers(e); + } +} + +} // namespace Render +} // namespace Qt3DRender + +QT_END_NAMESPACE diff --git a/src/render/backend/levelofdetail_p.h b/src/render/backend/levelofdetail_p.h new file mode 100644 index 000000000..83809a631 --- /dev/null +++ b/src/render/backend/levelofdetail_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QT3DRENDER_RENDER_LEVELOFDETAIL_H +#define QT3DRENDER_RENDER_LEVELOFDETAIL_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/backendnode_p.h> +#include <Qt3DRender/qt3drender_global.h> +#include <Qt3DRender/qlevelofdetail.h> +#include <QStringList> +#include <QVector3D> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QLevelOfDetail; + +namespace Render { + +class LevelOfDetailManager; + +class Q_AUTOTEST_EXPORT LevelOfDetail : public BackendNode +{ +public: + LevelOfDetail(); + ~LevelOfDetail(); + void cleanup(); + void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_FINAL; + + Qt3DCore::QNodeId camera() const { return m_camera; } + int currentIndex() const { return m_currentIndex; } + QLevelOfDetail::ThresholdType thresholdType() const { return m_thresholdType; } + QVector<qreal> thresholds() const { return m_thresholds; } + float radius() const { return m_radius; } + QVector3D center() const { return m_center; } + + void setCurrentIndex(int currentIndex); + +private: + void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL; + Qt3DCore::QNodeId m_camera; + int m_currentIndex; + QLevelOfDetail::ThresholdType m_thresholdType; + QVector<qreal> m_thresholds; + float m_radius; + QVector3D m_center; +}; + +} // namespace Render + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_RENDER_LEVELOFDETAIL_H diff --git a/src/render/backend/managers_p.h b/src/render/backend/managers_p.h index ed43fde13..ce6767958 100644 --- a/src/render/backend/managers_p.h +++ b/src/render/backend/managers_p.h @@ -58,6 +58,7 @@ #include <Qt3DRender/private/effect_p.h> #include <Qt3DRender/private/entity_p.h> #include <Qt3DRender/private/layer_p.h> +#include <Qt3DRender/private/levelofdetail_p.h> #include <Qt3DRender/private/material_p.h> #include <Qt3DRender/private/shader_p.h> #include <Qt3DRender/private/texture_p.h> @@ -176,6 +177,17 @@ public: LayerManager() {} }; +class LevelOfDetailManager : public Qt3DCore::QResourceManager< + LevelOfDetail, + Qt3DCore::QNodeId, + 16, + Qt3DCore::ArrayAllocatingPolicy, + Qt3DCore::NonLockingPolicy> +{ +public: + LevelOfDetailManager() {} +}; + class MaterialManager : public Qt3DCore::QResourceManager< Material, Qt3DCore::QNodeId, diff --git a/src/render/backend/nodemanagers.cpp b/src/render/backend/nodemanagers.cpp index e9b2abc3a..d83623ce2 100644 --- a/src/render/backend/nodemanagers.cpp +++ b/src/render/backend/nodemanagers.cpp @@ -71,6 +71,7 @@ NodeManagers::NodeManagers() , m_textureImageDataManager(new TextureImageDataManager()) , m_glTextureManager(new GLTextureManager(m_textureImageManager, m_textureDataManager, m_textureImageDataManager)) , m_layerManager(new LayerManager()) + , m_levelOfDetailManager(new LevelOfDetailManager()) , m_filterKeyManager(new FilterKeyManager()) , m_frameGraphManager(new FrameGraphManager()) , m_transformManager(new TransformManager()) @@ -107,6 +108,7 @@ NodeManagers::~NodeManagers() delete m_textureDataManager; delete m_textureImageDataManager; delete m_layerManager; + delete m_levelOfDetailManager; delete m_filterKeyManager; delete m_frameGraphManager; delete m_transformManager; @@ -202,6 +204,12 @@ LayerManager *NodeManagers::manager<Layer>() const Q_DECL_NOTHROW } template<> +LevelOfDetailManager *NodeManagers::manager<LevelOfDetail>() const Q_DECL_NOTHROW +{ + return m_levelOfDetailManager; +} + +template<> FilterKeyManager *NodeManagers::manager<FilterKey>() const Q_DECL_NOTHROW { return m_filterKeyManager; diff --git a/src/render/backend/nodemanagers_p.h b/src/render/backend/nodemanagers_p.h index e46e9355c..b1ea2a0de 100644 --- a/src/render/backend/nodemanagers_p.h +++ b/src/render/backend/nodemanagers_p.h @@ -94,6 +94,7 @@ class TextureManager; class TextureDataManager; class TextureImageDataManager; class LayerManager; +class LevelOfDetailManager; class LightManager; class ComputeCommandManager; class RenderStateManager; @@ -108,6 +109,7 @@ class Effect; class RenderPass; class Texture; class Layer; +class LevelOfDetail; class FilterKey; class FrameGraphNode; class Transform; @@ -183,6 +185,7 @@ public: inline TextureDataManager *textureDataManager() const Q_DECL_NOEXCEPT { return m_textureDataManager; } inline TextureImageDataManager *textureImageDataManager() const Q_DECL_NOEXCEPT { return m_textureImageDataManager; } inline LayerManager *layerManager() const Q_DECL_NOEXCEPT { return m_layerManager; } + inline LevelOfDetailManager *levelOfDetailManager() const Q_DECL_NOEXCEPT { return m_levelOfDetailManager; } inline FilterKeyManager *filterKeyManager() const Q_DECL_NOEXCEPT { return m_filterKeyManager; } inline FrameGraphManager *frameGraphManager() const Q_DECL_NOEXCEPT { return m_frameGraphManager; } inline TransformManager *transformManager() const Q_DECL_NOEXCEPT { return m_transformManager; } @@ -219,6 +222,7 @@ private: TextureImageDataManager *m_textureImageDataManager; GLTextureManager *m_glTextureManager; LayerManager *m_layerManager; + LevelOfDetailManager *m_levelOfDetailManager; FilterKeyManager *m_filterKeyManager; FrameGraphManager *m_frameGraphManager; TransformManager *m_transformManager; @@ -278,6 +282,9 @@ template<> QT3DRENDERSHARED_PRIVATE_EXPORT LayerManager *NodeManagers::manager<Layer>() const Q_DECL_NOEXCEPT; template<> +QT3DRENDERSHARED_PRIVATE_EXPORT LevelOfDetailManager *NodeManagers::manager<LevelOfDetail>() const Q_DECL_NOEXCEPT; + +template<> QT3DRENDERSHARED_PRIVATE_EXPORT FilterKeyManager *NodeManagers::manager<FilterKey>() const Q_DECL_NOEXCEPT; template<> diff --git a/src/render/backend/render-backend.pri b/src/render/backend/render-backend.pri index 8cd904efd..93e323caa 100644 --- a/src/render/backend/render-backend.pri +++ b/src/render/backend/render-backend.pri @@ -21,6 +21,7 @@ HEADERS += \ $$PWD/cameralens_p.h \ $$PWD/entity_p.h \ $$PWD/layer_p.h \ + $$PWD/levelofdetail_p.h \ $$PWD/nodefunctor_p.h \ $$PWD/transform_p.h \ $$PWD/boundingvolumedebug_p.h \ @@ -56,6 +57,7 @@ SOURCES += \ $$PWD/cameralens.cpp \ $$PWD/entity.cpp \ $$PWD/layer.cpp \ + $$PWD/levelofdetail.cpp \ $$PWD/transform.cpp \ $$PWD/boundingvolumedebug.cpp \ $$PWD/nodemanagers.cpp \ diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp index e1b1ee873..08ee7f428 100644 --- a/src/render/backend/renderer.cpp +++ b/src/render/backend/renderer.cpp @@ -83,6 +83,7 @@ #include <Qt3DRender/private/platformsurfacefilter_p.h> #include <Qt3DRender/private/loadbufferjob_p.h> #include <Qt3DRender/private/rendercapture_p.h> +#include <Qt3DRender/private/updatelevelofdetailjob_p.h> #include <Qt3DRender/private/offscreensurfacehelper_p.h> #include <Qt3DRender/qcameralens.h> @@ -167,6 +168,7 @@ Renderer::Renderer(QRenderAspect::RenderType type) , m_updateWorldBoundingVolumeJob(Render::UpdateWorldBoundingVolumeJobPtr::create()) , m_updateTreeEnabledJob(Render::UpdateTreeEnabledJobPtr::create()) , m_sendRenderCaptureJob(Render::SendRenderCaptureJobPtr::create(this)) + , m_updateLevelOfDetailJob(Render::UpdateLevelOfDetailJobPtr::create()) , m_updateMeshTriangleListJob(Render::UpdateMeshTriangleListJobPtr::create()) , m_filterCompatibleTechniqueJob(Render::FilterCompatibleTechniqueJobPtr::create()) , m_bufferGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering)) @@ -198,6 +200,7 @@ Renderer::Renderer(QRenderAspect::RenderType type) m_textureGathererJob->addDependency(m_syncTextureLoadingJob); // All world stuff depends on the RenderEntity's localBoundingVolume + m_updateLevelOfDetailJob->addDependency(m_updateMeshTriangleListJob); m_pickBoundingVolumeJob->addDependency(m_updateMeshTriangleListJob); m_filterCompatibleTechniqueJob->setRenderer(this); @@ -252,6 +255,7 @@ void Renderer::setNodeManagers(NodeManagers *managers) m_pickBoundingVolumeJob->setManagers(m_nodesManager); m_updateWorldBoundingVolumeJob->setManager(m_nodesManager->renderNodesManager()); m_sendRenderCaptureJob->setManagers(m_nodesManager); + m_updateLevelOfDetailJob->setManagers(m_nodesManager); m_updateMeshTriangleListJob->setManagers(m_nodesManager); m_filterCompatibleTechniqueJob->setManager(m_nodesManager->techniqueManager()); } @@ -443,6 +447,7 @@ void Renderer::setSceneRoot(QBackendNodeFactory *factory, Entity *sgRoot) m_calculateBoundingVolumeJob->setRoot(m_renderSceneRoot); m_cleanupJob->setRoot(m_renderSceneRoot); m_pickBoundingVolumeJob->setRoot(m_renderSceneRoot); + m_updateLevelOfDetailJob->setRoot(m_renderSceneRoot); m_updateTreeEnabledJob->setRoot(m_renderSceneRoot); } @@ -1226,6 +1231,7 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() m_pickBoundingVolumeJob->setRenderSettings(settings()); m_pickBoundingVolumeJob->setMouseEvents(pendingPickingEvents()); + m_updateLevelOfDetailJob->setFrameGraphRoot(frameGraphRoot()); // Set dependencies of resource gatherer for (const QAspectJobPtr &jobPtr : renderBinJobs) { jobPtr->addDependency(m_bufferGathererJob); @@ -1237,6 +1243,7 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() renderBinJobs.push_back(m_updateShaderDataTransformJob); renderBinJobs.push_back(m_updateMeshTriangleListJob); renderBinJobs.push_back(m_updateTreeEnabledJob); + renderBinJobs.push_back(m_updateLevelOfDetailJob); renderBinJobs.push_back(m_expandBoundingVolumeJob); renderBinJobs.push_back(m_updateWorldBoundingVolumeJob); renderBinJobs.push_back(m_calculateBoundingVolumeJob); diff --git a/src/render/backend/renderer_p.h b/src/render/backend/renderer_p.h index c7c8e247a..9b5c35ed1 100644 --- a/src/render/backend/renderer_p.h +++ b/src/render/backend/renderer_p.h @@ -138,6 +138,9 @@ class VSyncFrameAdvanceService; class PickEventFilter; class NodeManagers; +class UpdateLevelOfDetailJob; +typedef QSharedPointer<UpdateLevelOfDetailJob> UpdateLevelOfDetailJobPtr; + using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>; class QT3DRENDERSHARED_PRIVATE_EXPORT Renderer : public AbstractRenderer @@ -195,6 +198,7 @@ public: inline UpdateTreeEnabledJobPtr updateTreeEnabledJob() const { return m_updateTreeEnabledJob; } inline UpdateWorldTransformJobPtr updateWorldTransformJob() const { return m_worldTransformJob; } inline UpdateWorldBoundingVolumeJobPtr updateWorldBoundingVolumeJob() const { return m_updateWorldBoundingVolumeJob; } + inline UpdateLevelOfDetailJobPtr updateLevelOfDetailJob() const { return m_updateLevelOfDetailJob; } inline UpdateMeshTriangleListJobPtr updateMeshTriangleListJob() const { return m_updateMeshTriangleListJob; } inline FilterCompatibleTechniqueJobPtr filterCompatibleTechniqueJob() const { return m_filterCompatibleTechniqueJob; } inline SynchronizerJobPtr textureLoadSyncJob() const { return m_syncTextureLoadingJob; } @@ -310,6 +314,7 @@ private: UpdateWorldBoundingVolumeJobPtr m_updateWorldBoundingVolumeJob; UpdateTreeEnabledJobPtr m_updateTreeEnabledJob; SendRenderCaptureJobPtr m_sendRenderCaptureJob; + UpdateLevelOfDetailJobPtr m_updateLevelOfDetailJob; UpdateMeshTriangleListJobPtr m_updateMeshTriangleListJob; FilterCompatibleTechniqueJobPtr m_filterCompatibleTechniqueJob; diff --git a/src/render/frontend/qboundingsphere.cpp b/src/render/frontend/qboundingsphere.cpp new file mode 100644 index 000000000..4d8b1aba8 --- /dev/null +++ b/src/render/frontend/qboundingsphere.cpp @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qboundingsphere.h" +#include "qboundingsphere_p.h" + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +QBoundingSpherePrivate::QBoundingSpherePrivate() + : QObjectPrivate() + , m_radius(1.f) +{ + +} + +/*! + \class Qt3DRender::QBoundingSphere + \inmodule Qt3DRender + \since 5.9 + \brief The QBoundingSphere class provides a simple spherical volume, defined by it's center and radius. +*/ + +/*! + \qmltype LevelOfDetail + \instantiates Qt3DRender::QLevelOfDetail + \inherits Component3D + \inqmlmodule Qt3D.Render + \brief The BoundingSphere class provides a simple spherical volume, defined by it's center and radius. +*/ + +/*! + * \qmlproperty QVector3D BoundingSphere::center + * + * Specifies the center of the bounding sphere + */ + +/*! + * \property QBoundingSphere::center + * + * Specifies the center of the bounding sphere + */ + +/*! + * \qmlproperty qreal BoundingSphere::radius + * + * Specifies the radius of the bounding sphere + */ + +/*! + * \property QBoundingSphere::radius + * + * Specifies the radius of the bounding sphere + */ + +/*! \fn Qt3DRender::QBoundingSphere::QBoundingSphere(QObject *parent) + Constructs a new QBoundingSphere with the specified \a parent. + */ +QBoundingSphere::QBoundingSphere(QObject *parent) + : QObject(*new QBoundingSpherePrivate, parent) +{ + +} + +QBoundingSphere::QBoundingSphere(const QVector3D ¢er, float radius, QObject *parent) + : QBoundingSphere(parent) +{ + Q_D(QBoundingSphere); + d->m_center = center; + d->m_radius = radius; +} + +QVector3D QBoundingSphere::center() const +{ + Q_D(const QBoundingSphere); + return d->m_center; +} + +float QBoundingSphere::radius() const +{ + Q_D(const QBoundingSphere); + return d->m_radius; +} + +/*! + * Sets the radius of the bounding sphere. + */ +void QBoundingSphere::setRadius(float radius) +{ + Q_D(QBoundingSphere); + if (d->m_radius != radius) { + d->m_radius = radius; + emit radiusChanged(radius); + } +} + +/*! + * Sets the center of the bounding sphere. + */ +void QBoundingSphere::setCenter(const QVector3D ¢er) +{ + Q_D(QBoundingSphere); + if (d->m_center != center) { + d->m_center = center; + emit centerChanged(center); + } +} + +} // namespace Qt3DRender + +QT_END_NAMESPACE diff --git a/src/render/frontend/qboundingsphere.h b/src/render/frontend/qboundingsphere.h new file mode 100644 index 000000000..e7f9b7784 --- /dev/null +++ b/src/render/frontend/qboundingsphere.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QT3DRENDER_QBOUNDINGSPHERE_H +#define QT3DRENDER_QBOUNDINGSPHERE_H + +#include <Qt3DCore/qcomponent.h> +#include <Qt3DRender/qt3drender_global.h> + +#include <QVector3D> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QBoundingSpherePrivate; + +class QT3DRENDERSHARED_EXPORT QBoundingSphere : public QObject +{ + Q_OBJECT + Q_PROPERTY(QVector3D center READ center WRITE setCenter NOTIFY centerChanged) + Q_PROPERTY(float radius READ radius WRITE setRadius NOTIFY radiusChanged) +public: + explicit QBoundingSphere(QObject *parent = nullptr); + QBoundingSphere(const QVector3D ¢er, float radius, QObject *parent = nullptr); + + QVector3D center() const; + float radius() const; + +public Q_SLOTS: + void setRadius(float radius); + void setCenter(const QVector3D ¢er); + +Q_SIGNALS: + void radiusChanged(float radius); + void centerChanged(const QVector3D ¢er); + +private: + Q_DECLARE_PRIVATE(QBoundingSphere) +}; + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_QBOUNDINGSPHERE_H diff --git a/src/render/frontend/qboundingsphere_p.h b/src/render/frontend/qboundingsphere_p.h new file mode 100644 index 000000000..171e4440f --- /dev/null +++ b/src/render/frontend/qboundingsphere_p.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QT3DRENDER_QBOUNDINGSPHERE_P_H +#define QT3DRENDER_QBOUNDINGSPHERE_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 <private/qobject_p.h> +#include <qboundingsphere.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QT3DRENDERSHARED_EXPORT QBoundingSpherePrivate : public QObjectPrivate +{ +public: + QBoundingSpherePrivate(); + + Q_DECLARE_PUBLIC(QBoundingSphere) + + QVector3D m_center; + float m_radius; +}; + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_QBOUNDINGSPHERE_P_H diff --git a/src/render/frontend/qlevelofdetail.cpp b/src/render/frontend/qlevelofdetail.cpp new file mode 100644 index 000000000..0d70803ca --- /dev/null +++ b/src/render/frontend/qlevelofdetail.cpp @@ -0,0 +1,482 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qboundingsphere.h" +#include "qlevelofdetail.h" +#include "qlevelofdetail_p.h" +#include "qcamera.h" +#include <Qt3DCore/qpropertyupdatedchange.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +QLevelOfDetailPrivate::QLevelOfDetailPrivate() + : QComponentPrivate() + , m_camera(nullptr) + , m_currentIndex(0) + , m_thresholdType(QLevelOfDetail::DistanceToCamera) + , m_volumeOverride(nullptr) +{ + Q_Q(QLevelOfDetail); + m_volumeOverride = new QBoundingSphere(q); + QObject::connect(m_volumeOverride, SIGNAL(radiusChanged(float)), q, SLOT(_q_radiusChanged(float))); + QObject::connect(m_volumeOverride, SIGNAL(centerChanged(const QVector3D &)), q, SLOT(_q_centerChanged(const QVector3D&))); +} + +void QLevelOfDetailPrivate::_q_radiusChanged(float radius) +{ + notifyPropertyChange("radius", radius); +} + +void QLevelOfDetailPrivate::_q_centerChanged(const QVector3D ¢er) +{ + notifyPropertyChange("center", center); +} + +/*! + \class Qt3DRender::QLevelOfDetail + \inmodule Qt3DRender + \since 5.9 + \brief The QLevelOfDetail class provides a way of controlling the complexity + of rendered entities based on their size on the screen. + + QLevelOfDetail can be used to control the representation of an entity + based on distance from the observer or size on the screen. + + In order to improve rendering performance, objects that are very small + can be rendered using far fewer details, in geometry or texture. + + The component is controlled by specifying thresholds of values which are interpreted + as either distances from the camera or screen size. + + As the point of view changes, the currentIndex property will change to + reflect matching value in the range array. + + The currentIndex property can then be used, for example, to enable or + disable entities, change material, etc. + + The LevelOfDetail component is not shareable between multiple Entity's. + + \code + #include <Qt3DCore/QEntity> + #include <Qt3DRender/QGeometryRenderer> + #include <Qt3DRender/QLevelOfDetail> + + // Scene + Qt3DCore::QEntity *rootEntity = new Qt3DCore::Qt3DCore::QEntity; + + Qt3DCore::QEntity *renderableEntity = new Qt3DCore::QEntity(rootEntity); + Qt3DRender::QGeometryRenderer *geometryRenderer = new Qt3DCore::QGeometryRenderer(renderableEntity); + renderableEntity->addComponent(geometryRenderer); + Qt3DRender::QLevelOfDetail* lod = new Qt3Render::QLevelOfDetail(renderableEntity); + QVector<qreal> thresholds = {20, 35, 50, 65}; + lod->setThresholds(thresholds); + lod->setCamera(mainCamera); + renderableEntity->addComponent(lod); + + // connect to QLevelOfDetail::currentIndexChanged to toggle rendering + ... + \endcode +*/ + +/*! + \qmltype LevelOfDetail + \instantiates Qt3DRender::QLevelOfDetail + \inherits Component3D + \inqmlmodule Qt3D.Render + \since 5.9 + \brief LevelOfDetail provides a way of controlling the complexity of + rendered entities based on their size on the screen. + + LevelOfDetail can be used to control the representation of an entity + based on distance from the observer or size on the screen. + + In order to improve rendering performance, objects that are very small + can be rendered using far fewer details, in geometry or texture. + + The component is controlled by specifying thresholds of values which are interpreted + as either distances from the camera or screen size. + + As the point of view changes, the currentIndex property will change to + reflect matching value in the range array. + + The currentIndex property can then be used, for example, to enable or + disable entities, change source in an EntityLoader, or material. + + The LevelOfDetail component is not shareable between multiple Entity's. + + \code + import Qt3D.Core 2.0 + import Qt3D.Render 2.0 + + Entity { + id: root + + // Scene + Camera { id: mainCamera } + + LevelOfDetail { + id: lod + camera: mainCamera + thresholds: [20, 35, 50, 65] + thresholdType: LevelOfDetail.DistanceToCamera + } + + CylinderMesh { + id: mesh + + property var sliceValues: [20, 10, 6, 4] + slices: sliceValues[lod.currentIndex] + } + + Entity { + id: renderableEntity + components: [ mesh, lod ] + } + } + \endcode +*/ + + +/*! + * \enum Qt3DRender::QLevelOfDetail::ThresholdType + * + * Specifies how the values in the thresholds are interpreted + * + * \value DistanceToCamera Distance from the entity to the selected camera + * \value ProjectedScreenPixelSize Size of the entity when projected on the + * screen as seen from the selected camera, expressed in number of + * pixels on the side of the bounding square in screen space. + */ + +/*! + * \qmlproperty enumeration LevelOfDetail::ThresholdType + * + * Specifies how the values in the thresholds are interpreted + * + * \list + * \li DistanceToCamera Distance from the entity to the selected camera + * \li ProjectedScreenPixelSize Size of the entity when projected on the + * screen as seen from the selected camera, expressed in number of + * pixels on the side of the bounding square in screen space. + * \endlist + * \sa Qt3DRender::QLevelOfDetail::ThresholdType + */ + + +/*! + * \enum Qt3DRender::QLevelOfDetail::SizeProxyMode + * + * Specifies what is used as a proxy for the entity when computing distance + * or size. + * + * \value BoundingSphere use the bounding sphere specified by the center + * and radius properties. + * \value ChildrenBoundingSphere use the bounding sphere of the entity the + * component is attached to. + */ + +/*! + * \qmlproperty enumeration LevelOfDetail::SizeProxyMode + * + * Specifies what is used as a proxy for the entity when computing distance + * or size. + * + * \list + * \li BoundingSphere use the bounding sphere specified by the center + * and radius properties. + * \li ChildrenBoundingSphere use the bounding sphere of the entity the + * component is attached to. + * \endlist + * \sa Qt3DRender::QLevelOfDetail::SizeProxyMode + */ + + +/*! + * \qmlproperty Camera LevelOfDetail::camera + * + * Holds the id of the camera that is used to compute the actual distance or the screen size. + */ + +/*! + * \property QLevelOfDetail::camera + * + * Holds the id of the camera that is used to compute the actual distance or the screen size. + */ + +/*! + * \qmlproperty int LevelOfDetail::currentIndex + * + * The index in the range array which matches the current distance to the camera or screen size. + */ + +/*! + * \property QLevelOfDetail::currentIndex + * + * The index in the range array which matches the current distance to the camera or screen size. + */ + +/*! + * \qmlproperty int LevelOfDetail::thresholdType + * + * Specifies how range values are interpreted. + */ + +/*! + * \property QLevelOfDetail::thresholdType + * + * Specifies how range values are interpreted. + * \sa Qt3DRender::QLevelOfDetail::ThresholdType + */ + +/*! + * \qmlproperty QVector<qreal> LevelOfDetail::thresholds + * + * Array of range values as float point numbers. The value for the most detailed representation + * should be specified first. + * + * If LevelOfDetail::thresholdType is set to LevelOfDetail.Distance, values should be specified in + * ascending order, in camera space coordinates + * + * If LevelOfDetail::thresholdType is set to LevelOfDetail.ProjectedScreenPixelSize, values should + * be specified in descending order, in screen space pixels. + */ + +/*! + * \property QLevelOfDetail::thresholds + * + * Array of range values as float point numbers. The value for the most detailed representation + * should be specified first. + * + * If Qt3DRender::QLevelOfDetail::thresholdType is set to Qt3DRender::QLevelOfDetail::Distance, values should be specified in + * ascending order, in camera space coordinates + * + * If Qt3DRender::QLevelOfDetail::thresholdType is set to Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSize, values should + * be specified in descending order, in screen space pixels. + * + * \sa Qt3DRender::QLevelOfDetail::ThresholdType + */ + +/*! + * \qmlproperty int LevelOfDetail::volumeOverride + * + * Specifies what is used to evaluate the distance or screen size. + * + * The default is a sphere of radius 1 and centered at the local origin of the entity. + * This proxy volume is used to compute the distance to the camera or the size + * of the screen projection. + * + * If this value to null, the bounding volume of the entity is used. Care must be + * taken that this bounding volume never becomes invalid. + * + * \sa BoundingSphere + */ + +/*! + * \property QLevelOfDetail::volumeOverride + * + * The default is a sphere of radius 1 and centered at the local origin of the entity. + * This proxy volume is used to compute the distance to the camera or the size + * of the screen projection. + * + * If this value to nullptr, the bounding volume of the entity is used. Care must be + * taken that this bounding volume never becomes invalid. + * + * \sa QBoundingSphere + */ + + +/*! \fn Qt3DRender::QLevelOfDetail::QLevelOfDetail(Qt3DCore::QNode *parent) + Constructs a new QLevelOfDetail with the specified \a parent. + */ +QLevelOfDetail::QLevelOfDetail(QNode *parent) + : QComponent(*new QLevelOfDetailPrivate, parent) +{ +} + +/*! \internal */ +QLevelOfDetail::~QLevelOfDetail() +{ +} + +/*! \internal */ +QLevelOfDetail::QLevelOfDetail(QLevelOfDetailPrivate &dd, QNode *parent) + : QComponent(dd, parent) +{ +} + +/*! \internal */ +Qt3DCore::QNodeCreatedChangeBasePtr QLevelOfDetail::createNodeCreationChange() const +{ + auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QLevelOfDetailData>::create(this); + auto &data = creationChange->data; + + Q_D(const QLevelOfDetail); + if (d->m_camera) + data.camera = d->m_camera->id(); + data.currentIndex = d->m_currentIndex; + data.thresholdType = d->m_thresholdType; + data.thresholds = d->m_thresholds; + data.radius = d->m_volumeOverride ? d->m_volumeOverride->radius() : -1.f; + data.center = d->m_volumeOverride ? d->m_volumeOverride->center() : QVector3D(); + + return creationChange; +} + +/*! \internal */ +void QLevelOfDetail::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) +{ + Q_D(QLevelOfDetail); + Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change); + if (e->type() == Qt3DCore::PropertyUpdated) { + if (e->propertyName() == QByteArrayLiteral("currentIndex")) { + int ndx = e->value().value<int>(); + d->m_currentIndex = ndx; + emit currentIndexChanged(ndx); + } + } +} + +QCamera *QLevelOfDetail::camera() const +{ + Q_D(const QLevelOfDetail); + return d->m_camera; +} + +/*! + * Sets the camera relative to which distance and size are computed. + */ +void QLevelOfDetail::setCamera(QCamera *camera) +{ + Q_D(QLevelOfDetail); + if (d->m_camera != camera) { + d->m_camera = camera; + emit cameraChanged(d->m_camera); + } +} + +int QLevelOfDetail::currentIndex() const +{ + Q_D(const QLevelOfDetail); + return d->m_currentIndex; +} + +/*! + * Sets the current index. + * + * \note This should not normally be set by the user. + * + * However, if the component is disabled, then changing the + * current index is a simple way of switching between multiple + * representations. + */ +void QLevelOfDetail::setCurrentIndex(int currentIndex) +{ + Q_D(QLevelOfDetail); + if (d->m_currentIndex != currentIndex) { + d->m_currentIndex = currentIndex; + emit currentIndexChanged(d->m_currentIndex); + } +} + +QLevelOfDetail::ThresholdType QLevelOfDetail::thresholdType() const +{ + Q_D(const QLevelOfDetail); + return d->m_thresholdType; +} + +/*! + * Sets the way thresholds values are interpreted + * \sa Qt3DRender::QLevelOfDetail::ThresholdType + */ +void QLevelOfDetail::setThresholdType(QLevelOfDetail::ThresholdType thresholdType) +{ + Q_D(QLevelOfDetail); + if (d->m_thresholdType != thresholdType) { + d->m_thresholdType = thresholdType; + emit thresholdTypeChanged(d->m_thresholdType); + } +} + +QVector<qreal> QLevelOfDetail::thresholds() const +{ + Q_D(const QLevelOfDetail); + return d->m_thresholds; +} + +/*! + * Sets the range values. + * \sa Qt3DRender::QLevelOfDetail::thresholdType + */ +void QLevelOfDetail::setThresholds(QVector<qreal> thresholds) +{ + Q_D(QLevelOfDetail); + if (d->m_thresholds != thresholds) { + d->m_thresholds = thresholds; + thresholdsChanged(d->m_thresholds); + } +} + +QBoundingSphere *QLevelOfDetail::volumeOverride() const +{ + Q_D(const QLevelOfDetail); + return d->m_volumeOverride; +} + +void QLevelOfDetail::setVolumeOverride(QBoundingSphere *volumeOverride) +{ + Q_D(QLevelOfDetail); + if (d->m_volumeOverride != volumeOverride) { + if (d->m_volumeOverride) + disconnect(d->m_volumeOverride); + d->m_volumeOverride = volumeOverride; + if (d->m_volumeOverride) { + connect(d->m_volumeOverride, SIGNAL(radiusChanged(float)), this, SLOT(_q_radiusChanged(float))); + connect(d->m_volumeOverride, SIGNAL(centerChanged(const QVector3D &)), this, SLOT(_q_centerChanged(const QVector3D&))); + } + emit volumeOverrideChanged(volumeOverride); + } +} + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#include "moc_qlevelofdetail.cpp" diff --git a/src/render/frontend/qlevelofdetail.h b/src/render/frontend/qlevelofdetail.h new file mode 100644 index 000000000..677169f02 --- /dev/null +++ b/src/render/frontend/qlevelofdetail.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QT3DRENDER_QLEVELOFDETAIL_H +#define QT3DRENDER_QLEVELOFDETAIL_H + +#include <Qt3DCore/qcomponent.h> +#include <Qt3DRender/qt3drender_global.h> + +#include <QVector3D> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QCamera; +class QBoundingSphere; +class QLevelOfDetailPrivate; + +class QT3DRENDERSHARED_EXPORT QLevelOfDetail : public Qt3DCore::QComponent +{ + Q_OBJECT + Q_PROPERTY(Qt3DRender::QCamera *camera READ camera WRITE setCamera NOTIFY cameraChanged) + Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) + Q_PROPERTY(ThresholdType thresholdType READ thresholdType WRITE setThresholdType NOTIFY thresholdTypeChanged) + Q_PROPERTY(QVector<qreal> thresholds READ thresholds WRITE setThresholds NOTIFY thresholdsChanged) + Q_PROPERTY(Qt3DRender::QBoundingSphere *volumeOverride READ volumeOverride WRITE setVolumeOverride NOTIFY volumeOverrideChanged) + +public: + enum ThresholdType { + DistanceToCamera, + ProjectedScreenPixelSize, + }; + Q_ENUM(ThresholdType) // LCOV_EXCL_LINE + + explicit QLevelOfDetail(Qt3DCore::QNode *parent = nullptr); + ~QLevelOfDetail(); + + QCamera *camera() const; + int currentIndex() const; + ThresholdType thresholdType() const; + QVector<qreal> thresholds() const; + QBoundingSphere *volumeOverride() const; + +public Q_SLOTS: + void setCamera(QCamera *camera); + void setCurrentIndex(int currentIndex); + void setThresholdType(ThresholdType thresholdType); + void setThresholds(QVector<qreal> thresholds); + void setVolumeOverride(QBoundingSphere *volumeOverride); + +Q_SIGNALS: + void cameraChanged(QCamera *camera); + void currentIndexChanged(int currentIndex); + void thresholdTypeChanged(ThresholdType thresholdType); + void thresholdsChanged(QVector<qreal> thresholds); + void volumeOverrideChanged(QBoundingSphere *volumeOverride); + +protected: + explicit QLevelOfDetail(QLevelOfDetailPrivate &dd, Qt3DCore::QNode *parent = nullptr); + +private: + Q_DECLARE_PRIVATE(QLevelOfDetail) + Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE; + void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) Q_DECL_OVERRIDE; + Q_PRIVATE_SLOT(d_func(), void _q_radiusChanged(float)) + Q_PRIVATE_SLOT(d_func(), void _q_centerChanged(const QVector3D&)) +}; + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_QLEVELOFDETAIL_H diff --git a/src/render/frontend/qlevelofdetail_p.h b/src/render/frontend/qlevelofdetail_p.h new file mode 100644 index 000000000..ab25e9ad3 --- /dev/null +++ b/src/render/frontend/qlevelofdetail_p.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QT3DRENDER_QLEVELOFDETAIL_P_H +#define QT3DRENDER_QLEVELOFDETAIL_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 <private/qcomponent_p.h> +#include <qlevelofdetail.h> + +#include <QVector3D> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QLevelOfDetailPrivate : public Qt3DCore::QComponentPrivate +{ +public: + QLevelOfDetailPrivate(); + + Q_DECLARE_PUBLIC(QLevelOfDetail) + + void _q_radiusChanged(float radius); + void _q_centerChanged(const QVector3D ¢er); + + QCamera *m_camera; + int m_currentIndex; + QLevelOfDetail::ThresholdType m_thresholdType; + QVector<qreal> m_thresholds; + QPointer<QBoundingSphere> m_volumeOverride; +}; + +struct QLevelOfDetailData +{ + Qt3DCore::QNodeId camera; + int currentIndex; + QLevelOfDetail::ThresholdType thresholdType; + QVector<qreal> thresholds; + float radius; + QVector3D center; +}; + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_QLEVELOFDETAIL_P_H diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp index f518e7ce7..7bddecadf 100644 --- a/src/render/frontend/qrenderaspect.cpp +++ b/src/render/frontend/qrenderaspect.cpp @@ -51,6 +51,7 @@ #include <Qt3DRender/qcameraselector.h> #include <Qt3DRender/qlayer.h> #include <Qt3DRender/qlayerfilter.h> +#include <Qt3DRender/qlevelofdetail.h> #include <Qt3DRender/qmaterial.h> #include <Qt3DRender/qmesh.h> #include <Qt3DRender/qparameter.h> @@ -190,6 +191,7 @@ void QRenderAspectPrivate::registerBackendTypes() q->registerBackendType<Qt3DRender::QCameraLens>(QSharedPointer<Render::NodeFunctor<Render::CameraLens, Render::CameraManager> >::create(m_renderer)); q->registerBackendType<QLayer>(QSharedPointer<Render::NodeFunctor<Render::Layer, Render::LayerManager> >::create(m_renderer)); + q->registerBackendType<QLevelOfDetail>(QSharedPointer<Render::NodeFunctor<Render::LevelOfDetail, Render::LevelOfDetailManager> >::create(m_renderer)); q->registerBackendType<QSceneLoader>(QSharedPointer<Render::RenderSceneFunctor>::create(m_renderer, m_nodeManagers->sceneManager())); q->registerBackendType<QRenderTarget>(QSharedPointer<Render::NodeFunctor<Render::RenderTarget, Render::RenderTargetManager> >::create(m_renderer)); q->registerBackendType<QRenderTargetOutput>(QSharedPointer<Render::NodeFunctor<Render::RenderTargetOutput, Render::AttachmentManager> >::create(m_renderer)); diff --git a/src/render/frontend/render-frontend.pri b/src/render/frontend/render-frontend.pri index 829e3d756..649b3d673 100644 --- a/src/render/frontend/render-frontend.pri +++ b/src/render/frontend/render-frontend.pri @@ -2,11 +2,15 @@ INCLUDEPATH += $$PWD HEADERS += \ $$PWD/qabstractfunctor.h \ + $$PWD/qboundingsphere.h \ + $$PWD/qboundingsphere_p.h \ $$PWD/qrenderaspect.h \ $$PWD/qrenderaspect_p.h \ $$PWD/qitemmodelbuffer_p.h \ $$PWD/qlayer.h \ $$PWD/qlayer_p.h \ + $$PWD/qlevelofdetail.h \ + $$PWD/qlevelofdetail_p.h \ $$PWD/qrendertarget.h \ $$PWD/qrendertarget_p.h \ $$PWD/sphere_p.h \ @@ -25,10 +29,12 @@ HEADERS += \ SOURCES += \ $$PWD/qabstractfunctor.cpp \ + $$PWD/qboundingsphere.cpp \ $$PWD/qrenderaspect.cpp \ $$PWD/qitemmodelbuffer.cpp \ $$PWD/sphere.cpp \ $$PWD/qlayer.cpp \ + $$PWD/qlevelofdetail.cpp \ $$PWD/qrendertarget.cpp \ $$PWD/qcamera.cpp \ $$PWD/qcameralens.cpp \ diff --git a/src/render/jobs/job_common_p.h b/src/render/jobs/job_common_p.h index f3be2e6b0..90e29d0dc 100644 --- a/src/render/jobs/job_common_p.h +++ b/src/render/jobs/job_common_p.h @@ -96,6 +96,7 @@ namespace JobTypes { ClearBufferDrawIndex, UpdateMeshTriangleList, FilterCompatibleTechniques, + UpdateLevelOfDetail, SyncTextureLoading }; diff --git a/src/render/jobs/jobs.pri b/src/render/jobs/jobs.pri index 2827d959d..d7f05ec4c 100644 --- a/src/render/jobs/jobs.pri +++ b/src/render/jobs/jobs.pri @@ -24,6 +24,7 @@ HEADERS += \ $$PWD/updateworldboundingvolumejob_p.h \ $$PWD/sendrendercapturejob_p.h \ $$PWD/updateshaderdatatransformjob_p.h \ + $$PWD/updatelevelofdetailjob_p.h \ $$PWD/updatemeshtrianglelistjob_p.h \ $$PWD/pickboundingvolumeutils_p.h \ $$PWD/filtercompatibletechniquejob_p.h \ @@ -51,6 +52,7 @@ SOURCES += \ $$PWD/sendrendercapturejob.cpp \ $$PWD/updateshaderdatatransformjob.cpp \ $$PWD/updatemeshtrianglelistjob.cpp \ + $$PWD/updatelevelofdetailjob.cpp \ $$PWD/pickboundingvolumeutils.cpp \ $$PWD/filtercompatibletechniquejob.cpp \ $$PWD/updatetreeenabledjob.cpp diff --git a/src/render/jobs/pickboundingvolumeutils.cpp b/src/render/jobs/pickboundingvolumeutils.cpp index 1498021a7..1573aa112 100644 --- a/src/render/jobs/pickboundingvolumeutils.cpp +++ b/src/render/jobs/pickboundingvolumeutils.cpp @@ -102,6 +102,8 @@ QVector<ViewportCameraAreaTriplet> ViewportCameraAreaGatherer::gather(FrameGraph // Find all viewport/camera pairs by traversing from leaf to root for (Render::FrameGraphNode *leaf : qAsConst(m_leaves)) { ViewportCameraAreaTriplet vcaTriplet = gatherUpViewportCameraAreas(leaf); + if (!m_targetCamera.isNull() && vcaTriplet.cameraId != m_targetCamera) + continue; if (!vcaTriplet.cameraId.isNull() && isUnique(vcaTriplets, vcaTriplet)) vcaTriplets.push_back(vcaTriplet); } diff --git a/src/render/jobs/pickboundingvolumeutils_p.h b/src/render/jobs/pickboundingvolumeutils_p.h index f514c045f..0a65c58cc 100644 --- a/src/render/jobs/pickboundingvolumeutils_p.h +++ b/src/render/jobs/pickboundingvolumeutils_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <Qt3DCore/QNodeId> #include <Qt3DRender/private/qray3d_p.h> #include <Qt3DRender/private/trianglesvisitor_p.h> #include <Qt3DRender/private/qraycastingservice_p.h> @@ -82,9 +83,11 @@ QT3D_DECLARE_TYPEINFO_3(Qt3DRender, Render, PickingUtils, ViewportCameraAreaTrip class Q_AUTOTEST_EXPORT ViewportCameraAreaGatherer { public: + ViewportCameraAreaGatherer(const Qt3DCore::QNodeId &nodeId = Qt3DCore::QNodeId()) : m_targetCamera(nodeId) { } QVector<ViewportCameraAreaTriplet> gather(FrameGraphNode *root); private: + Qt3DCore::QNodeId m_targetCamera; QVector<FrameGraphNode *> m_leaves; void visit(FrameGraphNode *node); diff --git a/src/render/jobs/updatelevelofdetailjob.cpp b/src/render/jobs/updatelevelofdetailjob.cpp new file mode 100644 index 000000000..940d26850 --- /dev/null +++ b/src/render/jobs/updatelevelofdetailjob.cpp @@ -0,0 +1,230 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "updatelevelofdetailjob_p.h" +#include <Qt3DRender/QLevelOfDetail> +#include <Qt3DRender/private/job_common_p.h> +#include <Qt3DRender/private/nodemanagers_p.h> +#include <Qt3DRender/private/managers_p.h> +#include <Qt3DRender/private/sphere_p.h> + +QT_BEGIN_NAMESPACE + +namespace +{ + +template <unsigned N> +double approxRollingAverage(double avg, double input) { + avg -= avg / N; + avg += input / N; + return avg; +} + +} +namespace Qt3DRender { + +namespace Render { + +UpdateLevelOfDetailJob::UpdateLevelOfDetailJob() + : m_manager(nullptr) + , m_frameGraphRoot(nullptr) + , m_root(nullptr) + , m_filterValue(0.) +{ + SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateLevelOfDetail, 0); +} + +UpdateLevelOfDetailJob::~UpdateLevelOfDetailJob() +{ +} + +void UpdateLevelOfDetailJob::setRoot(Entity *root) +{ + m_root = root; +} + +void UpdateLevelOfDetailJob::setManagers(NodeManagers *manager) +{ + m_manager = manager; +} + +void UpdateLevelOfDetailJob::setFrameGraphRoot(FrameGraphNode *frameGraphRoot) +{ + m_frameGraphRoot = frameGraphRoot; +} + +void UpdateLevelOfDetailJob::run() +{ + Q_ASSERT(m_frameGraphRoot && m_root && m_manager); + updateEntityLod(m_root); +} + +bool UpdateLevelOfDetailJob::viewMatrixForCamera(const Qt3DCore::QNodeId &cameraId, + QMatrix4x4 &viewMatrix, + QMatrix4x4 &projectionMatrix) const +{ + Render::CameraLens *lens = nullptr; + Entity *camNode = m_manager->renderNodesManager()->lookupResource(cameraId); + if (camNode != nullptr && + (lens = camNode->renderComponent<CameraLens>()) != nullptr && + lens->isEnabled()) { + viewMatrix = *camNode->worldTransform(); + projectionMatrix = lens->projection(); + return true; + } + return false; +} + +QRect UpdateLevelOfDetailJob::windowViewport(const QSize &area, const QRectF &relativeViewport) const +{ + if (area.isValid()) { + const int areaWidth = area.width(); + const int areaHeight = area.height(); + return QRect(relativeViewport.x() * areaWidth, + (1.0 - relativeViewport.y() - relativeViewport.height()) * areaHeight, + relativeViewport.width() * areaWidth, + relativeViewport.height() * areaHeight); + } + return relativeViewport.toRect(); +} + +void UpdateLevelOfDetailJob::updateEntityLod(Entity *entity) +{ + if (!entity->isEnabled()) + return; // skip disabled sub-trees, since their bounding box is probably not valid anyway + + QVector<LevelOfDetail *> lods = entity->renderComponents<LevelOfDetail>(); + if (!lods.empty()) { + LevelOfDetail* lod = lods.front(); // other lods are ignored + + if (lod->isEnabled() && !lod->thresholds().isEmpty()) { + switch (lod->thresholdType()) { + case QLevelOfDetail::DistanceToCamera: + updateEntityLodByDistance(entity, lod); + break; + case QLevelOfDetail::ProjectedScreenPixelSize: + updateEntityLodByScreenArea(entity, lod); + break; + default: + Q_ASSERT(false); + break; + } + } + } + + const auto children = entity->children(); + for (Qt3DRender::Render::Entity *child : children) + updateEntityLod(child); +} + +void UpdateLevelOfDetailJob::updateEntityLodByDistance(Entity *entity, LevelOfDetail *lod) +{ + QMatrix4x4 viewMatrix; + QMatrix4x4 projectionMatrix; + if (!viewMatrixForCamera(lod->camera(), viewMatrix, projectionMatrix)) + return; + + const QVector<qreal> thresholds = lod->thresholds(); + QVector3D center = lod->center(); + if (lod->radius() > 0.f || entity->worldBoundingVolume() == nullptr) { + center = *entity->worldTransform() * center; + } else { + center = entity->worldBoundingVolume()->center(); + } + + const QVector3D tcenter = viewMatrix * center; + const float dist = tcenter.length(); + const int n = thresholds.size(); + for (int i=0; i<n; ++i) { + if (dist <= thresholds[i] || i == n -1) { + m_filterValue = approxRollingAverage<30>(m_filterValue, i); + i = qBound(0, static_cast<int>(qRound(m_filterValue)), n - 1); + if (lod->currentIndex() != i) + lod->setCurrentIndex(i); + break; + } + } +} + +void UpdateLevelOfDetailJob::updateEntityLodByScreenArea(Entity *entity, LevelOfDetail *lod) +{ + QMatrix4x4 viewMatrix; + QMatrix4x4 projectionMatrix; + if (!viewMatrixForCamera(lod->camera(), viewMatrix, projectionMatrix)) + return; + + PickingUtils::ViewportCameraAreaGatherer vcaGatherer(lod->camera()); + const QVector<PickingUtils::ViewportCameraAreaTriplet> vcaTriplets = vcaGatherer.gather(m_frameGraphRoot); + if (vcaTriplets.isEmpty()) + return; + + const PickingUtils::ViewportCameraAreaTriplet &vca = vcaTriplets.front(); + + const QVector<qreal> thresholds = lod->thresholds(); + Sphere bv(lod->center(), lod->radius()); + if (lod->radius() <= 0.f && entity->worldBoundingVolume() != nullptr) { + bv = *(entity->worldBoundingVolume()); + } else { + bv.transform(*entity->worldTransform()); + } + + bv.transform(projectionMatrix * viewMatrix); + const float sideLength = bv.radius() * 2.f; + float area = vca.viewport.width() * sideLength * vca.viewport.height() * sideLength; + + const QRect r = windowViewport(vca.area, vca.viewport); + area = std::sqrt(area * r.width() * r.height()); + + const int n = thresholds.size(); + for (int i = 0; i < n; ++i) { + if (thresholds[i] < area || i == n -1) { + m_filterValue = approxRollingAverage<30>(m_filterValue, i); + i = qBound(0, static_cast<int>(qRound(m_filterValue)), n - 1); + if (lod->currentIndex() != i) + lod->setCurrentIndex(i); + break; + } + } +} + +} // Render + +} // Qt3DRender + +QT_END_NAMESPACE diff --git a/src/render/jobs/updatelevelofdetailjob_p.h b/src/render/jobs/updatelevelofdetailjob_p.h new file mode 100644 index 000000000..30fe3004d --- /dev/null +++ b/src/render/jobs/updatelevelofdetailjob_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 QT3DRENDER_RENDER_UPDATELEVELOFDETAILJOB_H +#define QT3DRENDER_RENDER_UPDATELEVELOFDETAILJOB_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 <Qt3DCore/qaspectjob.h> +#include <Qt3DRender/private/qt3drender_global_p.h> +#include <Qt3DRender/private/pickboundingvolumeutils_p.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +namespace Render { + +class Entity; +class NodeManagers; +class LevelOfDetail; + +class QT3DRENDERSHARED_PRIVATE_EXPORT UpdateLevelOfDetailJob : public Qt3DCore::QAspectJob +{ +public: + UpdateLevelOfDetailJob(); + ~UpdateLevelOfDetailJob(); + + void setManagers(NodeManagers *manager); + void setFrameGraphRoot(FrameGraphNode *frameGraphRoot); + void setRoot(Entity *root); + void run() Q_DECL_FINAL; + + NodeManagers *managers() const { return m_manager; } + Entity *root() const { return m_root; } + +private: + void updateEntityLod(Entity *entity); + void updateEntityLodByDistance(Entity *entity, LevelOfDetail *lod); + void updateEntityLodByScreenArea(Entity *entity, LevelOfDetail *lod); + bool viewMatrixForCamera(const Qt3DCore::QNodeId &cameraId, QMatrix4x4 &viewMatrix, QMatrix4x4 &projectionMatrix) const; + QRect windowViewport(const QSize &area, const QRectF &relativeViewport) const; + + NodeManagers *m_manager; + FrameGraphNode *m_frameGraphRoot; + Entity *m_root; + double m_filterValue; +}; + +typedef QSharedPointer<UpdateLevelOfDetailJob> UpdateLevelOfDetailJobPtr; + +} // Render + +} // Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_RENDER_UPDATELEVELOFDETAILJOB_H diff --git a/tests/auto/render/levelofdetail/levelofdetail.pro b/tests/auto/render/levelofdetail/levelofdetail.pro new file mode 100644 index 000000000..496efc35c --- /dev/null +++ b/tests/auto/render/levelofdetail/levelofdetail.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_levelofdetail + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_levelofdetail.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/levelofdetail/tst_levelofdetail.cpp b/tests/auto/render/levelofdetail/tst_levelofdetail.cpp new file mode 100644 index 000000000..ab0e8c4b8 --- /dev/null +++ b/tests/auto/render/levelofdetail/tst_levelofdetail.cpp @@ -0,0 +1,145 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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:GPL-EXCEPT$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <qbackendnodetester.h> +#include <Qt3DRender/QLevelOfDetail> +#include <Qt3DRender/QBoundingSphere> +#include <Qt3DRender/private/levelofdetail_p.h> +#include <Qt3DRender/private/qlevelofdetail_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qbackendnode_p.h> +#include "testpostmanarbiter.h" +#include "testrenderer.h" + +class tst_LevelOfDetail : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT +private Q_SLOTS: + + void checkPeerPropertyMirroring() + { + // GIVEN + Qt3DRender::Render::LevelOfDetail renderLod; + Qt3DRender::QLevelOfDetail lod; + + // WHEN + simulateInitialization(&lod, &renderLod); + + // THEN + QCOMPARE(renderLod.peerId(), lod.id()); + QVERIFY(renderLod.camera().isNull() && lod.camera() == nullptr); + QCOMPARE(renderLod.currentIndex(), lod.currentIndex()); + QCOMPARE(renderLod.thresholdType(), lod.thresholdType()); + QCOMPARE(renderLod.thresholds(), lod.thresholds()); + QCOMPARE(renderLod.center(), lod.volumeOverride()->center()); + QCOMPARE(renderLod.radius(), lod.volumeOverride()->radius()); + } + + void checkInitialAndCleanedUpState() + { + // GIVEN + Qt3DRender::Render::LevelOfDetail renderLod; + TestRenderer renderer; + + // THEN + QCOMPARE(renderLod.camera(), Qt3DCore::QNodeId{}); + QCOMPARE(renderLod.currentIndex(), 0); + QCOMPARE(renderLod.thresholdType(), Qt3DRender::QLevelOfDetail::DistanceToCamera); + QVERIFY(renderLod.thresholds().empty()); + QCOMPARE(renderLod.radius(), 1.f); + QCOMPARE(renderLod.center(), QVector3D{}); + QVERIFY(renderLod.peerId().isNull()); + + // GIVEN + Qt3DRender::QLevelOfDetail lod; + lod.setThresholdType(Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSize); + + // WHEN + renderLod.setRenderer(&renderer); + simulateInitialization(&lod, &renderLod); + + // THEN + QCOMPARE(renderLod.thresholdType(), lod.thresholdType()); + } + + void checkPropertyChanges() + { + // GIVEN + TestRenderer renderer; + Qt3DRender::Render::LevelOfDetail renderLod; + renderLod.setRenderer(&renderer); + + // THEN + QVERIFY(renderLod.thresholdType() != Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSize); + QVERIFY(renderLod.camera().isNull()); + + { + // WHEN + Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setValue(static_cast<int>(Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSize)); + updateChange->setPropertyName("thresholdType"); + renderLod.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(renderLod.thresholdType(), Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSize); + QVERIFY(renderer.dirtyBits() != 0); + } + + { + QVector<qreal> thresholds = {20.f, 30.f, 40.f}; + QVariant v; + v.setValue<decltype(thresholds)>(thresholds); + + // WHEN + Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setValue(v); + updateChange->setPropertyName("thresholds"); + renderLod.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(renderLod.thresholds(), thresholds); + } + + { + // WHEN + Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId())); + updateChange->setValue(QVector3D(1., 2., 3.)); + updateChange->setPropertyName("center"); + renderLod.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(renderLod.center(), QVector3D(1., 2., 3.)); + } + } +}; + + +QTEST_APPLESS_MAIN(tst_LevelOfDetail) + +#include "tst_levelofdetail.moc" diff --git a/tests/auto/render/qlevelofdetail/qlevelofdetail.pro b/tests/auto/render/qlevelofdetail/qlevelofdetail.pro new file mode 100644 index 000000000..e8d7010a3 --- /dev/null +++ b/tests/auto/render/qlevelofdetail/qlevelofdetail.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qlevelofdetail + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_qlevelofdetail.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/qlevelofdetail/tst_qlevelofdetail.cpp b/tests/auto/render/qlevelofdetail/tst_qlevelofdetail.cpp new file mode 100644 index 000000000..e2ffdd9da --- /dev/null +++ b/tests/auto/render/qlevelofdetail/tst_qlevelofdetail.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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:GPL-EXCEPT$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DCore/private/qnode_p.h> +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> + +#include <Qt3DRender/qlevelofdetail.h> +#include <Qt3DRender/private/qlevelofdetail_p.h> + +#include "testpostmanarbiter.h" + +class tst_QLevelOfDetail: public QObject +{ + Q_OBJECT + +private Q_SLOTS: + + void checkCloning_data() + { + QTest::addColumn<Qt3DRender::QLevelOfDetail *>("lod"); + + Qt3DRender::QLevelOfDetail *defaultConstructed = new Qt3DRender::QLevelOfDetail(); + QTest::newRow("defaultConstructed") << defaultConstructed; + + Qt3DRender::QLevelOfDetail *lodDst = new Qt3DRender::QLevelOfDetail(); + QTest::newRow("distLod") << lodDst; + + Qt3DRender::QLevelOfDetail *lodPx = new Qt3DRender::QLevelOfDetail(); + QTest::newRow("pxLod") << lodPx; + } + + void checkCloning() + { + // GIVEN + QFETCH(Qt3DRender::QLevelOfDetail *, lod); + + // WHEN + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(lod); + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = creationChangeGenerator.creationChanges(); + + // THEN + QCOMPARE(creationChanges.size(), 1); + + const Qt3DCore::QNodeCreatedChangePtr<Qt3DRender::QLevelOfDetailData> creationChangeData = + qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QLevelOfDetailData>>(creationChanges.first()); + const Qt3DRender::QLevelOfDetailData &cloneData = creationChangeData->data; + + QCOMPARE(lod->id(), creationChangeData->subjectId()); + QCOMPARE(lod->isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(lod->metaObject(), creationChangeData->metaObject()); + QCOMPARE(lod->currentIndex(), cloneData.currentIndex); + QCOMPARE(lod->thresholdType(), cloneData.thresholdType); + QCOMPARE(lod->thresholds(), cloneData.thresholds); + } + + void checkPropertyUpdates() + { + // GIVEN + TestArbiter arbiter; + QScopedPointer<Qt3DRender::QLevelOfDetail> lod(new Qt3DRender::QLevelOfDetail()); + arbiter.setArbiterOnNode(lod.data()); + + { + // WHEN + lod->setThresholdType(Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSize); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "thresholdType"); + QCOMPARE(change->value().value<int>(), static_cast<int>(Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSize)); + + arbiter.events.clear(); + } + + { + // WHEN + QVector<qreal> thresholds = {10., 20., 30.}; + lod->setThresholds(thresholds); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "thresholds"); + QCOMPARE(change->value().value<decltype(thresholds)>(), thresholds); + + arbiter.events.clear(); + } + } +}; + +QTEST_MAIN(tst_QLevelOfDetail) + +#include "tst_qlevelofdetail.moc" diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro index 666723ae8..c1de2aff8 100644 --- a/tests/auto/render/render.pro +++ b/tests/auto/render/render.pro @@ -18,6 +18,8 @@ qtConfig(private_tests) { qbuffer \ qgeometry \ qgeometryrenderer \ + qlevelofdetail \ + levelofdetail \ buffer \ attribute \ geometry \ diff --git a/tests/manual/lod/ConeEntity.qml b/tests/manual/lod/ConeEntity.qml new file mode 100644 index 000000000..bfe6703b6 --- /dev/null +++ b/tests/manual/lod/ConeEntity.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.4 as QQ2 +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 +import Qt3D.Extras 2.0 + +Entity { + components: [ mesh, phongMaterial, transform ] + + ConeMesh { + id: mesh + bottomRadius: 1.5 + length: 3 + } + + PhongMaterial { + id: phongMaterial + diffuse: "red" + } + + Transform { + id: transform + scale: 4 + } +} diff --git a/tests/manual/lod/CuboidEntity.qml b/tests/manual/lod/CuboidEntity.qml new file mode 100644 index 000000000..875d98b32 --- /dev/null +++ b/tests/manual/lod/CuboidEntity.qml @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.4 as QQ2 +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 +import Qt3D.Extras 2.0 + +Entity { + components: [ mesh, phongMaterial, transform ] + + CuboidMesh { + id: mesh + yzMeshResolution: Qt.size(2, 2) + xzMeshResolution: Qt.size(2, 2) + xyMeshResolution: Qt.size(2, 2) + } + + PhongMaterial { + id: phongMaterial + diffuse: "yellow" + } + + Transform { + id: transform + scale: 4 + } +} diff --git a/tests/manual/lod/CylinderEntity.qml b/tests/manual/lod/CylinderEntity.qml new file mode 100644 index 000000000..f89bd3eeb --- /dev/null +++ b/tests/manual/lod/CylinderEntity.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.4 as QQ2 +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 +import Qt3D.Extras 2.0 + +Entity { + components: [ mesh, phongMaterial, transform ] + + CylinderMesh { + id: mesh + radius: 1 + length: 3 + } + + PhongMaterial { + id: phongMaterial + diffuse: "green" + } + + Transform { + id: transform + scale: 4 + } +} diff --git a/tests/manual/lod/SphereEntity.qml b/tests/manual/lod/SphereEntity.qml new file mode 100644 index 000000000..3671921b8 --- /dev/null +++ b/tests/manual/lod/SphereEntity.qml @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.4 as QQ2 +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 +import Qt3D.Extras 2.0 + +Entity { + components: [ mesh, material, transform ] + + SphereMesh { + id: mesh + radius: 1 + } + + PhongMaterial { + id: material + diffuse: "blue" + } + + Transform { + id: transform + scale: 4 + } +} diff --git a/tests/manual/lod/lod.pro b/tests/manual/lod/lod.pro new file mode 100644 index 000000000..32ccc6571 --- /dev/null +++ b/tests/manual/lod/lod.pro @@ -0,0 +1,20 @@ +!include( ../manual.pri ) { + error( "Couldn't find the manual.pri file!" ) +} + +QT += 3dcore 3drender 3dinput 3dquick qml quick 3dquickextras + +SOURCES += \ + main.cpp + +OTHER_FILES += \ + main.qml + +RESOURCES += \ + lod.qrc + +DISTFILES += \ + ConeEntity.qml \ + CuboidEntity.qml \ + CylinderEntity.qml \ + SphereEntity.qml diff --git a/tests/manual/lod/lod.qrc b/tests/manual/lod/lod.qrc new file mode 100644 index 000000000..746ac679e --- /dev/null +++ b/tests/manual/lod/lod.qrc @@ -0,0 +1,9 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + <file>ConeEntity.qml</file> + <file>CuboidEntity.qml</file> + <file>CylinderEntity.qml</file> + <file>SphereEntity.qml</file> + </qresource> +</RCC> diff --git a/tests/manual/lod/main.cpp b/tests/manual/lod/main.cpp new file mode 100644 index 000000000..dba6e0bff --- /dev/null +++ b/tests/manual/lod/main.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <Qt3DQuickExtras/qt3dquickwindow.h> +#include <QGuiApplication> + +int main(int argc, char* argv[]) +{ + QGuiApplication app(argc, argv); + Qt3DExtras::Quick::Qt3DQuickWindow view; + + view.setSource(QUrl("qrc:/main.qml")); + view.show(); + + return app.exec(); +} diff --git a/tests/manual/lod/main.qml b/tests/manual/lod/main.qml new file mode 100644 index 000000000..aea87f653 --- /dev/null +++ b/tests/manual/lod/main.qml @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt3D.Core 2.0 +import Qt3D.Render 2.2 +import Qt3D.Input 2.0 +import Qt3D.Extras 2.2 + +import QtQuick 2.0 as QQ2 + +Entity { + id: sceneRoot + + Camera { + id: camera + projectionType: CameraLens.PerspectiveProjection + fieldOfView: 45 + aspectRatio: 16/9 + nearPlane : 0.1 + farPlane : 1000.0 + 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 ) + } + + OrbitCameraController { camera: camera } + + Entity { + id: headlight + components: [ + DirectionalLight { + color: Qt.rgba(0.8, 0.8, 0.8, 1.0) + worldDirection: camera.viewVector + } + ] + } + + RenderSettings { + id : external_forward_renderer + activeFrameGraph : ForwardRenderer { + camera: camera + clearColor: "white" + } + } + + // Event Source will be set by the Qt3DQuickWindow + InputSettings { id: inputSettings } + + components: [external_forward_renderer, inputSettings] + + Entity { + components: [ + Transform { + id: transform + } + ] + + Entity { + components: [ + CylinderMesh { + id: mesh + radius: 1 + length: 3 + rings: 2 + slices: sliceValues[lod.currentIndex] + + property var sliceValues: [20, 10, 6, 4] + }, + Transform { + scale: 1.5 + translation: Qt.vector3d(-5, 0, 0) + rotation: fromAxisAndAngle(Qt.vector3d(1, 0, 0), 45) + }, + PhongMaterial { + id: material + diffuse: "lightgreen" + }, + LevelOfDetail { + id: lod + camera: camera + thresholds: [1000, 600, 300, 180] + thresholdType: LevelOfDetail.ProjectedScreenPixelSize + volumeOverride: BoundingSphere { + radius: 2. + } + } + ] + } + } + + Entity { + components: [ + Transform { + translation: transform.translation + } + ] + + LevelOfDetailLoader { + components: [ Transform { + scale: .5 + translation: Qt.vector3d(5, 0, 0) + } ] + + camera: camera + thresholds: [20, 35, 50, 65] + thresholdType: LevelOfDetail.DistanceToCamera + volumeOverride: null + sources: ["qrc:/SphereEntity.qml", "qrc:/CylinderEntity.qml", "qrc:/ConeEntity.qml", "qrc:/CuboidEntity.qml"] + } + } + + QQ2.SequentialAnimation { + QQ2.Vector3dAnimation { + target: transform + properties: "translation" + from: Qt.vector3d(0, 0, 10) + to: Qt.vector3d(0, 0, -50) + duration: 2500 + easing.type: QQ2.Easing.InOutQuad + } + QQ2.PropertyAnimation { + target: transform + properties: "translation" + from: Qt.vector3d(0, 0, -50) + to: Qt.vector3d(0, 0, 10) + duration: 2500 + easing.type: QQ2.Easing.InOutQuad + } + + loops: QQ2.Animation.Infinite + running: true + } +} diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro index bfb95bfc2..3b036e2ba 100644 --- a/tests/manual/manual.pro +++ b/tests/manual/manual.pro @@ -21,6 +21,7 @@ SUBDIRS += \ gooch-qml \ keyboardinput-qml \ loader-qml \ + lod \ mouseinput-qml \ multiplewindows-qml \ picking-qml \ |