texture_origin option for sprite rendering

This commit is contained in:
veclav talica 2024-08-01 00:52:15 +03:00
parent 374a9b9c58
commit 80ffc30075
7 changed files with 52 additions and 8 deletions

View File

@ -54,10 +54,11 @@ static void ingame_tick(struct state *state) {
input_set_mouse_captured(&ctx.input, !input_is_mouse_captured(&ctx.input)); input_set_mouse_captured(&ctx.input, !input_is_mouse_captured(&ctx.input));
} }
m_sprite(m_set(path, "/assets/light.png"), m_sprite(m_set(path, "/assets/player/baron-walk.png"),
m_set(rect, ((t_frect){ 0, 128, 256, 32 })), m_set(rect, ((t_frect){ 256, 256, 48, 48 })),
m_opt(color, ((t_color){ 255, 0, 0, 255 })), m_opt(color, ((t_color){ 255, 255, 255, 255 })),
m_opt(scale, false )); 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_sprite(m_set(path, "/assets/light.png"),
m_set(rect, ((t_frect){ 48, 64, 64, 64 })), m_set(rect, ((t_frect){ 48, 64, 64, 64 })),

View File

@ -31,6 +31,10 @@
/* warn: beware of double evaluation! */ /* 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)) #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) \ #define m_option_list_2(t0, m0) \
t0 m0##_opt; \ t0 m0##_opt; \
bool m0##_opt_set : 1; \ bool m0##_opt_set : 1; \
@ -72,6 +76,21 @@
bool m3##_opt_set : 1; \ bool m3##_opt_set : 1; \
bool m4##_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_(p_n, ...) m_concatenate(m_option_list_, p_n)(__VA_ARGS__)
#define m_option_list(...) m_option_list_(m_narg(__VA_ARGS__), __VA_ARGS__) #define m_option_list(...) m_option_list_(m_narg(__VA_ARGS__), __VA_ARGS__)

View File

@ -3,7 +3,7 @@
#define m_narg(...) m_narg_(__VA_ARGS__, m_rseq_n_()) #define m_narg(...) m_narg_(__VA_ARGS__, m_rseq_n_())
#define m_narg_(...) m_arg_n_(__VA_ARGS__) #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_arg_n_(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, N, ...) N
#define m_rseq_n_() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 #define m_rseq_n_() 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
#endif #endif

View File

@ -14,6 +14,7 @@ typedef struct push_sprite_args {
t_frect rect; t_frect rect;
m_option_list( m_option_list(
t_fvec2, texture_origin,
t_color, color, t_color, color,
float, rotation, float, rotation,
bool, flip_x, bool, flip_x,

View File

@ -1,8 +1,9 @@
#ifndef RENDERING_INTERNAL_API_H #ifndef RENDERING_INTERNAL_API_H
#define RENDERING_INTERNAL_API_H #define RENDERING_INTERNAL_API_H
#include "../util.h" #include "townengine/textures/internal_api.h"
#include "../textures/internal_api.h" #include "townengine/util.h"
#include "townengine/macros/option.h"
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <glad/glad.h> #include <glad/glad.h>
@ -17,6 +18,9 @@ struct sprite_primitive {
bool flip_x; bool flip_x;
bool flip_y; bool flip_y;
bool repeat; bool repeat;
m_option_list(
t_fvec2, texture_origin )
}; };
struct rect_primitive { struct rect_primitive {

View File

@ -70,6 +70,7 @@ void push_sprite(const t_push_sprite_args args) {
.flip_x = m_or(args, flip_x, false), .flip_x = m_or(args, flip_x, false),
.flip_y = m_or(args, flip_y, false), .flip_y = m_or(args, flip_y, false),
.repeat = !m_or(args, scale, true), .repeat = !m_or(args, scale, true),
m_opt_from(texture_origin, args, texture_origin)
}; };
struct primitive_2d primitive = { 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 }; uv1 = (t_fvec2){ rx * sprite.flip_x, ry * !sprite.flip_y };
uv2 = (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 }; 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; t_fvec2 v0, v1, v2, v3;

View File

@ -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 }; 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) { static inline t_fvec2 fvec2_scale(t_fvec2 a, float s) {
return (t_fvec2) { a.x * s, a.y * 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 \ t_fvec3: fvec3_sub \
)(p_any_vec0, p_any_vec1)) )(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), \ #define m_vec_scale(p_any_vec, p_any_scalar) (_Generic((p_any_vec), \
t_fvec2: fvec2_scale, \ t_fvec2: fvec2_scale, \
t_fvec3: fvec3_scale \ t_fvec3: fvec3_scale \