simplify how transforms work

Thu, 28 Mar 2024 23:30:21 +0100

author
Mike Becker <universe@uap-core.de>
date
Thu, 28 Mar 2024 23:30:21 +0100
changeset 45
18de2af03531
parent 44
b3da4096c607
child 46
d3285aed65b3

simplify how transforms work

src/ascension/ascension.h file | annotate | diff | comparison | revisions
src/ascension/datatypes.h file | annotate | diff | comparison | revisions
src/ascension/scene.h file | annotate | diff | comparison | revisions
src/ascension/text.h file | annotate | diff | comparison | revisions
src/ascension/transform.h file | annotate | diff | comparison | revisions
src/scene.c file | annotate | diff | comparison | revisions
src/text.c file | annotate | diff | comparison | revisions
test/snake.c file | annotate | diff | comparison | revisions
--- a/src/ascension/ascension.h	Tue Mar 26 20:37:21 2024 +0100
+++ b/src/ascension/ascension.h	Thu Mar 28 23:30:21 2024 +0100
@@ -34,9 +34,5 @@
 #include "text.h"
 #include "scene.h"
 
-// some auto-casting magic
-#define asc_node_update_transform(n) \
-    asc_node_update_transform(((AscSceneNode*)n))
-
 #endif /* ASCENSION_H */
 
--- a/src/ascension/datatypes.h	Tue Mar 26 20:37:21 2024 +0100
+++ b/src/ascension/datatypes.h	Thu Mar 28 23:30:21 2024 +0100
@@ -57,6 +57,7 @@
 typedef union asc_vec3f {
     struct { float x, y, z; };
     struct { float width, height, depth; };
+    struct { float pitch, yaw, roll; };
     float data[3];
 } asc_vec3f;
 
--- a/src/ascension/scene.h	Tue Mar 26 20:37:21 2024 +0100
+++ b/src/ascension/scene.h	Thu Mar 28 23:30:21 2024 +0100
@@ -61,12 +61,13 @@
     AscBehaviorNode *behaviors;
     asc_scene_free_func free_func;
     asc_scene_update_func update_func;
-    asc_scene_update_func transform_update_func;
     asc_scene_draw_func draw_func;
     unsigned depth;
+    asc_vec3f position;
+    asc_vec3f rotation;
+    asc_vec3f scale;
+    asc_transform transform;
     asc_transform world_transform;
-    asc_transform local_transform;
-    asc_transform final_transform;
     enum AscRenderGroup render_group;
     bool need_graphics_update;
     bool need_transform_update;
@@ -142,8 +143,52 @@
 #define asc_node_update(node) \
     ((AscSceneNode*)node)->need_graphics_update = true
 
+
 __attribute__((__nonnull__))
-void asc_node_update_transform(AscSceneNode *node);
+void asc_update_transform(AscSceneNode *node);
+
+
+__attribute__((__nonnull__)) static inline
+void asc_set_position(AscSceneNode *node, float x, float y, float z) {
+    node->position.x = x;
+    node->position.y = y;
+    node->position.z = z;
+    asc_update_transform(node);
+}
+
+__attribute__((__nonnull__)) static inline
+void asc_set_position2d(AscSceneNode *node, int x, int y) {
+    node->position.x = (float)x;
+    node->position.y = (float)y;
+    node->position.z = 0.f;
+    asc_update_transform(node);
+}
+
+__attribute__((__nonnull__)) static inline
+asc_vec2i asc_get_position2d(AscSceneNode *node) {
+    return (asc_vec2i) {(int) node->position.x, (int) node->position.y};
+}
+
+__attribute__((__nonnull__)) static inline
+void asc_set_scale(AscSceneNode *node, float width, float height, float depth) {
+    node->scale.width = width;
+    node->scale.height = height;
+    node->scale.depth = depth;
+    asc_update_transform(node);
+}
+
+__attribute__((__nonnull__)) static inline
+void asc_set_scale2d(AscSceneNode *node, int width, int height) {
+    node->scale.width = (float)width;
+    node->scale.height = (float)height;
+    node->scale.depth = 1.f;
+    asc_update_transform(node);
+}
+
+__attribute__((__nonnull__)) static inline
+asc_vec2i asc_get_scale2d(AscSceneNode *node) {
+    return (asc_vec2i) {(int) node->scale.width, (int) node->scale.height};
+}
 
 #endif // ASCENSION_SCENE_H
 
