implement that nodes inherit the world transform of their parent

Thu, 21 Mar 2024 20:24:31 +0100

author
Mike Becker <universe@uap-core.de>
date
Thu, 21 Mar 2024 20:24:31 +0100
changeset 38
6e5629ea4c5c
parent 37
8a8cc6725b48
child 39
7cf310cc47cb

implement that nodes inherit the world transform of their parent

src/ascension/datatypes.h file | annotate | diff | comparison | revisions
src/ascension/scene.h file | annotate | diff | comparison | revisions
src/scene.c file | annotate | diff | comparison | revisions
src/text.c file | annotate | diff | comparison | revisions
--- a/src/ascension/datatypes.h	Fri Mar 15 00:06:59 2024 +0100
+++ b/src/ascension/datatypes.h	Thu Mar 21 20:24:31 2024 +0100
@@ -149,4 +149,20 @@
     mat[asc_mat4_index(3,3)] = 1;
 }
 
+static inline void asc_mat4f_mulst(
+    asc_mat4f dest,
+    asc_mat4f const left,
+    asc_mat4f const right
+) {
+    for (unsigned i = 0; i < 4; i++) {
+        for (unsigned j = 0; j < 4; j++) {
+            dest[asc_mat4_index(i, j)] = 0;
+            for (int k = 0; k < 4; k++) {
+                dest[asc_mat4_index(i,j)] +=
+                        left[asc_mat4_index(i,k)] * right[asc_mat4_index(k,j)];
+            }
+        }
+    }
+}
+
 #endif //ASCENSION_DATATYPES_H
--- a/src/ascension/scene.h	Fri Mar 15 00:06:59 2024 +0100
+++ b/src/ascension/scene.h	Thu Mar 21 20:24:31 2024 +0100
@@ -64,7 +64,9 @@
     asc_scene_update_func update_func;
     asc_scene_update_func transform_update_func;
     asc_scene_draw_func draw_func;
-    asc_transform transform;
+    asc_transform world_transform;
+    asc_transform local_transform;
+    asc_transform final_transform;
     enum AscRenderGroup render_group;
     bool need_full_update;
     bool need_transform_update;
@@ -75,12 +77,8 @@
  */
 #define extend_asc_scene_node AscSceneNode base
 
-#define asc_node(obj) ((AscSceneNode*)obj)
-
 #define asc_node_update(node) \
     ((AscSceneNode*)node)->need_full_update = true
-#define asc_node_update_transform(node) \
-    ((AscSceneNode*)node)->need_transform_update = true
 
 struct asc_render_group_entry {
     asc_scene_draw_func draw;
@@ -144,5 +142,8 @@
 __attribute__((__nonnull__))
 void asc_scene_remove_behavior(AscBehaviorNode *node);
 
+__attribute__((__nonnull__))
+void asc_node_update_transform(AscSceneNode *node);
+
 #endif // ASCENSION_SCENE_H
 
--- a/src/scene.c	Fri Mar 15 00:06:59 2024 +0100
+++ b/src/scene.c	Thu Mar 21 20:24:31 2024 +0100
@@ -38,6 +38,17 @@
 
 #include <assert.h>
 
+static CxTreeIterator asc_scene_node_iterator(
+        AscSceneNode *node,
+        bool visit_on_exit
+) {
+    return cx_tree_iterator(
+            node, visit_on_exit,
+            offsetof(AscSceneNode, children),
+            offsetof(AscSceneNode, next)
+    );
+}
+
 void asc_scene_init(AscScene *scene) {
     if (scene->root != NULL) {
         asc_error("Scene is already initialized.");
@@ -78,11 +89,7 @@
     scene->rg_fonts_size = 0;
 
     // skip the root node deliberately, we know it's just the container
-    CxTreeIterator iter = cx_tree_iterator(
-            scene->root, false,
-            offsetof(AscSceneNode, children),
-            offsetof(AscSceneNode, next)
-    );
+    CxTreeIterator iter = asc_scene_node_iterator(scene->root, false);
     cxIteratorNext(iter);
 
     // update the children and add them to the render groups
@@ -103,8 +110,10 @@
         if (node->need_transform_update) {
             assert(node->transform_update_func != NULL);
             node->need_transform_update = false;
-            asc_transform_identity(node->transform);
+            asc_transform_identity(node->local_transform);
+            asc_transform_copy(node->world_transform, node->parent->world_transform);
             node->transform_update_func(node);
+            asc_mat4f_mulst(node->final_transform, node->local_transform, node->world_transform);
         }
 
         // add to render group
@@ -155,7 +164,9 @@
 AscSceneNode *asc_scene_node_empty(void) {
     AscSceneNode *node = calloc(1, sizeof(AscSceneNode));
     node->free_func = (asc_scene_free_func) free;
-    asc_transform_identity(node->transform);
+    asc_transform_identity(node->local_transform);
+    asc_transform_identity(node->world_transform);
+    asc_transform_identity(node->final_transform);
     return node;
 }
 
@@ -166,11 +177,7 @@
     asc_scene_node_unlink(node);
 
     // free the entire subtree
-    CxTreeIterator iter = cx_tree_iterator(
-            node, true,
-            offsetof(AscSceneNode, children),
-            offsetof(AscSceneNode, next)
-    );
+    CxTreeIterator iter = asc_scene_node_iterator(node, true);
     cx_foreach(AscSceneNode*, child, iter) {
         if (!iter.exiting) continue;
         if (child->free_func != NULL) {
@@ -224,3 +231,10 @@
             offsetof(AscBehaviorNode, next)
     );
 }
+
+void asc_node_update_transform(AscSceneNode *node) {
+    CxTreeIterator iter = asc_scene_node_iterator(node, false);
+    cx_foreach(AscSceneNode*, n, iter) {
+        n->need_transform_update = true;
+    }
+}
\ No newline at end of file
--- a/src/text.c	Fri Mar 15 00:06:59 2024 +0100
+++ b/src/text.c	Thu Mar 21 20:24:31 2024 +0100
@@ -39,7 +39,7 @@
 
     // Upload model matrix
     glUniformMatrix4fv(ASC_SHADER_FONT.base.model, 1,
-                       GL_FALSE, node->base.transform);
+                       GL_FALSE, node->base.final_transform);
 
     // Upload surface
     glActiveTexture(GL_TEXTURE0);
@@ -51,8 +51,8 @@
 }
 
 static void asc_text_update_transform(AscText *node) {
-    asc_transform_scale(node->base.transform, (float) node->dimension.width, (float) node->dimension.height, 0);
-    asc_transform_translate2i(node->base.transform, node->position);
+    asc_transform_scale2i(node->base.local_transform, node->dimension);
+    asc_transform_translate2i(node->base.world_transform, node->position);
 }
 
 static void asc_text_update(AscText *node) {

mercurial