summaryrefslogtreecommitdiffstats
path: root/src/quick3d/imports/scene3d/scene3ditem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick3d/imports/scene3d/scene3ditem.cpp')
-rw-r--r--src/quick3d/imports/scene3d/scene3ditem.cpp117
1 files changed, 108 insertions, 9 deletions
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;