diff options
author | Laszlo Agocs <laszlo.agocs@theqtcompany.com> | 2015-07-28 12:03:49 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@theqtcompany.com> | 2015-07-28 10:16:50 +0000 |
commit | 35455497abecb111a881b71b70451f2f5bfa8d28 (patch) | |
tree | 42bb1c6c00677ec2237e68860616eb16c5469efd | |
parent | 90623e3ccbeba4f498b3ce5c1b6c88f1122df434 (diff) |
Enhance assimp-cpp example with exploring the loaded scene tree
Finding and possibly modifying the named parts of the loaded scene
is essential in many cases. Therefore it is highly beneficial to
have an example showing how to do this from C++.
Change-Id: I3fefb80103b7e2f631464460c95067d414e4819f
Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
-rw-r--r-- | examples/qt3d/assimp-cpp/main.cpp | 73 |
1 files changed, 69 insertions, 4 deletions
diff --git a/examples/qt3d/assimp-cpp/main.cpp b/examples/qt3d/assimp-cpp/main.cpp index d068f443e..4b4048c6c 100644 --- a/examples/qt3d/assimp-cpp/main.cpp +++ b/examples/qt3d/assimp-cpp/main.cpp @@ -47,6 +47,58 @@ #include <Qt3DRenderer/QRenderAspect> #include <Qt3DRenderer/QForwardRenderer> +class SceneWalker : public QObject +{ +public: + SceneWalker(Qt3D::QSceneLoader *loader) : m_loader(loader) { } + + void onStatusChanged(); + +private: + void walkEntity(Qt3D::QEntity *e, int depth = 0); + + Qt3D::QSceneLoader *m_loader; +}; + +void SceneWalker::onStatusChanged() +{ + qDebug() << "Status changed:" << m_loader->status(); + if (m_loader->status() != Qt3D::QSceneLoader::Loaded) + return; + + // The QSceneLoader instance is a component of an entity. The loaded scene + // tree is added under this entity. + QVector<Qt3D::QEntity *> entities = m_loader->entities(); + + // Technically there could be multiple entities referencing the scene loader + // but sharing is discouraged, and in our case there will be one anyhow. + if (entities.isEmpty()) + return; + Qt3D::QEntity *root = entities[0]; + // Print the tree. + walkEntity(root); + + // To access a given node (like a named mesh in the scene), use QObject::findChild(). + // The scene structure and names always depend on the asset. + Qt3D::QEntity *e = root->findChild<Qt3D::QEntity *>(QStringLiteral("PlanePropeller_mesh")); // toyplane.obj + if (e) + qDebug() << "Found propeller node" << e << "with components" << e->components(); +} + +void SceneWalker::walkEntity(Qt3D::QEntity *e, int depth) +{ + Qt3D::QNodeList nodes = e->childrenNodes(); + for (int i = 0; i < nodes.count(); ++i) { + Qt3D::QNode *node = nodes[i]; + Qt3D::QEntity *entity = qobject_cast<Qt3D::QEntity *>(node); + if (entity) { + QString indent; + indent.fill(' ', depth * 2); + qDebug().noquote() << indent << "Entity:" << entity << "Components:" << entity->components(); + walkEntity(entity, depth + 1); + } + } +} int main(int ac, char **av) { @@ -90,12 +142,25 @@ int main(int ac, char **av) // Scene loader Qt3D::QEntity *sceneLoaderEntity = new Qt3D::QEntity(sceneRoot); Qt3D::QSceneLoader *sceneLoader = new Qt3D::QSceneLoader(sceneLoaderEntity); + SceneWalker sceneWalker(sceneLoader); + QObject::connect(sceneLoader, &Qt3D::QSceneLoader::statusChanged, &sceneWalker, &SceneWalker::onStatusChanged); sceneLoaderEntity->addComponent(sceneLoader); - QWidget *container = new QWidget(); - QFileDialog dialog; - dialog.setFileMode(QFileDialog::AnyFile); - sceneLoader->setSource(dialog.getOpenFileUrl(container, QStringLiteral("Open a scene file"))); + QStringList args = QCoreApplication::arguments(); + QUrl sourceFileName; + if (args.count() <= 1) { + QWidget *container = new QWidget(); + QFileDialog dialog; + dialog.setFileMode(QFileDialog::AnyFile); + sourceFileName = dialog.getOpenFileUrl(container, QStringLiteral("Open a scene file")); + } else { + sourceFileName = QUrl::fromLocalFile(args[1]); + } + + if (sourceFileName.isEmpty()) + return 0; + + sceneLoader->setSource(sourceFileName); engine.setRootEntity(sceneRoot); view.show(); |