8#include <QtQuick3DAssetUtils/private/qssgscenedesc_p.h>
9#include <QtQuick3DAssetUtils/private/qssgqmlutilities_p.h>
10#include <QtQuick3DAssetUtils/private/qssgrtutilities_p.h>
11#include <QtQuick3DAssetImport/private/qssgassetimportmanager_p.h>
12#include <QtQuick3DRuntimeRender/private/qssgrenderbuffermanager_p.h>
13#if QT_CONFIG(mimetype)
14#include <QtCore/qmimedatabase.h>
18
19
20
21
22
23
24
25
26
27
28
29
32
33
34
35
36
37
38
39
42
43
44
45
46
47
48
49
50
51
52
53
54
57
58
59
60
61
62
65
66
67
68
69
70
71
72
75
76
77
78
79
80
81
85QQuick3DRuntimeLoader::QQuick3DRuntimeLoader(QQuick3DNode *parent)
86 : QQuick3DNode(parent)
91QUrl QQuick3DRuntimeLoader::source()
const
96void QQuick3DRuntimeLoader::setSource(
const QUrl &newSource)
98 if (m_source == newSource)
101 const QQmlContext *context = qmlContext(
this);
102 auto resolvedUrl = (context ? context->resolvedUrl(newSource) : newSource);
104 if (m_source == resolvedUrl)
107 m_source = resolvedUrl;
108 emit sourceChanged();
110 if (isComponentComplete())
114void QQuick3DRuntimeLoader::componentComplete()
116 QQuick3DNode::componentComplete();
120QStringList QQuick3DRuntimeLoader::supportedExtensions()
122 static QStringList extensions;
123 if (!extensions.isEmpty())
126 static const QStringList supportedExtensions = { QLatin1StringView(
"obj"),
127 QLatin1StringView(
"gltf"),
128 QLatin1StringView(
"glb")};
130 QSSGAssetImportManager importManager;
131 const auto types = importManager.getImporterPluginInfos();
133 for (
const auto &t : types) {
134 for (
const QString &extension : t.inputExtensions) {
135 if (supportedExtensions.contains(extension))
136 extensions << extension;
142#if QT_CONFIG(mimetype)
143QList<QMimeType> QQuick3DRuntimeLoader::supportedMimeTypes()
145 static QList<QMimeType> mimeTypes;
146 if (!mimeTypes.isEmpty())
149 const QStringList &extensions = supportedExtensions();
152 for (
const auto &ext : extensions) {
154 const QString fileName = QLatin1StringView(
"test.") + ext;
155 mimeTypes << db.mimeTypesForFileName(fileName);
162static void boxBoundsRecursive(
const QQuick3DNode *baseNode,
const QQuick3DNode *node, QQuick3DBounds3 &accBounds)
167 if (
auto *model = qobject_cast<
const QQuick3DModel *>(node)) {
168 auto b = model->bounds();
169 for (
const QVector3D point : b.bounds.toQSSGBoxPoints()) {
170 auto p = model->mapPositionToNode(
const_cast<QQuick3DNode *>(baseNode), point);
171 if (Q_UNLIKELY(accBounds.bounds.isEmpty()))
172 accBounds.bounds = { p, p };
174 accBounds.bounds.include(p);
177 for (
auto *child : node->childItems())
178 boxBoundsRecursive(baseNode, qobject_cast<
const QQuick3DNode *>(child), accBounds);
181template<
typename Func>
186 for (
auto *child : obj->childItems()) {
187 if (
auto *model = qobject_cast<QQuick3DModel *>(child))
189 applyToModels(child, lambda);
193void QQuick3DRuntimeLoader::loadSource()
197 QSSGBufferManager::unregisterMeshData(m_assetId);
199 m_status = Status::Empty;
200 m_errorString = QStringLiteral(
"No file selected");
201 if (!m_source.isValid()) {
202 emit statusChanged();
203 emit errorStringChanged();
207 QSSGAssetImportManager importManager;
208 QSSGSceneDesc::Scene scene;
209 QString error(QStringLiteral(
"Unknown error"));
210 auto result = importManager.importFile(m_source, scene, &error);
213 case QSSGAssetImportManager::ImportState::Success:
214 m_errorString = QStringLiteral(
"Success!");
215 m_status = Status::Success;
217 case QSSGAssetImportManager::ImportState::IoError:
218 m_errorString = QStringLiteral(
"IO Error: ") + error;
219 m_status = Status::Error;
221 case QSSGAssetImportManager::ImportState::Unsupported:
222 m_errorString = QStringLiteral(
"Unsupported: ") + error;
223 m_status = Status::Error;
227 if (m_status == Status::Success) {
231 m_root =
new QQuick3DNode(
this);
232 m_imported = QSSGRuntimeUtils::createScene(*m_root, scene);
233 m_assetId = scene.id;
234 m_boundsDirty =
true;
235 m_instancingChanged = m_instancing !=
nullptr;
241 emit sourceChanged();
244 emit statusChanged();
245 emit errorStringChanged();
249void QQuick3DRuntimeLoader::updateModels()
251 if (m_instancingChanged) {
252 applyToModels(m_imported, [
this](QQuick3DModel *model) {
253 model->setInstancing(m_instancing);
254 model->setInstanceRoot(m_imported);
256 m_instancingChanged =
false;
260QQuick3DRuntimeLoader::Status QQuick3DRuntimeLoader::status()
const
265QString QQuick3DRuntimeLoader::errorString()
const
267 return m_errorString;
270QSSGRenderGraphObject *QQuick3DRuntimeLoader::updateSpatialNode(QSSGRenderGraphObject *node)
272 auto *result = QQuick3DNode::updateSpatialNode(node);
274 QMetaObject::invokeMethod(
this, &QQuick3DRuntimeLoader::boundsChanged, Qt::QueuedConnection);
278void QQuick3DRuntimeLoader::calculateBounds()
280 if (!m_imported || !m_boundsDirty)
283 m_bounds.bounds.setEmpty();
284 boxBoundsRecursive(m_imported, m_imported, m_bounds);
285 m_boundsDirty =
false;
288const QQuick3DBounds3 &QQuick3DRuntimeLoader::bounds()
const
291 auto *that =
const_cast<QQuick3DRuntimeLoader *>(
this);
292 that->calculateBounds();
293 return that->m_bounds;
299QQuick3DInstancing *QQuick3DRuntimeLoader::instancing()
const
304void QQuick3DRuntimeLoader::setInstancing(QQuick3DInstancing *newInstancing)
306 if (m_instancing == newInstancing)
309 QQuick3DObjectPrivate::attachWatcher(
this, &QQuick3DRuntimeLoader::setInstancing,
310 newInstancing, m_instancing);
312 m_instancing = newInstancing;
313 m_instancingChanged =
true;
315 emit instancingChanged();
Combined button and popup list for selecting options.
static void boxBoundsRecursive(const QQuick3DNode *baseNode, const QQuick3DNode *node, QQuick3DBounds3 &accBounds)
static void applyToModels(QQuick3DObject *obj, Func &&lambda)