pure-cpp 1.0.0
A C++ physics simulation benchmark comparing performance with Python implementations
display.hpp
Go to the documentation of this file.
1#ifndef DISPLAY_HPP
2#define DISPLAY_HPP
3
4/**
5 * \file display.hpp
6 * \brief Displaying spherical moving bodies.
7 * \author Laurent, Jules
8 * \author Le Bars, Yoann
9 * \ingroup UIRendering
10 *
11 * This file is part of the pure C++ benchmark.
12 *
13 * This program is free software: you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the Free
15 * Software Foundation, either version 3 of the License, or (at your option)
16 * any later version.
17 *
18 * This program is distributed in the hope that it will be useful, but WITHOUT
19 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
21 * more details.
22 *
23 * You should have received a copy of the GNU General Public License along with
24 * this program. If not, see <https://www.gnu.org/licenses/>.
25 */
26
27#include <QPointer>
28#include <QThread>
29#include <QTimer>
30#include <QVector3D>
31#include <Qt3DExtras/QForwardRenderer>
32#include <Qt3DExtras/QOrbitCameraController>
33#include <Qt3DExtras/Qt3DWindow>
34#include <Qt3DRender/QCamera>
35#include <cstddef>
36#include <tuple>
37#include <vector>
38
39#include "config.hpp"
40#include "constants.hpp"
41#include "pcg_random.hpp"
42#include "physics_worker.hpp"
43
44namespace Window {
45 /**
46 * \brief Manages the Qt3D window, scene setup, and the main simulation
47 * loop.
48 *
49 * This class orchestrates the 3D rendering and the physics worker thread.
50 * \ingroup UIRendering
51 */
52 class Display : public Qt3DExtras::Qt3DWindow {
53 Q_OBJECT
54
55 public:
56 /**
57 * \brief A tuple to hold the Qt-specific components for a single
58 * rendered body.
59 */
60 using BodyInformations = std::tuple< // NOLINT
61 QPointer<Qt3DCore::QEntity>, QPointer<Qt3DCore::QTransform>,
62 QPointer<Qt3DCore::QEntity>, QPointer<Qt3DCore::QTransform>,
63 QPointer<Qt3DCore::QEntity>, QPointer<Qt3DCore::QTransform>>;
64 /**
65 * \brief Initialise the 3D window and set up the scene.
66 *
67 * \param config The simulation configuration object.
68 */
69 explicit Display(const Configuration::SimulationConfig& config)
70 : iterationCount_(0),
71 maxIterations_(config.n_iter),
72 cleanupCalled_(false) {
73 showTorqueArrow_ = config.show_torque_arrow;
74 showAlphaArrow_ = config.show_alpha_arrow;
75 defaultFrameGraph()->setClearColor(QColor(0, 0, 0));
76
77 // --- Camera Setup ---
78 camera()->lens()->setPerspectiveProjection(45., 16. / 9., 0.1,
79 100000.);
80 camera()->setPosition(QVector3D(0, 0, 820));
81 camera()->setViewCenter(QVector3D(0, 0, 0));
82 rootEntity_ = std::make_unique<Qt3DCore::QEntity>();
83
84 // --- Physics Worker and Thread Setup ---
85 physicsThread_ = new QThread(this);
87 physicsWorker_->moveToThread(physicsThread_);
88
89 // Connect signals from the worker to slots in this (GUI) thread.
90 connect(physicsThread_, &QThread::started, physicsWorker_,
93 this, &Display::updateFrame, Qt::QueuedConnection);
95 this, &Display::simulationFinished); // NOLINT
96
97 // --- Simulation Timer Setup ---
98 // Create a reusable timer that will drive the simulation loop.
99 // This is more efficient than using QTimer::singleShot() for each
100 // frame.
101 simulationTimer_ = new QTimer(this);
102 connect(simulationTimer_, &QTimer::timeout, physicsWorker_,
104 // Stop the timer when the simulation finishes
106 simulationTimer_, &QTimer::stop, Qt::QueuedConnection);
107
108 // --- Scene Creation ---
109 createScene(config.seed);
110
111 // --- Camera Controller Setup ---
113 new Qt3DExtras::QOrbitCameraController(rootEntity_.get());
114 camController_->setLinearSpeed(50);
115 camController_->setLookSpeed(180);
116 camController_->setCamera(camera());
117
118 // Set the root entity for the scene.
119 setRootEntity(rootEntity_.get());
120 }
121
122 /// \brief Destructor to ensure worker thread is cleaned up.
123 ~Display() override;
124
125 /// \brief Performs cleanup actions, such as printing profiling reports.
126 void cleanup();
127
128 /// \brief Starts the physics simulation by starting the worker thread.
129 void runSimulation();
130
131 signals:
132 /**
133 * \brief Emitted when the simulation has run for n_iter iterations.
134 */
136
137 private slots:
138 /**
139 * \brief Slot to receive updated data from the physics worker and
140 * update the scene.
141 */
142 void updateFrame(const Model::Vector3dVec& positions,
143 const Model::QuaterniondVec& quaternions,
144 const Model::Vector3dVec& torques, // NOLINT
145 const Model::Vector3dVec& alphas, // NOLINT
146 std::size_t iteration); // NOLINT
147
148 private:
149 /// \brief The current iteration count.
150 std::size_t iterationCount_;
151
152 /// \brief Maximum number of iterations.
153 std::size_t maxIterations_;
154
155 /// \brief Flag to display torque vectors in the UI.
157
158 /// \brief Flag to display angular acceleration vectors in the UI.
160
161 /// \brief The root entity for the 3D scene.
162 std::unique_ptr<Qt3DCore::QEntity> rootEntity_;
163
164 /// \brief Mouse camera controller.
165 QPointer<Qt3DExtras::QOrbitCameraController> camController_;
166
167 /**
168 * \brief List of spheres representing bodies. This list differs from
169 * the actual physical bodies in the simulation.
170 */
171 std::vector<BodyInformations> bodies_;
172
173 /// \brief The worker object running the simulation.
174 /// Uses QPointer for safety: it becomes nullptr if the object is
175 /// destroyed.
176 QPointer<Model::PhysicsWorker> physicsWorker_;
177
178 /// \brief The thread where the physics worker runs.
179 /// Created with 'this' as parent, so Qt manages its lifetime.
181
182 /// \brief Timer to drive the simulation loop.
183 /// Reused timer that triggers physics steps automatically.
185
186 /// \brief Flag to track if cleanup has already been called.
187 /// This prevents cleanup from being called multiple times.
189
190 /**
191 * \brief Create and set up the spherical bodies in the scene.
192 *
193 * \param gen A seeded random number generator for reproducible body
194 * colours.
195 */
196 void createSpheres(Rng::Pcg32& gen);
197
198 /**
199 * \brief Set up the scene.
200 *
201 * \param seed The seed for the random number generator.
202 */
203 void createScene(unsigned int seed);
204
205 /**
206 * \brief Creates a 3D arrow entity for vector visualization.
207 * \param parent The parent entity.
208 * \param colour The colour of the arrow.
209 * \param radius The radius of the arrow's shaft.
210 * \param length The initial length of the arrow.
211 * \return A tuple containing the arrow's root entity and its
212 * transform component.
213 */
214 std::pair<Qt3DCore::QEntity*, Qt3DCore::QTransform*> createArrowEntity(
215 Qt3DCore::QEntity* parent, const QColor& colour, float radius,
216 float length);
217
218 /**
219 * \brief Updates the transform of an arrow entity to represent a 3D
220 * vector.
221 * \param arrowTransform The transform component of the arrow to update.
222 * \param vector The 3D vector to visualise.
223 * \param scaleFactor A multiplier for the arrow's length.
224 */
225 void updateVectorArrow(Qt3DCore::QTransform* arrowTransform,
226 const Model::Vector3d& vector,
227 double scaleFactor) const;
228 };
229}
230
231#endif // DISPLAY_HPP
Runs the physics simulation in a separate thread to keep the UI responsive.
void updatedBodyData(const Vector3dVec &positions, const QuaterniondVec &quaternions, const Vector3dVec &torques, const Vector3dVec &alphas, std::size_t iteration)
Emitted after each simulation step with the updated state of all bodies.
void startSimulation()
Starts the simulation loop.
void performSingleStep()
Performs a single step of the physics simulation and emits the results.
void simulationFinished()
Emitted when the simulation has completed all iterations.
A 32-bit Permuted Congruential Generator (pcg32).
Definition: pcg_random.hpp:37
Manages the Qt3D window, scene setup, and the main simulation loop.
Definition: display.hpp:52
void cleanup()
Performs cleanup actions, such as printing profiling reports.
Definition: display.cpp:185
std::unique_ptr< Qt3DCore::QEntity > rootEntity_
The root entity for the 3D scene.
Definition: display.hpp:162
std::size_t maxIterations_
Maximum number of iterations.
Definition: display.hpp:153
void createSpheres(Rng::Pcg32 &gen)
Create and set up the spherical bodies in the scene.
Definition: display.cpp:106
std::pair< Qt3DCore::QEntity *, Qt3DCore::QTransform * > createArrowEntity(Qt3DCore::QEntity *parent, const QColor &colour, float radius, float length)
Creates a 3D arrow entity for vector visualization.
Definition: display.cpp:60
bool cleanupCalled_
Flag to track if cleanup has already been called. This prevents cleanup from being called multiple ti...
Definition: display.hpp:188
~Display() override
Destructor to ensure worker thread is cleaned up.
Definition: display.cpp:43
QPointer< Model::PhysicsWorker > physicsWorker_
The worker object running the simulation. Uses QPointer for safety: it becomes nullptr if the object ...
Definition: display.hpp:176
void simulationFinished()
Emitted when the simulation has run for n_iter iterations.
std::tuple< QPointer< Qt3DCore::QEntity >, QPointer< Qt3DCore::QTransform >, QPointer< Qt3DCore::QEntity >, QPointer< Qt3DCore::QTransform >, QPointer< Qt3DCore::QEntity >, QPointer< Qt3DCore::QTransform > > BodyInformations
A tuple to hold the Qt-specific components for a single rendered body.
Definition: display.hpp:63
std::size_t iterationCount_
The current iteration count.
Definition: display.hpp:150
QTimer * simulationTimer_
Timer to drive the simulation loop. Reused timer that triggers physics steps automatically.
Definition: display.hpp:184
void updateFrame(const Model::Vector3dVec &positions, const Model::QuaterniondVec &quaternions, const Model::Vector3dVec &torques, const Model::Vector3dVec &alphas, std::size_t iteration)
Slot to receive updated data from the physics worker and update the scene.
Definition: display.cpp:298
QPointer< Qt3DExtras::QOrbitCameraController > camController_
Mouse camera controller.
Definition: display.hpp:165
void createScene(unsigned int seed)
Set up the scene.
Definition: display.cpp:162
QThread * physicsThread_
The thread where the physics worker runs. Created with 'this' as parent, so Qt manages its lifetime.
Definition: display.hpp:180
void runSimulation()
Starts the physics simulation by starting the worker thread.
Definition: display.cpp:172
bool showAlphaArrow_
Flag to display angular acceleration vectors in the UI.
Definition: display.hpp:159
void updateVectorArrow(Qt3DCore::QTransform *arrowTransform, const Model::Vector3d &vector, double scaleFactor) const
Updates the transform of an arrow entity to represent a 3D vector.
Definition: display.cpp:267
bool showTorqueArrow_
Flag to display torque vectors in the UI.
Definition: display.hpp:156
std::vector< BodyInformations > bodies_
List of spheres representing bodies. This list differs from the actual physical bodies in the simulat...
Definition: display.hpp:171
Display(const Configuration::SimulationConfig &config)
Initialise the 3D window and set up the scene.
Definition: display.hpp:69
Constants for the model.
A minimal C++ implementation of the PCG32 random number generator.
Worker object to run the physics simulation in a separate thread.