Mon, 12 May 2025 21:13:24 +0200
apply texture scaling
src/ascension/2d/sprite.h | file | annotate | diff | comparison | revisions | |
src/ascension/mesh.h | file | annotate | diff | comparison | revisions | |
src/mesh.c | file | annotate | diff | comparison | revisions | |
src/sprite.c | file | annotate | diff | comparison | revisions | |
test/snake/snake.c | file | annotate | diff | comparison | revisions |
--- a/src/ascension/2d/sprite.h Mon May 12 20:51:57 2025 +0200 +++ b/src/ascension/2d/sprite.h Mon May 12 21:13:24 2025 +0200 @@ -35,7 +35,11 @@ typedef struct AscSprite { AscSceneNode data; AscMesh mesh; + unsigned width; + unsigned height; AscTexture *texture; + enum asc_texture_scale_mode texture_scale_mode; + asc_vec2f texture_scale; } AscSprite; struct asc_sprite_create_args { @@ -66,4 +70,6 @@ void asc_sprite_draw(AscSprite const *sprite); +void asc_sprite_set_size(AscSceneNode *node, unsigned width, unsigned height); + #endif //ASCENSION_SPRITE_H
--- a/src/ascension/mesh.h Mon May 12 20:51:57 2025 +0200 +++ b/src/ascension/mesh.h Mon May 12 21:13:24 2025 +0200 @@ -43,6 +43,7 @@ unsigned vao; enum AscMeshType type; unsigned vtx_count; + unsigned vtx_data_size; float *vtx_data; } AscMesh;
--- a/src/mesh.c Mon May 12 20:51:57 2025 +0200 +++ b/src/mesh.c Mon May 12 21:13:24 2025 +0200 @@ -80,8 +80,25 @@ asc_mesh_allocate_buffers(mesh, 1); } + unsigned required_memory = 4 * sizeof(AscMeshVertex2d); + // free any previous data - free(mesh->vtx_data); + if (mesh->vtx_data && mesh->vtx_data_size < required_memory) { + free(mesh->vtx_data); + mesh->vtx_data = NULL; + } + + // allocate memory + AscMeshVertex2d *data; + if (mesh->vtx_data == NULL) { + asc_dprintf("Create plane in VBO %u and VAO %u", mesh->vbo, mesh->vao); + mesh->vtx_data_size = required_memory; + data = malloc(mesh->vtx_data_size); + mesh->vtx_data = (float*) data; + } else { + data = (AscMeshVertex2d*) mesh->vtx_data; + } + mesh->vtx_count = 4; // default values args.size.x = ASC_NONZERO_OR(1.f, args.size.x); @@ -89,30 +106,20 @@ args.uv_scale.x = ASC_NONZERO_OR(1.f, args.uv_scale.x); args.uv_scale.y = ASC_NONZERO_OR(1.f, args.uv_scale.y); - asc_dprintf("Create plane in VBO %u and VAO %u", mesh->vbo, mesh->vao); - mesh->vtx_count = 4; - AscMeshVertex2d data[4] = { - { - .pos = {{0.0f, 0.0f}}, - .uv = {{args.uv_offset.x, args.uv_offset.y}}, - } , // bottom left - { - .pos = {{0.0f, args.size.y}}, - .uv = {{args.uv_offset.x, args.uv_offset.y + args.uv_scale.y}}, - }, // top left - { - .pos = {{args.size.x, 0.0f}}, - .uv = {{args.uv_offset.x + args.uv_scale.x, args.uv_offset.y}}, - }, // bottom right - { - .pos = {{args.size.x, args.size.y}}, - .uv = {{args.uv_offset.x + args.uv_scale.x, args.uv_offset.y + args.uv_scale.y}}, - } // top right - }; - mesh->vtx_data = malloc(sizeof(data)); - memcpy(mesh->vtx_data, data, sizeof(data)); + // bottom left + data[0].pos = asc_vec2f_new(0.0f, 0.0f); + data[0].uv = asc_vec2f_new(args.uv_offset.x, args.uv_offset.y); + // top left + data[1].pos = asc_vec2f_new(0.0f, args.size.y); + data[1].uv = asc_vec2f_new(args.uv_offset.x, args.uv_offset.y + args.uv_scale.y); + // bottom right + data[2].pos = asc_vec2f_new(args.size.x, 0.0f); + data[2].uv = asc_vec2f_new(args.uv_offset.x + args.uv_scale.x, args.uv_offset.y); + // top right + data[3].pos = asc_vec2f_new(args.size.x, args.size.y); + data[3].uv = asc_vec2f_new(args.uv_offset.x + args.uv_scale.x, args.uv_offset.y + args.uv_scale.y); glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(data), mesh->vtx_data, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, mesh->vtx_data_size, mesh->vtx_data, GL_STATIC_DRAW); // TODO: this should not be repeated for every adjustment - but it will be moved to the batch renderer anyway glBindVertexArray(mesh->vao); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(AscMeshVertex2d), (void*)offsetof(AscMeshVertex2d, pos));
--- a/src/sprite.c Mon May 12 20:51:57 2025 +0200 +++ b/src/sprite.c Mon May 12 21:13:24 2025 +0200 @@ -40,12 +40,36 @@ sprite->texture->refcount--; } +static void asc_sprite_update(AscSceneNode *node) { + AscSprite *sprite = (AscSprite *) node; + + // calculate texture parameters + asc_vec2f uv_scale; + if (sprite->texture_scale_mode == ASC_TEXTURE_SCALE_REPEAT) { + uv_scale = asc_texture_calculate_uv_scale(sprite->texture, + asc_vec2u_new(sprite->width, sprite->height), sprite->texture_scale); + } else { + uv_scale = sprite->texture_scale; + } + + // update mesh + asc_mesh_plane_2d(&sprite->mesh, + .size = asc_vec2f_new(sprite->width, sprite->height), + .uv_scale = uv_scale + ); +} + AscSceneNode *asc_sprite_create(struct asc_sprite_create_args args) { AscSprite *sprite = calloc(1, sizeof(AscSprite)); - // special sprite parameters + // sprite parameters args.texture->refcount++; sprite->texture = args.texture; + sprite->width = args.width; + sprite->height = args.height; + sprite->texture_scale_mode = args.texture_scale_mode; + sprite->texture_scale.u = ASC_NONZERO_OR(1.f, args.texture_scale_x); + sprite->texture_scale.v = ASC_NONZERO_OR(1.f, args.texture_scale_y); // basic node parameters AscSceneNode *node = (AscSceneNode *) sprite; @@ -53,27 +77,13 @@ node->render_group = args.opaque ? ASC_RENDER_GROUP_SPRITE_OPAQUE : ASC_RENDER_GROUP_SPRITE_BLEND; + node->update_func = asc_sprite_update; node->destroy_func = asc_sprite_destroy; node->position = asc_vec3f_new(args.x, args.y, ASC_SCENE_2D_DEPTH_OFFSET); node->scale = asc_vec3f_one; - asc_node_update_transform(node); - // calculate texture parameters - asc_vec2f uv_scale; - uv_scale.u = ASC_NONZERO_OR(1.f, args.texture_scale_x); - uv_scale.v = ASC_NONZERO_OR(1.f, args.texture_scale_y); - if (args.texture_scale_mode == ASC_TEXTURE_SCALE_REPEAT) { - uv_scale = asc_texture_calculate_uv_scale(args.texture, - asc_vec2u_new(args.width, args.height), uv_scale); - } - - // initialize mesh - asc_mesh_plane_2d(&sprite->mesh, - .size = asc_vec2f_new(args.width, args.height), - .uv_scale = uv_scale - ); - + asc_node_update(node); return node; } @@ -97,3 +107,10 @@ // Draw mesh asc_mesh_draw_triangle_strip(&node->mesh); } + +void asc_sprite_set_size(AscSceneNode *node, unsigned width, unsigned height) { + AscSprite *sprite = (AscSprite*) node; + sprite->width = width; + sprite->height = height; + asc_node_update(node); +}
--- a/test/snake/snake.c Mon May 12 20:51:57 2025 +0200 +++ b/test/snake/snake.c Mon May 12 21:13:24 2025 +0200 @@ -86,8 +86,7 @@ if (asc_active_window->resized) { AscSceneNode *node = behavior->node; asc_vec2u window_size = asc_active_window->dimensions; - // TODO: replace scale with asc_sprite_set_size() - asc_set_scale(node, (float)window_size.width, (float)window_size.height, 1); + asc_sprite_set_size(node, window_size.width, window_size.height); } }