Revision control
++ // Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++
++ #include <QGuiApplication>
++ #include <QTimer>
++ #include <QOpenGLContext>
++ #include <QWindow>
++ #include <qmath.h>
++
++ #include <Qt3DCore/QNode>
++ #include <Qt3DCore/QEntity>
++ #include <Qt3DCore/QTransform>
++ #include <Qt3DCore/QAspectEngine>
++
++ #include <Qt3DExtras/QTorusMesh>
++ #include <Qt3DExtras/QForwardRenderer>
++ #include <Qt3DExtras/QPhongMaterial>
++
++ #include <Qt3DRender/QCamera>
++ #include <Qt3DRender/QCameraLens>
++ #include <Qt3DRender/QCameraSelector>
++ #include <Qt3DRender/QMesh>
++ #include <Qt3DRender/QPointLight>
++ #include <Qt3DRender/QRenderAspect>
++ #include <Qt3DRender/QRenderSettings>
++ #include <Qt3DRender/QRenderSurfaceSelector>
++ #include <Qt3DRender/private/qrenderaspect_p.h>
++ #include <Qt3DRender/private/abstractrenderer_p.h>
++
++
++ class ManualRenderer
++ {
++ public:
++ ManualRenderer()
++ : m_aspectEngine(new Qt3DCore::QAspectEngine())
++ , m_renderAspect(new Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Manual))
++ , m_renderer(nullptr)
++ {
++ }
++
++ ~ManualRenderer() {
++ m_aspectEngine->setRootEntity(Qt3DCore::QEntityPtr());
++ m_aspectEngine->unregisterAspect(m_renderAspect);
++ delete m_renderAspect;
++ delete m_aspectEngine;
++ }
++
++ void initialize(QWindow *window, QOpenGLContext *glCtx)
++ {
++ m_aspectEngine->registerAspect(m_renderAspect);
++ m_aspectEngine->setRunMode(Qt3DCore::QAspectEngine::Manual);
++
++ Qt3DRender::QRenderAspectPrivate *dRenderAspect = static_cast<decltype(dRenderAspect)>
++ (Qt3DRender::QRenderAspectPrivate::get(m_renderAspect));
++ m_renderer = dRenderAspect->m_renderer;
++ m_renderer->setOpenGLContext(glCtx);
++ m_renderer->initialize();
++
++ m_rootEntity.reset(createSceneTree(window));
++ m_aspectEngine->setRootEntity(m_rootEntity);
++ }
++
++ void render() {
++ qDebug() << Q_FUNC_INFO << "Updating Scene";
++ updateScene();
++ qDebug() << Q_FUNC_INFO << "Processing Frame";
++ // Launch jobs to process the frame
++ m_aspectEngine->processFrame();
++ qDebug() << Q_FUNC_INFO << "Rendering Frame";
++ // Submit Render Queues
++ m_renderer->render(true);
++ }
++
++ private:
++ Qt3DCore::QEntity *createSceneTree(QWindow *surface) {
++ // Root entity in the 3D scene.
++ Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity;
++ auto camera = new Qt3DRender::QCamera(rootEntity);
++ camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
++ camera->setPosition(QVector3D(0, 0, 40.0f));
++ camera->setViewCenter(QVector3D(0, 0, 0));
++
++ // Torus
++ Qt3DCore::QEntity *torusEntity = new Qt3DCore::QEntity(rootEntity);
++ auto material = new Qt3DExtras::QPhongMaterial(rootEntity);
++ auto torusTransform = new Qt3DCore::QTransform;
++ auto torusMesh = new Qt3DExtras::QTorusMesh;
++
++ torusMesh->setRadius(5);
++ torusMesh->setMinorRadius(1);
++ torusMesh->setRings(100);
++ torusMesh->setSlices(20);
++
++ torusTransform->setScale3D(QVector3D(1.5, 1, 0.5));
++ torusTransform->setRotation(QQuaternion::fromAxisAndAngle(QVector3D(1, 0, 0), 45.0f));
++
++ torusEntity->addComponent(torusMesh);
++ torusEntity->addComponent(material);
++ torusEntity->addComponent(torusTransform);
++
++ // FrameGraph
++ auto forwardRenderer = new Qt3DExtras::QForwardRenderer();
++ forwardRenderer->setSurface(surface);
++ forwardRenderer->setCamera(camera);
++ forwardRenderer->setClearColor(QColor(Qt::black));
++
++ auto renderSettings = new Qt3DRender::QRenderSettings();
++ renderSettings->setActiveFrameGraph(forwardRenderer);
++ rootEntity->addComponent(renderSettings);
++
++ return rootEntity;
++ }
++
++ void updateScene()
++ {
++ static int angle = 0;
++ // Update camera position
++ auto camera = m_rootEntity->findChild<Qt3DRender::QCamera *>();
++ Q_ASSERT(camera);
++
++ const double angleRad = qDegreesToRadians(double(angle));
++ const QVector3D newPos(qSin(angleRad), 0.0, qCos(angleRad));
++ camera->setPosition(newPos * 40.0f);
++
++ qDebug() << Q_FUNC_INFO << "Camera Transform Matrix" << camera->transform()->matrix();
++ qDebug() << Q_FUNC_INFO << "Camera ViewMatrix" << camera->viewMatrix();
++
++ angle = (angle + 1) % 360;
++ }
++
++ Qt3DCore::QEntityPtr m_rootEntity;
++ Qt3DCore::QAspectEngine *m_aspectEngine;
++ Qt3DRender::QRenderAspect *m_renderAspect;
++ Qt3DRender::Render::AbstractRenderer *m_renderer;
++ };
++
++ int main(int ac, char **av)
++ {
++ QSurfaceFormat format = QSurfaceFormat::defaultFormat();
++ #if QT_CONFIG(opengles2)
++ format.setRenderableType(QSurfaceFormat::OpenGLES);
++ #else
++ if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
++ format.setVersion(4, 3);
++ format.setProfile(QSurfaceFormat::CoreProfile);
++ }
++ #endif
++ format.setDepthBufferSize(24);
++ format.setSamples(4);
++ format.setStencilBufferSize(8);
++ QSurfaceFormat::setDefaultFormat(format);
++
++ QGuiApplication app(ac, av);
++
++ QWindow win;
++ win.setSurfaceType(QSurface::OpenGLSurface);
++ win.resize(1024, 768);
++ win.setFormat(format);
++ win.show();
++
++ QOpenGLContext ctx;
++ ctx.setFormat(format);
++ const bool ctxCreated = ctx.create();
++
++ if (!ctxCreated) {
++ qWarning() << "Failed to create GL context";
++ return -1;
++ }
++
++ ManualRenderer renderer;
++ renderer.initialize(&win, &ctx);
++
++ QTimer t;
++ QObject::connect(&t, &QTimer::timeout, &t, [&] { renderer.render(); });
++ t.start(16);
++
++ return app.exec();
++ }