Sun, 01 Jun 2025 14:28:30 +0200
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,