make draw function dynamic

Sat, 14 Jun 2025 12:38:37 +0200

author
Mike Becker <universe@uap-core.de>
date
Sat, 14 Jun 2025 12:38:37 +0200
changeset 150
3045f61bc4eb
parent 149
560772519ff9
child 151
42960d0c879b

make draw function dynamic

required to solve issue #384

src/ascension/datatypes.h file | annotate | diff | comparison | revisions
src/ascension/scene_node.h file | annotate | diff | comparison | revisions
src/ascension/sprite.h file | annotate | diff | comparison | revisions
src/scene.c file | annotate | diff | comparison | revisions
src/sprite.c file | annotate | diff | comparison | revisions
src/text.c file | annotate | diff | comparison | revisions
--- a/src/ascension/datatypes.h	Sat Jun 14 11:40:40 2025 +0200
+++ b/src/ascension/datatypes.h	Sat Jun 14 12:38:37 2025 +0200
@@ -186,6 +186,22 @@
     return asc_vec3f_new(v.x*s, v.y*s, v.z*s);
 }
 
+static inline unsigned asc_vec2u_sqrlen(asc_vec2u v) {
+    return v.x*v.x + v.y*v.y;
+}
+
+static inline unsigned asc_vec2i_sqrlen(asc_vec2i v) {
+    return v.x*v.x + v.y*v.y;
+}
+
+static inline float asc_vec2f_sqrlen(asc_vec2f v) {
+    return v.x*v.x + v.y*v.y;
+}
+
+static inline float asc_vec3f_sqrlen(asc_vec3f v) {
+    return v.x*v.x + v.y*v.y + v.z*v.z;
+}
+
 // --------------------------------------------------------------------------
 //   Matrix Functions
 // --------------------------------------------------------------------------
--- a/src/ascension/scene_node.h	Sat Jun 14 11:40:40 2025 +0200
+++ b/src/ascension/scene_node.h	Sat Jun 14 12:38:37 2025 +0200
@@ -35,15 +35,17 @@
 #include "transform.h"
 
 typedef struct asc_scene_node_s AscSceneNode;
+typedef struct asc_camera_s AscCamera; // opaque declared
 
 typedef void(*asc_scene_node_destroy_func)(AscSceneNode*);
 typedef void(*asc_scene_node_update_func)(AscSceneNode*);
+typedef void(*asc_scene_node_draw_func)(const AscCamera*,const AscSceneNode*);
 
 // TODO: rework the concept of render groups, because currently it is only half abstract, half hard-coded
 enum AscRenderGroup {
     ASC_RENDER_GROUP_NONE = -1,
-    ASC_RENDER_GROUP_SPRITE_OPAQUE,
-    ASC_RENDER_GROUP_SPRITE_BLEND,
+    ASC_RENDER_GROUP_2D_OPAQUE,
+    ASC_RENDER_GROUP_2D_BLEND,
     ASC_RENDER_GROUP_COUNT
 };
 
@@ -61,6 +63,7 @@
     CxList *behaviors;
     asc_scene_node_destroy_func destroy_func;
     asc_scene_node_update_func update_func;
+    asc_scene_node_draw_func draw_func;
     asc_vec3f position;
     asc_vec3f rotation;
     asc_vec3f scale;
--- a/src/ascension/sprite.h	Sat Jun 14 11:40:40 2025 +0200
+++ b/src/ascension/sprite.h	Sat Jun 14 12:38:37 2025 +0200
@@ -71,6 +71,6 @@
 
 void asc_sprite_set_size(AscSceneNode *node, unsigned width, unsigned height);
 
-void asc_sprite_draw(const AscCamera *camera, const AscSprite *node);
+void asc_sprite_draw(const AscCamera *camera, const AscSceneNode *node);
 
 #endif //ASCENSION_SPRITE_H
--- a/src/scene.c	Sat Jun 14 11:40:40 2025 +0200
+++ b/src/scene.c	Sat Jun 14 12:38:37 2025 +0200
@@ -30,7 +30,6 @@
 #include "ascension/scene.h"
 #include "ascension/behavior.h"
 #include "ascension/shader.h"
-#include "ascension/sprite.h"
 
 #include <cx/tree.h>
 #include <cx/array_list.h>
@@ -76,7 +75,7 @@
     }
 }
 
