From 80ffc30075f1bb0a3e9bcc60b971220f0d80d4d7 Mon Sep 17 00:00:00 2001 From: veclavtalica Date: Thu, 1 Aug 2024 00:52:15 +0300 Subject: [PATCH] texture_origin option for sprite rendering --- apps/testgame/scenes/ingame.c | 9 +++++---- townengine/macros/option.h | 19 +++++++++++++++++++ townengine/macros/varargcount.h | 4 ++-- townengine/rendering.h | 1 + townengine/rendering/internal_api.h | 8 ++++++-- townengine/rendering/sprites.h | 11 +++++++++++ townengine/vec.h | 8 ++++++++ 7 files changed, 52 insertions(+), 8 deletions(-) diff --git a/apps/testgame/scenes/ingame.c b/apps/testgame/scenes/ingame.c index 1e2bd24..a9e178b 100644 --- a/apps/testgame/scenes/ingame.c +++ b/apps/testgame/scenes/ingame.c @@ -54,10 +54,11 @@ static void ingame_tick(struct state *state) { input_set_mouse_captured(&ctx.input, !input_is_mouse_captured(&ctx.input)); } - m_sprite(m_set(path, "/assets/light.png"), - m_set(rect, ((t_frect){ 0, 128, 256, 32 })), - m_opt(color, ((t_color){ 255, 0, 0, 255 })), - m_opt(scale, false )); + m_sprite(m_set(path, "/assets/player/baron-walk.png"), + m_set(rect, ((t_frect){ 256, 256, 48, 48 })), + m_opt(color, ((t_color){ 255, 255, 255, 255 })), + m_opt(scale, false ), + m_opt(texture_origin, ((t_fvec2){ ctx.tick_count % 48, ctx.tick_count % 48 }))); m_sprite(m_set(path, "/assets/light.png"), m_set(rect, ((t_frect){ 48, 64, 64, 64 })), diff --git a/townengine/macros/option.h b/townengine/macros/option.h index 86cf119..2f73714 100644 --- a/townengine/macros/option.h +++ b/townengine/macros/option.h @@ -31,6 +31,10 @@ /* warn: beware of double evaluation! */ #define m_or(p_value, p_member, p_default) ((p_value).p_member##_opt_set ? (p_value).p_member##_opt : (p_default)) +/* warn: beware of double evaluation! */ +#define m_opt_from(p_member, p_value, p_member_from) .p_member##_opt = (p_value).p_member_from##_opt, \ + .p_member##_opt_set = (p_value).p_member_from##_opt_set + #define m_option_list_2(t0, m0) \ t0 m0##_opt; \ bool m0##_opt_set : 1; \ @@ -72,6 +76,21 @@ bool m3##_opt_set : 1; \ bool m4##_opt_set : 1; \ +#define m_option_list_12(t0, m0, t1, m1, t2, m2, \ + t3, m3, t4, m4, t5, m5) \ + t0 m0##_opt; \ + t1 m1##_opt; \ + t2 m2##_opt; \ + t3 m3##_opt; \ + t4 m4##_opt; \ + t5 m5##_opt; \ + bool m0##_opt_set : 1; \ + bool m1##_opt_set : 1; \ + bool m2##_opt_set : 1; \ + bool m3##_opt_set : 1; \ + bool m4##_opt_set : 1; \ + bool m5##_opt_set : 1; \ + #define m_option_list_(p_n, ...) m_concatenate(m_option_list_, p_n)(__VA_ARGS__) #define m_option_list(...) m_option_list_(m_narg(__VA_ARGS__), __VA_ARGS__) diff --git a/townengine/macros/varargcount.h b/townengine/macros/varargcount.h index 1cbef6a..636a9ed 100644 --- a/townengine/macros/varargcount.h +++ b/townengine/macros/varargcount.h @@ -3,7 +3,7 @@ #define m_narg(...) m_narg_(__VA_ARGS__, m_rseq_n_()) #define m_narg_(...) m_arg_n_(__VA_ARGS__) -#define m_arg_n_(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N -#define m_rseq_n_() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 +#define m_arg_n_(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, N, ...) N +#define m_rseq_n_() 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 #endif diff --git a/townengine/rendering.h b/townengine/rendering.h index b212e2c..7dbc367 100644 --- a/townengine/rendering.h +++ b/townengine/rendering.h @@ -14,6 +14,7 @@ typedef struct push_sprite_args { t_frect rect; m_option_list( + t_fvec2, texture_origin, t_color, color, float, rotation, bool, flip_x, diff --git a/townengine/rendering/internal_api.h b/townengine/rendering/internal_api.h index fed3aeb..4049e52 100644 --- a/townengine/rendering/internal_api.h +++ b/townengine/rendering/internal_api.h @@ -1,8 +1,9 @@ #ifndef RENDERING_INTERNAL_API_H #define RENDERING_INTERNAL_API_H -#include "../util.h" -#include "../textures/internal_api.h" +#include "townengine/textures/internal_api.h" +#include "townengine/util.h" +#include "townengine/macros/option.h" #include #include @@ -17,6 +18,9 @@ struct sprite_primitive { bool flip_x; bool flip_y; bool repeat; + + m_option_list( + t_fvec2, texture_origin ) }; struct rect_primitive { diff --git a/townengine/rendering/sprites.h b/townengine/rendering/sprites.h index ca95ad8..8eaf95d 100644 --- a/townengine/rendering/sprites.h +++ b/townengine/rendering/sprites.h @@ -70,6 +70,7 @@ void push_sprite(const t_push_sprite_args args) { .flip_x = m_or(args, flip_x, false), .flip_y = m_or(args, flip_y, false), .repeat = !m_or(args, scale, true), + m_opt_from(texture_origin, args, texture_origin) }; struct primitive_2d primitive = { @@ -220,6 +221,16 @@ static void render_sprites(const struct primitive_2d primitives[], uv1 = (t_fvec2){ rx * sprite.flip_x, ry * !sprite.flip_y }; uv2 = (t_fvec2){ rx * !sprite.flip_x, ry * !sprite.flip_y }; uv3 = (t_fvec2){ rx * !sprite.flip_x, ry * sprite.flip_y }; + + if (m_is_set(sprite, texture_origin)) { + /* displace origin */ + + const float ax = sprite.texture_origin_opt.x / srcrect.w; + const float ay = sprite.texture_origin_opt.y / srcrect.h; + + uv0.x += ax; uv1.x += ax; uv2.x += ax; uv3.x += ax; + uv0.y += ay; uv1.y += ay; uv2.y += ay; uv3.y += ay; + } } t_fvec2 v0, v1, v2, v3; diff --git a/townengine/vec.h b/townengine/vec.h index 768a3dc..3129a76 100644 --- a/townengine/vec.h +++ b/townengine/vec.h @@ -74,6 +74,10 @@ static inline t_fvec3 fvec3_sub(t_fvec3 a, t_fvec3 b) { return (t_fvec3) { a.x - b.x, a.y - b.y, a.z - b.z }; } +static inline t_fvec2 fvec2_div(t_fvec2 a, t_fvec2 b) { + return (t_fvec2) { a.x / b.x, a.y / b.y }; +} + static inline t_fvec2 fvec2_scale(t_fvec2 a, float s) { return (t_fvec2) { a.x * s, a.y * s }; } @@ -136,6 +140,10 @@ static inline t_fvec3 fvec3_rotate(t_fvec3 v, float angle, t_fvec3 axis) { t_fvec3: fvec3_sub \ )(p_any_vec0, p_any_vec1)) +#define m_vec_div(p_any_vec0, p_any_vec1) (_Generic((p_any_vec0), \ + t_fvec2: fvec2_div \ + )(p_any_vec0, p_any_vec1)) + #define m_vec_scale(p_any_vec, p_any_scalar) (_Generic((p_any_vec), \ t_fvec2: fvec2_scale, \ t_fvec3: fvec3_scale \