add possibility to modify the node's transformation matrix

Sun, 01 Jun 2025 14:28:30 +0200

author
Mike Becker <universe@uap-core.de>
date
Sun, 01 Jun 2025 14:28:30 +0200
changeset 133
823626940dc9
parent 132
a407a2b18c7c
child 134
42dcc8134a68

add possibility to modify the node's transformation matrix

src/ascension/scene_node.h file | annotate | diff | comparison | revisions
src/scene.c file | annotate | diff | comparison | revisions
--- a/src/ascension/scene_node.h	Sun Jun 01 14:28:00 2025 +0200
+++ b/src/ascension/scene_node.h	Sun Jun 01 14:28:30 2025 +0200
@@ -95,6 +95,12 @@
  */
 #define ASC_SCENE_NODE_TRANSFORM_UPDATED      0x08000000
 /**
+ * Set when the node's transform is directly manipulated via matrix operations.
+ * When this flag is set, position/rotation/scale values won't be used to
+ * calculate the transform matrix.
+ */
+#define ASC_SCENE_NODE_CUSTOM_TRANSFORM       0x10000000
+/**
  * Set when the node is not supposed to be shown on screen.
  */
 #define ASC_SCENE_BEHAVIOR_PAUSED             0x40000000
@@ -179,12 +185,14 @@
     node->position.x = x;
     node->position.y = y;
     node->position.z = z;
+    asc_clear_flag(node->flags, ASC_SCENE_NODE_CUSTOM_TRANSFORM);
     asc_node_update_transform(node);
 }
 
 ASC_TRANFORM_FUNC void asc_set_position2d(AscSceneNode *node, int x, int y) {
     node->position.x = (float)x;
     node->position.y = (float)y;
+    asc_clear_flag(node->flags, ASC_SCENE_NODE_CUSTOM_TRANSFORM);
     asc_node_update_transform(node);
 }
 
@@ -192,11 +200,59 @@
     return asc_vec2i_new(node->position.x, node->position.y);
 }
 
+ASC_TRANFORM_FUNC void asc_set_rotation(AscSceneNode *node, float x, float y, float z) {
+    node->rotation.x = x;
+    node->rotation.y = y;
+    node->rotation.z = z;
+    asc_clear_flag(node->flags, ASC_SCENE_NODE_CUSTOM_TRANSFORM);
+    asc_node_update_transform(node);
+}
+
 ASC_TRANFORM_FUNC 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_clear_flag(node->flags, ASC_SCENE_NODE_CUSTOM_TRANSFORM);
+    asc_node_update_transform(node);
+}
+
+
+/**
+ * Directly modifies the transformation matrix by multiplying it with another matrix.
+ * This will set the node to use the custom transform mode.
+ *
+ * @param node the node to modify
+ * @param matrix the matrix to multiply with the current transform
+ */
+ASC_TRANFORM_FUNC void asc_transform_multiply(AscSceneNode *node, const asc_transform matrix) {
+    asc_set_flag(node->flags, ASC_SCENE_NODE_CUSTOM_TRANSFORM);
+    asc_mat4f_mulst(node->transform, node->transform, matrix);
     asc_node_update_transform(node);
 }
 
+/**
+ * Directly sets the transformation matrix.
+ * This will set the node to use the custom transform mode.
+ *
+ * @param node the node to modify
+ * @param matrix the matrix to set as the transform
+ */
+ASC_TRANFORM_FUNC void asc_transform_set_matrix(AscSceneNode *node, const asc_transform matrix) {
+    asc_set_flag(node->flags, ASC_SCENE_NODE_CUSTOM_TRANSFORM);
+    memcpy(node->transform, matrix, sizeof(asc_transform));
+    asc_node_update_transform(node);
+}
+
+/**
+ * Resets the node to use component-based transformation.
+ * This will recalculate the transform matrix from position, rotation, and scale.
+ *
+ * @param node the node to modify
+ */
+ASC_TRANFORM_FUNC void asc_transform_reset_to_components(AscSceneNode *node) {
+    asc_clear_flag(node->flags, ASC_SCENE_NODE_CUSTOM_TRANSFORM);
+    asc_node_update_transform(node);
+}
+
+
 #endif
--- a/src/scene.c	Sun Jun 01 14:28:00 2025 +0200
+++ b/src/scene.c	Sun Jun 01 14:28:30 2025 +0200
@@ -122,13 +122,17 @@
         if (asc_test_flag(node->flags, ASC_SCENE_NODE_UPDATE_TRANSFORM)) {
             asc_set_flag(node->flags, ASC_SCENE_NODE_TRANSFORM_UPDATED);
             asc_clear_flag(node->flags, ASC_SCENE_NODE_UPDATE_TRANSFORM);
-            // TODO: FIXME: this makes it impossible to directly modify the transform with matrix operations!
-            asc_transform_from_vec3f(
-                    node->transform,
-                    node->position,
-                    node->scale,
-                    node->rotation
-            );
+
+            // Only recalculate from components if not using custom transform
+            if (!asc_test_flag(node->flags, ASC_SCENE_NODE_CUSTOM_TRANSFORM)) {
+                asc_transform_from_vec3f(
+                        node->transform,
+                        node->position,
+                        node->scale,
+                        node->rotation
+                );
+            }
+
             asc_mat4f_mulst(
                     node->world_transform,
                     node->transform,

mercurial