Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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#include <QtCore/qmimedatabase.h>
12
80
86
88{
89 return m_source;
90}
91
93{
94 if (m_source == newSource)
95 return;
96
97 const QQmlContext *context = qmlContext(this);
98 auto resolvedUrl = (context ? context->resolvedUrl(newSource) : newSource);
99
100 if (m_source == resolvedUrl)
101 return;
102
103 m_source = resolvedUrl;
105
107 loadSource();
108}
109
115
117{
118 static QStringList extensions;
119 if (!extensions.isEmpty())
120 return extensions;
121
122 static const QStringList supportedExtensions = { QLatin1StringView("obj"),
123 QLatin1StringView("gltf"),
124 QLatin1StringView("glb")};
125
126 QSSGAssetImportManager importManager;
127 const auto types = importManager.getImporterPluginInfos();
128
129 for (const auto &t : types) {
130 for (const QString &extension : t.inputExtensions) {
131 if (supportedExtensions.contains(extension))
132 extensions << extension;
133 }
134 }
135 return extensions;
136}
137
139{
140 static QList<QMimeType> mimeTypes;
141 if (!mimeTypes.isEmpty())
142 return mimeTypes;
143
144 const QStringList &extensions = supportedExtensions();
145
147 for (const auto &ext : extensions) {
148 // TODO: Change to db.mimeTypesForExtension(ext), once it is implemented (QTBUG-118566)
149 const QString fileName = QLatin1StringView("test.") + ext;
150 mimeTypes << db.mimeTypesForFileName(fileName);
151 }
152
153 return mimeTypes;
154}
155
156static void boxBoundsRecursive(const QQuick3DNode *baseNode, const QQuick3DNode *node, QQuick3DBounds3 &accBounds)
157{
158 if (!node)
159 return;
160
161 if (auto *model = qobject_cast<const QQuick3DModel *>(node)) {
162 auto b = model->bounds();
163 for (const QVector3D point : b.bounds.toQSSGBoxPoints()) {
164 auto p = model->mapPositionToNode(const_cast<QQuick3DNode *>(baseNode), point);
165 if (Q_UNLIKELY(accBounds.bounds.isEmpty()))
166 accBounds.bounds = { p, p };
167 else
168 accBounds.bounds.include(p);
169 }
170 }
171 for (auto *child : node->childItems())
172 boxBoundsRecursive(baseNode, qobject_cast<const QQuick3DNode *>(child), accBounds);
173}
174
175template<typename Func>
176static void applyToModels(QQuick3DObject *obj, Func &&lambda)
177{
178 if (!obj)
179 return;
180 for (auto *child : obj->childItems()) {
181 if (auto *model = qobject_cast<QQuick3DModel *>(child))
182 lambda(model);
183 applyToModels(child, lambda);
184 }
185}
186
187void QQuick3DRuntimeLoader::loadSource()
188{
189 delete m_root;
190 m_root.clear();
192
193 m_status = Status::Empty;
194 m_errorString = QStringLiteral("No file selected");
195 if (!m_source.isValid()) {
198 return;
199 }
200
201 QSSGAssetImportManager importManager;
203 QString error(QStringLiteral("Unknown error"));
204 auto result = importManager.importFile(m_source, scene, &error);
205
206 switch (result) {
208 m_errorString = QStringLiteral("Success!");
209 m_status = Status::Success;
210 break;
212 m_errorString = QStringLiteral("IO Error: ") + error;
213 m_status = Status::Error;
214 break;
216 m_errorString = QStringLiteral("Unsupported: ") + error;
217 m_status = Status::Error;
218 break;
219 }
220
223
224 if (m_status != Status::Success) {
225 m_source.clear();
227 return;
228 }
229
230 // We create a dummy root node here, as it will be the parent to the first-level nodes
231 // and resources. If we use 'this' those first-level nodes/resources won't be deleted
232 // when a new scene is loaded.
233 m_root = new QQuick3DNode(this);
234 m_imported = QSSGRuntimeUtils::createScene(*m_root, scene);
235 m_assetId = scene.id;
236 m_boundsDirty = true;
237 m_instancingChanged = m_instancing != nullptr;
238 updateModels();
239 // Cleanup scene before deleting.
240 scene.cleanup();
241}
242
243void QQuick3DRuntimeLoader::updateModels()
244{
245 if (m_instancingChanged) {
246 applyToModels(m_imported, [this](QQuick3DModel *model) {
247 model->setInstancing(m_instancing);
248 model->setInstanceRoot(m_imported);
249 });
250 m_instancingChanged = false;
251 }
252}
253
258
260{
261 return m_errorString;
262}
263
271
272void QQuick3DRuntimeLoader::calculateBounds()
273{
274 if (!m_imported || !m_boundsDirty)
275 return;
276
277 m_bounds.bounds.setEmpty();
278 boxBoundsRecursive(m_imported, m_imported, m_bounds);
279 m_boundsDirty = false;
280}
281
283{
284 if (m_boundsDirty) {
285 auto *that = const_cast<QQuick3DRuntimeLoader *>(this);
286 that->calculateBounds();
287 return that->m_bounds;
288 }
289
290 return m_bounds;
291}
292
294{
295 return m_instancing;
296}
297
299{
300 if (m_instancing == newInstancing)
301 return;
302
304 newInstancing, m_instancing);
305
306 m_instancing = newInstancing;
307 m_instancingChanged = true;
308 updateModels();
310}
311
\inmodule QtCore
QList< QMimeType > mimeTypesForFileName(const QString &fileName) const
Returns the MIME types for the file name fileName.
void clear() noexcept
Definition qpointer.h:87
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
QQuick3DNode(QQuick3DNode *parent=nullptr)
\qmltype Node \inherits Object3D \inqmlmodule QtQuick3D
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
QList< QMimeType > supportedMimeTypes
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.
QList< QSSGAssetImporterPluginInfo > getImporterPluginInfos() const
Q_ALWAYS_INLINE void setEmpty()
Sets empty to true.
static void unregisterMeshData(const QString &assetId)
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
\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:1882
void clear()
Resets the content of the QUrl.
Definition qurl.cpp:1909
The QVector3D class represents a vector or vertex in 3D space.
Definition qvectornd.h:171
void extension()
[6]
Definition dialogs.cpp:230
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:419
GLboolean GLboolean GLboolean b
GLsizei GLenum GLenum * types
GLhandleARB obj
[2]
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
QQmlContext * qmlContext(const QObject *obj)
Definition qqml.cpp:75
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]
QMimeDatabase db
[0]
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...