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#if QT_CONFIG(mimetype)
12#include <QtCore/qmimedatabase.h>
16
17
18
19
20
21
22
23
24
25
26
27
30
31
32
33
34
35
36
37
40
41
42
43
44
45
46
47
48
49
50
51
52
55
56
57
58
59
60
63
64
65
66
67
68
69
70
73
74
75
76
77
78
79
83QQuick3DRuntimeLoader::QQuick3DRuntimeLoader(QQuick3DNode *parent)
84 : QQuick3DNode(parent)
89QUrl QQuick3DRuntimeLoader::source()
const
94void QQuick3DRuntimeLoader::setSource(
const QUrl &newSource)
96 if (m_source == newSource)
99 const QQmlContext *context = qmlContext(
this);
100 auto resolvedUrl = (context ? context->resolvedUrl(newSource) : newSource);
102 if (m_source == resolvedUrl)
105 m_source = resolvedUrl;
106 emit sourceChanged();
108 if (isComponentComplete())
112void QQuick3DRuntimeLoader::componentComplete()
114 QQuick3DNode::componentComplete();
118QStringList QQuick3DRuntimeLoader::supportedExtensions()
120 static QStringList extensions;
121 if (!extensions.isEmpty())
124 static const QStringList supportedExtensions = { QLatin1StringView(
"obj"),
125 QLatin1StringView(
"gltf"),
126 QLatin1StringView(
"glb")};
128 QSSGAssetImportManager importManager;
129 const auto types = importManager.getImporterPluginInfos();
131 for (
const auto &t : types) {
132 for (
const QString &extension : t.inputExtensions) {
133 if (supportedExtensions.contains(extension))
134 extensions << extension;
140#if QT_CONFIG(mimetype)
141QList<QMimeType> QQuick3DRuntimeLoader::supportedMimeTypes()
143 static QList<QMimeType> mimeTypes;
144 if (!mimeTypes.isEmpty())
147 const QStringList &extensions = supportedExtensions();
150 for (
const auto &ext : extensions) {
152 const QString fileName = QLatin1StringView(
"test.") + ext;
153 mimeTypes << db.mimeTypesForFileName(fileName);
160static void boxBoundsRecursive(
const QQuick3DNode *baseNode,
const QQuick3DNode *node, QQuick3DBounds3 &accBounds)
165 if (
auto *model = qobject_cast<
const QQuick3DModel *>(node)) {
166 auto b = model->bounds();
167 for (
const QVector3D point : b.bounds.toQSSGBoxPoints()) {
168 auto p = model->mapPositionToNode(
const_cast<QQuick3DNode *>(baseNode), point);
169 if (Q_UNLIKELY(accBounds.bounds.isEmpty()))
170 accBounds.bounds = { p, p };
172 accBounds.bounds.include(p);
175 for (
auto *child : node->childItems())
176 boxBoundsRecursive(baseNode, qobject_cast<
const QQuick3DNode *>(child), accBounds);
179template<
typename Func>
184 for (
auto *child : obj->childItems()) {
185 if (
auto *model = qobject_cast<QQuick3DModel *>(child))
187 applyToModels(child, lambda);
191void QQuick3DRuntimeLoader::loadSource()
195 QSSGBufferManager::unregisterMeshData(m_assetId);
197 m_status = Status::Empty;
198 m_errorString = QStringLiteral(
"No file selected");
199 if (!m_source.isValid()) {
200 emit statusChanged();
201 emit errorStringChanged();
205 QSSGAssetImportManager importManager;
206 QSSGSceneDesc::Scene scene;
207 QString error(QStringLiteral(
"Unknown error"));
208 auto result = importManager.importFile(m_source, scene, &error);
211 case QSSGAssetImportManager::ImportState::Success:
212 m_errorString = QStringLiteral(
"Success!");
213 m_status = Status::Success;
215 case QSSGAssetImportManager::ImportState::IoError:
216 m_errorString = QStringLiteral(
"IO Error: ") + error;
217 m_status = Status::Error;
219 case QSSGAssetImportManager::ImportState::Unsupported:
220 m_errorString = QStringLiteral(
"Unsupported: ") + error;
221 m_status = Status::Error;
225 if (m_status == Status::Success) {
229 m_root =
new QQuick3DNode(
this);
230 m_imported = QSSGRuntimeUtils::createScene(*m_root, scene);
231 m_assetId = scene.id;
232 m_boundsDirty =
true;
233 m_instancingChanged = m_instancing !=
nullptr;
239 emit sourceChanged();
242 emit statusChanged();
243 emit errorStringChanged();
247void QQuick3DRuntimeLoader::updateModels()
249 if (m_instancingChanged) {
250 applyToModels(m_imported, [
this](QQuick3DModel *model) {
251 model->setInstancing(m_instancing);
252 model->setInstanceRoot(m_imported);
254 m_instancingChanged =
false;
258QQuick3DRuntimeLoader::Status QQuick3DRuntimeLoader::status()
const
263QString QQuick3DRuntimeLoader::errorString()
const
265 return m_errorString;
268QSSGRenderGraphObject *QQuick3DRuntimeLoader::updateSpatialNode(QSSGRenderGraphObject *node)
270 auto *result = QQuick3DNode::updateSpatialNode(node);
272 QMetaObject::invokeMethod(
this, &QQuick3DRuntimeLoader::boundsChanged, Qt::QueuedConnection);
276void QQuick3DRuntimeLoader::calculateBounds()
278 if (!m_imported || !m_boundsDirty)
281 m_bounds.bounds.setEmpty();
282 boxBoundsRecursive(m_imported, m_imported, m_bounds);
283 m_boundsDirty =
false;
286const QQuick3DBounds3 &QQuick3DRuntimeLoader::bounds()
const
289 auto *that =
const_cast<QQuick3DRuntimeLoader *>(
this);
290 that->calculateBounds();
291 return that->m_bounds;
297QQuick3DInstancing *QQuick3DRuntimeLoader::instancing()
const
302void QQuick3DRuntimeLoader::setInstancing(QQuick3DInstancing *newInstancing)
304 if (m_instancing == newInstancing)
307 QQuick3DObjectPrivate::attachWatcher(
this, &QQuick3DRuntimeLoader::setInstancing,
308 newInstancing, m_instancing);
310 m_instancing = newInstancing;
311 m_instancingChanged =
true;
313 emit instancingChanged();
static void boxBoundsRecursive(const QQuick3DNode *baseNode, const QQuick3DNode *node, QQuick3DBounds3 &accBounds)
static void applyToModels(QQuick3DObject *obj, Func &&lambda)