2022-06-08 12:47:24 +00:00
|
|
|
// Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
|
2024-02-23 14:41:04 +00:00
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
2015-04-18 13:03:27 +00:00
|
|
|
|
|
|
|
#include <QFileDialog>
|
|
|
|
#include <QApplication>
|
|
|
|
|
2016-01-15 14:09:44 +00:00
|
|
|
#include <Qt3DRender/QCamera>
|
2015-04-18 13:03:27 +00:00
|
|
|
#include <Qt3DCore/QEntity>
|
|
|
|
#include <Qt3DCore/QAspectEngine>
|
|
|
|
#include <Qt3DInput/QInputAspect>
|
2015-10-18 08:58:19 +00:00
|
|
|
#include <Qt3DRender/QSceneLoader>
|
|
|
|
#include <Qt3DRender/QRenderAspect>
|
2016-04-11 12:58:17 +00:00
|
|
|
#include <Qt3DExtras/QForwardRenderer>
|
2016-04-26 06:38:15 +00:00
|
|
|
#include <Qt3DExtras/qt3dwindow.h>
|
|
|
|
#include <Qt3DExtras/qfirstpersoncameracontroller.h>
|
2015-04-18 13:03:27 +00:00
|
|
|
|
2015-07-28 10:03:49 +00:00
|
|
|
class SceneWalker : public QObject
|
|
|
|
{
|
|
|
|
public:
|
2015-08-31 14:14:17 +00:00
|
|
|
SceneWalker(Qt3DRender::QSceneLoader *loader) : m_loader(loader) { }
|
2015-07-28 10:03:49 +00:00
|
|
|
|
|
|
|
void onStatusChanged();
|
|
|
|
|
|
|
|
private:
|
2015-10-12 19:45:19 +00:00
|
|
|
void walkEntity(Qt3DCore::QEntity *e, int depth = 0);
|
2015-07-28 10:03:49 +00:00
|
|
|
|
2015-08-31 14:14:17 +00:00
|
|
|
Qt3DRender::QSceneLoader *m_loader;
|
2015-07-28 10:03:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
void SceneWalker::onStatusChanged()
|
|
|
|
{
|
|
|
|
qDebug() << "Status changed:" << m_loader->status();
|
2016-03-02 14:54:14 +00:00
|
|
|
if (m_loader->status() != Qt3DRender::QSceneLoader::Ready)
|
2015-07-28 10:03:49 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
// The QSceneLoader instance is a component of an entity. The loaded scene
|
|
|
|
// tree is added under this entity.
|
2020-07-08 12:17:04 +00:00
|
|
|
QList<Qt3DCore::QEntity *> entities = m_loader->entities();
|
2015-07-28 10:03:49 +00:00
|
|
|
|
|
|
|
// 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;
|
2015-10-12 19:45:19 +00:00
|
|
|
Qt3DCore::QEntity *root = entities[0];
|
2015-07-28 10:03:49 +00:00
|
|
|
// 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.
|
2015-10-12 19:45:19 +00:00
|
|
|
Qt3DCore::QEntity *e = root->findChild<Qt3DCore::QEntity *>(QStringLiteral("PlanePropeller_mesh")); // toyplane.obj
|
2015-07-28 10:03:49 +00:00
|
|
|
if (e)
|
|
|
|
qDebug() << "Found propeller node" << e << "with components" << e->components();
|
|
|
|
}
|
|
|
|
|
2015-10-12 19:45:19 +00:00
|
|
|
void SceneWalker::walkEntity(Qt3DCore::QEntity *e, int depth)
|
2015-07-28 10:03:49 +00:00
|
|
|
{
|
2016-02-22 18:55:50 +00:00
|
|
|
Qt3DCore::QNodeVector nodes = e->childNodes();
|
2015-07-28 10:03:49 +00:00
|
|
|
for (int i = 0; i < nodes.count(); ++i) {
|
2015-10-12 19:45:19 +00:00
|
|
|
Qt3DCore::QNode *node = nodes[i];
|
|
|
|
Qt3DCore::QEntity *entity = qobject_cast<Qt3DCore::QEntity *>(node);
|
2015-07-28 10:03:49 +00:00
|
|
|
if (entity) {
|
|
|
|
QString indent;
|
|
|
|
indent.fill(' ', depth * 2);
|
|
|
|
qDebug().noquote() << indent << "Entity:" << entity << "Components:" << entity->components();
|
|
|
|
walkEntity(entity, depth + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-04-18 13:03:27 +00:00
|
|
|
|
|
|
|
int main(int ac, char **av)
|
|
|
|
{
|
|
|
|
QApplication app(ac, av);
|
2016-04-26 06:38:15 +00:00
|
|
|
Qt3DExtras::Qt3DWindow view;
|
2016-08-11 10:21:55 +00:00
|
|
|
view.defaultFrameGraph()->setClearColor(Qt::black);
|
2015-04-18 13:03:27 +00:00
|
|
|
|
|
|
|
// Root entity
|
2015-10-12 19:45:19 +00:00
|
|
|
Qt3DCore::QEntity *sceneRoot = new Qt3DCore::QEntity();
|
2015-04-18 13:03:27 +00:00
|
|
|
|
|
|
|
// Scene Camera
|
2016-04-19 13:25:04 +00:00
|
|
|
Qt3DRender::QCamera *camera = view.camera();
|
|
|
|
camera->setProjectionType(Qt3DRender::QCameraLens::PerspectiveProjection);
|
|
|
|
camera->setViewCenter(QVector3D(0.0f, 3.5f, 0.0f));
|
|
|
|
camera->setPosition(QVector3D(0.0f, 3.5f, 25.0f));
|
|
|
|
camera->setNearPlane(0.001f);
|
|
|
|
camera->setFarPlane(10000.0f);
|
2016-01-17 13:54:04 +00:00
|
|
|
|
2015-04-18 13:03:27 +00:00
|
|
|
// For camera controls
|
2016-04-26 06:38:15 +00:00
|
|
|
Qt3DExtras::QFirstPersonCameraController *camController = new Qt3DExtras::QFirstPersonCameraController(sceneRoot);
|
2016-04-19 13:25:04 +00:00
|
|
|
camController->setCamera(camera);
|
2015-04-18 13:03:27 +00:00
|
|
|
|
|
|
|
// Scene loader
|
2015-10-12 19:45:19 +00:00
|
|
|
Qt3DCore::QEntity *sceneLoaderEntity = new Qt3DCore::QEntity(sceneRoot);
|
2015-08-31 14:14:17 +00:00
|
|
|
Qt3DRender::QSceneLoader *sceneLoader = new Qt3DRender::QSceneLoader(sceneLoaderEntity);
|
2015-07-28 10:03:49 +00:00
|
|
|
SceneWalker sceneWalker(sceneLoader);
|
2015-08-31 14:14:17 +00:00
|
|
|
QObject::connect(sceneLoader, &Qt3DRender::QSceneLoader::statusChanged, &sceneWalker, &SceneWalker::onStatusChanged);
|
2015-04-18 13:03:27 +00:00
|
|
|
sceneLoaderEntity->addComponent(sceneLoader);
|
|
|
|
|
2015-07-28 10:03:49 +00:00
|
|
|
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);
|
2015-04-18 13:03:27 +00:00
|
|
|
|
2015-12-28 07:12:34 +00:00
|
|
|
view.setRootEntity(sceneRoot);
|
2015-04-18 13:03:27 +00:00
|
|
|
view.show();
|
|
|
|
|
|
|
|
return app.exec();
|
|
|
|
}
|