From 5102cd7ffba18b87050b8ecbaed3ee64ab60c462 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 7 Jan 2023 15:16:14 -0800 Subject: Recursively destroy a node's children when destroying the node. --- gfx/include/gfx/scene/node.h | 6 +++--- gfx/src/renderer/renderer.c | 10 ++++------ gfx/src/scene/node.c | 41 +++++++++++++++++++++++++++++++---------- gfx/src/scene/node_impl.h | 5 +++-- gfx/src/scene/scene.c | 32 +++++--------------------------- 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*); /// Create a new object node. SceneNode* gfx_make_object_node(SceneObject*); -/// Destroy the scene node. +/// Recursively destroy the scene node and its children. /// -/// The scene node is conveniently removed from the scene graph. +/// The scene node and its children are removed from the scene graph. /// -/// The node's camera, light, object, etc. is also conveniently destroyed. +/// Node resources -- cameras, lights, objects, etc. -- are also destroyed. void gfx_destroy_node(SceneNode**); /// 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 { } RenderState; static void draw_recursively( - RenderState* state, mat4 parent_transform, node_idx node_index) { + RenderState* state, mat4 parent_transform, const SceneNode* node) { assert(state); - const SceneNode* node = mem_get_node(node_index); - const mat4 node_transform = mat4_mul(parent_transform, node->transform); + const mat4 node_transform = mat4_mul(parent_transform, node->transform); // Activate light. if (node->type == LightNode) { @@ -197,10 +196,9 @@ static void draw_recursively( // Render children recursively. for (node_idx child_index = node->child; child_index.val;) { - draw_recursively(state, node_transform, child_index); - const SceneNode* child = mem_get_node(child_index); - child_index = child->next; + draw_recursively(state, node_transform, child); + child_index = child->next; } } 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) { return node; } -void gfx_destroy_node(SceneNode** node) { +static void destroy_node_rec(SceneNode* node) { assert(node); - assert(*node); + + // First child. + if (node->child.val) { + destroy_node_rec(mem_get_node(node->child)); + } + + // Right sibling. + if (node->next.val) { + destroy_node_rec(mem_get_node(node->next)); + } // Destroy the node's resource. - if ((*node)->type == CameraNode) { - SceneCamera* camera = mem_get_camera((*node)->camera); + if (node->type == CameraNode) { + SceneCamera* camera = mem_get_camera(node->camera); camera->parent.val = 0; // Avoid call into gfx_del_node(). gfx_destroy_camera(&camera); - } else if ((*node)->type == LightNode) { - Light* light = mem_get_light((*node)->light); + } else if (node->type == LightNode) { + Light* light = mem_get_light(node->light); light->parent.val = 0; // Avoid call into gfx_del_node(). gfx_destroy_light(&light); - } else if ((*node)->type == ObjectNode) { - SceneObject* object = mem_get_object((*node)->object); + } else if (node->type == ObjectNode) { + SceneObject* object = mem_get_object(node->object); object->parent.val = 0; // Avoid call into gfx_del_node(). gfx_destroy_object(&object); } - // TODO: Should destroy children recursively? + mem_free_node(&node); +} + +void gfx_destroy_node(SceneNode** node) { + assert(node); + assert(*node); + + // Since the node and the whole hierarchy under it gets destroyed, there is + // no need to individually detach every node from its hierarchy. We can simply + // detach the given node and then destroy it and its sub-hierarchy. TREE_REMOVE(*node); - mem_free_node(node); + + destroy_node_rec(*node); + + *node = 0; } // 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 { node_idx prev; // Previous sibling SceneNode. } SceneNode; -/// Destroy a node given its index without destroying its resource. +/// Recursively destroy a node given its index but without destroying the node +/// resources. /// -/// The node is conveniently removed from the scene graph. +/// The node and its children are removed from the scene graph. /// /// This function is for the library's internal use only. 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 @@ #include "scene_impl.h" -#include "camera_impl.h" #include "node_impl.h" -#include "object_impl.h" -#include "scene_graph.h" -#include "scene_memory.h" -static void scene_destroy_rec(node_idx node_index) { - assert(node_index.val); - - SceneNode* node = mem_get_node(node_index); - assert(node); - - // First child. - if (node->child.val) { - scene_destroy_rec(node->child); - } - - // Right sibling. - if (node->next.val) { - scene_destroy_rec(node->next); - } - - gfx_destroy_node(&node); -} +#include void scene_make(Scene* scene) { assert(scene); - SceneNode* root = gfx_make_node(); - assert(root); - scene->root = mem_get_node_index(root); + scene->root = gfx_make_node(); + assert(scene->root); } void scene_destroy(Scene* scene) { assert(scene); - scene_destroy_rec(scene->root); + gfx_destroy_node(&scene->root); } SceneNode* gfx_get_scene_root(Scene* scene) { assert(scene); - return mem_get_node(scene->root); + return scene->root; } 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 @@ #include "types.h" +typedef struct SceneNode SceneNode; + typedef struct Scene { - node_idx root; - scene_idx next; - scene_idx prev; + SceneNode* root; + scene_idx next; + scene_idx prev; } Scene; /// Create a new scene. -- cgit v1.2.3