Thu, 28 Mar 2024 23:30:21 +0100
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 |
1.1 --- a/src/ascension/ascension.h Tue Mar 26 20:37:21 2024 +0100 1.2 +++ b/src/ascension/ascension.h Thu Mar 28 23:30:21 2024 +0100 1.3 @@ -34,9 +34,5 @@ 1.4 #include "text.h" 1.5 #include "scene.h" 1.6 1.7 -// some auto-casting magic 1.8 -#define asc_node_update_transform(n) \ 1.9 - asc_node_update_transform(((AscSceneNode*)n)) 1.10 - 1.11 #endif /* ASCENSION_H */ 1.12
2.1 --- a/src/ascension/datatypes.h Tue Mar 26 20:37:21 2024 +0100 2.2 +++ b/src/ascension/datatypes.h Thu Mar 28 23:30:21 2024 +0100 2.3 @@ -57,6 +57,7 @@ 2.4 typedef union asc_vec3f { 2.5 struct { float x, y, z; }; 2.6 struct { float width, height, depth; }; 2.7 + struct { float pitch, yaw, roll; }; 2.8 float data[3]; 2.9 } asc_vec3f; 2.10
3.1 --- a/src/ascension/scene.h Tue Mar 26 20:37:21 2024 +0100 3.2 +++ b/src/ascension/scene.h Thu Mar 28 23:30:21 2024 +0100 3.3 @@ -61,12 +61,13 @@ 3.4 AscBehaviorNode *behaviors; 3.5 asc_scene_free_func free_func; 3.6 asc_scene_update_func update_func; 3.7 - asc_scene_update_func transform_update_func; 3.8 asc_scene_draw_func draw_func; 3.9 unsigned depth; 3.10 + asc_vec3f position; 3.11 + asc_vec3f rotation; 3.12 + asc_vec3f scale; 3.13 + asc_transform transform; 3.14 asc_transform world_transform; 3.15 - asc_transform local_transform; 3.16 - asc_transform final_transform; 3.17 enum AscRenderGroup render_group; 3.18 bool need_graphics_update; 3.19 bool need_transform_update; 3.20 @@ -142,8 +143,52 @@ 3.21 #define asc_node_update(node) \ 3.22 ((AscSceneNode*)node)->need_graphics_update = true 3.23 3.24 + 3.25 __attribute__((__nonnull__)) 3.26 -void asc_node_update_transform(AscSceneNode *node); 3.27 +void asc_update_transform(AscSceneNode *node); 3.28 + 3.29 + 3.30 +__attribute__((__nonnull__)) static inline 3.31 +void asc_set_position(AscSceneNode *node, float x, float y, float z) { 3.32 + node->position.x = x; 3.33 + node->position.y = y; 3.34 + node->position.z = z; 3.35 + asc_update_transform(node); 3.36 +} 3.37 + 3.38 +__attribute__((__nonnull__)) static inline 3.39 +void asc_set_position2d(AscSceneNode *node, int x, int y) { 3.40 + node->position.x = (float)x; 3.41 + node->position.y = (float)y; 3.42 + node->position.z = 0.f; 3.43 + asc_update_transform(node); 3.44 +} 3.45 + 3.46 +__attribute__((__nonnull__)) static inline 3.47 +asc_vec2i asc_get_position2d(AscSceneNode *node) { 3.48 + return (asc_vec2i) {(int) node->position.x, (int) node->position.y}; 3.49 +} 3.50 + 3.51 +__attribute__((__nonnull__)) static inline 3.52 +void asc_set_scale(AscSceneNode *node, float width, float height, float depth) { 3.53 + node->scale.width = width; 3.54 + node->scale.height = height; 3.55 + node->scale.depth = depth; 3.56 + asc_update_transform(node); 3.57 +} 3.58 + 3.59 +__attribute__((__nonnull__)) static inline 3.60 +void asc_set_scale2d(AscSceneNode *node, int width, int height) { 3.61 + node->scale.width = (float)width; 3.62 + node->scale.height = (float)height; 3.63 + node->scale.depth = 1.f; 3.64 + asc_update_transform(node); 3.65 +} 3.66 + 3.67 +__attribute__((__nonnull__)) static inline 3.68 +asc_vec2i asc_get_scale2d(AscSceneNode *node) { 3.69 + return (asc_vec2i) {(int) node->scale.width, (int) node->scale.height}; 3.70 +} 3.71 3.72 #endif // ASCENSION_SCENE_H 3.73
4.1 --- a/src/ascension/text.h Tue Mar 26 20:37:21 2024 +0100 4.2 +++ b/src/ascension/text.h Thu Mar 28 23:30:21 2024 +0100 4.3 @@ -35,12 +35,10 @@ 4.4 extend_asc_scene_node; 4.5 char *text; 4.6 AscFont const *font; 4.7 - asc_vec2i position; 4.8 asc_col4i color; 4.9 unsigned max_width; 4.10 bool hidden; 4.11 bool centered; 4.12 - asc_vec2i dimension; 4.13 unsigned tex_id; 4.14 } AscText; 4.15
5.1 --- a/src/ascension/transform.h Tue Mar 26 20:37:21 2024 +0100 5.2 +++ b/src/ascension/transform.h Thu Mar 28 23:30:21 2024 +0100 5.3 @@ -57,42 +57,41 @@ 5.4 5.5 ASC_TRANFORM_FUNC void asc_transform_translate( 5.6 asc_transform transform, 5.7 - float x, float y, float z 5.8 + asc_vec3f vec 5.9 ) { 5.10 - transform[asc_mat4_index(3, 0)] += x; 5.11 - transform[asc_mat4_index(3, 1)] += y; 5.12 - transform[asc_mat4_index(3, 2)] += z; 5.13 -} 5.14 - 5.15 -ASC_TRANFORM_FUNC void asc_transform_translate2i( 5.16 - asc_transform transform, 5.17 - asc_vec2i position 5.18 -) { 5.19 - asc_transform_translate( 5.20 - transform, 5.21 - (float) position.x, (float) position.y, 0 5.22 - ); 5.23 + transform[asc_mat4_index(3, 0)] += vec.x; 5.24 + transform[asc_mat4_index(3, 1)] += vec.y; 5.25 + transform[asc_mat4_index(3, 2)] += vec.z; 5.26 } 5.27 5.28 ASC_TRANFORM_FUNC void asc_transform_scale( 5.29 asc_transform transform, 5.30 - float x, float y, float z 5.31 + asc_vec3f vec 5.32 ) { 5.33 for (unsigned i = 0 ; i < 3 ; i++) { 5.34 - transform[asc_mat4_index(0, i)] *= x; 5.35 - transform[asc_mat4_index(1, i)] *= y; 5.36 - transform[asc_mat4_index(2, i)] *= z; 5.37 + transform[asc_mat4_index(0, i)] *= vec.width; 5.38 + transform[asc_mat4_index(1, i)] *= vec.height; 5.39 + transform[asc_mat4_index(2, i)] *= vec.depth; 5.40 } 5.41 } 5.42 5.43 -ASC_TRANFORM_FUNC void asc_transform_scale2i( 5.44 +ASC_TRANFORM_FUNC void asc_transform_rotate( 5.45 asc_transform transform, 5.46 - asc_vec2i dimensions 5.47 + asc_vec3f vec 5.48 ) { 5.49 - asc_transform_scale( 5.50 - transform, 5.51 - (float) dimensions.width, (float) dimensions.height, 0 5.52 - ); 5.53 + // TODO: implement 5.54 +} 5.55 + 5.56 +ASC_TRANFORM_FUNC void asc_transform_from_parts( 5.57 + asc_transform transform, 5.58 + asc_vec3f position, 5.59 + asc_vec3f scale, 5.60 + asc_vec3f rotation 5.61 +) { 5.62 + asc_transform_identity(transform); 5.63 + asc_transform_scale(transform, scale); 5.64 + asc_transform_translate(transform, position); 5.65 + asc_transform_rotate(transform, rotation); 5.66 } 5.67 5.68 #endif //ASCENSION_TRANSFORM_H
6.1 --- a/src/scene.c Tue Mar 26 20:37:21 2024 +0100 6.2 +++ b/src/scene.c Thu Mar 28 23:30:21 2024 +0100 6.3 @@ -123,12 +123,18 @@ 6.4 node->update_func(node); 6.5 } 6.6 if (node->need_transform_update) { 6.7 - assert(node->transform_update_func != NULL); 6.8 node->need_transform_update = false; 6.9 - asc_transform_identity(node->local_transform); 6.10 - asc_transform_copy(node->world_transform, node->parent->world_transform); 6.11 - node->transform_update_func(node); 6.12 - asc_mat4f_mulst(node->final_transform, node->local_transform, node->world_transform); 6.13 + asc_transform_from_parts( 6.14 + node->transform, 6.15 + node->position, 6.16 + node->scale, 6.17 + node->rotation 6.18 + ); 6.19 + asc_mat4f_mulst( 6.20 + node->world_transform, 6.21 + node->transform, 6.22 + node->parent->world_transform 6.23 + ); 6.24 } 6.25 6.26 // add to render group 6.27 @@ -174,7 +180,7 @@ 6.28 // Sprites 6.29 // ------- 6.30 // TODO: see if we can really always ignore the view matrix 6.31 - shader = &asc_context.active_window->glctx.shader.sprite; 6.32 + shader = &asc_context.active_window->glctx.shader.sprite.base; 6.33 glUseProgram(shader->id); 6.34 glUniformMatrix4fv(shader->projection, 1, 6.35 GL_FALSE, camera->projection); 6.36 @@ -192,9 +198,8 @@ 6.37 AscSceneNode *asc_scene_node_empty(void) { 6.38 AscSceneNode *node = calloc(1, sizeof(AscSceneNode)); 6.39 node->free_func = (asc_scene_free_func) free; 6.40 - asc_transform_identity(node->local_transform); 6.41 + asc_transform_identity(node->transform); 6.42 asc_transform_identity(node->world_transform); 6.43 - asc_transform_identity(node->final_transform); 6.44 return node; 6.45 } 6.46 6.47 @@ -260,9 +265,12 @@ 6.48 ); 6.49 } 6.50 6.51 -void asc_node_update_transform(AscSceneNode *node) { 6.52 +void asc_update_transform(AscSceneNode *node) { 6.53 + if (node->need_transform_update) return; 6.54 + 6.55 CxTreeIterator iter = asc_scene_node_iterator(node, false); 6.56 cx_foreach(AscSceneNode*, n, iter) { 6.57 + // TODO: break/continue when subtree is already marked for update 6.58 n->need_transform_update = true; 6.59 } 6.60 -} 6.61 \ No newline at end of file 6.62 +}
7.1 --- a/src/text.c Tue Mar 26 20:37:21 2024 +0100 7.2 +++ b/src/text.c Thu Mar 28 23:30:21 2024 +0100 7.3 @@ -42,7 +42,7 @@ 7.4 7.5 // Upload model matrix 7.6 glUniformMatrix4fv(shader->base.model, 1, 7.7 - GL_FALSE, node->base.final_transform); 7.8 + GL_FALSE, node->base.world_transform); 7.9 7.10 // Upload surface 7.11 glActiveTexture(GL_TEXTURE0); 7.12 @@ -56,11 +56,6 @@ 7.13 asc_primitives_draw_plane(); 7.14 } 7.15 7.16 -static void asc_text_update_transform(AscText *node) { 7.17 - asc_transform_scale2i(node->base.local_transform, node->dimension); 7.18 - asc_transform_translate2i(node->base.world_transform, node->position); 7.19 -} 7.20 - 7.21 static void asc_text_update(AscText *node) { 7.22 // short circuit if fully transparent or hidden, we don't need anything 7.23 if (node->color.alpha == 0 || node->hidden) { 7.24 @@ -87,9 +82,9 @@ 7.25 asc_error(SDL_GetError()); 7.26 return; 7.27 } 7.28 - node->dimension.width = surface->w; 7.29 - node->dimension.height = surface->h; 7.30 - asc_node_update_transform((AscSceneNode *) node); 7.31 + node->base.scale.width = (float) surface->w; 7.32 + node->base.scale.height = (float) surface->h; 7.33 + asc_update_transform((AscSceneNode *) node); 7.34 7.35 // Transfer Image Data 7.36 // TODO: move the image data transfer to a separate function - we will need it more often 7.37 @@ -113,11 +108,10 @@ 7.38 node->base.render_group = ASC_RENDER_GROUP_SPRITE_BLEND; 7.39 node->base.free_func = (asc_scene_free_func) asc_text_free; 7.40 node->base.update_func = (asc_scene_update_func) asc_text_update; 7.41 - node->base.transform_update_func = (asc_scene_update_func) asc_text_update_transform; 7.42 node->base.draw_func = (asc_scene_draw_func) asc_text_draw; 7.43 7.44 - node->position.x = x; 7.45 - node->position.y = y; 7.46 + node->base.position.x = (float) x; 7.47 + node->base.position.y = (float) y; 7.48 node->font = asc_context.active_font; 7.49 node->color = asc_context.ink; 7.50 if (text != NULL) { 7.51 @@ -126,7 +120,6 @@ 7.52 7.53 // initialize 7.54 asc_text_update(node); 7.55 - asc_text_update_transform(node); 7.56 7.57 return &node->base; 7.58 }
8.1 --- a/test/snake.c Tue Mar 26 20:37:21 2024 +0100 8.2 +++ b/test/snake.c Thu Mar 28 23:30:21 2024 +0100 8.3 @@ -55,14 +55,15 @@ 8.4 } 8.5 8.6 static void update_score_counter(AscSceneNode *node) { 8.7 - AscText *text = asc_text_data(node); 8.8 - 8.9 // tie to bottom left of the screen 8.10 if (asc_window_active->resized) { 8.11 asc_vec2i bottom_left = asc_window_active->dimensions; 8.12 - text->position.x = bottom_left.x - text->dimension.width - 10; 8.13 - text->position.y = bottom_left.y - text->dimension.height - 10; 8.14 - asc_node_update_transform(text); 8.15 + asc_vec2i scale = asc_get_scale2d(node); 8.16 + asc_set_position2d( 8.17 + node, 8.18 + bottom_left.x - scale.width - 10, 8.19 + bottom_left.y - scale.height - 10 8.20 + ); 8.21 } 8.22 } 8.23