1/****************************************************************************
2**
3** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include <QGuiApplication>
41#include <QTimer>
42#include <QOpenGLContext>
43#include <QWindow>
44#include <qmath.h>
45
46#include <Qt3DCore/QNode>
47#include <Qt3DCore/QEntity>
48#include <Qt3DCore/QTransform>
49#include <Qt3DCore/QAspectEngine>
50
51#include <Qt3DExtras/QTorusMesh>
52#include <Qt3DExtras/QForwardRenderer>
53#include <Qt3DExtras/QPhongMaterial>
54
55#include <Qt3DRender/QCamera>
56#include <Qt3DRender/QCameraLens>
57#include <Qt3DRender/QCameraSelector>
58#include <Qt3DRender/QMesh>
59#include <Qt3DRender/QPointLight>
60#include <Qt3DRender/QRenderAspect>
61#include <Qt3DRender/QRenderSettings>
62#include <Qt3DRender/QRenderSurfaceSelector>
63#include <Qt3DRender/private/qrenderaspect_p.h>
64
65
66class ManualRenderer
67{
68public:
69 ManualRenderer()
70 : m_aspectEngine(new Qt3DCore::QAspectEngine())
71 , m_renderAspect(new Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous))
72 {
73 }
74
75 ~ManualRenderer() {
76 m_aspectEngine->setRootEntity(Qt3DCore::QEntityPtr());
77 m_aspectEngine->unregisterAspect(aspect: m_renderAspect);
78 delete m_renderAspect;
79 delete m_aspectEngine;
80 }
81
82 void initialize(QWindow *window, QOpenGLContext *glCtx)
83 {
84 m_aspectEngine->registerAspect(aspect: m_renderAspect);
85 m_aspectEngine->setRunMode(Qt3DCore::QAspectEngine::Manual);
86
87 Qt3DRender::QRenderAspectPrivate *dRenderAspect = static_cast<decltype(dRenderAspect)>
88 (Qt3DRender::QRenderAspectPrivate::get(q: m_renderAspect));
89 dRenderAspect->renderInitialize(context: glCtx);
90
91 m_rootEntity.reset(t: createSceneTree(surface: window));
92 m_aspectEngine->setRootEntity(m_rootEntity);
93 }
94
95 void render() {
96 qDebug() << Q_FUNC_INFO << "Updating Scene";
97 updateScene();
98 qDebug() << Q_FUNC_INFO << "Processing Frame";
99 // Launch jobs to process the frame
100 m_aspectEngine->processFrame();
101 qDebug() << Q_FUNC_INFO << "Rendering Frame";
102 // Submit Render Queues
103 Qt3DRender::QRenderAspectPrivate *dRenderAspect = static_cast<decltype(dRenderAspect)>
104 (Qt3DRender::QRenderAspectPrivate::get(q: m_renderAspect));
105 dRenderAspect->renderSynchronous(swapBuffers: true);
106 }
107
108private:
109 Qt3DCore::QEntity *createSceneTree(QWindow *surface) {
110 // Root entity in the 3D scene.
111 Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity;
112 auto camera = new Qt3DRender::QCamera(rootEntity);
113 camera->lens()->setPerspectiveProjection(fieldOfView: 45.0f, aspect: 16.0f/9.0f, nearPlane: 0.1f, farPlane: 1000.0f);
114 camera->setPosition(QVector3D(0, 0, 40.0f));
115 camera->setViewCenter(QVector3D(0, 0, 0));
116
117 // Torus
118 Qt3DCore::QEntity *torusEntity = new Qt3DCore::QEntity(rootEntity);
119 auto material = new Qt3DExtras::QPhongMaterial(rootEntity);
120 auto torusTransform = new Qt3DCore::QTransform;
121 auto torusMesh = new Qt3DExtras::QTorusMesh;
122
123 torusMesh->setRadius(5);
124 torusMesh->setMinorRadius(1);
125 torusMesh->setRings(100);
126 torusMesh->setSlices(20);
127
128 torusTransform->setScale3D(QVector3D(1.5, 1, 0.5));
129 torusTransform->setRotation(QQuaternion::fromAxisAndAngle(axis: QVector3D(1, 0, 0), angle: 45.0f));
130
131 torusEntity->addComponent(comp: torusMesh);
132 torusEntity->addComponent(comp: material);
133 torusEntity->addComponent(comp: torusTransform);
134
135 // FrameGraph
136 auto forwardRenderer = new Qt3DExtras::QForwardRenderer();
137 forwardRenderer->setSurface(surface);
138 forwardRenderer->setCamera(camera);
139 forwardRenderer->setClearColor(QColor(Qt::black));
140
141 auto renderSettings = new Qt3DRender::QRenderSettings();
142 renderSettings->setActiveFrameGraph(forwardRenderer);
143 rootEntity->addComponent(comp: renderSettings);
144
145 return rootEntity;
146 }
147
148 void updateScene()
149 {
150 static int angle = 0;
151 // Update camera position
152 auto camera = m_rootEntity->findChild<Qt3DRender::QCamera *>();
153 Q_ASSERT(camera);
154
155 const double angleRad = qDegreesToRadians(degrees: double(angle));
156 const QVector3D newPos(qSin(v: angleRad), 0.0, qCos(v: angleRad));
157 camera->setPosition(newPos * 40.0f);
158
159 qDebug() << Q_FUNC_INFO << "Camera Transform Matrix" << camera->transform()->matrix();
160 qDebug() << Q_FUNC_INFO << "Camera ViewMatrix" << camera->viewMatrix();
161
162 angle = (angle + 1) % 360;
163 }
164
165 Qt3DCore::QEntityPtr m_rootEntity;
166 Qt3DCore::QAspectEngine *m_aspectEngine;
167 Qt3DRender::QRenderAspect *m_renderAspect;
168};
169
170int main(int ac, char **av)
171{
172 QSurfaceFormat format = QSurfaceFormat::defaultFormat();
173#ifdef QT_OPENGL_ES_2
174 format.setRenderableType(QSurfaceFormat::OpenGLES);
175#else
176 if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
177 format.setVersion(major: 4, minor: 3);
178 format.setProfile(QSurfaceFormat::CoreProfile);
179 }
180#endif
181 format.setDepthBufferSize(24);
182 format.setSamples(4);
183 format.setStencilBufferSize(8);
184 QSurfaceFormat::setDefaultFormat(format);
185
186 QGuiApplication app(ac, av);
187
188 QWindow win;
189 win.setSurfaceType(QSurface::OpenGLSurface);
190 win.resize(w: 1024, h: 768);
191 win.setFormat(format);
192 win.show();
193
194 QOpenGLContext ctx;
195 ctx.setFormat(format);
196 const bool ctxCreated = ctx.create();
197
198 if (!ctxCreated) {
199 qWarning() << "Failed to create GL context";
200 return -1;
201 }
202
203 ManualRenderer renderer;
204 renderer.initialize(window: &win, glCtx: &ctx);
205
206 QTimer t;
207 QObject::connect(sender: &t, signal: &QTimer::timeout, slot: [&] { renderer.render(); });
208 t.start(msec: 16);
209
210 return app.exec();
211}
212

source code of qt3d/tests/manual/manual-renderloop/main.cpp