skew testing

This commit is contained in:
jacob 2024-08-26 14:48:40 -05:00
parent 8bcc0bd356
commit 4ce85c1bef
3 changed files with 72 additions and 82 deletions

View File

@ -124,10 +124,12 @@ INTERNAL void spawn_test_entities(void)
struct v2 pos = V2(-1, -1); struct v2 pos = V2(-1, -1);
struct v2 size = V2(1, 1); struct v2 size = V2(1, 1);
f32 r = 0; f32 r = 0;
f32 skew = PI / 4;
struct entity *e = entity_alloc(root); struct entity *e = entity_alloc(root);
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size); struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
xf = xform_skewed_to(xf, skew);
entity_set_xform(e, xf); entity_set_xform(e, xf);
e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase")); e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase"));
@ -463,9 +465,9 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
f32 rot = v2_angle(dir) + PI / 2; f32 rot = v2_angle(dir) + PI / 2;
struct xform xf = XFORM_IDENT; struct xform xf = XFORM_IDENT;
xf = xform_rotate(xf, -rot); xf = xform_rotated(xf, -rot);
xf = xform_scale(xf, sprite_size); xf = xform_scaled(xf, sprite_size);
xf = xform_translate(xf, v2_neg(slice.center)); xf = xform_translated(xf, v2_neg(slice.center));
ent->sprite_local_xform = xf; ent->sprite_local_xform = xf;
} }
@ -491,7 +493,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
struct xform xf = entity_get_xform(ent); struct xform xf = entity_get_xform(ent);
xf.og = attach_pos; xf.og = attach_pos;
xf = xform_with_rotation(xf, v2_angle(attach_dir) + PI / 2); xf = xform_rotated_to(xf, v2_angle(attach_dir) + PI / 2);
entity_set_xform(ent, xf); entity_set_xform(ent, xf);
} }
} }
@ -586,8 +588,8 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
struct xform xf = entity_get_local_xform(ent); struct xform xf = entity_get_local_xform(ent);
xf.og = og; xf.og = og;
xf = xform_with_rotation(xf, r); xf = xform_rotated_to(xf, r);
xf = xform_with_scale(xf, s); xf = xform_scaled_to(xf, s);
entity_set_local_xform(ent, xf); entity_set_local_xform(ent, xf);
} }
} }
@ -797,7 +799,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
f32 forward_hold_angle_offset; f32 forward_hold_angle_offset;
{ {
struct xform xf_unrotated = xform_with_rotation(xf, 0); struct xform xf_unrotated = xform_rotated_to(xf, 0);
struct v2 hold_pos_unrotated = xform_mul_v2(xf_unrotated, xform_mul_v2(ent->sprite_local_xform, slice.center)); struct v2 hold_pos_unrotated = xform_mul_v2(xf_unrotated, xform_mul_v2(ent->sprite_local_xform, slice.center));
forward_hold_angle_offset = v2_angle_from_dirs(V2(0, -1), v2_sub(hold_pos_unrotated, xf_unrotated.og)); forward_hold_angle_offset = v2_angle_from_dirs(V2(0, -1), v2_sub(hold_pos_unrotated, xf_unrotated.og));
} }
@ -807,15 +809,15 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
struct v2 hold_pos; struct v2 hold_pos;
{ {
struct xform hold_pos_xf = xform_translate(ent->sprite_local_xform, slice.center); struct xform hold_pos_xf = xform_translated(ent->sprite_local_xform, slice.center);
hold_pos_xf = xform_mul(xf, hold_pos_xf); hold_pos_xf = xform_mul(xf, hold_pos_xf);
struct v2 hold_pos_xf_dir = xform_basis_mul_v2(hold_pos_xf, slice.dir); struct v2 hold_pos_xf_dir = xform_basis_mul_v2(hold_pos_xf, slice.dir);
hold_pos_xf = xform_with_rotation(hold_pos_xf, v2_angle(hold_pos_xf_dir) + PI / 2); hold_pos_xf = xform_rotated_to(hold_pos_xf, v2_angle(hold_pos_xf_dir) + PI / 2);
if (v2_eq(hold_pos_xf.og, ent_pos)) { if (v2_eq(hold_pos_xf.og, ent_pos)) {
/* If hold pos is same as origin (E.G if pivot is being used as hold pos), then move hold pos forward a tad to avoid issue */ /* If hold pos is same as origin (E.G if pivot is being used as hold pos), then move hold pos forward a tad to avoid issue */
hold_pos_xf = xform_translate(hold_pos_xf, V2(0, -1)); hold_pos_xf = xform_translated(hold_pos_xf, V2(0, -1));
} }
hold_pos = hold_pos_xf.og; hold_pos = hold_pos_xf.og;
} }
@ -837,7 +839,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
if (!F32_IS_NAN(final_xf_angle)) { if (!F32_IS_NAN(final_xf_angle)) {
const f32 angle_error_allowed = 0.001; const f32 angle_error_allowed = 0.001;
if (math_fabs(final_xf_angle - v2_angle(xf.bx)) > angle_error_allowed) { if (math_fabs(final_xf_angle - v2_angle(xf.bx)) > angle_error_allowed) {
xf = xform_with_rotation(xf, final_xf_angle); xf = xform_rotated_to(xf, final_xf_angle);
} }
} }

