diff options
author | 3gg <3gg@shellblade.net> | 2023-01-07 15:16:14 -0800 |
---|---|---|
committer | 3gg <3gg@shellblade.net> | 2023-01-07 15:16:14 -0800 |
commit | 5102cd7ffba18b87050b8ecbaed3ee64ab60c462 (patch) | |
tree | d76d5d9f351b95bcfc8accc4e620827a69f81cdf | |
parent | 3f186ba1570f61d8cc5a1b8cdbb4c1d5f18bd848 (diff) |
Recursively destroy a node's children when destroying the node.
-rw-r--r-- | gfx/include/gfx/scene/node.h | 6 | ||||
-rw-r--r-- | gfx/src/renderer/renderer.c | 10 | ||||
-rw-r--r-- | gfx/src/scene/node.c | 41 | ||||
-rw-r--r-- | gfx/src/scene/node_impl.h | 5 | ||||
-rw-r--r-- | gfx/src/scene/scene.c | 32 | ||||
-rw-r--r-- | gfx/src/scene/scene_impl.h | 8 |
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. |
24 | SceneNode* gfx_make_object_node(SceneObject*); | 24 | SceneNode* 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. |
31 | void gfx_destroy_node(SceneNode**); | 31 | void 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 | ||
124 | static void draw_recursively( | 124 | static 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 | ||
65 | void gfx_destroy_node(SceneNode** node) { | 65 | static 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 | |||
96 | void 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. |
40 | void gfx_del_node(node_idx); | 41 | void 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 | ||
9 | static 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 | ||
28 | void scene_make(Scene* scene) { | 7 | void 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 | ||
35 | void scene_destroy(Scene* scene) { | 13 | void 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 | ||
40 | SceneNode* gfx_get_scene_root(Scene* scene) { | 18 | SceneNode* 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 | ||
7 | typedef struct SceneNode SceneNode; | ||
8 | |||
7 | typedef struct Scene { | 9 | typedef 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. |