# HG changeset patch # User Mike Becker # Date 1711049071 -3600 # Node ID 6e5629ea4c5c7f5978bdcefdcfec73df6f98d81d # Parent 8a8cc6725b483a219f3a758c772d50b15e6c2cd3 implement that nodes inherit the world transform of their parent diff -r 8a8cc6725b48 -r 6e5629ea4c5c src/ascension/datatypes.h --- 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 diff -r 8a8cc6725b48 -r 6e5629ea4c5c src/ascension/scene.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 diff -r 8a8cc6725b48 -r 6e5629ea4c5c src/scene.c --- 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 +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 diff -r 8a8cc6725b48 -r 6e5629ea4c5c src/text.c --- 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) {