Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qquick3druntimeloader.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
5
6#include <QtQuick3DAssetUtils/private/qssgscenedesc_p.h>
7#include <QtQuick3DAssetUtils/private/qssgqmlutilities_p.h>
8#include <QtQuick3DAssetUtils/private/qssgrtutilities_p.h>
9#include <QtQuick3DAssetImport/private/qssgassetimportmanager_p.h>
10#include <QtQuick3DRuntimeRender/private/qssgrenderbuffermanager_p.h>
11
78
81{
82
83}
84
86{
87 return m_source;
88}
89
91{
92 if (m_source == newSource)
93 return;
94
95 const QQmlContext *context = qmlContext(this);
96 auto resolvedUrl = (context ? context->resolvedUrl(newSource) : newSource);
97
98 if (m_source == resolvedUrl)
99 return;
100
101 m_source = resolvedUrl;
103
105 loadSource();
106}
107
109{
111 loadSource();
112}
113
114static void boxBoundsRecursive(const QQuick3DNode *baseNode, const QQuick3DNode *node, QQuick3DBounds3 &accBounds)
115{
116 if (!node)
117 return;
118
119 if (auto *model = qobject_cast<const QQuick3DModel *>(node)) {
120 auto b = model->bounds();
121 for (const QVector3D point : b.bounds.toQSSGBoxPoints()) {
122 auto p = model->mapPositionToNode(const_cast<QQuick3DNode *>(baseNode), point);
123 if (Q_UNLIKELY(accBounds.bounds.isEmpty()))
124 accBounds.bounds = { p, p };
125 else
126 accBounds.bounds.include(p);
127 }
128 }
129 for (auto *child : node->childItems())
130 boxBoundsRecursive(baseNode, qobject_cast<const QQuick3DNode *>(child), accBounds);
131}
132
133template<typename Func>
134static void applyToModels(QQuick3DObject *obj, Func &&lambda)
135{
136 if (!obj)
137 return;
138 for (auto *child : obj->childItems()) {
139 if (auto *model = qobject_cast<QQuick3DModel *>(child))
140 lambda(model);
141 applyToModels(child, lambda);
142 }
143}
144
145void QQuick3DRuntimeLoader::loadSource()
146{
147 delete m_root;
148 m_root.clear();
150
151 m_status = Status::Empty;
152 m_errorString = QStringLiteral("No file selected");
153 if (!m_source.isValid()) {
156 return;
157 }
158
159 QSSGAssetImportManager importManager;
161 QString error(QStringLiteral("Unknown error"));
162 auto result = importManager.importFile(m_source, scene, &error);
163
164 switch (result) {
166 m_errorString = QStringLiteral("Success!");
167 m_status = Status::Success;
168 break;
170 m_errorString = QStringLiteral("IO Error: ") + error;
171 m_status = Status::Error;
172 break;
174 m_errorString = QStringLiteral("Unsupported: ") + error;
175 m_status = Status::Error;
176 break;
177 }
178
181
182 if (m_status != Status::Success) {
183 m_source.clear();
185 return;
186 }
187
188 // We create a dummy root node here, as it will be the parent to the first-level nodes
189 // and resources. If we use 'this' those first-level nodes/resources won't be deleted
190 // when a new scene is loaded.
191 m_root = new QQuick3DNode(this);
192 m_imported = QSSGRuntimeUtils::createScene(*m_root, scene);
193 m_assetId = scene.id;
194 m_boundsDirty = true;
195 m_instancingChanged = m_instancing != nullptr;
196 updateModels();
197 // Cleanup scene before deleting.
198 scene.cleanup();
199}
200
201void QQuick3DRuntimeLoader::updateModels()
202{
203 if (m_instancingChanged) {
204 applyToModels(m_imported, [this](QQuick3DModel *model) {
205 model->setInstancing(m_instancing);
206 model->setInstanceRoot(m_imported);
207 });
208 m_instancingChanged = false;
209 }
210}
211
213{
214 return m_status;
215}
216
218{
219 return m_errorString;
220}
221
223{
225 if (m_boundsDirty)
227 return result;
228}
229
230void QQuick3DRuntimeLoader::calculateBounds()
231{
232 if (!m_imported || !m_boundsDirty)
233 return;
234
235 m_bounds.bounds.setEmpty();
236 boxBoundsRecursive(m_imported, m_imported, m_bounds);
237 m_boundsDirty = false;
238}
239
241{
242 if (m_boundsDirty) {
243 auto *that = const_cast<QQuick3DRuntimeLoader *>(this);
244 that->calculateBounds();
245 return that->m_bounds;
246 }
247
248 return m_bounds;
249}
250
252{
253 return m_instancing;
254}
255
257{
258 if (m_instancing == newInstancing)
259 return;
260
262 newInstancing, m_instancing);
263
264 m_instancing = newInstancing;
265 m_instancingChanged = true;
266 updateModels();
268}
269
void clear()
Definition qpointer.h:70
The QQmlContext class defines a context within a QML engine.
Definition qqmlcontext.h:25
QSSGBounds3 bounds
\inmodule QtQuick3D \inherits QQuick3DObject
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
QSSGRenderGraphObject * updateSpatialNode(QSSGRenderGraphObject *node) override
static void attachWatcher(Context *context, Setter setter, Object3D *newO, Object3D *oldO)
Attach a object-destroyed-watcher to an object that's not owned.
\qmltype Object3D \inqmlmodule QtQuick3D \instantiates QQuick3DObject \inherits QtObject
bool isComponentComplete() const
QSSGRenderGraphObject * updateSpatialNode(QSSGRenderGraphObject *node) override
QQuick3DInstancing * instancing
QQuick3DRuntimeLoader(QQuick3DNode *parent=nullptr)
\qmltype RuntimeLoader \inherits Node \inqmlmodule QtQuick3D.AssetUtils
void setSource(const QUrl &newSource)
void setInstancing(QQuick3DInstancing *newInstancing)
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
ImportState importFile(const QString &filename, const QDir &outputPath, QString *error=nullptr)
Q_ALWAYS_INLINE void setEmpty()
Sets empty to true.
void include(const QVector3D &v)
expands the volume to include v
Q_ALWAYS_INLINE bool isEmpty() const
static void unregisterMeshData(const QString &assetId)
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
\inmodule QtCore
Definition qurl.h:94
bool isValid() const
Returns true if the URL is non-empty and valid; otherwise returns false.
Definition qurl.cpp:1874
void clear()
Resets the content of the QUrl.
Definition qurl.cpp:1901
The QVector3D class represents a vector or vertex in 3D space.
Definition qvectornd.h:171
Q_QUICK3DASSETUTILS_EXPORT QQuick3DNode * createScene(QQuick3DNode &parent, const QSSGSceneDesc::Scene &scene)
Combined button and popup list for selecting options.
@ QueuedConnection
static void * context
#define Q_UNLIKELY(x)
DBusConnection const char DBusError * error
T qobject_cast(QObject *object)
\variable QObject::staticMetaObject
Definition qobject.h:385
GLboolean GLboolean GLboolean b
GLhandleARB obj
[2]
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
QQmlContext * qmlContext(const QObject *obj)
Definition qqml.cpp:71
static void boxBoundsRecursive(const QQuick3DNode *baseNode, const QQuick3DNode *node, QQuick3DBounds3 &accBounds)
static void applyToModels(QQuick3DObject *obj, Func &&lambda)
static QUrl resolvedUrl(const QUrl &url, const QQmlRefPointer< QQmlContextData > &context)
#define QStringLiteral(str)
#define emit
QSqlQueryModel * model
[16]
QGraphicsScene scene
[0]
QLayoutItem * child
[0]
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent