From 6799f7bd263202d8697c5e27bf12f4e66e4c0ed1 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 17 Feb 2024 14:35:11 -0800 Subject: Introduce gfx_update(). --- game/src/plugins/viewer.c | 19 +++++++------------ gfx/include/gfx/renderer.h | 4 ++++ gfx/include/gfx/scene/model.h | 3 +++ gfx/include/gfx/scene/node.h | 21 ++++++++------------- gfx/src/renderer/renderer.c | 33 +++++++++++++++++++++++++++++++++ gfx/src/scene/model.c | 4 ++++ gfx/src/scene/node.c | 29 +++++++++++++++-------------- 7 files changed, 74 insertions(+), 39 deletions(-) diff --git a/game/src/plugins/viewer.c b/game/src/plugins/viewer.c index 945a422..88821af 100644 --- a/game/src/plugins/viewer.c +++ b/game/src/plugins/viewer.c @@ -155,21 +155,15 @@ void update(Game* game, State* state, double t, double dt) { assert(state->scene); assert(state->camera); - // TODO: Move this to some sort of update_scene(). Note that models do not - // need to be animated if they are not visible to the camera. The camera - // update also should happen first. - Anima* anima = gfx_get_model_anima(state->model); - if (anima) { - gfx_update_animation(anima, (R)t); - } - const vec3 orbit_point = vec3_make(0, 2, 0); Camera* camera = gfx_get_camera_camera(state->camera); spatial3_orbit( &camera->spatial, orbit_point, /*radius=*/5, - /*azimuth=*/t * 0.5, /*zenith=*/0); + /*azimuth=*/(R)(t * 0.5), /*zenith=*/0); spatial3_lookat(&camera->spatial, orbit_point); + + gfx_update(state->scene, state->camera, (R)t); } /// Render the bounding boxes of all scene objects. @@ -207,9 +201,10 @@ static void render_bounding_boxes_rec(ImmRenderer* imm, const SceneNode* node) { } // Render children's boxes. - for (NodeIter it = gfx_get_node_child(node); it; - it = gfx_get_next_child(it)) { - render_bounding_boxes_rec(imm, gfx_get_iter_node(it)); + const SceneNode* child = gfx_get_node_child(node); + while (child) { + render_bounding_boxes_rec(imm, child); + child = gfx_get_node_sibling(child); } } diff --git a/gfx/include/gfx/renderer.h b/gfx/include/gfx/renderer.h index c420889..78d8bbd 100644 --- a/gfx/include/gfx/renderer.h +++ b/gfx/include/gfx/renderer.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,9 @@ typedef struct RenderSceneParams { /// Render the scene. void gfx_render_scene(Renderer*, const RenderSceneParams*); +/// Update the scene. +void gfx_update(Scene*, const SceneCamera*, R t); + // ----------------------------------------------------------------------------- // Immediate Mode Renderer. // ----------------------------------------------------------------------------- diff --git a/gfx/include/gfx/scene/model.h b/gfx/include/gfx/scene/model.h index f4972a9..c55fc8c 100644 --- a/gfx/include/gfx/scene/model.h +++ b/gfx/include/gfx/scene/model.h @@ -9,3 +9,6 @@ Anima* gfx_get_model_anima(Model*); /// Return the model's root node. const SceneNode* gfx_get_model_root(const Model*); + +/// Return the model's root node. +SceneNode* gfx_get_model_root_mut(Model*); diff --git a/gfx/include/gfx/scene/node.h b/gfx/include/gfx/scene/node.h index d048894..77db85c 100644 --- a/gfx/include/gfx/scene/node.h +++ b/gfx/include/gfx/scene/node.h @@ -13,9 +13,6 @@ typedef struct Model Model; typedef struct SceneCamera SceneCamera; typedef struct SceneObject SceneObject; -/// Scene node iterator. -typedef uint32_t NodeIter; - /// Scene node type. typedef enum NodeType { LogicalNode, @@ -116,19 +113,17 @@ SceneObject* gfx_get_node_object(const SceneNode*); /// Get the node's parent. const SceneNode* gfx_get_node_parent(const SceneNode*); -/// Get an iterator to the node's first child. -NodeIter gfx_get_node_child(const SceneNode*); - -/// Get the iterator's next sibling node. -NodeIter gfx_get_next_child(NodeIter); +/// Get the node's first child. +const SceneNode* gfx_get_node_child(const SceneNode*); -// TODO: Think about NodeIter and NodeIterMut for const safety. +/// Get the node's first child. +SceneNode* gfx_get_node_child_mut(SceneNode*); -/// Get a scene node from the iterator. -const SceneNode* gfx_get_iter_node(NodeIter); +/// Get the node's immediate sibling. +const SceneNode* gfx_get_node_sibling(const SceneNode*); -/// Get a scene node from the iterator. -SceneNode* gfx_get_iter_node_mut(NodeIter); +/// Get the node's immediate sibling. +SceneNode* gfx_get_node_sibling_mut(SceneNode*); /// Get the node's (local) transform. mat4 gfx_get_node_transform(const SceneNode*); diff --git a/gfx/src/renderer/renderer.c b/gfx/src/renderer/renderer.c index 30704e3..c72f719 100644 --- a/gfx/src/renderer/renderer.c +++ b/gfx/src/renderer/renderer.c @@ -363,3 +363,36 @@ void gfx_render_scene(Renderer* renderer, const RenderSceneParams* params) { draw_recursively(&state, mat4_id(), scene->root); } + +static void update_rec(SceneNode* node, const SceneCamera* camera, R t) { + assert(node); + assert(camera); + + const NodeType node_type = gfx_get_node_type(node); + + // TODO: Models do not need to be animated if they are not visible to the + // camera. + if (node_type == AnimaNode) { + Anima* anima = gfx_get_node_anima(node); + gfx_update_animation(anima, (R)t); + } else if (node_type == ModelNode) { + Model* model = gfx_get_node_model(node); + SceneNode* root = gfx_get_model_root_mut(model); + update_rec(root, camera, t); + } + + // Children. + SceneNode* child = gfx_get_node_child_mut(node); + while (child) { + update_rec(child, camera, t); + child = gfx_get_node_sibling_mut(child); + } +} + +void gfx_update(Scene* scene, const SceneCamera* camera, R t) { + assert(scene); + assert(camera); + + SceneNode* node = gfx_get_scene_root(scene); + update_rec(node, camera, t); +} diff --git a/gfx/src/scene/model.c b/gfx/src/scene/model.c index 89ff0c3..507c478 100644 --- a/gfx/src/scene/model.c +++ b/gfx/src/scene/model.c @@ -39,3 +39,7 @@ const SceneNode* gfx_get_model_root(const Model* model) { assert(model); return mem_get_node(model->root); } + +SceneNode* gfx_get_model_root_mut(Model* model) { + return (SceneNode*)gfx_get_model_root(model); +} diff --git a/gfx/src/scene/node.c b/gfx/src/scene/node.c index 0fbb696..05f6428 100644 --- a/gfx/src/scene/node.c +++ b/gfx/src/scene/node.c @@ -234,29 +234,30 @@ const SceneNode* gfx_get_node_parent(const SceneNode* node) { return mem_get_node(node->parent); } -NodeIter gfx_get_node_child(const SceneNode* node) { +const SceneNode* gfx_get_node_child(const SceneNode* node) { assert(node); - return (NodeIter)node->child.val; + if (node->child.val) { + return mem_get_node(node->child); + } else { + return 0; + } } -NodeIter gfx_get_next_child(NodeIter it) { - if (!it) { - return it; - } - const SceneNode* cur_child = mem_get_node((node_idx){.val = it}); - const node_idx next_child = cur_child->next; - return (NodeIter)next_child.val; +SceneNode* gfx_get_node_child_mut(SceneNode* node) { + return (SceneNode*)gfx_get_node_child(node); } -const SceneNode* gfx_get_iter_node(NodeIter it) { - if (!it) { +const SceneNode* gfx_get_node_sibling(const SceneNode* node) { + assert(node); + if (node->next.val) { + return mem_get_node(node->next); + } else { return 0; } - return mem_get_node((node_idx){.val = it}); } -SceneNode* gfx_get_iter_node_mut(NodeIter it) { - return (SceneNode*)gfx_get_iter_node(it); +SceneNode* gfx_get_node_sibling_mut(SceneNode* node) { + return (SceneNode*)gfx_get_node_sibling(node); } mat4 gfx_get_node_transform(const SceneNode* node) { -- cgit v1.2.3