Aeon Engine c550894
AeonGames Open Source Game Engine
Loading...
Searching...
No Matches
Scene.cpp
1/*
2Copyright (C) 2014-2019,2021,2025,2026 Rodrigo Jose Hernandez Cordoba
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16#include "aeongames/AeonEngine.hpp"
17#include "aeongames/Scene.hpp"
18#include "aeongames/Node.hpp"
20#include "aeongames/Renderer.hpp"
21#include "aeongames/ProtoBufHelpers.hpp"
22#include <cstring>
23#include <cassert>
24#include <algorithm>
25#include <sstream>
26#include <variant>
27
29#ifdef _MSC_VER
30#pragma warning( push )
31#pragma warning( disable : PROTOBUF_WARNINGS )
32#endif
33#include <google/protobuf/text_format.h>
34#include "scene.pb.h"
35#ifdef _MSC_VER
36#pragma warning( pop )
37#endif
38
39#include "aeongames/Resource.hpp"
40
41namespace AeonGames
42{
47 mName{ "Scene" },
48 mNodes{}
49 {
50 }
51
53 {
54 for ( auto & mRootNode : mNodes )
55 {
56 Remove ( mRootNode.get() );
57 }
58 }
59
60 void Scene::Load ( const std::string& aFilename )
61 {
62 Load ( crc32i ( aFilename.c_str(), aFilename.size() ) );
63 }
64 void Scene::Load ( uint32_t aId )
65 {
66 std::vector<uint8_t> buffer ( GetResourceSize ( aId ), 0 );
67 LoadResource ( aId, buffer.data(), buffer.size() );
68 try
69 {
70 Load ( buffer.data(), buffer.size() );
71 }
72 catch ( ... )
73 {
74 throw;
75 }
76 }
77 void Scene::Load ( const void* aBuffer, size_t aBufferSize )
78 {
79 Deserialize ( {reinterpret_cast<const char*> ( aBuffer ), aBufferSize} );
80 }
81
82 void Scene::SetName ( const char* aName )
83 {
84 mName = aName;
85 }
86
87 const char* const Scene::GetName() const
88 {
89 return mName.c_str();
90 }
91
92 void Scene::SetCamera ( Node* aNode )
93 {
94 mCamera = aNode;
95 }
96
97 void Scene::SetCamera ( uint32_t aNodeId )
98 {
99 SetCamera ( Find ( [aNodeId] ( const Node & aNode ) -> bool { return aNode.GetId() == aNodeId; } ) );
100 }
101
102 void Scene::SetCamera ( const std::string& aNodeName )
103 {
104 SetCamera ( crc32i ( aNodeName.c_str(), aNodeName.size() ) );
105 }
106
107 const Node* Scene::GetCamera() const
108 {
109 return mCamera;
110 }
111
112 void Scene::SetFieldOfView ( float aFieldOfView )
113 {
114 mFieldOfView = aFieldOfView;
115 }
116
117 void Scene::SetNear ( float aNear )
118 {
119 mNear = aNear;
120 }
121
122 void Scene::SetFar ( float aFar )
123 {
124 mFar = aFar;
125 }
126
128 {
129 return mFieldOfView;
130 }
131 float Scene::GetNear() const
132 {
133 return mNear;
134 }
135 float Scene::GetFar() const
136 {
137 return mFar;
138 }
139
140 void Scene::SetViewMatrix ( const Matrix4x4& aMatrix )
141 {
142 mViewMatrix = aMatrix;
143 }
144
146 {
147 return mViewMatrix;
148 }
149
151 {
152 return mNodes.size();
153 }
154
155 Node* Scene::GetChild ( size_t aIndex ) const
156 {
157 return mNodes.at ( aIndex ).get();
158 }
159
160 size_t Scene::GetChildIndex ( const Node* aNode ) const
161 {
162 auto index = std::find_if ( mNodes.begin(), mNodes.end(),
163 [aNode] ( const std::unique_ptr<Node>& node )
164 {
165 return node.get() == aNode;
166 } );
167 if ( index != mNodes.end() )
168 {
169 return index - mNodes.begin();
170 }
171 throw std::runtime_error ( "Node is not a child of this object." );
172 }
173
174 const Node& Scene::operator[] ( const std::size_t index ) const
175 {
176 return * ( mNodes[index] );
177 }
178
179 Node& Scene::operator[] ( const std::size_t index )
180 {
181 return const_cast<Node&> ( static_cast<const Scene&> ( *this ) [index] );
182 }
183
184 void Scene::Update ( const double delta )
185 {
186 LoopTraverseDFSPreOrder ( [delta] ( Node & aNode )
187 {
188 aNode.Update ( delta );
189 } );
190 }
191
192 void Scene::BroadcastMessage ( uint32_t aMessageType, const void* aMessageData )
193 {
194 for ( auto & mRootNode : mNodes )
195 {
196 mRootNode->LoopTraverseDFSPreOrder ( [aMessageType, aMessageData] ( Node & node )
197 {
198 if ( node.mFlags[Node::Enabled] )
199 {
200 node.ProcessMessage ( aMessageType, aMessageData );
201 }
202 } );
203 }
204 }
205
206 void Scene::LoopTraverseDFSPreOrder ( const std::function<void ( Node& ) >& aAction )
207 {
208 for ( auto & mRootNode : mNodes )
209 {
210 mRootNode->LoopTraverseDFSPreOrder ( aAction );
211 }
212 }
213
215 const std::function<void ( Node& ) >& aPreamble,
216 const std::function<void ( Node& ) >& aPostamble )
217 {
218 for ( auto & mRootNode : mNodes )
219 {
220 mRootNode->LoopTraverseDFSPreOrder ( aPreamble, aPostamble );
221 }
222 }
223
224 void Scene::LoopTraverseDFSPreOrder ( const std::function<void ( const Node& ) >& aAction ) const
225 {
226 for ( const auto& mRootNode : mNodes )
227 {
228 static_cast<const Node*> ( mRootNode.get() )->LoopTraverseDFSPreOrder ( aAction );
229 }
230 }
231
232 void Scene::LoopTraverseDFSPostOrder ( const std::function<void ( Node& ) >& aAction )
233 {
234 for ( auto & mRootNode : mNodes )
235 {
236 mRootNode->LoopTraverseDFSPostOrder ( aAction );
237 }
238 }
239
240 void Scene::LoopTraverseDFSPostOrder ( const std::function<void ( const Node& ) >& aAction ) const
241 {
242 for ( const auto& mRootNode : mNodes )
243 {
244 static_cast<const Node*> ( mRootNode.get() )->LoopTraverseDFSPostOrder ( aAction );
245 }
246 }
247
248 Node* Scene::Find ( const std::function<bool ( const Node& ) >& aUnaryPredicate ) const
249 {
250 for ( const auto& mRootNode : mNodes )
251 {
252 if ( Node * node = static_cast<Node * > ( mRootNode.get() )->Find ( aUnaryPredicate ) )
253 {
254 return node;
255 }
256 }
257 return nullptr;
258 }
259
260 void Scene::RecursiveTraverseDFSPreOrder ( const std::function<void ( Node& ) >& aAction )
261 {
262 for ( auto & mRootNode : mNodes )
263 {
264 mRootNode->RecursiveTraverseDFSPreOrder ( aAction );
265 }
266 }
267
268 void Scene::RecursiveTraverseDFSPostOrder ( const std::function<void ( Node& ) >& aAction )
269 {
270 for ( auto & mRootNode : mNodes )
271 {
272 mRootNode->RecursiveTraverseDFSPostOrder ( aAction );
273 }
274 }
275
276 Node* Scene::Insert ( size_t aIndex, std::unique_ptr<Node> aNode )
277 {
278 // Never append null pointers.
279 if ( aNode == nullptr )
280 {
281 return nullptr;
282 }
283 std::visit ( [&aNode] ( auto&& parent )
284 {
285 if ( parent != nullptr )
286 {
287 if ( !parent->Remove ( aNode.get() ) )
288 {
289 std::cout << LogLevel::Warning << "Parent for node " << aNode->GetName() << " did not have it as a child.";
290 }
291 }
292 },
293 aNode->mParent );
294 aNode->mParent = this;
295 std::vector<std::unique_ptr<Node >>::iterator inserted_node;
296 if ( aIndex < mNodes.size() )
297 {
298 inserted_node = mNodes.insert ( mNodes.begin() + aIndex, std::move ( aNode ) );
299 }
300 else
301 {
302 inserted_node = mNodes.insert ( mNodes.end(), std::move ( aNode ) );
303 }
304 // Force a recalculation of the LOCAL transform
305 // by setting the GLOBAL transform to itself.
306 ( *inserted_node )->SetGlobalTransform ( ( *inserted_node )->mGlobalTransform );
307 return ( *inserted_node ).get();
308 }
309
310 Node* Scene::Add ( std::unique_ptr<Node> aNode )
311 {
312 // Never append null pointers.
313 if ( aNode == nullptr )
314 {
315 return nullptr;
316 }
317 std::visit ( [&aNode] ( auto&& parent )
318 {
319 if ( parent != nullptr )
320 {
321 if ( !parent->Remove ( aNode.get() ) )
322 {
323 std::cout << LogLevel::Warning << "Parent for node " << aNode->GetName() << " did not have it as a child.";
324 }
325 }
326 },
327 aNode->mParent );
328 aNode->mParent = this;
329 mNodes.emplace_back ( std::move ( aNode ) );
330 // Force a recalculation of the LOCAL transform
331 // by setting the GLOBAL transform to itself.
332 mNodes.back()->SetGlobalTransform ( mNodes.back()->mGlobalTransform );
333 return mNodes.back().get();
334 }
335
336 std::unique_ptr<Node> Scene::Remove ( Node* aNode )
337 {
338 if ( aNode == nullptr )
339 {
340 return nullptr;
341 }
342 // If passed a null or this pointer find SHOULD not find it on release builds.
343 auto it = std::find_if ( mNodes.begin(), mNodes.end(),
344 [aNode] ( const std::unique_ptr<Node>& node )
345 {
346 return aNode == node.get();
347 } );
348 if ( it != mNodes.end() )
349 {
350 // Force recalculation of transforms.
351 aNode->mParent = static_cast<Node*> ( nullptr );
352 aNode->SetLocalTransform ( aNode->mGlobalTransform );
353 std::unique_ptr<Node> removed_node{std::move ( * ( it ) ) };
354 mNodes.erase ( it );
355 return removed_node;
356 }
357 return nullptr;
358 }
359
360 std::unique_ptr<Node> Scene::RemoveByIndex ( size_t aIndex )
361 {
362 if ( aIndex >= mNodes.size() )
363 {
364 return nullptr;
365 }
366 mNodes[aIndex]->mParent = static_cast<Node*> ( nullptr );
367 mNodes[aIndex]->SetLocalTransform ( mNodes[aIndex]->mGlobalTransform );
368 auto it = mNodes.begin() + aIndex;
369 std::unique_ptr<Node> removed_node{std::move ( * ( it ) ) };
370 mNodes.erase ( it );
371 return removed_node;
372 }
373
374 std::string Scene::Serialize ( bool aAsBinary ) const
375 {
376 static SceneMsg scene_buffer;
377 *scene_buffer.mutable_name() = mName;
378 if ( mCamera )
379 {
380 *scene_buffer.mutable_camera()->mutable_node() = mCamera->GetName();
381 scene_buffer.mutable_camera()->set_field_of_view ( mFieldOfView );
382 scene_buffer.mutable_camera()->set_near_plane ( mNear );
383 scene_buffer.mutable_camera()->set_far_plane ( mFar );
384 }
385 std::unordered_map<const Node*, NodeMsg*> node_map;
387 [&node_map] ( const Node & node )
388 {
389 NodeMsg* node_buffer;
390 auto parent = node_map.find ( GetNodePtr ( node.GetParent() ) );
391 if ( parent != node_map.end() )
392 {
393 node_buffer = ( *parent ).second->add_node();
394 }
395 else
396 {
397 node_buffer = scene_buffer.add_node();
398 }
399 node.Serialize ( *node_buffer );
400 node_map.emplace ( std::make_pair ( &node, node_buffer ) );
401 } );
402 std::stringstream serialization;
403 if ( aAsBinary )
404 {
405 serialization << "AEONSCE" << '\0';
406 if ( !scene_buffer.SerializeToOstream ( &serialization ) )
407 {
408 std::cerr << LogLevel::Error << "Failed to serialize scene to binary format.";
409 throw std::runtime_error ( "Failed to serialize scene to binary format." );
410 }
411 }
412 else
413 {
414 std::string text;
415 serialization << "AEONSCE\n";
416 google::protobuf::TextFormat::Printer printer;
417 if ( !printer.PrintToString ( scene_buffer, &text ) )
418 {
419 std::cerr << LogLevel::Error << "Failed to serialize scene to text format.";
420 throw std::runtime_error ( "Failed to serialize scene to text format." );
421 }
422 serialization << text;
423 }
424 scene_buffer.Clear();
425 return serialization.str();
426 }
427 void Scene::Deserialize ( const std::string& aSerializedScene )
428 {
429 static std::mutex m{};
430 static SceneMsg scene_buffer{};
431 std::lock_guard<std::mutex> hold ( m );
432 LoadProtoBufObject ( scene_buffer, aSerializedScene.data(), aSerializedScene.size(), "AEONSCE"_mgk );
433 mName = scene_buffer.name();
434
435 std::unordered_map<const NodeMsg*, std::tuple<const NodeMsg*, int, Node* >> node_map;
436 for ( auto &i : scene_buffer.node() )
437 {
438 const NodeMsg* node = &i;
439 node_map[node] = std::tuple<const NodeMsg*, int, Node*> {nullptr, 0, Add ( std::make_unique<Node>() ) };
440 std::get<2> ( node_map[node] )->Deserialize ( *node );
441 while ( node )
442 {
443 if ( std::get<1> ( node_map[node] ) < node->node().size() )
444 {
445 const NodeMsg* prev = node;
446 node = &node->node ( std::get<1> ( node_map[node] ) );
447 node_map[node] = std::tuple<const NodeMsg*, int, Node*> {prev, 0, std::get<2> ( node_map[prev] )->Add ( std::make_unique<Node>() ) };
448 std::get<2> ( node_map[node] )->Deserialize ( *node );
449 ++std::get<1> ( node_map[prev] );
450 }
451 else
452 {
453 std::get<1> ( node_map[node] ) = 0;
454 node = std::get<0> ( node_map[node] );
455 }
456 }
457 }
458 SetCamera ( scene_buffer.camera().node() );
459 mFieldOfView = scene_buffer.camera().field_of_view();
460 mFieldOfView = ( mFieldOfView == 0.0f ) ? 60.0f : mFieldOfView;
461 mNear = scene_buffer.camera().near_plane();
462 mNear = ( mNear == 0.0f ) ? 1.0f : mNear;
463 mFar = scene_buffer.camera().far_plane();
464 mFar = ( mFar == 0.0f ) ? 1600.0f : mFar;
465 if ( mCamera )
466 {
467 mViewMatrix = mCamera->GetGlobalTransform().GetInvertedMatrix();
468 }
469 scene_buffer.Clear();
470 }
471}
Defines log severity levels and stream output for the AeonGames engine.
#define LoopTraverseDFSPreOrder(...)
Macro generating LoopTraverseDFSPreOrder implementations for const and non-const variants.
Definition Node.cpp:425
Provides the DLL_PROTOBUF export/import macro for protobuf wrapper classes.
Header for the Scene class.
4 by 4 matrix in colum mayor order.
Definition Matrix4x4.hpp:35
DLL void SetLocalTransform(const Transform &aTransform)
Set the local transform relative to the parent.
Definition Node.cpp:137
DLL uint32_t GetId() const
Get the unique identifier of this node.
Definition Node.cpp:210
DLL void Serialize(NodeMsg &aNodeMsg) const
Serialize this node's state into a protobuf message.
Definition Node.cpp:218
DLL void ProcessMessage(uint32_t aMessageType, const void *aMessageData)
Deliver a message to this node and its components.
Definition Node.cpp:573
DLL NodeParent GetParent() const
Get this node's parent.
Definition Node.cpp:73
DLL void Update(const double delta)
Update this node and its children.
Definition Node.cpp:565
DLL void BroadcastMessage(uint32_t aMessageType, const void *aMessageData)
Broadcast a message to all nodes in the scene.
Definition Scene.cpp:192
DLL void Deserialize(const std::string &aSerializedScene)
Deserialize a scene from a string.
Definition Scene.cpp:427
DLL const Node * GetCamera() const
Get the current camera node.
Definition Scene.cpp:107
DLL void RecursiveTraverseDFSPostOrder(const std::function< void(Node &) > &aAction)
Recursive depth-first post-order traversal of all nodes in the scene.
Definition Scene.cpp:268
DLL float GetNear() const
Get the near clipping plane distance.
Definition Scene.cpp:131
DLL void SetNear(float aNear)
Set the near clipping plane distance.
Definition Scene.cpp:117
DLL std::unique_ptr< Node > RemoveByIndex(size_t aIndex)
Remove a top-level node by index.
Definition Scene.cpp:360
DLL void RecursiveTraverseDFSPreOrder(const std::function< void(Node &) > &aAction)
Recursive depth-first pre-order traversal of all nodes in the scene.
Definition Scene.cpp:260
DLL void LoopTraverseDFSPostOrder(const std::function< void(Node &) > &aAction)
Iterative depth-first post-order traversal of all nodes in the scene.
Definition Scene.cpp:232
DLL ~Scene()
Destructor.
Definition Scene.cpp:52
DLL void LoopTraverseDFSPreOrder(const std::function< void(Node &) > &aAction)
Iterative depth-first pre-order traversal of all nodes in the scene.
Definition Scene.cpp:206
DLL void SetFieldOfView(float aFieldOfView)
Set the vertical field of view.
Definition Scene.cpp:112
DLL float GetFar() const
Get the far clipping plane distance.
Definition Scene.cpp:135
DLL void SetCamera(Node *aNode)
Set rendering camera.
Definition Scene.cpp:92
DLL void SetName(const char *aName)
Set the scene name.
Definition Scene.cpp:82
DLL Node * Insert(size_t aIndex, std::unique_ptr< Node > aNode)
Insert a top-level node at a specific index.
Definition Scene.cpp:276
DLL void SetFar(float aFar)
Set the far clipping plane distance.
Definition Scene.cpp:122
DLL const char *const GetName() const
Get the scene name.
Definition Scene.cpp:87
DLL void Load(uint32_t aId)
Load a scene from a resource identified by id.
Definition Scene.cpp:64
DLL float GetFieldOfView() const
Get the vertical field of view.
Definition Scene.cpp:127
DLL Scene()
Construct an empty scene.
Definition Scene.cpp:46
DLL size_t GetChildIndex(const Node *aNode) const
Get the index of a top-level child node.
Definition Scene.cpp:160
DLL std::string Serialize(bool aAsBinary=true) const
Serialize the scene to a string.
Definition Scene.cpp:374
DLL const Node & operator[](const std::size_t index) const
Access a top-level child node by index (const).
Definition Scene.cpp:174
DLL size_t GetChildrenCount() const
Get the number of top-level child nodes.
Definition Scene.cpp:150
DLL Node * Add(std::unique_ptr< Node > aNode)
Add a top-level node to the scene.
Definition Scene.cpp:310
DLL const Matrix4x4 & GetViewMatrix() const
Get the current view matrix.
Definition Scene.cpp:145
DLL void Update(const double delta)
Update all nodes in the scene.
Definition Scene.cpp:184
DLL void SetViewMatrix(const Matrix4x4 &aMatrix)
Set the view matrix directly.
Definition Scene.cpp:140
DLL Node * Find(const std::function< bool(const Node &) > &aUnaryPredicate) const
Find the first node matching a predicate via depth-first search.
Definition Scene.cpp:248
DLL Node * GetChild(size_t aIndex) const
Get a top-level child node by index.
Definition Scene.cpp:155
DLL std::unique_ptr< Node > Remove(Node *aNode)
Remove a top-level node by pointer.
Definition Scene.cpp:336
<- This is here just for the literals
Definition AABB.hpp:31
DLL size_t GetResourceSize(uint32_t crc)
Node * GetNodePtr(const NodeParent &aNodeParent)
Extract the Node pointer from a NodeParent variant.
Definition Node.hpp:41
uint32_t crc32i(const char *message, size_t size, uint32_t previous_crc)
Compute the CRC32 of a given message, continuing from a previous CRC value.
Definition CRC.cpp:27
DLL void LoadResource(uint32_t crc, void *buffer, size_t buffer_size)
@ Warning
Potential issues that may need attention.
Definition LogLevel.hpp:32
@ Error
Error conditions.
Definition LogLevel.hpp:33
void LoadProtoBufObject(T &t, const void *aData, size_t aSize, uint64_t aMagick)
Loads a Protocol Buffer Object from a meory buffer into the provided reference.