LearnOpenGL

Translation in progress of learnopengl.com.
git clone https://git.mtkn.jp/LearnOpenGL
Log | Files | Refs

Scene-Graph.html (29501B)


      1 <!DOCTYPE html>
      2 <html lang="ja"> 
      3 <head>
      4     <meta charset="utf-8"/>
      5     <title>LearnOpenGL</title>
      6     <link rel="shortcut icon" type="image/ico" href="/favicon.ico"  />
      7 	<link rel="stylesheet" href="../static/style.css" />
      8 	<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"> </script>
      9 	<script src="/static/functions.js"></script>
     10 </head>
     11 <body>
     12 	<nav>
     13 <ol>
     14 	<li id="Introduction">
     15 		<a href="https://learnopengl.com/Introduction">はじめに</a>
     16 	</li>
     17 	<li id="Getting-started">
     18 		<span class="closed">入門</span>
     19 		<ol>
     20 			<li id="Getting-started/OpenGL">
     21 				<a href="https://learnopengl.com/Getting-started/OpenGL">OpenGL </a>
     22 			</li>
     23 			<li id="Getting-started/Creating-a-window">
     24 				<a href="https://learnopengl.com/Getting-started/Creating-a-window">ウィンドウの作成</a>
     25 			</li>
     26 			<li id="Getting-started/Hello-Window">
     27 				<a href="https://learnopengl.com/Getting-started/Hello-Window">最初のウィンドウ</a>
     28 			</li>
     29 			<li id="Getting-started/Hello-Triangle">
     30 				<a href="https://learnopengl.com/Getting-started/Hello-Triangle">最初の三角形</a>
     31 			</li>
     32 			<li id="Getting-started/Shaders">
     33 				<a href="https://learnopengl.com/Getting-started/Shaders">シェーダー</a>
     34 			</li>
     35 			<li id="Getting-started/Textures">
     36 				<a href="https://learnopengl.com/Getting-started/Textures">テクスチャ</a>
     37 			</li>
     38 			<li id="Getting-started/Transformations">
     39 				<a href="https://learnopengl.com/Getting-started/Transformations">座標変換</a>
     40 			</li>
     41 			<li id="Getting-started/Coordinate-Systems">
     42 				<a href="https://learnopengl.com/Getting-started/Coordinate-Systems">座標系</a>
     43 			</li>
     44 			<li id="Getting-started/Camera">
     45 				<a href="https://learnopengl.com/Getting-started/Camera">カメラ</a>
     46 			</li>
     47 			<li id="Getting-started/Review">
     48 				<a href="https://learnopengl.com/Getting-started/Review">まとめ</a>
     49 			</li>
     50 		</ol>
     51 	</li>
     52 	<li id="Lighting">
     53 		<span class="closed">Lighting </span>
     54 		<ol>
     55 			<li id="Lighting/Colors">
     56 				<a href="https://learnopengl.com/Lighting/Colors">Colors </a>
     57 			</li>
     58 			<li id="Lighting/Basic-Lighting">
     59 				<a href="https://learnopengl.com/Lighting/Basic-Lighting">Basic Lighting </a>
     60 			</li>
     61 			<li id="Lighting/Materials">
     62 				<a href="https://learnopengl.com/Lighting/Materials">Materials </a>
     63 			</li>
     64 			<li id="Lighting/Lighting-maps">
     65 				<a href="https://learnopengl.com/Lighting/Lighting-maps">Lighting maps </a>
     66 			</li>
     67 			<li id="Lighting/Light-casters">
     68 				<a href="https://learnopengl.com/Lighting/Light-casters">Light casters </a>
     69 			</li>
     70 			<li id="Lighting/Multiple-lights">
     71 				<a href="https://learnopengl.com/Lighting/Multiple-lights">Multiple lights </a>
     72 			</li>
     73 			<li id="Lighting/Review">
     74 				<a href="https://learnopengl.com/Lighting/Review">Review </a>
     75 			</li>
     76 		</ol>
     77 	</li>
     78 	<li id="Model-Loading">
     79 		<span class="closed">Model Loading </span>
     80 		<ol>
     81 			<li id="Model-Loading/Assimp">
     82 				<a href="https://learnopengl.com/Model-Loading/Assimp">Assimp </a>
     83 			</li>
     84 			<li id="Model-Loading/Mesh">
     85 				<a href="https://learnopengl.com/Model-Loading/Mesh">Mesh </a>
     86 			</li>
     87 			<li id="Model-Loading/Model">
     88 				<a href="https://learnopengl.com/Model-Loading/Model">Model </a>
     89 			</li>
     90 		</ol>
     91 	</li>
     92 	<li id="Advanced-OpenGL">
     93 		<span class="closed">Advanced OpenGL </span>
     94 		<ol>
     95 			<li id="Advanced-OpenGL/Depth-testing">
     96 				<a href="https://learnopengl.com/Advanced-OpenGL/Depth-testing">Depth testing </a>
     97 			</li>
     98 			<li id="Advanced-OpenGL/Stencil-testing">
     99 				<a href="https://learnopengl.com/Advanced-OpenGL/Stencil-testing">Stencil testing </a>
    100 			</li>
    101 			<li id="Advanced-OpenGL/Blending">
    102 				<a href="https://learnopengl.com/Advanced-OpenGL/Blending">Blending </a>
    103 			</li>
    104 			<li id="Advanced-OpenGL/Face-culling">
    105 				<a href="https://learnopengl.cm/Advanced-OpenGL/Face-culling">Face culling </a>
    106 			</li>
    107 			<li id="Advanced-OpenGL/Framebuffers">
    108 				<a href="https://learnopengl.com/Advanced-OpenGL/Framebuffers">Framebuffers </a>
    109 			</li>
    110 			<li id="Advanced-OpenGL/Cubemaps">
    111 				<a href="https://learnopengl.com/Advanced-OpenGL/Cubemaps">Cubemaps </a>
    112 			</li>
    113 			<li id="Advanced-OpenGL/Advanced-Data">
    114 				<a href="https://learnopengl.com/Advanced-OpenGL/Advanced-Data">Advanced Data </a>
    115 			</li>
    116 			<li id="Advanced-OpenGL/Advanced-GLSL">
    117 				<a href="https://learnopengl.com/Advanced-OpenGL/Advanced-GLSL">Advanced GLSL </a>
    118 			</li>
    119 			<li id="Advanced-OpenGL/Geometry-Shader">
    120 				<a href="https://learnopengl.com/Advanced-OpenGL/Geometry-Shader">Geometry Shader </a>
    121 			</li>
    122 			<li id="Advanced-OpenGL/Instancing">
    123 				<a href="https://learnopengl.com/Advanced-OpenGL/Instancing">Instancing </a>
    124 			</li>
    125 			<li id="Advanced-OpenGL/Anti-Aliasing">
    126 				<a href="https://learnopengl.com/Advanced-OpenGL/Anti-Aliasing">Anti Aliasing </a>
    127 			</li>
    128 		</ol>
    129 	</li>
    130 	<li id="Advanced-Lighting">
    131 		<span class="closed">Advanced Lighting </span>
    132 		<ol>
    133 			<li id="Advanced-Lighting/Advanced-Lighting">
    134 				<a href="https://learnopengl.com/Advanced-Lighting/Advanced-Lighting">Advanced Lighting </a>
    135 			</li>
    136 			<li id="Advanced-Lighting/Gamma-Correction">
    137 				<a href="https://learnopengl.com/Advanced-Lighting/Gamma-Correction">Gamma Correction </a>
    138 			</li>
    139 			<li id="Advanced-Lighting/Shadows">
    140 				<span class="closed">Shadows </span>
    141 				<ol>
    142 					<li id="Advanced-Lighting/Shadows/Shadow-Mapping">
    143 						<a href="https://learnopengl.com/Advanced-Lighting/Shadows/Shadow-Mapping">Shadow Mapping </a>
    144 					</li>
    145 					<li id="Advanced-Lighting/Shadows/Point-Shadows">
    146 						<a href="https://learnopengl.com/Advanced-Lighting/Shadows/Point-Shadows">Point Shadows </a>
    147 					</li>
    148 				</ol>
    149 			</li>
    150 			<li id="Advanced-Lighting/Normal-Mapping">
    151 				<a href="https://learnopengl.com/Advanced-Lighting/Normal-Mapping">Normal Mapping </a>
    152 			</li>
    153 			<li id="Advanced-Lighting/Parallax-Mapping">
    154 				<a href="https://learnopengl.com/Advanced-Lighting/Parallax-Mapping">Parallax Mapping </a>
    155 			</li>
    156 			<li id="Advanced-Lighting/HDR">
    157 				<a href="https://learnopengl.com/Advanced-Lighting/HDR">HDR </a>
    158 			</li>
    159 			<li id="Advanced-Lighting/Bloom">
    160 				<a href="https://learnopengl.com/Advanced-Lighting/Bloom">Bloom </a>
    161 			</li>
    162 			<li id="Advanced-Lighting/Deferred-Shading">
    163 				<a href="https://learnopengl.com/Advanced-Lighting/Deferred-Shading">Deferred Shading </a>
    164 			</li>
    165 			<li id="Advanced-Lighting/SSAO">
    166 				<a href="https://learnopengl.com/Advanced-Lighting/SSAO">SSAO </a>
    167 			</li>
    168 		</ol>
    169 	</li>
    170 	<li id="PBR">
    171 		<span class="closed">PBR </span>
    172 		<ol>
    173 			<li id="PBR/Theory">
    174 				<a href="https://learnopengl.com/PBR/Theory">Theory </a>
    175 			</li>
    176 			<li id="PBR/Lighting">
    177 				<a href="https://learnopengl.com/PBR/Lighting">Lighting </a>
    178 			</li>
    179 			<li id="PBR/IBL">
    180 				<span class="closed">IBL </span>
    181 				<ol>
    182 					<li id="PBR/IBL/Diffuse-irradiance">
    183 						<a href="https://learnopengl.com/PBR/IBL/Diffuse-irradiance">Diffuse irradiance </a>
    184 					</li>
    185 					<li id="PBR/IBL/Specular-IBL">
    186 						<a href="https://learnopengl.com/PBR/IBL/Specular-IBL">Specular IBL </a>
    187 					</li>
    188 				</ol>
    189 			</li>
    190 		</ol>
    191 	</li>
    192 	<li id="In-Practice">
    193 		<span class="closed">In Practice </span>
    194 		<ol>
    195 			<li id="In-Practice/Debugging">
    196 				<a href="https://learnopengl.com/In-Practice/Debugging">Debugging </a>
    197 			</li>
    198 			<li id="In-Practice/Text-Rendering">
    199 				<a href="https://learnopengl.com/In-Practice/Text-Rendering">Text Rendering </a>
    200 			</li>
    201 			<li id="In-Practice/2D-Game">
    202 				<span class="closed">2D Game </span>
    203 				<ol>
    204 					<li id="In-Practice/2D-Game/Breakout">
    205 						<a href="https://learnopengl.com/In-Practice/2D-Game/Breakout">Breakout </a>
    206 					</li>
    207 					<li id="In-Practice/2D-Game/Setting-up">
    208 						<a href="https://learnopengl.com/In-Practice/2D-Game/Setting-up">Setting up </a>
    209 					</li>
    210 					<li id="In-Practice/2D-Game/Rendering-Sprites">
    211 						<a href="https://learnopengl.com/In-Practice/2D-Game/Rendering-Sprites">Rendering Sprites </a>
    212 					</li>
    213 					<li id="In-Practice/2D-Game/Levels">
    214 						<a href="https://learnopengl.com/In-Practice/2D-Game/Levels">Levels </a>
    215 					</li>
    216 					<li id="In-Practice/2D-Game/Collisions">
    217 						<span class="closed">Collisions </span>
    218 						<ol>
    219 							<li id="In-Practice/2D-Game/Collisions/Ball">
    220 								<a href="https://learnopengl.com/In-Practice/2D-Game/Collisions/Ball">Ball </a>
    221 							</li>
    222 							<li id="In-Practice/2D-Game/Collisions/Collision-detection">
    223 								<a href="https://learnopengl.com/In-Practice/2D-Game/Collisions/Collision-detection">Collision detection </a>
    224 							</li>
    225 							<li id="In-Practice/2D-Game/Collisions/Collision-resolution">
    226 								<a href="https://learnopengl.com/In-Practice/2D-Game/Collisions/Collision-resolution">Collision resolution </a>
    227 							</li>
    228 						</ol>
    229 					</li>
    230 					<li id="In-Practice/2D-Game/Particles">
    231 						<a href="https://learnopengl.com/In-Practice/2D-Game/Particles">Particles </a>
    232 					</li>
    233 					<li id="In-Practice/2D-Game/Postprocessing">
    234 						<a href="https://learnopengl.com/In-Practice/2D-Game/Postprocessing">Postprocessing </a>
    235 					</li>
    236 					<li id="In-Practice/2D-Game/Powerups">
    237 						<a href="https://learnopengl.com/In-Practice/2D-Game/Powerups">Powerups </a>
    238 					</li>
    239 					<li id="In-Practice/2D-Game/Audio">
    240 						<a href="https://learnopengl.com/In-Practice/2D-Game/Audio">Audio </a>
    241 					</li>
    242 					<li id="In-Practice/2D-Game/Render-text">
    243 						<a href="https://learnopengl.com/In-Practice/2D-Game/Render-text">Render text </a>
    244 					</li>
    245 					<li id="In-Practice/2D-Game/Final-thoughts">
    246 						<a href="https://learnopengl.com/In-Practice/2D-Game/Final-thoughts">Final thoughts </a>
    247 					</li>
    248 				</ol>
    249 			</li>
    250 		</ol>
    251 	</li>
    252 	<li id="Guest-Articles">
    253 		<span class="closed">Guest Articles </span>
    254 		<ol>
    255 			<li id="Guest-Articles/How-to-publish">
    256 				<a href="https://learnopengl.com/Guest-Articles/How-to-publish">How to publish </a>
    257 			</li>
    258 			<li id="Guest-Articles/2020">
    259 				<span class="closed">2020 </span>
    260 				<ol>
    261 					<li id="Guest-Articles/2020/OIT">
    262 						<span class="closed">OIT </span>
    263 						<ol>
    264 							<li id="Guest-Articles/2020/OIT/Introduction">
    265 								<a href="https://learnopengl.com/Guest-Articles/2020/OIT/Introduction">Introduction </a>
    266 							</li>
    267 							<li id="Guest-Articles/2020/OIT/Weighted-Blended">
    268 								<a href="https://learnopengl.com/Guest-Articles/2020/OIT/Weighted-Blended">Weighted Blended </a>
    269 							</li>
    270 						</ol>
    271 					</li>
    272 					<li id="Guest-Articles/2020/Skeletal-Animation">
    273 						<a href="https://learnopengl.com/Guest-Articles/2020/Skeletal-Animation">Skeletal Animation </a>
    274 					</li>
    275 				</ol>
    276 			</li>
    277 			<li id="Guest-Articles/2021">
    278 				<span class="closed">2021 </span>
    279 				<ol>
    280 					<li id="Guest-Articles/2021/CSM">
    281 						<a href="https://learnopengl.com/Guest-Articles/2021/CSM">CSM </a>
    282 					</li>
    283 					<li id="Guest-Articles/2021/Scene">
    284 						<span class="closed">Scene </span>
    285 						<ol>
    286 							<li id="Guest-Articles/2021/Scene/Scene-Graph">
    287 								<a href="https://learnopengl.com/Guest-Articles/2021/Scene/Scene-Graph">Scene Graph </a>
    288 							</li>
    289 							<li id="Guest-Articles/2021/Scene/Frustum-Culling">
    290 								<a href="https://learnopengl.com/Guest-Articles/2021/Scene/Frustum-Culling">Frustum Culling </a>
    291 							</li>
    292 						</ol>
    293 					</li>
    294 					<li id="Guest-Articles/2021/Tessellation">
    295 						<span class="closed">Tessellation </span>
    296 						<ol>
    297 							<li id="Guest-Articles/2021/Tessellation/Height-map">
    298 								<a href="https://learnopengl.com/Guest-Articles/2021/Tessellation/Height-map">Height map </a>
    299 							</li>
    300 						</ol>
    301 					</li>
    302 				</ol>
    303 			</li>
    304 		</ol>
    305 	</li>
    306 	<li id="Code-repository">
    307 		<a href="https://learnopengl.com/Code-repository">Code repository </a>
    308 	</li>
    309 	<li id="Translations">
    310 		<a href="https://learnopengl.com/Translations">Translations </a>
    311 	</li>
    312 	<li id="About">
    313 		<a href="https://learnopengl.com/About">About </a>
    314 	</li>
    315 </ol>
    316 	</nav>
    317 	<main>
    318     <div id="content">
    319     <h1 id="content-title">Scene Graph</h1>
    320 <h1 id="content-url" style='display:none;'>Guest-Articles/2021/Scene/Scene-Graph</h1>
    321 <p>
    322         In this article, we will talk about the <def>scene graph</def>.
    323 		A scene graph is not a class or an object, it's more like a pattern that allows you to create inheritance.
    324 		This pattern is used a lot in game engines.
    325 		For example, it is used in animation to manage bones.
    326 		If I move my arm, my hand needs to move too.
    327 		To obtain this result, I need a hierarchy with parents and children.
    328 		Thanks to it, my hand will be a child of my arm that is also a child of my body.
    329 		This hierarchy has the consequence of representing objects in global and local space.
    330 		Global space is based on position/rotation and scale based on the world and local space is based on its parent.
    331 		So, if I only move my hand, its local and global position will change but not the local and global position of my arm.
    332 		However, if I move my arm, its local and global position will change but also the global position of my hand.
    333 		Scene graphs can take a lot of forms: register or not the parent, list or contiguous buffer to store the children, flags...
    334 		Firstly, we will see a quick example of it.
    335 		In a second time, we will see simple optimizations to improve it.
    336 		So, talk less, code more ! ;D
    337 	</p>
    338 
    339 	<div class="box">
    340       <img src="/img/guest/2021/scene_graph/graph.png" width="400" style="display: inline" alt="Graph example"/>
    341       <img src="/img/guest/2021/scene_graph/sceneGraph.png" width="400" style="display: inline" alt="Scene graph example in editor"/>
    342 	</div>
    343 
    344 	<p>
    345 		First of all, let’s create a transform.
    346 		Transform will contain local and global space information about our entities
    347 	</p>
    348 
    349 	<pre><code>
    350 struct Transform
    351 {
    352 	/*SPACE INFORMATION*/
    353 	//Local space information
    354 	glm::vec3 pos = { 0.0f, 0.0f, 0.0f };
    355 	glm::vec3 eulerRot = { 0.0f, 0.0f, 0.0f };
    356 	glm::vec3 scale = { 1.0f, 1.0f, 1.0f };
    357 
    358     //Global space information concatenate in matrix
    359 	glm::mat4 modelMatrix = glm::mat4(1.0f);
    360 };
    361 	</code></pre>
    362 
    363 	<note>
    364 		In this example, we use the Euler angle system.
    365 		The Euler system is easy to use and understand but it contains a lot of undesirable effects: <a href="https://en.wikipedia.org/wiki/Gimbal_lock" target="_blank">Gimbal lock</a>, shortest angle between to angle thanks to lerp is wrong, cost and size...
    366         To avoid it, we need to use <strong>quaternion</strong> but it needs to be hidden because it's hard to represent a rotation thanks to it.
    367 		To have a better understanding of this tutorial we will use the Euler angle but I invite you to do some research on quaternion. 
    368 	</note>
    369 
    370 	<p>
    371 		Now we can represent local and global space information about an object.
    372 		We will make create a class called <funct>Entity</funct>.
    373 		This class will simply wrap the space information with a model for the visual demonstration.
    374 	</p>
    375 
    376 	<pre><code>
    377 class Entity : public Model
    378 {
    379 public:
    380 [...]
    381 
    382 Transform transform;
    383 
    384 	// constructor, expects a filepath to a 3D model.
    385 	Entity(string const& path, bool gamma = false) : Model(path, gamma)
    386 	{}
    387 };
    388 	</code></pre>
    389 	<p>
    390 		The scene graph is still missing. So, let's add it into the Entity class.
    391 	</p>
    392 	<pre><code>
    393 /*SCENE GRAPH*/
    394 std::list<std::unique_ptr<Entity>> children;
    395 	Entity* parent = nullptr;
    396 	</code></pre>
    397 	<p>
    398 		As we said, scene graphs can take a lot of forms: use std::vector instead of std::list, don't register its parent to simplify the size of the class...
    399 		In our example we used std::list. 
    400 		We don't want our entity address to change at all.
    401 		My parents’ address always needs to be valid.
    402 		Then, I used std::unique_ptr because it's the cleanest approach to avoid a leak.
    403 		Memory leak appears happens if you allocate memory thanks to new or malloc and forget to call delete or free when datas disappears.
    404 		Information is still in memory but you cannot have access to it.
    405 		If you want more information about it, many tutorials talk about it more clearly.
    406 	</p>
    407 
    408 	<p>
    409 		<dl>
    410 			<dt>
    411 				We need now to create a function to add a child to our entity.
    412 				This function will be easy:
    413 			</dt>
    414 			<dd>
    415 				1: Add entity
    416 			</dd>
    417 			<dd>
    418 				2: Register parent of this new entity as the current entity
    419 			</dd>
    420 		  </dl> 
    421 	</p>
    422 
    423 
    424 	<pre><code>
    425 template<typename... TArgs>
    426 void addChild(const TArgs&... args)
    427 {
    428 	children.emplace_back(std::make_unique<Entity>(args...));
    429 	children.back()->parent = this;
    430 }
    431 	</code></pre>
    432 
    433 	<note>
    434         A variadic template allows us to create an entity with any constructor that you want to use without overloading the addChild function.
    435 		I used it in this example to awake your curiosity and show you a simple use of it.
    436 	</note>
    437 
    438 	<p>
    439 	Ok, perfect! It's almost done, courage!
    440 	Now we have scene graphs and space information but something is still missing.
    441 	When we want to send space information to our shader, we need a model matrix.
    442 	However, we don't see how to compute it thanks to our parents and our local information.
    443 	First, we need a function to create a local model matrix that represents an object in space based on its parent.
    444 	This function will be added to the transform class. 
    445 	</p>
    446 
    447 	<pre><code>
    448 glm::mat4 getLocalModelMatrix()
    449 {
    450 	const glm::mat4 transformX = <function id='57'>glm::rotate</function>(glm::mat4(1.0f),
    451 						 <function id='63'>glm::radians</function>(eulerRot.x),
    452 						 glm::vec3(1.0f, 0.0f, 0.0f));
    453 	const glm::mat4 transformY = <function id='57'>glm::rotate</function>(glm::mat4(1.0f),
    454 						 <function id='63'>glm::radians</function>(eulerRot.y),
    455 						 glm::vec3(0.0f, 1.0f, 0.0f));
    456 	const glm::mat4 transformZ = <function id='57'>glm::rotate</function>(glm::mat4(1.0f),
    457 						 <function id='63'>glm::radians</function>(eulerRot.z),
    458 						 glm::vec3(0.0f, 0.0f, 1.0f));
    459 
    460 	// Y * X * Z
    461 	const glm::mat4 roationMatrix = transformY * transformX * transformZ;
    462 
    463 	// translation * rotation * scale (also know as TRS matrix)
    464 	return <function id='55'>glm::translate</function>(glm::mat4(1.0f), pos) *
    465 				roationMatrix *
    466 				<function id='56'>glm::scale</function>(glm::mat4(1.0f), scale);
    467 }
    468 	</code></pre>
    469 
    470 	<p>
    471 		To combine multiple model matrices, we need to multiply them.
    472 		So if I multiply the local model matrix of my hand with the model matrix of the world with arm and arm with hand, I will obtain the global matrix of my hand!
    473 		So, let's implement a function in entity class that will do it for us: 
    474 	</p>
    475 
    476 	<pre><code>
    477 void updateSelfAndChild()
    478 {
    479 	if (parent)
    480 		modelMatrix = parent->modelMatrix * getLocalModelMatrix();
    481 	else
    482 		modelMatrix = getLocalModelMatrix();
    483 
    484 	for (auto&& child : children)
    485 	{
    486 		child->updateSelfAndChild();
    487 	}
    488 }
    489 	</code></pre>
    490 
    491 	<p>
    492 		Now, if I update the world, all of my entities contained will also be updated and our global model matrix will be computed.
    493 		Finally, we just need to add some code in the main function to add multiple moons with the same local distance and scale and code in the main loop to move the first entity.
    494 	</p>
    495 
    496 	<pre><code>
    497 /*BEFOR THE MAIN LOOP*/
    498 
    499 // load entities
    500 // -----------
    501 const char* pathStr = "resources/objects/planet/planet.obj";
    502 Entity ourEntity(FileSystem::getPath(pathStr));
    503 ourEntity.transform.pos.x = 10;
    504 const float scale = 0.75;
    505 ourEntity.transform.scale = { scale, scale, scale };
    506 
    507 {
    508 	Entity* lastEntity = &ourEntity;
    509 
    510 	for (unsigned int i = 0; i &lt; 10; ++i)
    511 	{
    512 		lastEntity->addChild(FileSystem::getPath(pathStr));
    513 		lastEntity = lastEntity->children.back().get();
    514 
    515 		//Set tranform values
    516 		lastEntity->transform.pos.x = 10;
    517 		lastEntity->transform.scale = { scale, scale, scale };
    518 	}
    519 }
    520 ourEntity.updateSelfAndChild();
    521 
    522 /*IN THE MAIN LOOP*/
    523 
    524 // draw our scene graph
    525 Entity* lastEntity = &ourEntity;
    526 while (lastEntity->children.size())
    527 {
    528 	ourShader.setMat4("model", lastEntity->transform.modelMatrix);
    529 	lastEntity->Draw(ourShader);
    530 	lastEntity = lastEntity->children.back().get();
    531 }
    532 
    533 ourEntity.transform.eulerRot.y += 20 * deltaTime;
    534 ourEntity.updateSelfAndChild();
    535 	</code></pre>
    536 	
    537 	<p>
    538 		We can see this result thanks to this code.
    539 	</p>
    540 
    541       <img src="/img/guest/2021/scene_graph/result.png" alt="Graph example"/>
    542 
    543 	<h2>Optimization</h2>
    544 
    545 	<p>
    546         Being pragmatic is essential to implement a new feature but now let's see how to optimize it.
    547         Firstly, in the main loop, we always update the model matrix even if it doesn't move.
    548 		In programming, a pattern called a dirty flag can help us.
    549         A dirty flag is a simple boolean called "isDirty" that allows us to know if an entity was moved during the previous frame.
    550         So, if the user scales, rotates or translates it, we need to set this flag on.
    551 		Don't forget, the model matrix is based on the parent model matrix.
    552 		So if I change it, I also need to compute all its children's matrix.
    553         This flag will be set off in the update function when the model matrix was recomputed.
    554 	</p>
    555 
    556 	<warning>
    557         This pattern is very powerful but can be integrated easily only if you encapsulate your class correctly.
    558 		I haven’t done it to give you an example of rigid code without the possibility to evolve and change easily.
    559 		This code requires the programmer to code its functionality perfectly and is difficult to change, improve or optimize.
    560 		But in production, time is a precious resource and you sometimes need to implement the feature without optimizing.
    561 		One day, if your feature becomes the performance bottleneck, you need to change it easily.
    562 		Encapsulation, private/protected, getter/setter is C++ advantage that allows you to do it.
    563 		Encapsulation has its downsides too.
    564 		It can increase the size of your class and reduce its visibility.
    565 		It can also be laborious if you create a getter/setter for all your members.
    566         An illarouse <a href="https://www.youtube.com/watch?v=-AQfQFcXac8" target="_blank">video</a> show the c++ limit but keep in mind this example and make do the balance in function of your situation.
    567 	</warning>
    568 
    569 	<p>
    570 		Let's remake do again transform function with encapsulation and dirty flag 
    571 	</p>
    572 
    573 	<pre><code>
    574 class Transform
    575 {
    576 protected:
    577 	//Local space information
    578 	glm::vec3 m_pos = { 0.0f, 0.0f, 0.0f };
    579 	glm::vec3 m_eulerRot = { 0.0f, 0.0f, 0.0f }; //In degrees
    580 	glm::vec3 m_scale = { 1.0f, 1.0f, 1.0f };
    581 
    582 	//Global space information concatenate in matrix
    583 	glm::mat4 m_modelMatrix = glm::mat4(1.0f);
    584 
    585 	//Dirty flag
    586 	bool m_isDirty = true;
    587 
    588 protected:
    589 	glm::mat4 getLocalModelMatrix()
    590 	{
    591 		const glm::mat4 transformX = <function id='57'>glm::rotate</function>(glm::mat4(1.0f),
    592 					<function id='63'>glm::radians</function>(m_eulerRot.x),
    593 					glm::vec3(1.0f, 0.0f, 0.0f));
    594 		const glm::mat4 transformY = <function id='57'>glm::rotate</function>(glm::mat4(1.0f),
    595 					<function id='63'>glm::radians</function>(m_eulerRot.y),
    596 					glm::vec3(0.0f, 1.0f, 0.0f));
    597 		const glm::mat4 transformZ = <function id='57'>glm::rotate</function>(glm::mat4(1.0f),
    598 					<function id='63'>glm::radians</function>(m_eulerRot.z),
    599 					glm::vec3(0.0f, 0.0f, 1.0f));
    600 
    601 		// Y * X * Z
    602 		const glm::mat4 roationMatrix = transformY * transformX * transformZ;
    603 
    604 		// translation * rotation * scale (also know as TRS matrix)
    605 		return <function id='55'>glm::translate</function>(glm::mat4(1.0f), m_pos) *
    606 					roationMatrix *
    607 					<function id='56'>glm::scale</function>(glm::mat4(1.0f), m_scale);
    608 	}
    609 public:
    610 
    611 	void computeModelMatrix()
    612 	{
    613 		m_modelMatrix = getLocalModelMatrix();
    614 	}
    615 
    616 	void computeModelMatrix(const glm::mat4& parentGlobalModelMatrix)
    617 	{
    618 		m_modelMatrix = parentGlobalModelMatrix * getLocalModelMatrix();
    619 	}
    620 
    621 	void setLocalPosition(const glm::vec3& newPosition)
    622 	{
    623 		m_pos = newPosition;
    624 		m_isDirty = true;
    625 	}
    626 
    627 	[...]
    628 
    629 	const glm::vec3& getLocalPosition()
    630 	{
    631 		return m_pos;
    632 	}
    633 
    634 	[...]
    635 
    636 	const glm::mat4& getModelMatrix()
    637 	{
    638 		return m_modelMatrix;
    639 	}
    640 
    641 	bool isDirty()
    642 	{
    643 		return m_isDirty;
    644 	}
    645 };
    646 
    647 
    648 class Entity : public Model
    649 {
    650 public:
    651 	//Scene graph
    652 	std::list<std::unique_ptr<Entity>> children;
    653 	Entity* parent = nullptr;
    654 
    655 	//Space information
    656 	Transform transform;
    657 
    658 	// constructor, expects a filepath to a 3D model.
    659 	Entity(string const& path, bool gamma = false) : Model(path, gamma)
    660 	{}
    661 
    662 	//Add child. Argument input is argument of any constructor that you create.
    663 	//By default you can use the default constructor and don't put argument input.
    664 	template<typename... TArgs>
    665 	void addChild(const TArgs&... args)
    666 	{
    667 		children.emplace_back(std::make_unique<Entity>(args...));
    668 		children.back()->parent = this;
    669 	}
    670 
    671 	//Update transform if it was changed
    672 	void updateSelfAndChild()
    673 	{
    674 		if (!transform.isDirty())
    675 			return;
    676 
    677 		forceUpdateSelfAndChild();
    678 	}
    679 
    680 	//Force update of transform even if local space don't change
    681 	void forceUpdateSelfAndChild()
    682 	{
    683 		if (parent)
    684 			transform.computeModelMatrix(parent->transform.getModelMatrix());
    685 		else
    686 			transform.computeModelMatrix();
    687 
    688 		for (auto&& child : children)
    689 		{
    690 			child->forceUpdateSelfAndChild();
    691 		}
    692 	}
    693 };
    694 	</code></pre>
    695 	
    696 	<p>
    697 	Perfect! Another solution to improve performance can be memorizing the local Model matrix.
    698 	Thanks to it, we avoid recomputing all child local model matrices if the parent is moved.
    699 	This solution improves performance but transforms become heavier.
    700 	This size is really important for your hardware.
    701 	We will see why in the limitation subchapter.
    702 	You can find the code <a href="https://learnopengl.com/code_viewer_gh.php?code=src/8.guest/2021/1.scene/1.scene_graph/scene_graph.cpp" target="_blank">here</a>.
    703 	</p>
    704 
    705 	<h2>Limitation</h2>
    706 
    707 	<p>
    708 		Do you ever hear about <def>data oriented design</def> ? No ? Let's talk brevely about it !
    709 	</p>
    710 	<p>
    711 		This design is based on how your hardware works.
    712 		In your computer, data is aligned into your memory.
    713 		When you use data like a variable, this data is sent to the cache.
    714 		The cache is a very fast memory but without a lot of space.
    715 		This memory is localized into your CPU.
    716 		For example, if you want to make a cake, you need to go to a supermarket (hard disk) to buy ingredients.
    717 		A supermarket is very big but is also very far from your home.
    718 		When you buy your ingredients, you store them in your fridge (RAM).
    719 		Your fridge contains ingredients that you need to live but I hope for you that you don't live only with cake ^^
    720 		It is also small but near to your kitchen worktop.
    721 		And finally, your kitchen worktop (the cache) is small and can't contain all your ingredients but is very near to your preparation.
    722 		It's the same for the PC!
    723 		When you need to process data, your system will copy your data but also all datas after in cache (depending on your cache line size).
    724 		So, if all your datas are not contiguous in your memory, you will be as slow as if you need to take eggs one by one in your fridge to make your cake.
    725 		std::list is a noncontiguous array.
    726 		std::map will probably make the job better but inheritance cannot be aligned into your memory because it's a tree.
    727 		So, if you want to make RTS for example, with an independent unit, you probably don't need or don't want a scene graph to manage your entities.
    728 	</p>
    729 
    730 	<note>
    731 		std::map is tree and is aligned in memory but scene graph will jump into this memory and will be slower than don't use inheritance.
    732 	</note>
    733 
    734 	<p>
    735 		You know now what a Scene graph is and how to use it with its limitations.
    736 		In the next chapter, we will talk about frustum culling with a scene graph.
    737 	</p>
    738 
    739 	<h2>Additional resources</h2>
    740 
    741 	<ul>
    742 		<li><a href="https://walterkuppens.com/post/wtf-is-a-scene-graph/" target="_blank">
    743 			walterkuppens article about scene graph</a>: An article by Walter Kuppens with another approach of the scene graph.</li>
    744 
    745 		<li><a href="https://webglfundamentals.org/webgl/lessons/webgl-scene-graph.html" target="_blank">
    746 			webglfundamentals article and demonstration about scene graph</a>: An article with animated webGL code and animated demonstration</li>			
    747     </ul>
    748 	
    749       <author>
    750 			<strong>Article by: </strong>Six Jonathan<br>
    751 			<strong>Contact: </strong><a href="Six-Jonathan@orange.fr" target="_blank">e-mail</a><br>
    752 			<strong>Date: </strong> 09/2021<br>
    753 			<div>
    754 				<a href="https://github.com/Renardjojo">
    755 					<svg height="32" aria-hidden="true" viewBox="0 0 16 16" version="1.1" width="32" data-view-component="true" class="octicon octicon-mark-github v-align-middle">
    756 						<path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path>
    757 					</svg>
    758 				</a>
    759 				<a href="https://www.linkedin.com/in/jonathan-six-4553611a9/">
    760 					<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 34 34" class="global-nav__logo">
    761 						<path d="M34,2.5v29A2.5,2.5,0,0,1,31.5,34H2.5A2.5,2.5,0,0,1,0,31.5V2.5A2.5,2.5,0,0,1,2.5,0h29A2.5,2.5,0,0,1,34,2.5ZM10,13H5V29h5Zm.45-5.5A2.88,2.88,0,0,0,7.59,4.6H7.5a2.9,2.9,0,0,0,0,5.8h0a2.88,2.88,0,0,0,2.95-2.81ZM29,19.28c0-4.81-3.06-6.68-6.1-6.68a5.7,5.7,0,0,0-5.06,2.58H17.7V13H13V29h5V20.49a3.32,3.32,0,0,1,3-3.58h.19c1.59,0,2.77,1,2.77,3.52V29h5Z" fill="currentColor"></path>
    762 					</svg>
    763 				</a>
    764 			</div>
    765       </author>
    766 
    767   
    768        
    769 
    770     </div>
    771     
    772 	</main>
    773 </body>
    774 </html>