diff options
| author | 3gg <3gg@shellblade.net> | 2023-05-26 13:59:57 -0700 |
|---|---|---|
| committer | 3gg <3gg@shellblade.net> | 2023-05-26 13:59:57 -0700 |
| commit | 49d327315f5be8b72b7c100ec95ecaa5ace8126d (patch) | |
| tree | c32d76d88a1d6fadb289af7044d6a06c6a1f201c | |
| parent | f815866f62e0f6a371c0e1cb4a385b41bcffd1ce (diff) | |
Add node getters and iterators.
| -rw-r--r-- | gfx/include/gfx/scene/node.h | 60 | ||||
| -rw-r--r-- | 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 @@ | |||
| 1 | #pragma once | 1 | #pragma once |
| 2 | 2 | ||
| 3 | #include "animation.h" | 3 | #include "animation.h" |
| 4 | |||
| 4 | #include <math/fwd.h> | 5 | #include <math/fwd.h> |
| 6 | #include <math/mat4.h> | ||
| 7 | |||
| 8 | #include <stdint.h> | ||
| 5 | 9 | ||
| 6 | typedef struct Anima Anima; | 10 | typedef struct Anima Anima; |
| 7 | typedef struct Joint Joint; | 11 | typedef struct Joint Joint; |
| @@ -9,6 +13,9 @@ typedef struct Light Light; | |||
| 9 | typedef struct SceneCamera SceneCamera; | 13 | typedef struct SceneCamera SceneCamera; |
| 10 | typedef struct SceneObject SceneObject; | 14 | typedef struct SceneObject SceneObject; |
| 11 | 15 | ||
| 16 | /// Scene node iterator. | ||
| 17 | typedef uint32_t NodeIter; | ||
| 18 | |||
| 12 | /// Scene node type. | 19 | /// Scene node type. |
| 13 | typedef enum NodeType { | 20 | typedef enum NodeType { |
| 14 | LogicalNode, | 21 | LogicalNode, |
| @@ -25,6 +32,10 @@ typedef enum NodeType { | |||
| 25 | /// Light, SceneObject, etc), as well as of child nodes. | 32 | /// Light, SceneObject, etc), as well as of child nodes. |
| 26 | typedef struct SceneNode SceneNode; | 33 | typedef struct SceneNode SceneNode; |
| 27 | 34 | ||
| 35 | // ----------------------------------------------------------------------------- | ||
| 36 | // Constructors and destructor. | ||
| 37 | // ----------------------------------------------------------------------------- | ||
| 38 | |||
| 28 | /// Create a new scene node. | 39 | /// Create a new scene node. |
| 29 | /// | 40 | /// |
| 30 | /// This node does not contain any camera, light, object, etc. and exists simply | 41 | /// This node does not contain any camera, light, object, etc. and exists simply |
| @@ -68,6 +79,10 @@ void gfx_construct_object_node(SceneNode*, SceneObject*); | |||
| 68 | /// Node resources -- cameras, lights, objects, etc. -- are also destroyed. | 79 | /// Node resources -- cameras, lights, objects, etc. -- are also destroyed. |
| 69 | void gfx_destroy_node(SceneNode**); | 80 | void gfx_destroy_node(SceneNode**); |
| 70 | 81 | ||
| 82 | // ----------------------------------------------------------------------------- | ||
| 83 | // Getters. | ||
| 84 | // ----------------------------------------------------------------------------- | ||
| 85 | |||
| 71 | /// Return the node's type. | 86 | /// Return the node's type. |
| 72 | NodeType gfx_get_node_type(const SceneNode*); | 87 | NodeType gfx_get_node_type(const SceneNode*); |
| 73 | 88 | ||
| @@ -76,6 +91,45 @@ NodeType gfx_get_node_type(const SceneNode*); | |||
| 76 | /// The node must be of type AnimaNode. | 91 | /// The node must be of type AnimaNode. |
| 77 | Anima* gfx_get_node_anima(const SceneNode*); | 92 | Anima* gfx_get_node_anima(const SceneNode*); |
| 78 | 93 | ||
| 94 | /// Get the node's camera. | ||
| 95 | /// | ||
| 96 | /// The node must be of type CameraNode. | ||
| 97 | SceneCamera* gfx_get_node_camera(const SceneNode* node); | ||
| 98 | |||
| 99 | /// Get the node's joint. | ||
| 100 | /// | ||
| 101 | /// The node must be of type JointNode. | ||
| 102 | Joint* gfx_get_node_joint(const SceneNode*); | ||
| 103 | |||
| 104 | /// Get the node's light. | ||
| 105 | /// | ||
| 106 | /// The node must be of type LightNode. | ||
| 107 | Light* gfx_get_node_light(const SceneNode*); | ||
| 108 | |||
| 109 | /// Get the node's scene object. | ||
| 110 | /// | ||
| 111 | /// The node must be of type ObjectNode. | ||
| 112 | SceneObject* gfx_get_node_object(const SceneNode*); | ||
| 113 | |||
| 114 | /// Get an iterator to the node's first child. | ||
| 115 | NodeIter gfx_get_node_child(const SceneNode*); | ||
| 116 | |||
| 117 | /// Get the iterator's next sibling node. | ||
| 118 | NodeIter gfx_get_next_child(NodeIter); | ||
| 119 | |||
| 120 | /// Get a scene node from the iterator. | ||
| 121 | const SceneNode* gfx_get_iter_node(NodeIter); | ||
| 122 | |||
| 123 | /// Get the node's (local) transform. | ||
| 124 | mat4 gfx_get_node_transform(const SceneNode*); | ||
| 125 | |||
| 126 | /// Get the node's global transform. | ||
| 127 | mat4 gfx_get_node_global_transform(const SceneNode*); | ||
| 128 | |||
| 129 | // ----------------------------------------------------------------------------- | ||
| 130 | // Setters. | ||
| 131 | // ----------------------------------------------------------------------------- | ||
| 132 | |||
| 79 | /// Set the node's parent. | 133 | /// Set the node's parent. |
| 80 | /// | 134 | /// |
| 81 | /// Pass in null to unwire from the existing parent, if one exists. | 135 | /// 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); | |||
| 93 | /// Set the node's rotation. | 147 | /// Set the node's rotation. |
| 94 | void gfx_set_node_rotation_mat(SceneNode*, const mat4* rotation); | 148 | void gfx_set_node_rotation_mat(SceneNode*, const mat4* rotation); |
| 95 | 149 | ||
| 96 | /// Get the node's (local) transform. | ||
| 97 | mat4 gfx_get_node_transform(const SceneNode*); | ||
| 98 | |||
| 99 | /// Get the node's global transform. | ||
| 100 | mat4 gfx_get_node_global_transform(const SceneNode*); | ||
| 101 | |||
| 102 | /// Log the node's hierarchy. | 150 | /// Log the node's hierarchy. |
| 103 | void gfx_log_node_hierarchy(const SceneNode*); | 151 | 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) { | |||
| 227 | return node->type; | 227 | return node->type; |
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | #define NODE_GET(node, field, expected_type) \ | ||
| 231 | { \ | ||
| 232 | assert(node); \ | ||
| 233 | assert(node->type == expected_type); \ | ||
| 234 | return mem_get_##field(node->field); \ | ||
| 235 | } | ||
| 236 | |||
| 230 | Anima* gfx_get_node_anima(const SceneNode* node) { | 237 | Anima* gfx_get_node_anima(const SceneNode* node) { |
| 238 | NODE_GET(node, anima, AnimaNode); | ||
| 239 | } | ||
| 240 | |||
| 241 | SceneCamera* gfx_get_node_camera(const SceneNode* node) { | ||
| 242 | NODE_GET(node, camera, CameraNode); | ||
| 243 | } | ||
| 244 | |||
| 245 | Joint* gfx_get_node_joint(const SceneNode* node) { | ||
| 246 | NODE_GET(node, joint, JointNode); | ||
| 247 | } | ||
| 248 | |||
| 249 | Light* gfx_get_node_light(const SceneNode* node) { | ||
| 250 | NODE_GET(node, light, LightNode); | ||
| 251 | } | ||
| 252 | |||
| 253 | SceneObject* gfx_get_node_object(const SceneNode* node) { | ||
| 254 | NODE_GET(node, object, ObjectNode); | ||
| 255 | } | ||
| 256 | |||
| 257 | NodeIter gfx_get_node_child(const SceneNode* node) { | ||
| 231 | assert(node); | 258 | assert(node); |
| 232 | assert(node->type == AnimaNode); | 259 | return (NodeIter)node->child.val; |
| 233 | return mem_get_anima(node->anima); | 260 | } |
| 261 | |||
| 262 | NodeIter gfx_get_next_child(NodeIter it) { | ||
| 263 | if (!it) { | ||
| 264 | return it; | ||
| 265 | } | ||
| 266 | const SceneNode* cur_child = mem_get_node((node_idx){.val = it}); | ||
| 267 | const node_idx next_child = cur_child->next; | ||
| 268 | return (NodeIter)next_child.val; | ||
| 269 | } | ||
| 270 | |||
| 271 | const SceneNode* gfx_get_iter_node(NodeIter it) { | ||
| 272 | if (!it) { | ||
| 273 | return 0; | ||
| 274 | } | ||
| 275 | return mem_get_node((node_idx){.val = it}); | ||
| 276 | } | ||
| 277 | |||
| 278 | mat4 gfx_get_node_transform(const SceneNode* node) { | ||
| 279 | assert(node); | ||
| 280 | return node->transform; | ||
| 281 | } | ||
| 282 | |||
| 283 | mat4 gfx_get_node_global_transform(const SceneNode* node) { | ||
| 284 | assert(node); | ||
| 285 | mat4 transform = node->transform; | ||
| 286 | node_idx parent_index = node->parent; | ||
| 287 | while (parent_index.val != 0) { | ||
| 288 | const SceneNode* parent = mem_get_node(parent_index); | ||
| 289 | transform = mat4_mul(parent->transform, transform); | ||
| 290 | parent_index = parent->parent; | ||
| 291 | } | ||
| 292 | return transform; | ||
| 234 | } | 293 | } |
| 235 | 294 | ||
| 236 | void gfx_set_node_parent(SceneNode* child, SceneNode* parent) { | 295 | void gfx_set_node_parent(SceneNode* child, SceneNode* parent) { |
| @@ -263,23 +322,6 @@ void gfx_set_node_rotation_mat(SceneNode* node, const mat4* rotation) { | |||
| 263 | mat4_set_3x3(&node->transform, *rotation); | 322 | mat4_set_3x3(&node->transform, *rotation); |
| 264 | } | 323 | } |
| 265 | 324 | ||
| 266 | mat4 gfx_get_node_transform(const SceneNode* node) { | ||
| 267 | assert(node); | ||
| 268 | return node->transform; | ||
| 269 | } | ||
| 270 | |||
| 271 | mat4 gfx_get_node_global_transform(const SceneNode* node) { | ||
| 272 | assert(node); | ||
| 273 | mat4 transform = node->transform; | ||
| 274 | node_idx parent_index = node->parent; | ||
| 275 | while (parent_index.val != 0) { | ||
| 276 | const SceneNode* parent = mem_get_node(parent_index); | ||
| 277 | transform = mat4_mul(parent->transform, transform); | ||
| 278 | parent_index = parent->parent; | ||
| 279 | } | ||
| 280 | return transform; | ||
| 281 | } | ||
| 282 | |||
| 283 | static const char* get_node_type_str(NodeType type) { | 325 | static const char* get_node_type_str(NodeType type) { |
| 284 | switch (type) { | 326 | switch (type) { |
| 285 | case LogicalNode: | 327 | case LogicalNode: |
