apply texture scaling

Mon, 12 May 2025 21:13:24 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 12 May 2025 21:13:24 +0200
changeset 118
830608f7e7d9
parent 117
d1267f656a97
child 119
581c1735fb27

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);
     }
 }
 

mercurial