--- a/src/ascension/text.h	Tue Mar 26 20:37:21 2024 +0100
+++ b/src/ascension/text.h	Thu Mar 28 23:30:21 2024 +0100
@@ -35,12 +35,10 @@
     extend_asc_scene_node;
     char *text;
     AscFont const *font;
-    asc_vec2i position;
     asc_col4i color;
     unsigned max_width;
     bool hidden;
     bool centered;
-    asc_vec2i dimension;
     unsigned tex_id;
 } AscText;
 
--- a/src/ascension/transform.h	Tue Mar 26 20:37:21 2024 +0100
+++ b/src/ascension/transform.h	Thu Mar 28 23:30:21 2024 +0100
@@ -57,42 +57,41 @@
 
 ASC_TRANFORM_FUNC void asc_transform_translate(
         asc_transform transform,
-        float x, float y, float z
+        asc_vec3f vec
 ) {
-    transform[asc_mat4_index(3, 0)] += x;
-    transform[asc_mat4_index(3, 1)] += y;
-    transform[asc_mat4_index(3, 2)] += z;
-}
-
-ASC_TRANFORM_FUNC void asc_transform_translate2i(
-        asc_transform transform,
-        asc_vec2i position
-) {
-    asc_transform_translate(
-            transform,
-            (float) position.x, (float) position.y, 0
-    );
+    transform[asc_mat4_index(3, 0)] += vec.x;
+    transform[asc_mat4_index(3, 1)] += vec.y;
+    transform[asc_mat4_index(3, 2)] += vec.z;
 }
 
 ASC_TRANFORM_FUNC void asc_transform_scale(
         asc_transform transform,
-        float x, float y, float z
+        asc_vec3f vec
 ) {
     for (unsigned i = 0 ; i < 3 ; i++) {
-        transform[asc_mat4_index(0, i)] *= x;
-        transform[asc_mat4_index(1, i)] *= y;
-        transform[asc_mat4_index(2, i)] *= z;
+        transform[asc_mat4_index(0, i)] *= vec.width;
+        transform[asc_mat4_index(1, i)] *= vec.height;
+        transform[asc_mat4_index(2, i)] *= vec.depth;
     }
 }
 
-ASC_TRANFORM_FUNC void asc_transform_scale2i(
+ASC_TRANFORM_FUNC void asc_transform_rotate(
         asc_transform transform,
-        asc_vec2i dimensions
+        asc_vec3f vec
 ) {
-    asc_transform_scale(
-            transform,
-            (float) dimensions.width, (float) dimensions.height, 0
-    );
+    // TODO: implement
+}
+
+ASC_TRANFORM_FUNC void asc_transform_from_parts(
+        asc_transform transform,
+        asc_vec3f position,
+        asc_vec3f scale,
+        asc_vec3f rotation
+) {
+    asc_transform_identity(transform);
+    asc_transform_scale(transform, scale);
+    asc_transform_translate(transform, position);
+    asc_transform_rotate(transform, rotation);
 }
 
 #endif //ASCENSION_TRANSFORM_H
--- a/src/scene.c	Tue Mar 26 20:37:21 2024 +0100
+++ b/src/scene.c	Thu Mar 28 23:30:21 2024 +0100
@@ -123,12 +123,18 @@
             node->update_func(node);
         }
         if (node->need_transform_update) {
-            assert(node->transform_update_func != NULL);
             node->need_transform_update = false;
-            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);
+            asc_transform_from_parts(
+                    node->transform,
+                    node->position,
+                    node->scale,
+                    node->rotation
+            );
+            asc_mat4f_mulst(
+                    node->world_transform,
+                    node->transform,
+                    node->parent->world_transform
+            );
         }
 
         // add to render group
@@ -174,7 +180,7 @@
         // Sprites
         // -------
         // TODO: see if we can really always ignore the view matrix
