diff options
-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: |