summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2023-01-07 15:16:14 -0800
committer3gg <3gg@shellblade.net>2023-01-07 15:16:14 -0800
commit5102cd7ffba18b87050b8ecbaed3ee64ab60c462 (patch)
treed76d5d9f351b95bcfc8accc4e620827a69f81cdf
parent3f186ba1570f61d8cc5a1b8cdbb4c1d5f18bd848 (diff)
Recursively destroy a node's children when destroying the node.
-rw-r--r--gfx/include/gfx/scene/node.h6
-rw-r--r--gfx/src/renderer/renderer.c10
-rw-r--r--gfx/src/scene/node.c41
-rw-r--r--gfx/src/scene/node_impl.h5
-rw-r--r--gfx/src/scene/scene.c32
-rw-r--r--gfx/src/scene/scene_impl.h8
6 files changed, 51 insertions, 51 deletions
diff --git a/gfx/include/gfx/scene/node.h b/gfx/include/gfx/scene/node.h
index a09bdbc..292a91f 100644
--- a/gfx/include/gfx/scene/node.h
+++ b/gfx/include/gfx/scene/node.h
@@ -23,11 +23,11 @@ SceneNode* gfx_make_light_node(Light*);
23/// Create a new object node. 23/// Create a new object node.
24SceneNode* gfx_make_object_node(SceneObject*); 24SceneNode* gfx_make_object_node(SceneObject*);
25 25
26/// Destroy the scene node. 26/// Recursively destroy the scene node and its children.
27/// 27///
28/// The scene node is conveniently removed from the scene graph. 28/// The scene node and its children are removed from the scene graph.
29/// 29///
30/// The node's camera, light, object, etc. is also conveniently destroyed. 30/// Node resources -- cameras, lights, objects, etc. -- are also destroyed.
31void gfx_destroy_node(SceneNode**); 31void gfx_destroy_node(SceneNode**);
32 32
33/// Set the node's parent. 33/// Set the node's parent.
diff --git a/gfx/src/renderer/renderer.c b/gfx/src/renderer/renderer.c
index 3654546..8b101db 100644
--- a/gfx/src/renderer/renderer.c
+++ b/gfx/src/renderer/renderer.c
@@ -122,10 +122,9 @@ typedef struct RenderState {
122} RenderState; 122} RenderState;
123 123
124static void draw_recursively( 124static void draw_recursively(
125 RenderState* state, mat4 parent_transform, node_idx node_index) { 125 RenderState* state, mat4 parent_transform, const SceneNode* node) {
126 assert(state); 126 assert(state);
127 const SceneNode* node = mem_get_node(node_index); 127 const mat4 node_transform = mat4_mul(parent_transform, node->transform);
128 const mat4 node_transform = mat4_mul(parent_transform, node->transform);
129 128
130 // Activate light. 129 // Activate light.
131 if (node->type == LightNode) { 130 if (node->type == LightNode) {
@@ -197,10 +196,9 @@ static void draw_recursively(
197 196
198 // Render children recursively. 197 // Render children recursively.
199 for (node_idx child_index = node->child; child_index.val;) { 198 for (node_idx child_index = node->child; child_index.val;) {
200 draw_recursively(state, node_transform, child_index);
201
202 const SceneNode* child = mem_get_node(child_index); 199 const SceneNode* child = mem_get_node(child_index);
203 child_index = child->next; 200 draw_recursively(state, node_transform, child);
201 child_index = child->next;
204 } 202 }
205} 203}
206 204
diff --git a/gfx/src/scene/node.c b/gfx/src/scene/node.c
index ee2f169..71e0e0b 100644
--- a/gfx/src/scene/node.c
+++ b/gfx/src/scene/node.c
@@ -62,28 +62,49 @@ SceneNode* gfx_make_object_node(SceneObject* object) {
62 return node; 62 return node;
63} 63}
64 64
65void gfx_destroy_node(SceneNode** node) { 65static void destroy_node_rec(SceneNode* node) {
66 assert(node); 66 assert(node);
67 assert(*node); 67
68 // First child.
69 if (node->child.val) {
70 destroy_node_rec(mem_get_node(node->child));
71 }
72
73 // Right sibling.
74 if (node->next.val) {
75 destroy_node_rec(mem_get_node(node->next));
76 }
68 77
69 // Destroy the node's resource. 78 // Destroy the node's resource.
70 if ((*node)->type == CameraNode) { 79 if (node->type == CameraNode) {
71 SceneCamera* camera = mem_get_camera((*node)->camera); 80 SceneCamera* camera = mem_get_camera(node->camera);
72 camera->parent.val = 0; // Avoid call into gfx_del_node(). 81 camera->parent.val = 0; // Avoid call into gfx_del_node().
73 gfx_destroy_camera(&camera); 82 gfx_destroy_camera(&camera);
74 } else if ((*node)->type == LightNode) { 83 } else if (node->type == LightNode) {
75 Light* light = mem_get_light((*node)->light); 84 Light* light = mem_get_light(node->light);
76 light->parent.val = 0; // Avoid call into gfx_del_node(). 85 light->parent.val = 0; // Avoid call into gfx_del_node().
77 gfx_destroy_light(&light); 86 gfx_destroy_light(&light);
78 } else if ((*node)->type == ObjectNode) { 87 } else if (node->type == ObjectNode) {
79 SceneObject* object = mem_get_object((*node)->object); 88 SceneObject* object = mem_get_object(node->object);
80 object->parent.val = 0; // Avoid call into gfx_del_node(). 89 object->parent.val = 0; // Avoid call into gfx_del_node().
81 gfx_destroy_object(&object); 90 gfx_destroy_object(&object);
82 } 91 }
83 92
84 // TODO: Should destroy children recursively? 93 mem_free_node(&node);
94}
95
96void gfx_destroy_node(SceneNode** node) {
97 assert(node);
98 assert(*node);
99
100 // Since the node and the whole hierarchy under it gets destroyed, there is
101 // no need to individually detach every node from its hierarchy. We can simply
102 // detach the given node and then destroy it and its sub-hierarchy.
85 TREE_REMOVE(*node); 103 TREE_REMOVE(*node);
86 mem_free_node(node); 104
105 destroy_node_rec(*node);
106
107 *node = 0;
87} 108}
88 109
89// TODO: Think more about ownership of nodes and resources. Should this function 110// TODO: Think more about ownership of nodes and resources. Should this function
diff --git a/gfx/src/scene/node_impl.h b/gfx/src/scene/node_impl.h
index f4aea79..b5c4af8 100644
--- a/gfx/src/scene/node_impl.h
+++ b/gfx/src/scene/node_impl.h
@@ -32,9 +32,10 @@ typedef struct SceneNode {
32 node_idx prev; // Previous sibling SceneNode. 32 node_idx prev; // Previous sibling SceneNode.
33} SceneNode; 33} SceneNode;
34 34
35/// Destroy a node given its index without destroying its resource. 35/// Recursively destroy a node given its index but without destroying the node
36/// resources.
36/// 37///
37/// The node is conveniently removed from the scene graph. 38/// The node and its children are removed from the scene graph.
38/// 39///
39/// This function is for the library's internal use only. 40/// This function is for the library's internal use only.
40void gfx_del_node(node_idx); 41void gfx_del_node(node_idx);
diff --git a/gfx/src/scene/scene.c b/gfx/src/scene/scene.c
index 9e974de..d0d5e82 100644
--- a/gfx/src/scene/scene.c
+++ b/gfx/src/scene/scene.c
@@ -1,43 +1,21 @@
1#include "scene_impl.h" 1#include "scene_impl.h"
2 2
3#include "camera_impl.h"
4#include "node_impl.h" 3#include "node_impl.h"
5#include "object_impl.h"
6#include "scene_graph.h"
7#include "scene_memory.h"
8 4
9static void scene_destroy_rec(node_idx node_index) { 5#include <assert.h>
10 assert(node_index.val);
11
12 SceneNode* node = mem_get_node(node_index);
13 assert(node);
14
15 // First child.
16 if (node->child.val) {
17 scene_destroy_rec(node->child);
18 }
19
20 // Right sibling.
21 if (node->next.val) {
22 scene_destroy_rec(node->next);
23 }
24
25 gfx_destroy_node(&node);
26}
27 6
28void scene_make(Scene* scene) { 7void scene_make(Scene* scene) {
29 assert(scene); 8 assert(scene);
30 SceneNode* root = gfx_make_node(); 9 scene->root = gfx_make_node();
31 assert(root); 10 assert(scene->root);
32 scene->root = mem_get_node_index(root);
33} 11}
34 12
35void scene_destroy(Scene* scene) { 13void scene_destroy(Scene* scene) {
36 assert(scene); 14 assert(scene);
37 scene_destroy_rec(scene->root); 15 gfx_destroy_node(&scene->root);
38} 16}
39 17
40SceneNode* gfx_get_scene_root(Scene* scene) { 18SceneNode* gfx_get_scene_root(Scene* scene) {
41 assert(scene); 19 assert(scene);
42 return mem_get_node(scene->root); 20 return scene->root;
43} 21}
diff --git a/gfx/src/scene/scene_impl.h b/gfx/src/scene/scene_impl.h
index e6544dd..25ec8da 100644
--- a/gfx/src/scene/scene_impl.h
+++ b/gfx/src/scene/scene_impl.h
@@ -4,10 +4,12 @@
4 4
5#include "types.h" 5#include "types.h"
6 6
7typedef struct SceneNode SceneNode;
8
7typedef struct Scene { 9typedef struct Scene {
8 node_idx root; 10 SceneNode* root;
9 scene_idx next; 11 scene_idx next;
10 scene_idx prev; 12 scene_idx prev;
11} Scene; 13} Scene;
12 14
13/// Create a new scene. 15/// Create a new scene.