-        shader = &asc_context.active_window->glctx.shader.sprite;
+        shader = &asc_context.active_window->glctx.shader.sprite.base;
         glUseProgram(shader->id);
         glUniformMatrix4fv(shader->projection, 1,
                            GL_FALSE, camera->projection);
@@ -192,9 +198,8 @@
 AscSceneNode *asc_scene_node_empty(void) {
     AscSceneNode *node = calloc(1, sizeof(AscSceneNode));
     node->free_func = (asc_scene_free_func) free;
-    asc_transform_identity(node->local_transform);
+    asc_transform_identity(node->transform);
     asc_transform_identity(node->world_transform);
-    asc_transform_identity(node->final_transform);
     return node;
 }
 
@@ -260,9 +265,12 @@
     );
 }
 
-void asc_node_update_transform(AscSceneNode *node) {
+void asc_update_transform(AscSceneNode *node) {
+    if (node->need_transform_update) return;
+
     CxTreeIterator iter = asc_scene_node_iterator(node, false);
     cx_foreach(AscSceneNode*, n, iter) {
+        // TODO: break/continue when subtree is already marked for update
         n->need_transform_update = true;
     }
-}
\ No newline at end of file
+}
--- a/src/text.c	Tue Mar 26 20:37:21 2024 +0100
+++ b/src/text.c	Thu Mar 28 23:30:21 2024 +0100
@@ -42,7 +42,7 @@
 
     // Upload model matrix
     glUniformMatrix4fv(shader->base.model, 1,
-                       GL_FALSE, node->base.final_transform);
+                       GL_FALSE, node->base.world_transform);
 
     // Upload surface
     glActiveTexture(GL_TEXTURE0);
@@ -56,11 +56,6 @@
     asc_primitives_draw_plane();
 }
 
-static void asc_text_update_transform(AscText *node) {
-    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) {
     // short circuit if fully transparent or hidden, we don't need anything
     if (node->color.alpha == 0 || node->hidden) {
@@ -87,9 +82,9 @@
         asc_error(SDL_GetError());
         return;
     }
-    node->dimension.width = surface->w;
-    node->dimension.height = surface->h;
-    asc_node_update_transform((AscSceneNode *) node);
+    node->base.scale.width = (float) surface->w;
+    node->base.scale.height = (float) surface->h;
+    asc_update_transform((AscSceneNode *) node);
 
     // Transfer Image Data
     // TODO: move the image data transfer to a separate function - we will need it more often
@@ -113,11 +108,10 @@
     node->base.render_group = ASC_RENDER_GROUP_SPRITE_BLEND;
     node->base.free_func = (asc_scene_free_func) asc_text_free;
     node->base.update_func = (asc_scene_update_func) asc_text_update;
-    node->base.transform_update_func = (asc_scene_update_func) asc_text_update_transform;
     node->base.draw_func = (asc_scene_draw_func) asc_text_draw;
 
-    node->position.x = x;
-    node->position.y = y;
+    node->base.position.x = (float) x;
+    node->base.position.y = (float) y;
     node->font = asc_context.active_font;
     node->color = asc_context.ink;
     if (text != NULL) {
@@ -126,7 +120,6 @@
 
     // initialize
     asc_text_update(node);
-    asc_text_update_transform(node);
 
     return &node->base;
 }
--- a/test/snake.c	Tue Mar 26 20:37:21 2024 +0100
+++ b/test/snake.c	Thu Mar 28 23:30:21 2024 +0100
@@ -55,14 +55,15 @@
 }
 
 static void update_score_counter(AscSceneNode *node) {
-    AscText *text = asc_text_data(node);
-
     // tie to bottom left of the screen
     if (asc_window_active->resized) {
         asc_vec2i bottom_left = asc_window_active->dimensions;
-        text->position.x = bottom_left.x - text->dimension.width - 10;
-        text->position.y = bottom_left.y - text->dimension.height - 10;
-        asc_node_update_transform(text);
+        asc_vec2i scale = asc_get_scale2d(node);
+        asc_set_position2d(
+                node,
+                bottom_left.x - scale.width - 10,
+                bottom_left.y - scale.height - 10
+        );
     }
 }
 

mercurial