rework transformation math functions, add separate 'world' transform functions
This commit is contained in:
parent
ed8b03941e
commit
7708b8e5b8
@ -37,12 +37,12 @@
|
|||||||
#define GAME_PHYSICS_ENABLE_RELAXATION 1
|
#define GAME_PHYSICS_ENABLE_RELAXATION 1
|
||||||
|
|
||||||
#define USER_DRAW_MENKOWSKI 0
|
#define USER_DRAW_MENKOWSKI 0
|
||||||
#define GAME_PHYSICS_ENABLE_GROUND_FRICTION 0
|
#define GAME_PHYSICS_ENABLE_GROUND_FRICTION 1
|
||||||
#define GAME_PHYSICS_ENABLE_COLLISION 1
|
#define GAME_PHYSICS_ENABLE_COLLISION 0
|
||||||
#define GAME_SPAWN_LOTS 0
|
#define GAME_SPAWN_LOTS 0
|
||||||
#define GAME_SPAWN_TESTENT 0
|
#define GAME_SPAWN_TESTENT 0
|
||||||
#define GAME_SPAWN_BOX 1
|
#define GAME_SPAWN_BOX 1
|
||||||
#define GAME_PLAYER_AIM 0
|
#define GAME_PLAYER_AIM 1
|
||||||
|
|
||||||
#define GAME_MAX_LINEAR_VELOCITY 100
|
#define GAME_MAX_LINEAR_VELOCITY 100
|
||||||
#define GAME_MAX_ANGULAR_VELOCITY ((2 * PI) * 20)
|
#define GAME_MAX_ANGULAR_VELOCITY ((2 * PI) * 20)
|
||||||
|
|||||||
169
src/game.c
169
src/game.c
@ -149,19 +149,20 @@ INTERNAL void spawn_test_entities(f32 offset)
|
|||||||
pos = v2_add(pos, V2(0, offset_all));
|
pos = v2_add(pos, V2(0, offset_all));
|
||||||
|
|
||||||
//struct v2 size = V2(1, 1);
|
//struct v2 size = V2(1, 1);
|
||||||
struct v2 size = V2(0.5, 0.5);
|
//struct v2 size = V2(0.5, 0.5);
|
||||||
//struct v2 size = V2(0.5, 0.25);
|
struct v2 size = V2(0.5, 0.25);
|
||||||
//struct v2 size = V2(1.0, 1.0);
|
//struct v2 size = V2(1.0, 1.0);
|
||||||
//struct v2 size = V2(1.5, 1.5);
|
//struct v2 size = V2(1.5, 1.5);
|
||||||
f32 r = PI;
|
//f32 r = PI;
|
||||||
//f32 r = PI / 4;
|
//f32 r = PI / 4;
|
||||||
//f32 r = PI / 3;
|
//f32 r = PI / 3;
|
||||||
//f32 r = 0.05;
|
//f32 r = 0.05;
|
||||||
//f32 r = PI / 2;
|
//f32 r = PI / 2;
|
||||||
//f32 r = PI;
|
//f32 r = PI;
|
||||||
//f32 r = 0;
|
f32 r = 0;
|
||||||
|
|
||||||
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
||||||
|
//xf.bx.y = -1.f;
|
||||||
#else
|
#else
|
||||||
struct xform xf = { .bx = {0.0382978655, -0.498547733}, .by = {0.498547733, 0.0382978655}, .og = {2.01672602, -1.06180537}, };
|
struct xform xf = { .bx = {0.0382978655, -0.498547733}, .by = {0.498547733, 0.0382978655}, .og = {2.01672602, -1.06180537}, };
|
||||||
#endif
|
#endif
|
||||||
@ -194,7 +195,7 @@ INTERNAL void spawn_test_entities(f32 offset)
|
|||||||
e->linear_ground_friction = 200;
|
e->linear_ground_friction = 200;
|
||||||
e->angular_ground_friction = 100;
|
e->angular_ground_friction = 100;
|
||||||
|
|
||||||
//entity_enable_prop(e, ENTITY_PROP_TEST);
|
entity_enable_prop(e, ENTITY_PROP_TEST);
|
||||||
|
|
||||||
player_ent = e;
|
player_ent = e;
|
||||||
}
|
}
|
||||||
@ -821,27 +822,12 @@ INTERNAL void integrate_positions_from_velocities(f32 dt)
|
|||||||
ent->linear_velocity = v2_clamp_len(ent->linear_velocity, GAME_MAX_LINEAR_VELOCITY);
|
ent->linear_velocity = v2_clamp_len(ent->linear_velocity, GAME_MAX_LINEAR_VELOCITY);
|
||||||
ent->angular_velocity = clamp_f32(ent->angular_velocity, -GAME_MAX_ANGULAR_VELOCITY, GAME_MAX_ANGULAR_VELOCITY);
|
ent->angular_velocity = clamp_f32(ent->angular_velocity, -GAME_MAX_ANGULAR_VELOCITY, GAME_MAX_ANGULAR_VELOCITY);
|
||||||
|
|
||||||
#if 0
|
|
||||||
struct xform xf = entity_get_xform(ent);
|
struct xform xf = entity_get_xform(ent);
|
||||||
struct v2 tick_linear_velocity = v2_mul(ent->linear_velocity, dt);
|
struct v2 tick_linear_velocity = v2_mul(ent->linear_velocity, dt);
|
||||||
f32 tick_angular_velocity = ent->angular_velocity * dt;
|
f32 tick_angular_velocity = ent->angular_velocity * dt;
|
||||||
xf.og = v2_add(xf.og, tick_linear_velocity);
|
xf.og = v2_add(xf.og, tick_linear_velocity);
|
||||||
xf = xform_rotated(xf, tick_angular_velocity);
|
xf = xform_basis_rotated_world(xf, tick_angular_velocity);
|
||||||
entity_set_xform(ent, xf);
|
entity_set_xform(ent, xf);
|
||||||
#else
|
|
||||||
struct xform xf = entity_get_xform(ent);
|
|
||||||
struct v2 tick_linear_velocity = v2_mul(ent->linear_velocity, dt);
|
|
||||||
f32 tick_angular_velocity = ent->angular_velocity * dt;
|
|
||||||
xf.og = v2_add(xf.og, tick_linear_velocity);
|
|
||||||
|
|
||||||
//xf = xform_rotated_to(xf, xform_get_rotation(xf) + tick_angular_velocity);
|
|
||||||
|
|
||||||
f32 old_angle = xform_get_rotation(xf);
|
|
||||||
f32 new_angle = old_angle + tick_angular_velocity;
|
|
||||||
xf = xform_rotated_to(xf, new_angle);
|
|
||||||
|
|
||||||
entity_set_xform(ent, xf);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1048,15 +1034,17 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
{
|
{
|
||||||
struct xform cxf = ent->sprite_local_xform;
|
struct xform cxf = ent->sprite_local_xform;
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (entity_has_prop(ent, ENTITY_PROP_TEST)) {
|
if (entity_has_prop(ent, ENTITY_PROP_TEST)) {
|
||||||
f32 scale = 0.5;
|
f32 scale = 0.5;
|
||||||
cxf = xform_scaled(cxf, V2(scale, scale));
|
cxf = xform_scaled(cxf, V2(scale, scale));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("shape"), ent->animation_frame);
|
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("shape"), ent->animation_frame);
|
||||||
ent->local_collider = collider_from_quad(xform_mul_quad(cxf, quad_from_rect(slice.rect)));
|
ent->local_collider = collider_from_quad(xform_mul_quad(cxf, quad_from_rect(slice.rect)));
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
if (entity_has_prop(ent, ENTITY_PROP_TEST)) {
|
if (entity_has_prop(ent, ENTITY_PROP_TEST)) {
|
||||||
//if ((true)) {
|
//if ((true)) {
|
||||||
#if 1
|
#if 1
|
||||||
@ -1113,7 +1101,7 @@ 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 = attach_pos;
|
xf.og = attach_pos;
|
||||||
xf = xform_rotated_to(xf, v2_angle(attach_dir) + PI / 2);
|
xf = xform_basis_with_rotation_world(xf, v2_angle(attach_dir) + PI / 2);
|
||||||
entity_set_local_xform(ent, xf);
|
entity_set_local_xform(ent, xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1222,8 +1210,8 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
(UNUSED)scale;
|
(UNUSED)scale;
|
||||||
|
|
||||||
struct xform xf = entity_get_local_xform(ent);
|
struct xform xf = entity_get_local_xform(ent);
|
||||||
//xf = xform_rotated_to(xf, rot);
|
xf = xform_rotated_to(xf, rot);
|
||||||
//xf = xform_scaled_to(xf, scale);
|
xf = xform_scaled_to(xf, scale);
|
||||||
entity_set_local_xform(ent, xf);
|
entity_set_local_xform(ent, xf);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -1328,39 +1316,39 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
|
|
||||||
if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) {
|
if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) {
|
||||||
struct xform xf = entity_get_xform(ent);
|
struct xform xf = entity_get_xform(ent);
|
||||||
|
struct xform sprite_xf = xform_mul(xf, ent->sprite_local_xform);
|
||||||
|
f32 old_angle = xform_get_rotation(xf);
|
||||||
|
|
||||||
/* Solve for final angle using law of sines */
|
/* Solve for final angle using law of sines */
|
||||||
f32 final_xf_angle;
|
f32 final_xf_angle;
|
||||||
{
|
{
|
||||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite);
|
|
||||||
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("attach.wep"), ent->animation_frame);
|
|
||||||
|
|
||||||
f32 forward_hold_angle_offset;
|
|
||||||
{
|
|
||||||
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));
|
|
||||||
forward_hold_angle_offset = v2_angle_from_dirs(V2(0, -1), v2_sub(hold_pos_unrotated, xf_unrotated.og));
|
|
||||||
}
|
|
||||||
|
|
||||||
struct v2 ent_pos = xf.og;
|
struct v2 ent_pos = xf.og;
|
||||||
struct v2 focus_pos = v2_add(ent_pos, ent->control.focus);
|
struct v2 focus_pos = v2_add(ent_pos, ent->control.focus);
|
||||||
|
|
||||||
struct v2 hold_pos;
|
struct v2 sprite_hold_pos;
|
||||||
|
struct v2 sprite_hold_dir;
|
||||||
{
|
{
|
||||||
struct xform hold_pos_xf = xform_translated(ent->sprite_local_xform, slice.center);
|
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite);
|
||||||
hold_pos_xf = xform_mul(xf, hold_pos_xf);
|
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("attach.wep"), ent->animation_frame);
|
||||||
|
sprite_hold_pos = slice.center;
|
||||||
|
sprite_hold_dir = slice.dir;
|
||||||
|
}
|
||||||
|
|
||||||
struct v2 hold_pos_xf_dir = xform_basis_mul_v2(hold_pos_xf, slice.dir);
|
struct v2 hold_dir = xform_basis_mul_v2(sprite_xf, sprite_hold_dir);
|
||||||
hold_pos_xf = xform_rotated_to(hold_pos_xf, v2_angle(hold_pos_xf_dir) + PI / 2);
|
struct v2 hold_pos = xform_mul_v2(sprite_xf, sprite_hold_pos);
|
||||||
|
if (v2_eq(hold_pos, 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_translated(hold_pos_xf, V2(0, -1));
|
sprite_hold_pos = v2_add(sprite_hold_pos, V2(0, -1));
|
||||||
}
|
hold_pos = xform_mul_v2(sprite_xf, sprite_hold_pos);
|
||||||
hold_pos = hold_pos_xf.og;
|
}
|
||||||
|
|
||||||
|
f32 forward_hold_angle_offset;
|
||||||
|
{
|
||||||
|
struct xform xf_unrotated = xform_basis_with_rotation_world(xf, 0);
|
||||||
|
struct v2 hold_pos_unrotated = xform_mul_v2(xf_unrotated, xform_mul_v2(ent->sprite_local_xform, sprite_hold_pos));
|
||||||
|
forward_hold_angle_offset = v2_angle_from_dirs(V2(0, -1), v2_sub(hold_pos_unrotated, xf_unrotated.og));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2 hold_dir = xform_basis_mul_v2(xf, xform_basis_mul_v2(ent->sprite_local_xform, slice.dir));
|
|
||||||
struct v2 hold_ent_dir = v2_sub(ent_pos, hold_pos);
|
struct v2 hold_ent_dir = v2_sub(ent_pos, hold_pos);
|
||||||
struct v2 focus_ent_dir = v2_sub(ent_pos, focus_pos);
|
struct v2 focus_ent_dir = v2_sub(ent_pos, focus_pos);
|
||||||
|
|
||||||
@ -1376,98 +1364,15 @@ 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) {
|
f32 diff = final_xf_angle - old_angle;
|
||||||
xf = xform_rotated_to(xf, final_xf_angle);
|
if (math_fabs(diff) > angle_error_allowed) {
|
||||||
|
xf = xform_basis_rotated_world(xf, diff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
entity_set_xform(ent, xf);
|
entity_set_xform(ent, xf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
|
|
||||||
struct entity *ent = &store->entities[entity_index];
|
|
||||||
if (!entity_is_valid_and_active(ent)) continue;
|
|
||||||
|
|
||||||
if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) {
|
|
||||||
struct xform xf = entity_get_xform(ent);
|
|
||||||
|
|
||||||
/* Solve for final angle using law of sines */
|
|
||||||
f32 final_xf_angle;
|
|
||||||
{
|
|
||||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite);
|
|
||||||
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("attach.wep"), ent->animation_frame);
|
|
||||||
|
|
||||||
f32 forward_hold_angle_offset;
|
|
||||||
{
|
|
||||||
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));
|
|
||||||
forward_hold_angle_offset = v2_angle_from_dirs(V2(0, -1), v2_sub(hold_pos_unrotated, xf_unrotated.og));
|
|
||||||
}
|
|
||||||
|
|
||||||
struct v2 ent_pos = xf.og;
|
|
||||||
struct v2 focus_pos = v2_add(ent_pos, ent->control.focus);
|
|
||||||
|
|
||||||
struct v2 hold_pos;
|
|
||||||
{
|
|
||||||
struct xform hold_pos_xf = xform_translated(ent->sprite_local_xform, slice.center);
|
|
||||||
hold_pos_xf = xform_mul(xf, hold_pos_xf);
|
|
||||||
|
|
||||||
struct v2 hold_pos_xf_dir = xform_basis_mul_v2(hold_pos_xf, slice.dir);
|
|
||||||
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 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_translated(hold_pos_xf, V2(0, -1));
|
|
||||||
}
|
|
||||||
hold_pos = hold_pos_xf.og;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct v2 hold_dir = xform_basis_mul_v2(xf, xform_basis_mul_v2(ent->sprite_local_xform, slice.dir));
|
|
||||||
struct v2 hold_ent_dir = v2_sub(ent_pos, hold_pos);
|
|
||||||
struct v2 focus_ent_dir = v2_sub(ent_pos, focus_pos);
|
|
||||||
|
|
||||||
f32 hold_ent_len = v2_len(hold_ent_dir);
|
|
||||||
f32 focus_ent_len = v2_len(focus_ent_dir);
|
|
||||||
|
|
||||||
f32 final_hold_angle_btw_ent_and_focus = v2_angle_from_dirs(hold_ent_dir, hold_dir);
|
|
||||||
f32 final_focus_angle_btw_ent_and_hold = math_asin((math_sin(final_hold_angle_btw_ent_and_focus) * hold_ent_len) / focus_ent_len);
|
|
||||||
f32 final_ent_angle_btw_focus_and_hold = PI - (final_focus_angle_btw_ent_and_hold + final_hold_angle_btw_ent_and_focus);
|
|
||||||
|
|
||||||
final_xf_angle = v2_angle_from_dirs(V2(0, -1), v2_sub(focus_pos, ent_pos)) + final_ent_angle_btw_focus_and_hold - forward_hold_angle_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!F32_IS_NAN(final_xf_angle)) {
|
|
||||||
const f32 angle_error_allowed = 0.001f;
|
|
||||||
f32 cur_angle = v2_angle(xf.bx);
|
|
||||||
f32 diff = final_xf_angle - cur_angle;
|
|
||||||
if (math_fabs(diff) > angle_error_allowed) {
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
#if 0
|
|
||||||
/* Create force */
|
|
||||||
struct entity *f = entity_alloc(ent);
|
|
||||||
entity_enable_prop(f, ENTITY_PROP_TORQUE);
|
|
||||||
|
|
||||||
i32 dir = math_fsign(diff);
|
|
||||||
f32 damp = math_fabs(math_fmod(diff, 2 * PI)) / (2 * PI);
|
|
||||||
f32 torque = ent->control_torque * dir * damp;
|
|
||||||
|
|
||||||
f->torque = torque;
|
|
||||||
activate_now(f);
|
|
||||||
#else
|
|
||||||
/* TODO: Remove this (testing) */
|
|
||||||
/* Create force */
|
|
||||||
if (!ent->test_torque_applied) {
|
|
||||||
ent->test_torque_applied = true;
|
|
||||||
entity_apply_angular_impulse(ent, 10);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
|
|||||||
167
src/math.h
167
src/math.h
@ -746,16 +746,11 @@ INLINE b32 v2_is_zero(struct v2 a)
|
|||||||
return a.x == 0 && a.y == 0;
|
return a.x == 0 && a.y == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 v2_lerp(struct v2 val0, struct v2 val1, f32 t)
|
|
||||||
{
|
|
||||||
return V2(math_lerp(val0.x, val1.x, t), math_lerp(val0.y, val1.y, t));
|
|
||||||
}
|
|
||||||
|
|
||||||
INLINE struct v2 v2_rotated(struct v2 v, f32 a)
|
INLINE struct v2 v2_rotated(struct v2 v, f32 a)
|
||||||
{
|
{
|
||||||
f32 sin = math_sin(a);
|
f32 c = math_cos(a);
|
||||||
f32 cos = math_cos(a);
|
f32 s = math_sin(a);
|
||||||
return V2(v.x * cos - v.y * sin, v.x * sin + v.y * cos);
|
return V2(v.x * c - v.y * s, v.x * s + v.y * c);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 v2_from_angle(f32 a)
|
INLINE struct v2 v2_from_angle(f32 a)
|
||||||
@ -786,6 +781,20 @@ INLINE struct v2 v2_closest_point_ray(struct v2 ray_pos, struct v2 ray_dir_norm,
|
|||||||
return v2_add(ray_pos, ray_dir_closest);
|
return v2_add(ray_pos, ray_dir_closest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Interpolate position vectors */
|
||||||
|
INLINE struct v2 v2_lerp(struct v2 val0, struct v2 val1, f32 t)
|
||||||
|
{
|
||||||
|
return V2(math_lerp(val0.x, val1.x, t), math_lerp(val0.y, val1.y, t));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interpolate direction vectors (spherical lerp) */
|
||||||
|
INLINE struct v2 v2_slerp(struct v2 val0, struct v2 val1, f32 t)
|
||||||
|
{
|
||||||
|
f32 rot = math_lerp_angle(v2_angle(val0), v2_angle(val1), t);
|
||||||
|
f32 len = math_lerp(v2_len(val0), v2_len(val1), t);
|
||||||
|
return v2_mul(v2_from_angle(rot), len);
|
||||||
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Mat4x4
|
* Mat4x4
|
||||||
* ========================== */
|
* ========================== */
|
||||||
@ -867,11 +876,11 @@ 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_mul(struct xform a, struct xform b);
|
||||||
INLINE struct xform xform_rotated(struct xform xf, f32 angle);
|
INLINE struct xform xform_rotated(struct xform xf, f32 angle);
|
||||||
INLINE struct xform xform_scaled(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_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 f32 xform_get_rotation(struct xform xf);
|
INLINE f32 xform_get_rotation(struct xform xf);
|
||||||
@ -890,6 +899,26 @@ INLINE struct xform xform_from_pos(struct v2 v)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INLINE struct xform xform_from_rotation(f32 r)
|
||||||
|
{
|
||||||
|
struct xform res;
|
||||||
|
f32 c = math_cos(r);
|
||||||
|
f32 s = math_sin(r);
|
||||||
|
res.bx = V2(c, s);
|
||||||
|
res.by = V2(-s, c);
|
||||||
|
res.og = V2(0, 0);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE struct xform xform_from_scale(struct v2 scale)
|
||||||
|
{
|
||||||
|
struct xform res;
|
||||||
|
res.bx = V2(scale.x, 0);
|
||||||
|
res.by = V2(0, scale.y);
|
||||||
|
res.og = V2(0, 0);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
@ -900,87 +929,63 @@ INLINE struct xform xform_from_trs(struct trs trs)
|
|||||||
|
|
||||||
INLINE struct xform xform_translated(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.y * v.x + xf.by.y * v.y + xf.og.y);
|
||||||
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
|
|
||||||
);
|
|
||||||
return xf;
|
return xf;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct xform xform_rotated(struct xform xf, f32 angle)
|
INLINE struct xform xform_translated_world(struct xform xf, struct v2 v)
|
||||||
{
|
{
|
||||||
f32 c = math_cos(angle);
|
xf.og = v2_add(xf.og, v);
|
||||||
f32 s = math_sin(angle);
|
return xf;
|
||||||
struct xform res = xf;
|
}
|
||||||
res.bx.x = xf.bx.x * c + xf.by.x * s;
|
|
||||||
res.bx.y = xf.bx.y * c + xf.by.y * s;
|
INLINE struct xform xform_rotated(struct xform xf, f32 r)
|
||||||
res.by.x = xf.bx.x * -s + xf.by.x * c;
|
{
|
||||||
res.by.y = xf.bx.y * -s + xf.by.y * c;
|
return xform_mul(xf, xform_from_rotation(r));
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE struct xform xform_rotated_world(struct xform xf, f32 r)
|
||||||
|
{
|
||||||
|
return xform_mul(xform_from_rotation(r), xf);
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE struct xform xform_basis_rotated_world(struct xform xf, f32 r)
|
||||||
|
{
|
||||||
|
f32 diff = r;
|
||||||
|
f32 c = math_cos(diff);
|
||||||
|
f32 s = math_sin(diff);
|
||||||
|
xf.bx = V2(xf.bx.x * c - xf.bx.y * s, xf.bx.x * s + xf.bx.y * c);
|
||||||
|
xf.by = V2(xf.by.x * c - xf.by.y * s, xf.by.x * s + xf.by.y * c);
|
||||||
|
return xf;
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE struct xform xform_basis_with_rotation_world(struct xform xf, f32 r)
|
||||||
|
{
|
||||||
|
return xform_basis_rotated_world(xf, r - xform_get_rotation(xf));
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE struct xform xform_scaled(struct xform xf, struct v2 scale)
|
||||||
|
{
|
||||||
|
xf.bx = v2_mul(xf.bx, scale.x);
|
||||||
|
xf.by = v2_mul(xf.by, scale.y);
|
||||||
|
return xf;
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE struct xform xform_scaled_world(struct xform xf, struct v2 scale)
|
||||||
|
{
|
||||||
|
struct xform res;
|
||||||
|
res.bx = v2_mul_v2(xf.bx, scale);
|
||||||
|
res.by = v2_mul_v2(xf.by, scale);
|
||||||
|
res.og = v2_mul_v2(xf.og, scale);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct xform xform_scaled(struct xform xf, struct v2 v)
|
|
||||||
{
|
|
||||||
xf.bx = v2_mul(xf.bx, v.x);
|
|
||||||
xf.by = v2_mul(xf.by, v.y);
|
|
||||||
return xf;
|
|
||||||
}
|
|
||||||
|
|
||||||
INLINE struct xform xform_rotated_to(struct xform xf, f32 r)
|
|
||||||
{
|
|
||||||
/* TODO: Maintain skew/shear? */
|
|
||||||
struct v2 scale = xform_get_scale(xf);
|
|
||||||
f32 c = math_cos(r);
|
|
||||||
f32 s = math_sin(r);
|
|
||||||
xf.bx = V2(c, s);
|
|
||||||
xf.by = V2(-s, c);
|
|
||||||
xf = xform_scaled_to(xf, scale);
|
|
||||||
return xf;
|
|
||||||
}
|
|
||||||
|
|
||||||
INLINE struct xform xform_scaled_to(struct xform xf, struct v2 s)
|
|
||||||
{
|
|
||||||
xf.bx = v2_with_len(xf.bx, s.x);
|
|
||||||
xf.by = v2_with_len(xf.by, s.y);
|
|
||||||
return xf;
|
|
||||||
}
|
|
||||||
|
|
||||||
INLINE struct xform xform_trs(struct xform xf, struct trs trs)
|
|
||||||
{
|
|
||||||
xf = xform_translated(xf, trs.t);
|
|
||||||
xf = xform_rotated(xf, trs.r);
|
|
||||||
xf = xform_scaled(xf, trs.s);
|
|
||||||
return xf;
|
|
||||||
}
|
|
||||||
|
|
||||||
INLINE struct xform xform_trs_pivot_r(struct xform xf, struct trs trs, struct v2 pivot)
|
|
||||||
{
|
|
||||||
xf = xform_translated(xf, trs.t);
|
|
||||||
xf = xform_rotated(xf, trs.r);
|
|
||||||
xf = xform_translated(xf, v2_neg(pivot));
|
|
||||||
xf = xform_scaled(xf, trs.s);
|
|
||||||
return xf;
|
|
||||||
}
|
|
||||||
|
|
||||||
INLINE struct xform xform_trs_pivot_rs(struct xform xf, struct trs trs, struct v2 pivot)
|
|
||||||
{
|
|
||||||
xf = xform_translated(xf, trs.t);
|
|
||||||
xf = xform_rotated(xf, trs.r);
|
|
||||||
xf = xform_scaled(xf, trs.s);
|
|
||||||
xf = xform_translated(xf, v2_neg(pivot));
|
|
||||||
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 v2 og = v2_lerp(a.og, b.og, t);
|
struct xform res;
|
||||||
f32 rot = math_lerp_angle(xform_get_rotation(a), xform_get_rotation(b), t);
|
res.bx = v2_slerp(a.bx, b.bx, t);
|
||||||
struct v2 scale = v2_lerp(xform_get_scale(a), xform_get_scale(b), t);
|
res.by = v2_slerp(a.by, b.by, t);
|
||||||
|
res.og = v2_lerp(a.og, b.og, t);
|
||||||
struct xform res = xform_from_pos(og);
|
|
||||||
res = xform_rotated(res, rot);
|
|
||||||
res = xform_scaled(res, scale);
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -698,7 +698,7 @@ INTERNAL void user_update(void)
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
if (G.debug_camera) {
|
if (G.debug_camera) {
|
||||||
G.world_view = xform_rotated_to(G.world_view, 0);
|
G.world_view = xform_basis_with_rotation_world(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) {
|
||||||
@ -750,7 +750,10 @@ 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_translated(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_translated(G.world_view, trs.t);
|
||||||
|
G.world_view = xform_rotated(G.world_view, trs.r);
|
||||||
|
G.world_view = xform_scaled(G.world_view, trs.s);
|
||||||
|
G.world_view = xform_translated(G.world_view, v2_neg(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);
|
||||||
|
|
||||||
@ -1282,7 +1285,7 @@ INTERNAL void user_update(void)
|
|||||||
/* Draw hierarchy */
|
/* Draw hierarchy */
|
||||||
if (entity_has_prop(parent, ENTITY_PROP_ACTIVE) && !parent->is_root) {
|
if (entity_has_prop(parent, ENTITY_PROP_ACTIVE) && !parent->is_root) {
|
||||||
u32 color = RGBA_32_F(0.6, 0.6, 1, 0.75);
|
u32 color = RGBA_32_F(0.6, 0.6, 1, 0.75);
|
||||||
f32 thickness = 5;
|
f32 thickness = 2;
|
||||||
f32 arrow_height = 15;
|
f32 arrow_height = 15;
|
||||||
|
|
||||||
struct v2 start = xform_mul_v2(G.world_view, xf.og);
|
struct v2 start = xform_mul_v2(G.world_view, xf.og);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user