Kale
Loading...
Searching...
No Matches
Scene.cpp
Go to the documentation of this file.
1/*
2 Copyright 2022 Rishi Challa
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17#include "Scene.hpp"
18
20
21#ifdef KALE_OPENGL
22
24
25#endif
26
27#ifdef KALE_VULKAN
28
30
31#endif
32
33#include <algorithm>
34#include <sstream>
35
36using namespace Kale;
37
42 updateNodes.resize(std::thread::hardware_concurrency());
43 preUpdateNodes.resize(std::thread::hardware_concurrency());
44 threadedNodePerformanceTimes.resize(std::thread::hardware_concurrency());
45 nodesPreUpdated = std::thread::hardware_concurrency();
46 generation = 0;
47
49 viewport = {size.x * 1080.0f / size.y, 1080.0f};
50
52 worldToScreen.translate(Vector2f(1920.0f, 1080.0f) / -2.0f);
53 sceneBounds = Rect{{(1920.0f - viewport.x) / 2.0f, 1080.0f}, {(1920.0f + viewport.x) / 2.0f, 0.0f}};
54}
55
60Scene::Scene(const std::string& filename) {
61
62 // Default Setup
63 updateNodes.resize(std::thread::hardware_concurrency());
64 preUpdateNodes.resize(std::thread::hardware_concurrency());
65 threadedNodePerformanceTimes.resize(std::thread::hardware_concurrency());
66 nodesPreUpdated = std::thread::hardware_concurrency();
67 generation = 0;
68
70 viewport = {size.x * 1080.0f / size.y, 1080.0f};
71
73 worldToScreen.translate(Vector2f(1920.0f, 1080.0f) / -2.0f);
74 sceneBounds = Rect{{(1920.0f - viewport.x) / 2.0f, 1080.0f}, {(1920.0f + viewport.x) / 2.0f, 0.0f}};
75
76 // Run the loading on the main thread, this way it is done after the node map is populated and is done without concern for where
77 // the constructor is called from
78 mainApp->runTaskOnMainThread([&, filename]() {
79 try {
80 // Load json from file
81 std::ifstream jsonFile(mainApp->getAssetFolderPath() + filename);
82 JSON sceneConfig = JSON::parse(jsonFile, nullptr, true, true);
83 bgColor = sceneConfig["bgColor"].get<Color>();
84 camera = sceneConfig["camera"].get<Camera>();
85
86 // Get the nodes in JSON form then loop through them and parse them/add them
87 std::vector<JSON> nodes = sceneConfig["nodes"].get<std::vector<JSON>>();
88 for (const JSON& json : nodes) {
89 std::shared_ptr<Node> node = nodeMap[json["node"].get<std::string>()](json);
90 addNode(node);
91 }
92 }
93 catch (const std::exception& e) {
94 using namespace std::string_literals;
95 console.warn("Scene Loading Failed - "s + e.what());
96 }
97 });
98}
99
104 Vector2f size = mainApp->getWindow().getFramebufferSize().cast<float>();
105 viewport = {size.x * 1080.0f / size.y, 1080.0f};
106
109 worldToScreen.translate(Vector2f(1920.0f, 1080.0f) / -2.0f);
110 sceneBounds = Rect{{(1920.0f - viewport.x) / 2.0f, 1080.0f}, {(1920.0f + viewport.x) / 2.0f, 0.0f}};
111}
112
118
119 // Return if no nodes need to be added
120 if (nodesToAdd.empty() && nodesToRemove.empty()) return;
121
122 // Add all the nodes till there's none left to add
123 while (!nodesToAdd.empty()) {
124 // Get the node and add it to the main list
125 std::shared_ptr<Node> node = nodesToAdd.front();
126 nodesToAdd.pop();
127 nodes.push_back(node);
128
129 // Find the thread with the current smallest total update time
130 size_t threadIndex = std::distance(threadedNodePerformanceTimes.begin(),
131 std::min_element(threadedNodePerformanceTimes.begin(), threadedNodePerformanceTimes.end(),
132 [](const std::pair<float, float>& a, const std::pair<float, float>& b) -> bool {
133 return a.first > b.first;
134 }
135 )
136 );
137
138 // Add the node to the thread with the smallest update time and add it to the thread's total time
139 threadedNodePerformanceTimes[threadIndex].first += node->updateTime;
140 updateNodes[threadIndex].push_back(node);
141
142 // Find the thread with the current smallest total pre update time
143 threadIndex = std::distance(threadedNodePerformanceTimes.begin(),
144 std::min_element(threadedNodePerformanceTimes.begin(), threadedNodePerformanceTimes.end(),
145 [](const std::pair<float, float>& a, const std::pair<float, float>& b) -> bool {
146 return a.second > b.second;
147 }
148 )
149 );
150
151 // Add the node to the thread with the smallest pre update time and add it to the thread's total time
152 threadedNodePerformanceTimes[threadIndex].second += node->preUpdateTime;
153 preUpdateNodes[threadIndex].push_back(node);
154
155 node->begin(*this);
156 }
157
158 while (!nodesToRemove.empty()) {
159 // Get the node and remove it from the main list
160 std::shared_ptr<Node> node = nodesToRemove.front();
161 nodesToRemove.pop();
162 nodes.remove(node);
163
164 bool updateFound = false;
165 bool preUpdateFound = false;
166
167 // Loop through the threads till we find the thread holding the update
168 for (size_t threadIndex = 0; threadIndex < updateNodes.size(); threadIndex++) {
169
170 if (updateFound && preUpdateFound) break;
171
172 if (!updateFound) {
173 // Check if the node is updated in this thread
174 auto it = std::find(updateNodes[threadIndex].begin(), updateNodes[threadIndex].end(), node);
175 if (it != updateNodes[threadIndex].end()) {
176 // Remove the node from updates & update the performance times
177 threadedNodePerformanceTimes[threadIndex].first -= node->updateTime;
178 updateNodes[threadIndex].erase(it);
179 updateFound = true;
180 }
181 }
182
183 if (!preUpdateFound) {
184 // Check if the node is pre updated in this thread
185 auto it = std::find(preUpdateNodes[threadIndex].begin(), preUpdateNodes[threadIndex].end(), node);
186 if (it != preUpdateNodes[threadIndex].end()) {
187 // Remove the node from updates & update the performance times
188 threadedNodePerformanceTimes[threadIndex].second -= node->preUpdateTime;
189 preUpdateNodes[threadIndex].erase(it);
190 preUpdateFound = true;
191 }
192 }
193 }
194
195 node->end(*this);
196 }
197}
198
203void Scene::render(float deltaTime) const {
204
205#ifdef KALE_OPENGL
207#endif
208
209 Transform cameraToScreen(worldToScreen * camera);
210 for (const std::shared_ptr<Node>& node : nodes)
211 node->render(cameraToScreen, deltaTime);
212
213 // Swaps the buffers/uses the swapchain to display output
214#ifdef KALE_OPENGL
216#endif
217
218#ifdef KALE_VULKAN
219 // Vulkan::Core::swapBuffers();
220#endif
221}
222
228void Scene::update(size_t threadNum, float deltaTime) {
229
230 // Pre updating
231 onPreUpdate(threadNum, deltaTime);
232 for (std::shared_ptr<Node>& node : preUpdateNodes[threadNum]) node->preUpdate(threadNum, *this, deltaTime);
233
234 // mark pre updating as done & notify other threads if necessary
235 {
236 std::unique_lock lock(nodePreUpdateMutex);
238 size_t localGeneration = generation;
239 if (nodesPreUpdated == 0) {
240 generation++;
242 nodePreUpdateCondVar.notify_all();
243 }
244 else {
245 nodePreUpdateCondVar.wait(lock, [&]() -> bool { return localGeneration != generation; });
246 }
247 }
248
249 // notify other threads if applicable
251
252 // Updating
253 onUpdate(threadNum, deltaTime);
254 for (std::shared_ptr<Node>& node : updateNodes[threadNum]) node->update(threadNum, *this, deltaTime);
255}
256
264void Scene::onUpdate(size_t threadNum, float deltaTime) {
265 // Empty Body
266}
267
275void Scene::onPreUpdate(size_t threadNum, float deltaTime) {
276 // Empty Body
277}
278
283 mainApp->getWindow().registerEvents(dynamic_cast<EventHandler*>(this));
284}
285
290 mainApp->getWindow().removeEvents(dynamic_cast<EventHandler*>(this));
291}
292
297const std::list<std::shared_ptr<Node>>& Scene::getNodes() const {
298 return nodes;
299}
300
306 return bgColor;
307}
308
313const Camera& Scene::getCamera() const {
314 return camera;
315}
316
322 return viewport;
323}
324
331 return sceneBounds;
332}
std::string getAssetFolderPath() const
void runTaskOnMainThread(std::function< void()> task)
size_t getNumUpdateThreads() const noexcept
Window & getWindow() noexcept
void warn(T msg)
Definition Logger.hpp:182
T & get(size_t i)
Definition Matrix.hpp:170
static void clearScreen(const Vector4f &color) noexcept
Definition Core.cpp:111
static void swapBuffers() noexcept
Definition Core.cpp:119
Rect sceneBounds
Definition Scene.hpp:162
virtual void onPresent()
Definition Scene.cpp:282
void update(size_t threadNum, float deltaTime)
Definition Scene.cpp:228
std::mutex nodePreUpdateMutex
Definition Scene.hpp:93
void updateNodeStructures()
Definition Scene.cpp:117
std::list< std::shared_ptr< Node > > nodes
Definition Scene.hpp:58
virtual void onSceneChange()
Definition Scene.cpp:289
std::condition_variable nodePreUpdateCondVar
Definition Scene.hpp:98
std::queue< std::shared_ptr< Node > > nodesToRemove
Definition Scene.hpp:83
Vector4f bgColor
Definition Scene.hpp:143
const std::list< std::shared_ptr< Node > > & getNodes() const
Definition Scene.cpp:297
void addNode(std::shared_ptr< T > &node)
Definition Scene.hpp:168
Color getBgColor() const
Definition Scene.cpp:305
void render(float deltaTime) const
Definition Scene.cpp:203
Transform worldToScreen
Definition Scene.hpp:114
size_t generation
Definition Scene.hpp:108
Rect getSceneBounds() const
Definition Scene.cpp:330
std::queue< std::shared_ptr< Node > > nodesToAdd
Definition Scene.hpp:78
Camera camera
Definition Scene.hpp:148
void onWindowResize(Vector2ui oldSize, Vector2ui newSize) override
Definition Scene.cpp:103
virtual void onPreUpdate(size_t threadNum, float deltaTime)
Definition Scene.cpp:275
static std::unordered_map< std::string, std::function< std::shared_ptr< Node >(JSON)> > nodeMap
Definition Scene.hpp:53
virtual void onUpdate(size_t threadNum, float deltaTime)
Definition Scene.cpp:264
std::vector< std::list< std::shared_ptr< Node > > > updateNodes
Definition Scene.hpp:63
std::vector< std::pair< float, float > > threadedNodePerformanceTimes
Definition Scene.hpp:73
Vector2f getViewport() const
Definition Scene.cpp:321
size_t nodesPreUpdated
Definition Scene.hpp:103
std::vector< std::list< std::shared_ptr< Node > > > preUpdateNodes
Definition Scene.hpp:68
const Camera & getCamera() const
Definition Scene.cpp:313
Vector2f viewport
Definition Scene.hpp:156
void scale(const Vector2f &vec)
void translate(const Vector2f &vec)
Vector2< A > cast() const
Definition Vector.hpp:144
void removeEvents(EventHandler *handler)
Definition Window.cpp:31
Vector2ui getFramebufferSize() const
void registerEvents(EventHandler *handler)
Definition Window.cpp:24
nlohmann::json JSON
Definition Scene.hpp:39
Application * mainApp
Logger console
Definition Logger.hpp:317
Vector2< float > Vector2f
Definition Vector.hpp:598