VisuTwin Canvas
C++ 3D Engine — Metal Backend
Loading...
Searching...
No Matches
engine.h
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2025-2026 Arnis Lektauers
3//
4// Created by Arnis Lektauers on 18.07.2025.
5//
6#pragma once
7
8#include <SDL3/SDL.h>
9
10#include "appOptions.h"
12#include "scene/scene.h"
14#include "applicationStats.h"
15#include "constants.h"
16#include "sceneRegistry.h"
20#include "i18n/i18n.h"
24
25namespace visutwin::canvas
26{
28
37 class Engine : public EventHandler, public std::enable_shared_from_this<Engine>
38 {
39 public:
40 Engine(SDL_Window* window) : _window(window) {}
41
42 virtual ~Engine();
43
44 void init(const AppOptions& appOptions);
45
46 // Destroys application and removes all event listeners
47 void destroy();
48
49 // Start the application
50 void start();
51
52 const std::shared_ptr<Scene>& scene() const { return _scene; }
53 const std::shared_ptr<GraphicsDevice>& graphicsDevice() const { return _graphicsDevice; }
54
55 // Controls how the canvas fills the window and resizes when the window changes
56 void setCanvasFillMode(FillMode mode, int width = 0, int height = 0);
57
58 // Change the resolution of the canvas
59 void setCanvasResolution(ResolutionMode mode, int width = 0, int height = 0);
60
61 // Resize the application's canvas
62 std::pair<int, int> resizeCanvas(int width = 0, int height = 0);
63
64 // Updates the {@link GraphicsDevice} canvas size to match the canvas size on the document page.
65 // It is recommended to call this function when the canvas size changes
66 // (e.g. on window resize and orientation change events) so that the canvas resolution is immediately updated.
67 void updateCanvasSize();
68
69 // Update the engine (variable timestep — called once per frame)
70 void update(float dt);
71
72 // Run one fixed-timestep simulation substep (deterministic dt)
73 void fixedUpdate(float fixedDt);
74
75 // Update all input devices managed by the engine
76 void inputUpdate(float dt);
77
78 // Render the application's scene for one frame
79 void render();
80
81 // Fixed timestep configuration
82 float fixedDeltaTime() const { return _fixedDeltaTime; }
83 void setFixedDeltaTime(float dt) { _fixedDeltaTime = dt; }
84
85 int maxFixedSubSteps() const { return _maxFixedSubSteps; }
86 void setMaxFixedSubSteps(int n) { _maxFixedSubSteps = n; }
87
88 // Interpolation alpha (0..1) between the last two fixed-update states.
89 // Use in rendering to smooth visual positions when sim rate != frame rate.
90 float fixedTimeAlpha() const { return _fixedTimeAlpha; }
91
92 std::shared_ptr<Entity> root() { return _root; }
93
94 std::shared_ptr<ScriptRegistry> scripts() const { return _scripts; }
95
96 std::shared_ptr<ComponentSystemRegistry> systems() const { return _systems; }
97
98 SDL_Window* sdlWindow() const { return _window; }
99
101 BatchManager* batcher() { return _batcher.get(); }
102
104 const std::shared_ptr<ResourceLoader>& loader() const { return _loader; }
105
106 protected:
107 virtual double processTimestamp(double timestamp) { return timestamp; }
108
109 private:
110 friend MakeTickCallback makeTick(const std::shared_ptr<Engine>& engine);
111
112 static std::unordered_map<std::string, std::shared_ptr<Engine>> _engines;
113
114 // Render a layer composition
115 void renderComposition();
116
117 void tick();
118
119 void initDefaultMaterial();
120
121 void initProgramLibrary();
122
123 void registerSceneImmediate(const std::shared_ptr<Scene>& scene);
124
125 void fillFrameStatsBasic(double now, float dt, float ms);
126
127 void fillFrameStats();
128
129 std::shared_ptr<GraphicsDevice> _graphicsDevice;
130
131 std::shared_ptr<Entity> _root;
132 std::shared_ptr<ForwardRenderer> _renderer;
133
134 std::shared_ptr<Scene> _scene;
135
136 // The application's component system registry
137 std::shared_ptr<ComponentSystemRegistry> _systems;
138
139 void* _frameRequestId = nullptr;
140 float _timeScale = 1.0f;
141 float _maxDeltaTime = 0.1f;
142
143 // The total number of frames the application has updated since start() was called
144 long _frame = 0;
145
146 // When true, the application's render function is called every frame
147 bool _autoRender = true;
148
149 std::shared_ptr<ApplicationStats> _stats;
150
151 std::shared_ptr<ResourceLoader> _loader;
152 std::shared_ptr<AssetRegistry> _assets;
153 std::shared_ptr<BundleRegistry> _bundles;
154 std::shared_ptr<SceneRegistry> _scenes;
155 std::shared_ptr<ScriptRegistry> _scripts;
156 std::shared_ptr<I18n> _i18n;
157
158 // Default layers
159 std::shared_ptr<Layer> _defaultLayerWorld;
160 std::shared_ptr<Layer> _defaultLayerDepth;
161 std::shared_ptr<Layer> _defaultLayerSkybox;
162 std::shared_ptr<Layer> _defaultLayerUi;
163 std::shared_ptr<Layer> _defaultLayerImmediate;
164
165 std::vector<std::string> _scriptsOrder;
166 std::string _scriptPrefix;
167
168 std::shared_ptr<Lightmapper> _lightmapper;
169
170 std::shared_ptr<BatchManager> _batcher;
171
172 std::shared_ptr<Controller> _controller;
173 std::shared_ptr<Keyboard> _keyboard;
174 std::shared_ptr<Mouse> _mouse;
175 std::shared_ptr<GamePads> _gamepads;
176 std::shared_ptr<TouchDevice> _touch;
177 std::shared_ptr<ElementInput> _elementInput;
178 std::shared_ptr<XrManager> _xr;
179
180 MakeTickCallback _tick;
181
183
185
186 bool _allowResize = true;
187
188 bool _inFrameUpdate = false;
189
190 double _time = 0.0;
191
192 // Fixed timestep state
193 float _fixedDeltaTime = 1.0f / 60.0f;
194 double _fixedTimeAccumulator = 0.0;
195 int _maxFixedSubSteps = 8;
196 float _fixedTimeAlpha = 0.0f;
197
198 bool _renderNextFrame = false;
199
200 bool _destroyRequested = false;
201
202 std::unordered_map<std::string, std::shared_ptr<Entity>> _entityIndex;
203
204 bool _inTools = false;
205
206 // Runtime parity checks for frame lifecycle ordering.
207 bool _frameStartCalled = false;
208 bool _renderCompositionCalled = false;
209 bool _frameEndCalled = false;
210
211 SDL_Window* _window;
212 };
213
214 MakeTickCallback makeTick(const std::shared_ptr<Engine>& engine);
215}
void setCanvasResolution(ResolutionMode mode, int width=0, int height=0)
Definition engine.cpp:442
std::shared_ptr< ScriptRegistry > scripts() const
Definition engine.h:94
SDL_Window * sdlWindow() const
Definition engine.h:98
std::shared_ptr< Entity > root()
Definition engine.h:92
int maxFixedSubSteps() const
Definition engine.h:85
void setFixedDeltaTime(float dt)
Definition engine.h:83
float fixedDeltaTime() const
Definition engine.h:82
const std::shared_ptr< ResourceLoader > & loader() const
Definition engine.h:104
void update(float dt)
Definition engine.cpp:548
BatchManager * batcher()
Definition engine.h:101
std::pair< int, int > resizeCanvas(int width=0, int height=0)
Definition engine.cpp:406
friend MakeTickCallback makeTick(const std::shared_ptr< Engine > &engine)
Definition engine.cpp:24
void init(const AppOptions &appOptions)
Definition engine.cpp:207
void setCanvasFillMode(FillMode mode, int width=0, int height=0)
Definition engine.cpp:400
float fixedTimeAlpha() const
Definition engine.h:90
Engine(SDL_Window *window)
Definition engine.h:40
virtual double processTimestamp(double timestamp)
Definition engine.h:107
const std::shared_ptr< Scene > & scene() const
Definition engine.h:52
void setMaxFixedSubSteps(int n)
Definition engine.h:86
std::shared_ptr< ComponentSystemRegistry > systems() const
Definition engine.h:96
void fixedUpdate(float fixedDt)
Definition engine.cpp:636
const std::shared_ptr< GraphicsDevice > & graphicsDevice() const
Definition engine.h:53
void inputUpdate(float dt)
Definition engine.cpp:532
std::function< void(double, void *)> MakeTickCallback
Definition xrManager.h:14
MakeTickCallback makeTick(const std::shared_ptr< Engine > &app)
Definition engine.cpp:24