From 49d327315f5be8b72b7c100ec95ecaa5ace8126d Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Fri, 26 May 2023 13:59:57 -0700 Subject: Add node getters and iterators. --- gfx/include/gfx/scene/node.h | 60 +++++++++++++++++++++++++++++---- gfx/src/scene/node.c | 80 +++++++++++++++++++++++++++++++++----------- 2 files changed, 115 insertions(+), 25 deletions(-) diff --git a/gfx/include/gfx/scene/node.h b/gfx/include/gfx/scene/node.h index ab6ca12..5d168c9 100644 --- a/gfx/include/gfx/scene/node.h +++ b/gfx/include/gfx/scene/node.h @@ -1,7 +1,11 @@ #pragma once #include "animation.h" + #include +#include + +#include typedef struct Anima Anima; typedef struct Joint Joint; @@ -9,6 +13,9 @@ typedef struct Light Light; typedef struct SceneCamera SceneCamera; typedef struct SceneObject SceneObject; +/// Scene node iterator. +typedef uint32_t NodeIter; + /// Scene node type. typedef enum NodeType { LogicalNode, @@ -25,6 +32,10 @@ typedef enum NodeType { /// Light, SceneObject, etc), as well as of child nodes. typedef struct SceneNode SceneNode; +// ----------------------------------------------------------------------------- +// Constructors and destructor. +// ----------------------------------------------------------------------------- + /// Create a new scene node. /// /// This node does not contain any camera, light, object, etc. and exists simply @@ -68,6 +79,10 @@ void gfx_construct_object_node(SceneNode*, SceneObject*); /// Node resources -- cameras, lights, objects, etc. -- are also destroyed. void gfx_destroy_node(SceneNode**); +// ----------------------------------------------------------------------------- +// Getters. +// ----------------------------------------------------------------------------- + /// Return the node's type. NodeType gfx_get_node_type(const SceneNode*); @@ -76,6 +91,45 @@ NodeType gfx_get_node_type(const SceneNode*); /// The node must be of type AnimaNode. Anima* gfx_get_node_anima(const SceneNode*); +/// Get the node's camera. +/// +/// The node must be of type CameraNode. +SceneCamera* gfx_get_node_camera(const SceneNode* node); + +/// Get the node's joint. +/// +/// The node must be of type JointNode. +Joint* gfx_get_node_joint(const SceneNode*); + +/// Get the node's light. +/// +/// The node must be of type LightNode. +Light* gfx_get_node_light(const SceneNode*); + +/// Get the node's scene object. +/// +/// The node must be of type ObjectNode. +SceneObject* gfx_get_node_object(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 a scene node from the iterator. +const SceneNode* gfx_get_iter_node(NodeIter); + +/// Get the node's (local) transform. +mat4 gfx_get_node_transform(const SceneNode*); + +/// Get the node's global transform. +mat4 gfx_get_node_global_transform(const SceneNode*); + +// ----------------------------------------------------------------------------- +// Setters. +// ----------------------------------------------------------------------------- + /// Set the node's parent. /// /// Pass in null to unwire from the existing parent, if one exists. @@ -93,11 +147,5 @@ void gfx_set_node_rotation(SceneNode*, const quat* rotation); /// Set the node's rotation. void gfx_set_node_rotation_mat(SceneNode*, const mat4* rotation); -/// Get the node's (local) transform. -mat4 gfx_get_node_transform(const SceneNode*); - -/// Get the node's global transform. -mat4 gfx_get_node_global_transform(const SceneNode*); - /// Log the node's hierarchy. void gfx_log_node_hierarchy(const SceneNode*); diff --git a/gfx/src/scene/node.c b/gfx/src/scene/node.c index 760951b..ea0f19d 100644 --- a/gfx/src/scene/node.c +++ b/gfx/src/scene/node.c @@ -227,10 +227,69 @@ NodeType gfx_get_node_type(const SceneNode* node) { return node->type; } +#define NODE_GET(node, field, expected_type) \ + { \ + assert(node); \ + assert(node->type == expected_type); \ + return mem_get_##field(node->field); \ + } + Anima* gfx_get_node_anima(const SceneNode* node) { + NODE_GET(node, anima, AnimaNode); +} + +SceneCamera* gfx_get_node_camera(const SceneNode* node) { + NODE_GET(node, camera, CameraNode); +} + +Joint* gfx_get_node_joint(const SceneNode* node) { + NODE_GET(node, joint, JointNode); +} + +Light* gfx_get_node_light(const SceneNode* node) { + NODE_GET(node, light, LightNode); +} + +SceneObject* gfx_get_node_object(const SceneNode* node) { + NODE_GET(node, object, ObjectNode); +} + +NodeIter gfx_get_node_child(const SceneNode* node) { assert(node); - assert(node->type == AnimaNode); - return mem_get_anima(node->anima); + return (NodeIter)node->child.val; +} + +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; +} + +const SceneNode* gfx_get_iter_node(NodeIter it) { + if (!it) { + return 0; + } + return mem_get_node((node_idx){.val = it}); +} + +mat4 gfx_get_node_transform(const SceneNode* node) { + assert(node); + return node->transform; +} + +mat4 gfx_get_node_global_transform(const SceneNode* node) { + assert(node); + mat4 transform = node->transform; + node_idx parent_index = node->parent; + while (parent_index.val != 0) { + const SceneNode* parent = mem_get_node(parent_index); + transform = mat4_mul(parent->transform, transform); + parent_index = parent->parent; + } + return transform; } void gfx_set_node_parent(SceneNode* child, SceneNode* parent) { @@ -263,23 +322,6 @@ void gfx_set_node_rotation_mat(SceneNode* node, const mat4* rotation) { mat4_set_3x3(&node->transform, *rotation); } -mat4 gfx_get_node_transform(const SceneNode* node) { - assert(node); - return node->transform; -} - -mat4 gfx_get_node_global_transform(const SceneNode* node) { - assert(node); - mat4 transform = node->transform; - node_idx parent_index = node->parent; - while (parent_index.val != 0) { - const SceneNode* parent = mem_get_node(parent_index); - transform = mat4_mul(parent->transform, transform); - parent_index = parent->parent; - } - return transform; -} - static const char* get_node_type_str(NodeType type) { switch (type) { case LogicalNode: -- cgit v1.2.3