-static void asc_scene_draw_sprites(
+static void asc_scene_draw2d(
         const AscScene *scene,
         const CxList *opaque,
         const CxList *blend
@@ -85,25 +84,25 @@
     glClear(GL_DEPTH_BUFFER_BIT);
     const AscCamera *camera = asc_scene_camera(scene);
 
-    // render opaque sprites from front to back
+    // render opaque nodes from front to back
     CxIterator iter_opaque = cxListBackwardsIterator(opaque);
 
-    // render sprites with alpha value from back to front
+    // render nodes with alpha blending from back to front
     CxIterator iter_blend = cxListIterator(blend);
 
     // TODO: implement interleaving by depth
     // TODO: implement sorting by shader ID to reduce shader switches
     if (cxIteratorValid(iter_opaque)) {
         glDisable(GL_BLEND);
-        cx_foreach(const AscSprite*, node, iter_opaque) {
-            asc_sprite_draw(camera, node);
+        cx_foreach(const AscSceneNode*, node, iter_opaque) {
+            node->draw_func(camera, node);
         }
     }
     if (cxIteratorValid(iter_blend)) {
         glEnable(GL_BLEND);
         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-        cx_foreach(const AscSprite*, node, iter_blend) {
-            asc_sprite_draw(camera, node);
+        cx_foreach(const AscSceneNode*, node, iter_blend) {
+            node->draw_func(camera, node);
         }
     }
 }
@@ -210,13 +209,9 @@
     asc_shader_use(NULL, NULL);
 
     // 2D Elements
-    // ===========
-
-    // Sprites
-    // -------
-    asc_scene_draw_sprites(scene,
-        render_group[ASC_RENDER_GROUP_SPRITE_OPAQUE],
-        render_group[ASC_RENDER_GROUP_SPRITE_BLEND]
+    asc_scene_draw2d(scene,
+        render_group[ASC_RENDER_GROUP_2D_OPAQUE],
+        render_group[ASC_RENDER_GROUP_2D_BLEND]
     );
 }
 
--- a/src/sprite.c	Sat Jun 14 11:40:40 2025 +0200
+++ b/src/sprite.c	Sat Jun 14 12:38:37 2025 +0200
@@ -106,6 +106,28 @@
     );
 }
 
+void asc_sprite_draw(const AscCamera *camera, const AscSceneNode *node) {
+    asc_ptr_cast(const AscSprite, sprite, node);
+
+    // Activate shader
+    // TODO: scene should know which shader we are going to activate s.t. it can pre-sort nodes
+    const AscSpriteShader *shader =
+            sprite->texture->target == GL_TEXTURE_RECTANGLE
+                ? asc_sprite_shader_rect()
+                : asc_sprite_shader_uv();
+    asc_shader_use(&shader->program, camera);
+
+    // Upload model matrix
+    glUniformMatrix4fv(shader->program.model, 1,
+                       GL_FALSE, node->world_transform);
+
+    // Bind texture
+    asc_texture_bind(sprite->texture, shader->tex, 0);
+
+    // Draw mesh
+    asc_mesh_draw_triangle_strip(&sprite->mesh);
+}
+
 AscSceneNode *asc_sprite_create(struct asc_sprite_create_args args) {
     AscSprite *sprite = cxZallocDefault(sizeof(AscSprite));
 
@@ -122,10 +144,11 @@
     AscSceneNode *node = (AscSceneNode *) sprite;
     asc_scene_node_name(node, args.name);
     node->render_group = args.opaque
-                             ? ASC_RENDER_GROUP_SPRITE_OPAQUE
-                             : ASC_RENDER_GROUP_SPRITE_BLEND;
+                             ? ASC_RENDER_GROUP_2D_OPAQUE
+                             : ASC_RENDER_GROUP_2D_BLEND;
     node->update_func = asc_sprite_update;
     node->destroy_func = asc_sprite_destroy;
+    node->draw_func = asc_sprite_draw;
 
     node->position = asc_vec3f_new(args.x, args.y, ASC_SCENE_2D_DEPTH_OFFSET);
     node->scale = asc_vec3f_one;
@@ -134,25 +157,6 @@
     return node;
 }
 
-void asc_sprite_draw(const AscCamera *camera, const AscSprite *node) {
-    // Activate shader
-    const AscSpriteShader *shader =
-            node->texture->target == GL_TEXTURE_RECTANGLE
-                ? asc_sprite_shader_rect()
-                : asc_sprite_shader_uv();
-    asc_shader_use(&shader->program, camera);
-
-    // Upload model matrix
-    glUniformMatrix4fv(shader->program.model, 1,
-                       GL_FALSE, node->data.world_transform);
-
-    // Bind texture
-    asc_texture_bind(node->texture, shader->tex, 0);
-
-    // 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;
--- a/src/text.c	Sat Jun 14 11:40:40 2025 +0200
+++ b/src/text.c	Sat Jun 14 12:38:37 2025 +0200
@@ -97,9 +97,10 @@
 
     // node properties
     asc_scene_node_name(node, args.name);
-    node->render_group = ASC_RENDER_GROUP_SPRITE_BLEND;
+    node->render_group = ASC_RENDER_GROUP_2D_BLEND;
     node->destroy_func = asc_text_destroy;
     node->update_func = asc_text_update;
+    node->draw_func = asc_sprite_draw;
     node->position = asc_vec3f_new(args.x, args.y, ASC_SCENE_2D_DEPTH_OFFSET);
     node->scale = asc_vec3f_one;
 

mercurial