View File

@ -629,6 +629,13 @@ INLINE struct v2 v2_lerp(struct v2 val0, struct v2 val1, f32 t)
return res; return res;
} }
INLINE struct v2 v2_rotated(struct v2 v, f32 a)
{
f32 sin = math_sin(a);
f32 cos = math_cos(a);
return V2(v.x * cos - v.y * sin, v.x * sin + v.y * cos);
}
INLINE struct v2 v2_from_angle(f32 a) INLINE struct v2 v2_from_angle(f32 a)
{ {
return V2(math_cos(a), math_sin(a)); return V2(math_cos(a), math_sin(a));
@ -738,15 +745,15 @@ INLINE struct mat4x4 mat4x4_mul(struct mat4x4 m1, struct mat4x4 m2)
/* Takes a translation, rotation, and scale as optional parameters for constructing an xform */ /* Takes a translation, rotation, and scale as optional parameters for constructing an xform */
#define XFORM_TRS(...) xform_from_trs((struct trs) { .t = V2(0,0), .s = V2(1, 1), .r = 0, __VA_ARGS__ }) #define XFORM_TRS(...) xform_from_trs((struct trs) { .t = V2(0,0), .s = V2(1, 1), .r = 0, __VA_ARGS__ })
INLINE struct xform xform_rotate(struct xform xf, f32 angle); INLINE struct xform xform_rotated(struct xform xf, f32 angle);
INLINE struct xform xform_scale(struct xform xf, struct v2 v); INLINE struct xform xform_scaled(struct xform xf, struct v2 v);
INLINE struct v2 xform_basis_mul_v2(struct xform xf, struct v2 v); INLINE struct v2 xform_basis_mul_v2(struct xform xf, struct v2 v);
INLINE struct v2 xform_mul_v2(struct xform xf, struct v2 v); INLINE struct v2 xform_mul_v2(struct xform xf, struct v2 v);
INLINE struct xform xform_with_scale(struct xform xf, struct v2 s); INLINE struct xform xform_scaled_to(struct xform xf, struct v2 s);
INLINE f32 xform_get_determinant(struct xform xf); INLINE f32 xform_get_determinant(struct xform xf);
INLINE struct v2 xform_get_scale(struct xform xf); INLINE struct v2 xform_get_scale(struct xform xf);
INLINE struct trs trs_from_xform(struct xform m); INLINE f32 xform_get_skew(struct xform xf);
INLINE struct trs trs_lerp(struct trs a, struct trs b, f32 t); INLINE struct xform xform_skewed_to(struct xform xf, f32 s);
INLINE b32 xform_eq(struct xform xf1, struct xform xf2) INLINE b32 xform_eq(struct xform xf1, struct xform xf2)
{ {
@ -765,93 +772,105 @@ INLINE struct xform xform_from_pos(struct v2 v)
INLINE struct xform xform_from_trs(struct trs trs) INLINE struct xform xform_from_trs(struct trs trs)
{ {
struct xform xf = XFORM_POS(trs.t); struct xform xf = XFORM_POS(trs.t);
xf = xform_rotate(xf, trs.r); xf = xform_rotated(xf, trs.r);
xf = xform_scale(xf, trs.s); xf = xform_scaled(xf, trs.s);
return xf; return xf;
} }
INLINE struct xform xform_translate(struct xform xf, struct v2 v) INLINE struct xform xform_translated(struct xform xf, struct v2 v)
{ {
xf.og = V2( xf.og = V2(
xf.bx.x * v.x + xf.by.x * v.y + xf.og.x, xf.bx.x * v.x + xf.by.x * v.y + xf.og.x,
xf.bx.y * v.x + xf.by.y * v.y + xf.og.y xf.bx.y * v.x + xf.by.y * v.y + xf.og.y
); );
return xf; return xf;
} }
INLINE struct xform xform_rotate(struct xform xf, f32 angle) INLINE struct xform xform_rotated(struct xform xf, f32 angle)
{ {
f32 c = math_cos(angle); f32 c = math_cos(angle);
f32 s = math_sin(angle); f32 s = math_sin(angle);
struct xform res = xf; struct xform res = xf;
res.bx.x = xf.bx.x * c + xf.by.x * s; res.bx.x = xf.bx.x * c + xf.by.x * s;
res.bx.y = xf.bx.y * c + xf.by.y * s; res.bx.y = xf.bx.y * c + xf.by.y * s;
res.by.x = xf.bx.x * -s + xf.by.x * c; res.by.x = xf.bx.x * -s + xf.by.x * c;
res.by.y = xf.bx.y * -s + xf.by.y * c; res.by.y = xf.bx.y * -s + xf.by.y * c;
return res; return res;
} }
INLINE struct xform xform_scale(struct xform xf, struct v2 v) INLINE struct xform xform_scaled(struct xform xf, struct v2 v)
{ {
xf.bx = v2_mul(xf.bx, v.x); xf.bx = v2_mul(xf.bx, v.x);
xf.by = v2_mul(xf.by, v.y); xf.by = v2_mul(xf.by, v.y);
return xf; return xf;
} }
INLINE struct xform xform_with_rotation(struct xform xf, f32 r) INLINE struct xform xform_rotated_to(struct xform xf, f32 r)
{ {
struct v2 scale = xform_get_scale(xf); struct v2 scale = xform_get_scale(xf);
f32 skew = xform_get_skew(xf);
f32 c = math_cos(r); f32 c = math_cos(r);
f32 s = math_sin(r); f32 s = math_sin(r);
xf.bx = V2(c, s); xf.bx = V2(c, s);
xf.by = V2(-s, c); xf.by = V2(-s, c);
xf = xform_with_scale(xf, scale); xf = xform_scaled_to(xf, scale);
xf = xform_skewed_to(xf, skew);
return xf; return xf;
} }
INLINE struct xform xform_with_scale(struct xform xf, struct v2 s) INLINE struct xform xform_scaled_to(struct xform xf, struct v2 s)
{ {
xf.bx = v2_mul(v2_norm(xf.bx), s.x); xf.bx = v2_mul(v2_norm(xf.bx), s.x);
xf.by = v2_mul(v2_norm(xf.by), s.y); xf.by = v2_mul(v2_norm(xf.by), s.y);
return xf; return xf;
} }
INLINE struct xform xform_skewed_to(struct xform xf, f32 s)
{
i32 det_sign = math_fsign(xform_get_determinant(xf));
struct v2 by = xf.by;
f32 len = v2_len(by);
/* TODO: Is norm & mul by len really necessary? */
by = v2_mul(v2_norm(v2_rotated(xf.bx, PI * 0.5f + s)), len);
by = v2_mul(by, det_sign);
xf.by = by;
return xf;
}
INLINE struct xform xform_trs(struct xform xf, struct trs trs) INLINE struct xform xform_trs(struct xform xf, struct trs trs)
{ {
xf = xform_translate(xf, trs.t); xf = xform_translated(xf, trs.t);
xf = xform_rotate(xf, trs.r); xf = xform_rotated(xf, trs.r);
xf = xform_scale(xf, trs.s); xf = xform_scaled(xf, trs.s);
return xf; return xf;
} }
INLINE struct xform xform_trs_pivot_r(struct xform xf, struct trs trs, struct v2 pivot) INLINE struct xform xform_trs_pivot_r(struct xform xf, struct trs trs, struct v2 pivot)
{ {
xf = xform_translate(xf, trs.t); xf = xform_translated(xf, trs.t);
xf = xform_rotate(xf, trs.r); xf = xform_rotated(xf, trs.r);
xf = xform_translate(xf, v2_neg(pivot)); xf = xform_translated(xf, v2_neg(pivot));
xf = xform_scale(xf, trs.s); xf = xform_scaled(xf, trs.s);
return xf; return xf;
} }
INLINE struct xform xform_trs_pivot_rs(struct xform xf, struct trs trs, struct v2 pivot) INLINE struct xform xform_trs_pivot_rs(struct xform xf, struct trs trs, struct v2 pivot)
{ {
xf = xform_translate(xf, trs.t); xf = xform_translated(xf, trs.t);
xf = xform_rotate(xf, trs.r); xf = xform_rotated(xf, trs.r);
xf = xform_scale(xf, trs.s); xf = xform_scaled(xf, trs.s);
xf = xform_translate(xf, v2_neg(pivot)); xf = xform_translated(xf, v2_neg(pivot));
return xf; return xf;
} }
INLINE struct xform xform_lerp(struct xform a, struct xform b, f32 t) INLINE struct xform xform_lerp(struct xform a, struct xform b, f32 t)
{ {
struct trs trs_a = trs_from_xform(a); struct xform res;
struct trs trs_b = trs_from_xform(b); res.og = v2_lerp(a.og, b.og, t);
struct trs trs = trs_lerp(trs_a, trs_b, t); res.bx = v2_lerp(a.bx, b.bx, t);
return xform_from_trs(trs); res.by = v2_lerp(a.by, b.by, t);
return res;
} }
INLINE struct xform xform_invert(struct xform xf) INLINE struct xform xform_invert(struct xform xf)
@ -874,13 +893,11 @@ INLINE struct xform xform_invert(struct xform xf)
INLINE struct xform xform_mul(struct xform a, struct xform b) INLINE struct xform xform_mul(struct xform a, struct xform b)
{ {
struct xform res; struct xform res;
res.bx.x = a.bx.x * b.bx.x + a.by.x * b.bx.y; res.bx.x = a.bx.x * b.bx.x + a.by.x * b.bx.y;
res.bx.y = a.bx.y * b.bx.x + a.by.y * b.bx.y; res.bx.y = a.bx.y * b.bx.x + a.by.y * b.bx.y;
res.by.x = a.bx.x * b.by.x + a.by.x * b.by.y; res.by.x = a.bx.x * b.by.x + a.by.x * b.by.y;
res.by.y = a.bx.y * b.by.x + a.by.y * b.by.y; res.by.y = a.bx.y * b.by.x + a.by.y * b.by.y;
res.og = xform_mul_v2(a, b.og); res.og = xform_mul_v2(a, b.og);
return res; return res;
} }
@ -931,15 +948,8 @@ INLINE f32 xform_get_determinant(struct xform xf)
INLINE f32 xform_get_skew(struct xform xf) INLINE f32 xform_get_skew(struct xform xf)
{ {
f32 det = xform_get_determinant(xf); i32 det_sign = math_fsign(xform_get_determinant(xf));
i32 det_sign = math_fsign(det); f32 dot = v2_dot(v2_norm(xf.bx), v2_norm(xf.by)) * det_sign;
struct v2 bx_norm = v2_norm(xf.bx);
struct v2 by_norm = v2_norm(xf.by);
by_norm = v2_mul(by_norm, det_sign);
f32 dot = v2_dot(bx_norm, by_norm);
return math_acos(dot) - (PI / 2.0f); return math_acos(dot) - (PI / 2.0f);
} }
@ -974,28 +984,6 @@ INLINE struct v2 xform_get_scale(struct xform xf)
return V2(v2_len(xf.bx), det_sign * v2_len(xf.by)); return V2(v2_len(xf.bx), det_sign * v2_len(xf.by));
} }
/* ========================== *
* Trs
* ========================== */
INLINE struct trs trs_lerp(struct trs a, struct trs b, f32 t)
{
struct trs res;
res.t = v2_lerp(a.t, b.t, t);
res.r = math_lerp_angle(a.r, b.r, t);
res.s = v2_lerp(a.s, b.s, t);
return res;
}
INLINE struct trs trs_from_xform(struct xform xf)
{
struct trs trs = { 0 };
trs.t = xf.og;
trs.r = xform_get_rotation(xf);
trs.s = xform_get_scale(xf);
return trs;
}
/* ========================== * /* ========================== *
* Quad * Quad
* ========================== */ * ========================== */

View File

@ -661,7 +661,7 @@ INTERNAL void user_update(void)
* ========================== */ * ========================== */
if (G.debug_camera) { if (G.debug_camera) {
G.world_view = xform_with_rotation(G.world_view, 0); G.world_view = xform_rotated_to(G.world_view, 0);
/* Pan view */ /* Pan view */
if (G.bind_states[USER_BIND_KIND_PAN].is_held) { if (G.bind_states[USER_BIND_KIND_PAN].is_held) {
@ -670,7 +670,7 @@ INTERNAL void user_update(void)
} }
G.debug_camera_panning = true; G.debug_camera_panning = true;
struct v2 offset = v2_sub(G.debug_camera_pan_start, xform_invert_mul_v2(G.world_view, G.viewport_cursor)); struct v2 offset = v2_sub(G.debug_camera_pan_start, xform_invert_mul_v2(G.world_view, G.viewport_cursor));
G.world_view = xform_translate(G.world_view, v2_neg(offset)); G.world_view = xform_translated(G.world_view, v2_neg(offset));
G.debug_camera_pan_start = xform_invert_mul_v2(G.world_view, G.viewport_cursor); G.debug_camera_pan_start = xform_invert_mul_v2(G.world_view, G.viewport_cursor);
} else { } else {
G.debug_camera_panning = false; G.debug_camera_panning = false;
@ -683,9 +683,9 @@ INTERNAL void user_update(void)
f32 zoom_rate = 2; f32 zoom_rate = 2;
f32 zoom = math_pow(zoom_rate, input_zooms); f32 zoom = math_pow(zoom_rate, input_zooms);
struct v2 world_cursor = xform_invert_mul_v2(G.world_view, G.viewport_cursor); struct v2 world_cursor = xform_invert_mul_v2(G.world_view, G.viewport_cursor);
G.world_view = xform_translate(G.world_view, world_cursor); G.world_view = xform_translated(G.world_view, world_cursor);
G.world_view = xform_scale(G.world_view, V2(zoom, zoom)); G.world_view = xform_scaled(G.world_view, V2(zoom, zoom));
G.world_view = xform_translate(G.world_view, v2_neg(world_cursor)); G.world_view = xform_translated(G.world_view, v2_neg(world_cursor));
} }
} else { } else {
struct xform xf = entity_get_xform(active_camera); struct xform xf = entity_get_xform(active_camera);
@ -712,7 +712,7 @@ INTERNAL void user_update(void)
struct v2 pivot = center; struct v2 pivot = center;
G.world_view = XFORM_IDENT; G.world_view = XFORM_IDENT;
G.world_view = xform_translate(G.world_view, pivot); G.world_view = xform_translated(G.world_view, pivot);
G.world_view = xform_trs_pivot_rs(G.world_view, trs, pivot); G.world_view = xform_trs_pivot_rs(G.world_view, trs, pivot);
} }
G.world_cursor = xform_invert_mul_v2(G.world_view, G.viewport_cursor); G.world_cursor = xform_invert_mul_v2(G.world_view, G.viewport_cursor);