diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2019-08-08 14:45:29 +0200 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2019-08-27 17:08:23 +0200 |
commit | 91dc1e1a61651a82a0ee5ce6ad3b24e82f526be6 (patch) | |
tree | f54c30c337a9bae1e0b5d9c8622dd599344f46bf | |
parent | f9306d34bde648975b2a3e24eea01aaa4b6bd679 (diff) |
Introduce Scene3DView
Allows to render several 3D scenes using a single Scene3D. To be used when
you need multiple Scene3D instances.
[ChangeLog] Introduce Scene3DView to render multiple distinct 3D scenes
Change-Id: I5d51c5935218cc84c15d57def3703aa0d92040ba
Reviewed-by: Mike Krus <mike.krus@kdab.com>
18 files changed, 1049 insertions, 17 deletions
diff --git a/examples/qt3d/qt3d.pro b/examples/qt3d/qt3d.pro index 2f8d624af..91163a0d1 100644 --- a/examples/qt3d/qt3d.pro +++ b/examples/qt3d/qt3d.pro @@ -21,7 +21,8 @@ SUBDIRS += \ scene2d \ phong-cubes \ pbr-materials \ - controlsunderlay + controlsunderlay \ + scene3dview qtHaveModule(multimedia): SUBDIRS += audio-visualizer-qml diff --git a/examples/qt3d/scene3dview/AnimatedEntity.qml b/examples/qt3d/scene3dview/AnimatedEntity.qml new file mode 100644 index 000000000..12575b314 --- /dev/null +++ b/examples/qt3d/scene3dview/AnimatedEntity.qml @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE: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.0 +import Qt3D.Input 2.0 +import Qt3D.Extras 2.0 + +import QtQuick 2.0 as QQ2 + + +Entity { + id: sceneRoot + property color sceneColor + property bool clearColor: true + + Camera { + id: camera + projectionType: CameraLens.PerspectiveProjection + fieldOfView: 45 + nearPlane : 0.1 + farPlane : 1000.0 + position: Qt.vector3d( 0.0, 0.0, 40.0 ) + upVector: Qt.vector3d( 0.0, 1.0, 0.0 ) + viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 ) + } + + FirstPersonCameraController { camera: camera } + + components: [ + RenderSettings { + activeFrameGraph: ForwardRenderer { + camera: camera + clearColor: "transparent" + clearBuffers: sceneRoot.clearColor ? ClearBuffers.ColorDepthBuffer : ClearBuffers.DepthBuffer + } + }, + InputSettings { } + ] + + PhongMaterial { + id: material + diffuse: sceneColor + } + + TorusMesh { + id: torusMesh + radius: 5 + minorRadius: 1 + rings: 100 + slices: 20 + } + + Transform { + id: torusTransform + scale3D: Qt.vector3d(1.5, 1, 0.5) + rotation: fromAxisAndAngle(Qt.vector3d(1, 0, 0), 45) + } + + Entity { + id: torusEntity + components: [ torusMesh, material, torusTransform ] + } + + SphereMesh { + id: sphereMesh + radius: 3 + } + + Transform { + id: sphereTransform + property real userAngle: 0.0 + matrix: { + var m = Qt.matrix4x4(); + m.rotate(userAngle, Qt.vector3d(0, 1, 0)) + m.translate(Qt.vector3d(20, 0, 0)); + return m; + } + } + + QQ2.NumberAnimation { + target: sphereTransform + property: "userAngle" + duration: 10000 + from: 0 + to: 360 + + loops: QQ2.Animation.Infinite + running: true + } + + Entity { + id: sphereEntity + components: [ sphereMesh, material, sphereTransform ] + } +} diff --git a/examples/qt3d/scene3dview/doc/images/scene3dview.png b/examples/qt3d/scene3dview/doc/images/scene3dview.png Binary files differnew file mode 100644 index 000000000..d697d1850 --- /dev/null +++ b/examples/qt3d/scene3dview/doc/images/scene3dview.png diff --git a/examples/qt3d/scene3dview/doc/src/scene3dview.qdoc b/examples/qt3d/scene3dview/doc/src/scene3dview.qdoc new file mode 100644 index 000000000..721929350 --- /dev/null +++ b/examples/qt3d/scene3dview/doc/src/scene3dview.qdoc @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example scene3dview + \title Qt 3D: Scene3DView QML Example + \ingroup qt3d-examples-qml + \brief A QML application that demonstrates visualizing multiple 3D scenes + using Scene3D and Scene3DView. + + \image scene3dview.png + + This example demonstrates visualizing multiple 3D scenes from a Qt Quick + application usinc Scene3D and Scene3DView. Each 3D scene contains a single + active camera and a single active light source. Visualized data is assumed + to be at a fixed location. + + \include examples-run.qdocinc + + \section1 Visualizing 3D Scenes + + First we set up a Scene3D instance that will be required for our + Scene3DView instanced. + + \snippet scene3dview/main.qml 0 + + Then we instanciate our Scene3DView instances and make them reference the + Scene3D. We also provide a root Entity for each Scene3DView with a \e + scene3dview/AnimatedEntity.qml. + + \snippet scene3dview/main.qml 1 + + Care has to be taken that only the first Scene3DView clears the color + buffer. We don't want each Scene3DView to clear the screen as that would + erase content for all but the last Scene3DView. + + \snippet scene3dview/main.qml 1.1 +*/ diff --git a/examples/qt3d/scene3dview/main.cpp b/examples/qt3d/scene3dview/main.cpp new file mode 100644 index 000000000..8886263f4 --- /dev/null +++ b/examples/qt3d/scene3dview/main.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE: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 <QGuiApplication> +#include <QQuickView> + +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + + QQuickView view; + + view.resize(500, 500); + view.setResizeMode(QQuickView::SizeRootObjectToView); + view.setSource(QUrl("qrc:/main.qml")); + view.show(); + + return app.exec(); +} diff --git a/examples/qt3d/scene3dview/main.qml b/examples/qt3d/scene3dview/main.qml new file mode 100644 index 000000000..d2a3fc3e0 --- /dev/null +++ b/examples/qt3d/scene3dview/main.qml @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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.14 +import QtQuick.Scene3D 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 + +Item { + + //! [0] + Scene3D { + id: scene3dInstance + anchors.fill: parent + focus: true + aspects: ["input", "logic"] + cameraAspectRatioMode: Scene3D.AutomaticAspectRatio + multisample: true + } + //! [0] + + ColumnLayout { + anchors.fill: parent + Grid { + id: grid + Layout.fillWidth: true + Layout.fillHeight: true + columns: 2 + rows: 2 + spacing: 50 + + readonly property int cellWidth: (width - spacing ) * 0.5 + readonly property int cellHeight: (height -spacing) * 0.5 + readonly property var colors: ["green", "gray", "orange", "blue"] + readonly property int maxInstances: grid.rows * grid.columns + + Repeater { + id: gridRepeater + model: grid.rows * grid.columns + + //! [1] + Rectangle { + width: grid.cellWidth + height: grid.cellHeight + color: "darkRed" + scale: ma.pressed || ma.containsMouse ? 0.8 : 1 + Behavior on scale { NumberAnimation { duration: 750 } } + + Scene3DView { + onXChanged: console.log(("X (%1): %2").arg(model.index).arg(x)) + scene3D: scene3dInstance + anchors.fill: parent + AnimatedEntity { + sceneColor: grid.colors[model.index] + //! [1.1] + // Only clear the color for the first Scene3DView + clearColor: model.index === 0 + //! [1.1] + } + } + Text { + anchors { + horizontalCenter: parent.horizontalCenter + bottom: parent.bottom + } + + color: "white" + font.bold: true + text: "Scene3DView " + (model.index + 1) + } + + MouseArea { + id: ma + anchors.fill: parent + hoverEnabled: true + } + } + //! [1] + } + } + + RowLayout { + Layout.alignment: Qt.AlignHCenter + Button { + text: "-" + onClicked: gridRepeater.model = Math.max(1, gridRepeater.count - 1); + } + Text { text: "Instances (%1/%2)".arg(gridRepeater.count).arg(grid.maxInstances) } + Button { + text: "+" + onClicked: gridRepeater.model = Math.min(grid.maxInstances, gridRepeater.count + 1); + } + } + } +} diff --git a/examples/qt3d/scene3dview/scene3dview.pro b/examples/qt3d/scene3dview/scene3dview.pro new file mode 100644 index 000000000..4e1052b7b --- /dev/null +++ b/examples/qt3d/scene3dview/scene3dview.pro @@ -0,0 +1,15 @@ +!include( ../examples.pri ) { + error( "Couldn't find the examples.pri file!" ) +} + +QT += qml quick 3dinput + +SOURCES += \ + main.cpp + +OTHER_FILES += \ + AnimatedEntity.qml \ + main.qml + +RESOURCES += \ + scene3dview.qrc diff --git a/examples/qt3d/scene3dview/scene3dview.qrc b/examples/qt3d/scene3dview/scene3dview.qrc new file mode 100644 index 000000000..dff72ed5a --- /dev/null +++ b/examples/qt3d/scene3dview/scene3dview.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file>AnimatedEntity.qml</file> + <file>main.qml</file> + </qresource> +</RCC> diff --git a/src/quick3d/imports/scene3d/importsscene3d.pro b/src/quick3d/imports/scene3d/importsscene3d.pro index a97dac09a..e29f7b831 100644 --- a/src/quick3d/imports/scene3d/importsscene3d.pro +++ b/src/quick3d/imports/scene3d/importsscene3d.pro @@ -17,7 +17,8 @@ HEADERS += \ scene3drenderer_p.h \ scene3dsgnode_p.h \ scene3dsgmaterialshader_p.h \ - scene3dsgmaterial_p.h + scene3dsgmaterial_p.h \ + scene3dview_p.h SOURCES += \ qtquickscene3dplugin.cpp \ @@ -27,7 +28,8 @@ SOURCES += \ scene3drenderer.cpp \ scene3dsgnode.cpp \ scene3dsgmaterialshader.cpp \ - scene3dsgmaterial.cpp + scene3dsgmaterial.cpp \ + scene3dview.cpp OTHER_FILES += qmldir diff --git a/src/quick3d/imports/scene3d/qtquickscene3dplugin.cpp b/src/quick3d/imports/scene3d/qtquickscene3dplugin.cpp index f93a8fdd1..00f24070e 100644 --- a/src/quick3d/imports/scene3d/qtquickscene3dplugin.cpp +++ b/src/quick3d/imports/scene3d/qtquickscene3dplugin.cpp @@ -42,6 +42,7 @@ #include <QtQml> #include <scene3ditem_p.h> +#include <scene3dview_p.h> QT_BEGIN_NAMESPACE @@ -49,6 +50,7 @@ void QtQuickScene3DPlugin::registerTypes(const char *uri) { qmlRegisterType<Qt3DRender::Scene3DItem>(uri, 2, 0, "Scene3D"); qmlRegisterType<Qt3DRender::Scene3DItem, 14>(uri, 2, 14, "Scene3D"); + qmlRegisterType<Qt3DRender::Scene3DView>(uri, 2, 14, "Scene3DView"); // Auto-increment the import to stay in sync with ALL future Qt minor versions qmlRegisterModule(uri, 2, QT_VERSION_MINOR); diff --git a/src/quick3d/imports/scene3d/scene3ditem.cpp b/src/quick3d/imports/scene3d/scene3ditem.cpp index 8f3d0b9a6..098cab032 100644 --- a/src/quick3d/imports/scene3d/scene3ditem.cpp +++ b/src/quick3d/imports/scene3d/scene3ditem.cpp @@ -72,6 +72,7 @@ #include <scene3dlogging_p.h> #include <scene3drenderer_p.h> #include <scene3dsgnode_p.h> +#include <scene3dview_p.h> #include <Qt3DCore/private/qaspectengine_p.h> #include <Qt3DCore/private/qaspectmanager_p.h> @@ -122,16 +123,33 @@ namespace Qt3DRender { \endqml to that material. + + It is not recommended to instantiate more than a single Scene3D instance + per application. The reason for this is that a Scene3D instance + instantiates the entire Qt 3D engine (memory managers, thread pool, render + ...) under the scene. You should instead look into using \l Scene3DView + instances in conjunction with a single Scene3D instance. + + When using Scene3D with Scene3DViews the following conditions are expected: + \list + \li The compositingMode is set to FBO + \li The Scene3D is sized to occupy the full window size + \li The Scene3D instance is instantiated prior to any Scene3DView + \li The Scene3D entity property is left unset + \endlist */ Scene3DItem::Scene3DItem(QQuickItem *parent) : QQuickItem(parent) , m_entity(nullptr) + , m_viewHolderEntity(nullptr) + , m_viewHolderFG(nullptr) , m_aspectEngine(new Qt3DCore::QAspectEngine()) , m_renderAspect(nullptr) , m_renderer(nullptr) , m_rendererCleaner(new Scene3DCleaner()) , m_multisample(true) , m_dirty(true) + , m_dirtyViews(false) , m_clearsWindowByDefault(true) , m_disableClearWindow(false) , m_cameraAspectRatioMode(AutomaticAspectRatio) @@ -186,7 +204,7 @@ Qt3DCore::QEntity *Scene3DItem::entity() const void Scene3DItem::setAspects(const QStringList &aspects) { if (!m_aspects.isEmpty()) { - qWarning() << "Aspects already set on the Scene3D, ignoring"; + qCWarning(Scene3D) << "Aspects already set on the Scene3D, ignoring"; return; } @@ -312,6 +330,66 @@ Scene3DItem::CompositingMode Scene3DItem::compositingMode() const return m_compositingMode; } +// MainThread called by Scene3DView +void Scene3DItem::addView(Scene3DView *view) +{ + if (m_views.contains(view)) + return; + + Qt3DRender::QFrameGraphNode *viewFG = view->viewFrameGraph(); + Qt3DCore::QEntity *subtreeRoot = view->viewSubtree(); + + if (m_viewHolderEntity == nullptr) { + m_viewHolderEntity = new Qt3DCore::QEntity; + + if (m_entity != nullptr) { + qCWarning(Scene3D) << "Scene3DView is not supported if the Scene3D entity property has been set"; + } + + Qt3DRender::QRenderSettings *settings = new Qt3DRender::QRenderSettings(); + Qt3DRender::QRenderSurfaceSelector *surfaceSelector = new Qt3DRender::QRenderSurfaceSelector(); + m_viewHolderFG = surfaceSelector; + surfaceSelector->setSurface(window()); + + // Copy setting properties from first View + QVector<Qt3DRender::QRenderSettings *> viewRenderSettings = subtreeRoot->componentsOfType<Qt3DRender::QRenderSettings>(); + if (viewRenderSettings.size() > 0) { + Qt3DRender::QRenderSettings *viewRenderSetting = viewRenderSettings.first(); + settings->setRenderPolicy(viewRenderSetting->renderPolicy()); + settings->pickingSettings()->setPickMethod(viewRenderSetting->pickingSettings()->pickMethod()); + settings->pickingSettings()->setPickResultMode(viewRenderSetting->pickingSettings()->pickResultMode()); + } + settings->setActiveFrameGraph(m_viewHolderFG); + m_viewHolderEntity->addComponent(settings); + + setEntity(m_viewHolderEntity); + } + + // Parent FG and Subtree + viewFG->setParent(m_viewHolderFG); + subtreeRoot->setParent(m_viewHolderEntity); + + m_views.push_back(view); + m_dirtyViews |= true; +} + +// MainThread called by Scene3DView +void Scene3DItem::removeView(Scene3DView *view) +{ + if (!m_views.contains(view)) + return; + + Qt3DRender::QFrameGraphNode *viewFG = view->viewFrameGraph(); + Qt3DCore::QEntity *subtreeRoot = view->viewSubtree(); + + // Unparent FG and Subtree + viewFG->setParent(Q_NODE_NULLPTR); + subtreeRoot->setParent(Q_NODE_NULLPTR); + + m_views.removeOne(view); + m_dirtyViews |= true; +} + void Scene3DItem::applyRootEntityChange() { if (m_aspectEngine->rootEntity() != m_entity) { @@ -391,6 +469,20 @@ void Scene3DItem::onBeforeSync() m_renderer->setCompositingMode(m_compositingMode); const bool usesFBO = m_compositingMode == FBO; + // Make renderer aware of any Scene3DView we are dealing with + if (m_dirtyViews) { + // Scene3DViews checks + if (m_entity != m_viewHolderEntity) { + qCWarning(Scene3D) << "Scene3DView is not supported if the Scene3D entity property has been set"; + } + if (!usesFBO) { + qCWarning(Scene3D) << "Scene3DView is only supported when Scene3D compositingMode is set to FBO"; + } + // The Scene3DRender will take care of providing the texture containing the 3D scene + m_renderer->setScene3DViews(m_views); + m_dirtyViews = false; + } + Q_ASSERT(m_aspectEngine->runMode() == Qt3DCore::QAspectEngine::Manual); m_aspectEngine->processFrame(); // The above essentially sets the number of RV for the RenderQueue and @@ -412,10 +504,13 @@ void Scene3DItem::onBeforeSync() // When using the FBO mode, only the QQuickItem needs to be updated // When using the Underlay mode, the whole windows needs updating - if (usesFBO) + if (usesFBO) { QQuickItem::update(); - else + for (Scene3DView *view : m_views) + view->update(); + } else { window()->update(); + } } void Scene3DItem::setWindowSurface(QObject *rootObject) @@ -539,21 +634,17 @@ QSGNode *Scene3DItem::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNode m_renderer->setCleanerHelper(m_rendererCleaner); } const bool usesFBO = m_compositingMode == FBO; + const bool hasScene3DViews = !m_views.empty(); Scene3DSGNode *fboNode = static_cast<Scene3DSGNode *>(node); // When usin Scene3DViews or Scene3D in Underlay mode // we shouldn't be managing a Scene3DSGNode - if (!usesFBO) { + if (!usesFBO || hasScene3DViews) { if (fboNode != nullptr) { delete fboNode; fboNode = nullptr; m_renderer->setSGNode(fboNode); } - // Record clearBeforeRendering value before we force it to false - m_clearsWindowByDefault = window()->clearBeforeRendering(); - m_disableClearWindow = true; - if (m_clearsWindowByDefault) - window()->setClearBeforeRendering(false); } else { // Regular Scene3D only case // Create SGNode if using FBO and no Scene3DViews @@ -562,11 +653,19 @@ QSGNode *Scene3DItem::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNode m_renderer->setSGNode(fboNode); } fboNode->setRect(boundingRect()); + } + if (usesFBO) { // Reset clear flag if we've set it to false it's still set to that if (m_disableClearWindow && !window()->clearBeforeRendering()) window()->setClearBeforeRendering(m_clearsWindowByDefault); m_disableClearWindow = false; + } else { + // Record clearBeforeRendering value before we force it to false + m_clearsWindowByDefault = window()->clearBeforeRendering(); + m_disableClearWindow = true; + if (m_clearsWindowByDefault) + window()->setClearBeforeRendering(false); } return fboNode; diff --git a/src/quick3d/imports/scene3d/scene3ditem_p.h b/src/quick3d/imports/scene3d/scene3ditem_p.h index ae7a4600e..4a2fc7f44 100644 --- a/src/quick3d/imports/scene3d/scene3ditem_p.h +++ b/src/quick3d/imports/scene3d/scene3ditem_p.h @@ -69,6 +69,8 @@ class QCamera; class QRenderAspect; class Scene3DRenderer; class Scene3DCleaner; +class Scene3DView; +class QFrameGraphNode; class Scene3DItem : public QQuickItem { @@ -106,6 +108,9 @@ public: Q_ENUM(CompositingMode) // LCOV_EXCL_LINE CompositingMode compositingMode() const; + void addView(Scene3DView *view); + void removeView(Scene3DView *view); + public Q_SLOTS: void setAspects(const QStringList &aspects); void setEntity(Qt3DCore::QEntity *entity); @@ -135,6 +140,8 @@ private: QStringList m_aspects; Qt3DCore::QEntity *m_entity; + Qt3DCore::QEntity *m_viewHolderEntity; + Qt3DRender::QFrameGraphNode *m_viewHolderFG; Qt3DCore::QAspectEngine *m_aspectEngine; QRenderAspect *m_renderAspect; @@ -143,6 +150,7 @@ private: bool m_multisample; bool m_dirty; + bool m_dirtyViews; bool m_clearsWindowByDefault; bool m_disableClearWindow; @@ -150,6 +158,7 @@ private: CameraAspectRatioMode m_cameraAspectRatioMode; CompositingMode m_compositingMode; QOffscreenSurface *m_dummySurface; + QVector<Scene3DView *> m_views; }; } // Qt3DRender diff --git a/src/quick3d/imports/scene3d/scene3drenderer.cpp b/src/quick3d/imports/scene3d/scene3drenderer.cpp index bc75e0861..bc4dbd362 100644 --- a/src/quick3d/imports/scene3d/scene3drenderer.cpp +++ b/src/quick3d/imports/scene3d/scene3drenderer.cpp @@ -57,6 +57,7 @@ #include <scene3ditem_p.h> #include <scene3dlogging_p.h> #include <scene3dsgnode_p.h> +#include <scene3dview_p.h> QT_BEGIN_NAMESPACE @@ -159,6 +160,7 @@ Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *asp , m_needsShutdown(true) , m_forceRecreate(false) , m_shouldRender(false) + , m_dirtyViews(false) , m_allowRendering(0) { Q_CHECK_PTR(m_item); @@ -313,9 +315,23 @@ void Scene3DRenderer::beforeSynchronize() m_texture.reset(m_window->createTextureFromId(m_finalFBO->texture(), m_finalFBO->size(), QQuickWindow::TextureHasAlphaChannel)); } + // We can render either the Scene3D or the Scene3DView but not both + // at the same time + Q_ASSERT((m_node == nullptr || m_views.empty()) || + (m_node != nullptr && m_views.empty()) || + (m_node == nullptr && !m_views.empty())); + // Set texture on node if (m_node && (!m_node->texture() || generateNewTexture)) m_node->setTexture(m_texture.data()); + + // Set textures on Scene3DView + if (m_dirtyViews || generateNewTexture) { + for (Scene3DView *view : qAsConst(m_views)) + if (!view->texture() || generateNewTexture) + view->setTexture(m_texture.data()); + m_dirtyViews = false; + } } if (m_aspectEngine->rootEntity() != m_item->entity()) { @@ -326,6 +342,9 @@ void Scene3DRenderer::beforeSynchronize() if (m_node) m_node->markDirty(QSGNode::DirtyMaterial); + for (Scene3DView *view : qAsConst(m_views)) + view->markSGNodeDirty(); + m_item->update(); } } @@ -340,6 +359,13 @@ void Scene3DRenderer::setCompositingMode(Scene3DItem::CompositingMode mode) m_compositingMode = mode; } +// Main Thread, Render Thread locked +void Scene3DRenderer::setScene3DViews(const QVector<Scene3DView *> views) +{ + m_views = views; + m_dirtyViews = true; +} + void Scene3DRenderer::setSGNode(Scene3DSGNode *node) { m_node = node; diff --git a/src/quick3d/imports/scene3d/scene3drenderer_p.h b/src/quick3d/imports/scene3d/scene3drenderer_p.h index 11dfef77d..4f3651cd3 100644 --- a/src/quick3d/imports/scene3d/scene3drenderer_p.h +++ b/src/quick3d/imports/scene3d/scene3drenderer_p.h @@ -72,6 +72,7 @@ namespace Qt3DRender { class QRenderAspect; class Scene3DCleaner; class Scene3DSGNode; +class Scene3DViews; class Scene3DRenderer : public QObject { @@ -87,6 +88,8 @@ public: void allowRender(); void setCompositingMode(Scene3DItem::CompositingMode mode); + void setScene3DViews(const QVector<Scene3DView *> views); + public Q_SLOTS: void render(); void shutdown(); @@ -115,8 +118,10 @@ private: bool m_needsShutdown; bool m_forceRecreate; bool m_shouldRender; + bool m_dirtyViews; QSemaphore m_allowRendering; Scene3DItem::CompositingMode m_compositingMode; + QVector<Scene3DView *> m_views; friend class Scene3DCleaner; }; diff --git a/src/quick3d/imports/scene3d/scene3dsgnode.cpp b/src/quick3d/imports/scene3d/scene3dsgnode.cpp index 8806b59a9..c38e9ffeb 100644 --- a/src/quick3d/imports/scene3d/scene3dsgnode.cpp +++ b/src/quick3d/imports/scene3d/scene3dsgnode.cpp @@ -74,13 +74,12 @@ Scene3DSGNode::~Scene3DSGNode() // is terminated. } -void Scene3DSGNode::setRect(const QRectF &rect) +void Scene3DSGNode::setRect(const QRectF &rect, const QRectF textureRect) { if (rect != m_rect) { m_rect = rect; - // Map the item's bounding rect to normalized texture coordinates - const QRectF sourceRect(0.0f, 1.0f, 1.0f, -1.0f); - QSGGeometry::updateTexturedRectGeometry(&m_geometry, m_rect, sourceRect); + // By default, map the item's bounding rect to normalized texture coordinates + QSGGeometry::updateTexturedRectGeometry(&m_geometry, m_rect, textureRect); markDirty(DirtyGeometry); } } diff --git a/src/quick3d/imports/scene3d/scene3dsgnode_p.h b/src/quick3d/imports/scene3d/scene3dsgnode_p.h index 68b68eea5..388c8a605 100644 --- a/src/quick3d/imports/scene3d/scene3dsgnode_p.h +++ b/src/quick3d/imports/scene3d/scene3dsgnode_p.h @@ -75,7 +75,7 @@ public: } QSGTexture *texture() const Q_DECL_NOTHROW { return m_material.texture(); } - void setRect(const QRectF &rect); + void setRect(const QRectF &rect, const QRectF textureRect = QRectF(0.0f, 1.0f, 1.0f, -1.0f)); QRectF rect() const Q_DECL_NOTHROW { return m_rect; } private: diff --git a/src/quick3d/imports/scene3d/scene3dview.cpp b/src/quick3d/imports/scene3d/scene3dview.cpp new file mode 100644 index 000000000..9d298b435 --- /dev/null +++ b/src/quick3d/imports/scene3d/scene3dview.cpp @@ -0,0 +1,318 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 "scene3dview_p.h" +#include <Qt3DCore/QEntity> +#include <Qt3DRender/QRenderSettings> +#include <Qt3DRender/QFrameGraphNode> +#include <Qt3DRender/QLayer> +#include <Qt3DRender/QLayerFilter> +#include <Qt3DRender/QViewport> +#include <scene3dsgnode_p.h> +#include <scene3ditem_p.h> +#include <QQuickWindow> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +/*! + \qmltype Scene3DView + \inherits Item + \inqmlmodule QtQuick.Scene3D + \since 5.14 + + \preliminary + + \brief The Scene3DView type is used to integrate a Qt 3D sub scene into a + QtQuick 2 scene using Scene3D. Whereas you should only use a single Scene3D + instance per application, you can have multiple Scene3DView instances. + + Essentially, if you need to render multiple scenes each in a separate view, + you should use a single Scene3D instance and as many Scene3DView items as + you have scenes to render. + + Typical usage looks like: + \qml + Scene3D { + id: mainScene3D + anchors.fill: parent + } + + Scene3DView { + id: view1 + scene3D: mainScene3D + width: 200 + height: 200 + Entity { + ... + } + } + + Scene3DView { + id: view2 + scene3D: mainScene3D + width: 200 + height: 200 + x: 200 + Entity { + ... + } + } + \endqml + + There are a few limitations when using Scene3DView: + \list + \li The Scene3D compositingMode has to be set to FBO + \li The Scene3D is sized to occupy the full window size (at the very least + it must be sized as wide as the area occupied by all Scene3DViews) + \li The Scene3D instance is instantiated prior to any Scene3DView + \li The Scene3D entity property is left unset + \endlist + + Scene3D behaves likes a texture atlas from which all Scene3DView instances. + For this reason, care should be taken that only the first Scene3DView + declared in the scene clears the color/depth. Additionally overlapping + Scene3DView instances is discouraged as this might not produce the expected + output. + + It is expected that a Scene3DView's Entity provide a RenderSettings with a + valid SceneGraph. Please note that only the RenderSettings of the first + Scene3DView instantiated will be taken into account. + + There are no restriction on the sharing of elements between different scenes + in different Scene3DView instances. + */ + +namespace { + +Qt3DRender::QFrameGraphNode *frameGraphFromEntity(Qt3DCore::QEntity *entity) +{ + const auto renderSettingsComponents = entity->componentsOfType<Qt3DRender::QRenderSettings>(); + + if (renderSettingsComponents.size() > 0) { + Qt3DRender::QRenderSettings *renderSettings = renderSettingsComponents.first(); + return renderSettings->activeFrameGraph(); + } + return nullptr; +} + +} + +Scene3DView::Scene3DView(QQuickItem *parent) + : QQuickItem(parent) + , m_scene3D(nullptr) + , m_entity(nullptr) + , m_previousFGParent(nullptr) + , m_holderEntity(new Qt3DCore::QEntity()) + , m_holderLayer(new Qt3DRender::QLayer()) + , m_holderLayerFilter(new Qt3DRender::QLayerFilter()) + , m_holderViewport(new Qt3DRender::QViewport()) + , m_dirtyFlags(DirtyNode|DirtyTexture) + , m_texture(nullptr) +{ + setFlag(QQuickItem::ItemHasContents, true);\ + + m_holderLayer->setRecursive(true); + m_holderEntity->addComponent(m_holderLayer); + m_holderLayerFilter->setParent(m_holderViewport); + m_holderLayerFilter->addLayer(m_holderLayer); +} + +Scene3DView::~Scene3DView() +{ + if (m_entity) + abandonSubtree(m_entity); + + if (m_scene3D) + m_scene3D->removeView(this); +} + +Qt3DCore::QEntity *Scene3DView::entity() const +{ + return m_entity; +} + +Scene3DItem *Scene3DView::scene3D() const +{ + return m_scene3D; +} + +Qt3DCore::QEntity *Scene3DView::viewSubtree() const +{ + return m_holderEntity; +} + +QFrameGraphNode *Scene3DView::viewFrameGraph() const +{ + return m_holderViewport; +} + +// Called by Scene3DRender::beforeSynchronizing in RenderThread +void Scene3DView::setTexture(QSGTexture *texture) +{ + m_dirtyFlags |= DirtyTexture; + m_texture = texture; + QQuickItem::update(); +} + +QSGTexture *Scene3DView::texture() const +{ + return m_texture; +} + +// Called by Scene3DRender::beforeSynchronizing in RenderThread +void Scene3DView::markSGNodeDirty() +{ + m_dirtyFlags |= DirtyNode; + QQuickItem::update(); +} + +// Main Thread +void Scene3DView::setEntity(Qt3DCore::QEntity *entity) +{ + if (m_entity == entity) + return; + + if (m_entity) + abandonSubtree(m_entity); + + m_entity = entity; + emit entityChanged(); + + if (m_entity) + adoptSubtree(m_entity); +} + +// Main Thread +void Scene3DView::setScene3D(Scene3DItem *scene3D) +{ + if (m_scene3D == scene3D) + return; + + if (m_scene3D) { + m_scene3D->removeView(this); + QObject::disconnect(m_scene3DDestroyedConnection); + } + + setTexture(nullptr); + m_scene3D = scene3D; + emit scene3DChanged(); + + + if (m_scene3D) { + m_scene3DDestroyedConnection = QObject::connect(m_scene3D, + &Scene3DItem::destroyed, + this, + [this] { + m_scene3D = nullptr; + }); + m_scene3D->addView(this); + } +} + +// Render Thread +QSGNode *Scene3DView::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData *) +{ + Scene3DSGNode *fboNode = static_cast<Scene3DSGNode *>(node); + if (fboNode == nullptr) + fboNode = new Scene3DSGNode(); + + // We only need to draw a sub part of the texture based + // on our size, Scene3D essentially acts as a TextureAtlas + const QRectF itemRect(mapRectToScene(boundingRect())); + const QSize winSize = window() ? window()->size() : QSize(); + const QRectF normalizedViewportRect(itemRect.x() / winSize.width(), + itemRect.y() / winSize.height(), + itemRect.width() / winSize.width(), + itemRect.height() / winSize.height()); + // Swap Y axis to match GL coordinates + const QRectF textureRect(itemRect.x() / winSize.width(), + 1.0f - (itemRect.y() / winSize.height()), + itemRect.width() / winSize.width(), + -(itemRect.height() / winSize.height())); + + // TO DO: Should be done from main thread + // updateViewport + m_holderViewport->setNormalizedRect(normalizedViewportRect); + + // update node rect and texture coordinates + fboNode->setRect(boundingRect(), textureRect); + + if (m_dirtyFlags & DirtyTexture) { + fboNode->setTexture(m_texture); + m_dirtyFlags.setFlag(DirtyTexture, false); + } + if (m_dirtyFlags & DirtyNode) { + fboNode->markDirty(QSGNode::DirtyMaterial); + m_dirtyFlags.setFlag(DirtyNode, false); + } + + return fboNode; +} + +// Main Thread +void Scene3DView::adoptSubtree(Qt3DCore::QEntity *subtree) +{ + // Reparent FrameGraph + Qt3DRender::QFrameGraphNode *fgNode = frameGraphFromEntity(subtree); + if (fgNode) { + m_previousFGParent = fgNode->parentNode(); + fgNode->setParent(m_holderLayerFilter); + } + + // Insert Entity Subtree + subtree->setParent(m_holderEntity); +} + +// Main Thread +void Scene3DView::abandonSubtree(Qt3DCore::QEntity *subtree) +{ + // Remove FrameGraph part + Qt3DRender::QFrameGraphNode *fgNode = frameGraphFromEntity(subtree); + if (fgNode) + fgNode->setParent(m_previousFGParent); + + // Remove Entity Subtree + subtree->setParent(Q_NODE_NULLPTR); +} + +} // Qt3DRender + +QT_END_NAMESPACE diff --git a/src/quick3d/imports/scene3d/scene3dview_p.h b/src/quick3d/imports/scene3d/scene3dview_p.h new file mode 100644 index 000000000..ffb80f93b --- /dev/null +++ b/src/quick3d/imports/scene3d/scene3dview_p.h @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 SCENE3DVIEW_P_H +#define SCENE3DVIEW_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtQuick/QQuickItem> +#include <QtCore/QFlags> + +QT_BEGIN_NAMESPACE + +class QSGTexture; + +namespace Qt3DCore { +class QEntity; +class QNode; +} + +namespace Qt3DRender { + +class QLayer; +class QLayerFilter; +class Scene3DItem; +class QFrameGraphNode; +class QViewport; + +class Scene3DView : public QQuickItem +{ + Q_OBJECT + Q_PROPERTY(Qt3DCore::QEntity* entity READ entity WRITE setEntity NOTIFY entityChanged) + Q_PROPERTY(Qt3DRender::Scene3DItem *scene3D READ scene3D WRITE setScene3D NOTIFY scene3DChanged) + Q_CLASSINFO("DefaultProperty", "entity") + +public: + enum DirtyFlag { + DirtyNode = 1 << 0, + DirtyTexture = 1 << 1 + }; + Q_DECLARE_FLAGS(DirtyFlags, DirtyFlag) + + explicit Scene3DView(QQuickItem *parent = nullptr); + ~Scene3DView(); + + Qt3DCore::QEntity *entity() const; + Scene3DItem *scene3D() const; + + Qt3DCore::QEntity *viewSubtree() const; + Qt3DRender::QFrameGraphNode *viewFrameGraph() const; + + void setTexture(QSGTexture *texture); + QSGTexture *texture() const; + + void markSGNodeDirty(); + +public Q_SLOTS: + void setEntity(Qt3DCore::QEntity *entity); + void setScene3D(Scene3DItem *scene3D); + +Q_SIGNALS: + void entityChanged(); + void scene3DChanged(); + +private: + QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *nodeData) override; + void adoptSubtree(Qt3DCore::QEntity *subtree); + void abandonSubtree(Qt3DCore::QEntity *subtree); + + Scene3DItem *m_scene3D; + Qt3DCore::QEntity *m_entity; + Qt3DCore::QNode *m_previousFGParent; + + Qt3DCore::QEntity *m_holderEntity; + Qt3DRender::QLayer *m_holderLayer; + Qt3DRender::QLayerFilter *m_holderLayerFilter; + Qt3DRender::QViewport *m_holderViewport; + + QMetaObject::Connection m_scene3DDestroyedConnection; + + DirtyFlags m_dirtyFlags; + QSGTexture *m_texture; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(Scene3DView::DirtyFlags) + + +} // Qt3DRender + +QT_END_NAMESPACE + +#endif // SCENE3DVIEW_P_H |