more fixed up capsule collision. remove transform matrix skewing

This commit is contained in:
jacob 2024-10-12 00:37:15 -05:00
parent 6951fa62e3
commit 73b7fef768
5 changed files with 136 additions and 120 deletions

BIN
res/graphics/box_rounded.ase (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -24,58 +24,6 @@ INTERNAL void _dbgbreakable(void)
struct v2 collider_support_point(struct collider_shape *a, struct xform xf, struct v2 dir)
{
#if 0
struct v2 *points = a->points;
u32 count = a->count;
f32 radius = a->radius;
/* TODO: Could probably binary search for largest dot since shape is convex */
struct v2 furthest = ZI;
f32 furthest_dot = -F32_INFINITY;
for (u32 i = 0; i < count; ++i) {
struct v2 p = xform_mul_v2(xf, points[i]);
f32 dot = v2_dot(dir, p);
if (dot > furthest_dot) {
furthest = p;
furthest_dot = dot;
}
}
if (radius > 0.0) {
dir = v2_mul_v2(v2_with_len(dir, radius), xform_get_scale(xf));
furthest = v2_add(furthest, dir);
}
return furthest;
#elif 0
struct v2 *points = a->points;
u32 count = a->count;
f32 radius = a->radius;
/* TODO: Could probably binary search for largest dot since shape is convex */
struct xform inv = xform_invert(xf);
dir = xform_basis_mul_v2(inv, dir);
struct v2 furthest = ZI;
f32 furthest_dot = -F32_INFINITY;
for (u32 i = 0; i < count; ++i) {
struct v2 p = points[i];
f32 dot = v2_dot(dir, p);
if (dot > furthest_dot) {
furthest = p;
furthest_dot = dot;
}
}
if (radius > 0.0) {
dir = v2_with_len(dir, radius);
furthest = v2_add(furthest, dir);
}
furthest = xform_mul_v2(xf, furthest);
return furthest;
#else
struct v2 *points = a->points;
u32 count = a->count;
f32 radius = a->radius;
@ -102,7 +50,6 @@ struct v2 collider_support_point(struct collider_shape *a, struct xform xf, stru
furthest = xform_mul_v2(xf, furthest);
return furthest;
#endif
}
INTERNAL u32 collider_support_point_index(struct collider_shape *a, struct xform xf, struct v2 dir)
@ -149,8 +96,8 @@ struct collider_collision_points_result collider_collision_points(struct collide
/* TODO: Parameterize */
/* How close can non-overlapping shapes be before collision is considered */
//const f32 tolerance = 0.f;
const f32 tolerance = 0.05f;
//const f32 tolerance = 0.05f;
const f32 tolerance = 0.005f;
/* NOTE: Should always be less than tolerance, since colliding=true if origin is within this distance. */
const f32 min_unique_pt_dist_sq = 0.0001f * 0.0001f;
@ -468,7 +415,7 @@ struct collider_collision_points_result collider_collision_points(struct collide
DBGSTEP;
{
const f32 wedge_epsilon = 0.001f;
const f32 wedge_epsilon = 0.05f;
//const f32 wedge_epsilon = 0.1f;
/* shape0 a -> b winding = clockwise */
@ -610,20 +557,87 @@ struct collider_collision_points_result collider_collision_points(struct collide
struct v2 vab1 = v2_sub(b1, a1);
{
struct v2 va0a1 = v2_sub(a1, a0);
struct v2 vb0b1 = v2_sub(b1, b0);
f32 vab0_wedge_normal = v2_wedge(vab0, normal);
f32 vab1_wedge_normal = v2_wedge(vab1, normal);
b32 collapse0 = math_fabs(vab0_wedge_normal) < wedge_epsilon;
b32 collapse1 = math_fabs(vab1_wedge_normal) < wedge_epsilon;
if (collapse0) {
if (v2_dot(b0, normal) >= v2_dot(a0, normal)) {
a0 = b0;
a0t = 1;
b0t = 0;
} else {
b0 = a0;
a0t = 0;
b0t = 1;
}
vab0 = V2(0, 0);
}
if (collapse1) {
if (v2_dot(b1, normal) < v2_dot(a1, normal)) {
a1 = b1;
a1t = 1;
b1t = 0;
} else {
b1 = a1;
a1t = 0;
b1t = 1;
}
vab1 = V2(0, 0);
}
struct v2 va0a1 = v2_sub(a1, a0);
struct v2 vb0b1 = v2_sub(b1, b0);
f32 va0a1_wedge_normal = v2_wedge(va0a1, normal);
f32 vb0b1_wedge_normal = v2_wedge(vb0b1, normal);
if (math_fabs(vab0_wedge_normal) > 0.01f) {
#if 0
if (math_fabs(vab0_wedge_normal) > 0.1f) {
f32 w = 1 / vab0_wedge_normal;
a0t = clamp_f32(va0a1_wedge_normal * w, 0, 1);
b0t = clamp_f32(vb0b1_wedge_normal * -w, 0, 1);
} else {
DEBUGBREAKABLE;
if (v2_dot(b0, normal) >= v2_dot(a0, normal)) {
a0t = 1;
b0t = 0;
} else {
a0t = 0;
b0t = 1;
}
}
if (math_fabs(vab1_wedge_normal) > 0.1f) {
f32 w = 1 / vab1_wedge_normal;
a1t = clamp_f32(-va0a1_wedge_normal * w, 0, 1);
b1t = clamp_f32(-vb0b1_wedge_normal * -w, 0, 1);
} else {
if (v2_dot(b1, normal) < v2_dot(a1, normal)) {
a1t = 1;
b1t = 0;
} else {
a1t = 0;
b1t = 1;
}
}
#elif 0
if (math_fabs(vab0_wedge_normal) > 0.01f) {
f32 w = 1 / vab0_wedge_normal;
a0t = clamp_f32(va0a1_wedge_normal * w, 0, 1);
b0t = clamp_f32(vb0b1_wedge_normal * -w, 0, 1);
} else {
if (v2_dot(b0, normal) >= v2_dot(a0, normal)) {
a0t = 1;
b0t = 0;
} else {
a0t = 0;
b0t = 1;
}
}
if (math_fabs(vab1_wedge_normal) > 0.01f) {
@ -631,8 +645,27 @@ struct collider_collision_points_result collider_collision_points(struct collide
a1t = clamp_f32(-va0a1_wedge_normal * w, 0, 1);
b1t = clamp_f32(-vb0b1_wedge_normal * -w, 0, 1);
} else {
DEBUGBREAKABLE;
if (v2_dot(b1, normal) < v2_dot(a1, normal)) {
a1t = 1;
b1t = 0;
} else {
a1t = 0;
b1t = 1;
}
}
#else
if (!collapse0) {
f32 w = 1 / vab0_wedge_normal;
a0t = clamp_f32(va0a1_wedge_normal * w, 0, 1);
b0t = clamp_f32(vb0b1_wedge_normal * -w, 0, 1);
}
if (!collapse1) {
f32 w = 1 / vab1_wedge_normal;
a1t = clamp_f32(-va0a1_wedge_normal * w, 0, 1);
b1t = clamp_f32(-vb0b1_wedge_normal * -w, 0, 1);
}
#endif
}
struct v2 a0_clipped = v2_add(a0, v2_mul(vab0, a0t));
@ -675,7 +708,7 @@ struct collider_collision_points_result collider_collision_points(struct collide
point->point = contact_b;
}
#if 0
#if 1
res.a0 = a0_clipped;
res.a1 = a1_clipped;
res.b0 = b0_clipped;

View File

@ -136,19 +136,20 @@ INTERNAL void spawn_test_entities(f32 offset)
struct entity *e = entity_alloc(root);
#if 1
//struct v2 pos = V2(0.25, -10);
//struct v2 pos = V2(0.25, -7);
//struct v2 pos = V2(0.25, -5.27);
struct v2 pos = V2(0.5, -1);
struct v2 pos = V2(0.5, -2);
//struct v2 pos = V2(1.0295, -1);
pos = v2_add(pos, V2(0, offset));
pos = v2_add(pos, V2(0, offset_all));
//struct v2 size = V2(1, 1);
//struct v2 size = V2(0.5, 0.5);
struct v2 size = V2(1.0, 0.5);
struct v2 size = V2(0.5, 0.5);
//struct v2 size = V2(3.0, 0.5);
//struct v2 size = V2(1.0, 1.0);
//struct v2 size = V2(1.5, 1.5);
//f32 r = PI;
//f32 r = PI / 4;
//f32 r = PI / 3;
@ -156,22 +157,17 @@ INTERNAL void spawn_test_entities(f32 offset)
//f32 r = PI / 2;
//f32 r = PI;
f32 r = 0;
//f32 skew = PI / 4;
//f32 skew = 0.9f;
f32 skew = 0;
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
xf = xform_skewed_to(xf, skew);
#else
struct xform xf = { .bx = {0.282509595, -0.412540406}, .by = {0.412528992, 0.282521814}, .og = {3.34883189, -1.35877287} };
#endif
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/box.ase"));
e->sprite = sprite_tag_from_path(STR("res/graphics/box_rounded.ase"));
//e->sprite_span_name = STR("idle.unarmed");
//e->sprite_span_name = STR("idle.one_handed");
e->sprite_span_name = STR("idle.two_handed");
e->sprite_tint = RGBA_32_F(1, 1, 1, 0.25);
entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
#if GAME_PHYSICS_ENABLE_GROUND_FRICTION
@ -200,7 +196,6 @@ INTERNAL void spawn_test_entities(f32 offset)
{
struct entity *e = entity_alloc(root);
#if 1
//struct v2 pos = V2(0.25, -10);
//struct v2 pos = V2(0.25, -7);
//struct v2 pos = V2(0.25, -5.27);
@ -217,15 +212,9 @@ INTERNAL void spawn_test_entities(f32 offset)
//f32 r = PI / 3;
//f32 r = 0.05;
//f32 r = PI / 2;
//f32 r = 0;
//f32 skew = PI / 4;
f32 skew = 0;
f32 r = 0;
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
xf = xform_skewed_to(xf, skew);
#else
struct xform xf = { .bx = {0.256749988, 0.429049402}, .by = {-0.429063231, 0.256720454}, .og = {2.91935277, -0.965838134} };
#endif
entity_set_xform(e, xf);
@ -255,6 +244,7 @@ INTERNAL void spawn_test_entities(f32 offset)
#endif
/* Weapon */
#if 1
if (player_ent->valid) {
#if 0
struct v2 pos = V2(1, 0);
@ -275,6 +265,7 @@ INTERNAL void spawn_test_entities(f32 offset)
player_ent->equipped = e->handle;
}
#endif
/* Box */
#if GAME_SPAWN_BOX
@ -288,6 +279,7 @@ INTERNAL void spawn_test_entities(f32 offset)
#else
//struct v2 size = V2(5000, 1);
struct v2 size = V2(50, 1);
//struct v2 size = V2(1, 1);
#endif
//f32 rot = PI / 4;
f32 rot = 0;
@ -1077,21 +1069,29 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
/* Update collider */
{
struct xform cxf = ent->sprite_local_xform;
if (entity_has_prop(ent, ENTITY_PROP_TEST)) {
f32 scale = 0.5;
cxf = xform_scaled(cxf, V2(scale, scale));
}
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("shape"), ent->animation_frame);
ent->local_collider = collider_from_quad(xform_mul_quad(ent->sprite_local_xform, quad_from_rect(slice.rect)));
ent->local_collider = collider_from_quad(xform_mul_quad(cxf, quad_from_rect(slice.rect)));
#if 1
if (entity_has_prop(ent, ENTITY_PROP_TEST)) {
//if ((true)) {
#if 0
ent->local_collider.points[0] = V2(0, 0);
ent->local_collider.count = 1;
ent->local_collider.radius = 0.5;
#elif 0
#elif 1
ent->local_collider.points[0] = V2(0, 0.5);
ent->local_collider.points[1] = V2(0, -0.5);
ent->local_collider.count = 2;
ent->local_collider.radius = 0.25;
#elif 1
#elif 0
#if 1
/* "Bad" winding order */
ent->local_collider.points[0] = V2(-0.5, 0.5);
@ -1106,7 +1106,9 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
ent->local_collider.radius = 0.25;
//ent->local_collider.radius = math_fabs(math_sin(G.tick.time) / 3);
#else
ent->local_collider.radius = 0.5;
//ent->local_collider.radius = 0.5;
ent->local_collider.radius = 0.25;
//ent->local_collider.radius = 0.;
#endif
}
#endif
@ -1220,7 +1222,6 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
struct v2 og = v2_mul(V2(math_cos(t), math_sin(t)), 3);
f32 r = t * 3;
struct v2 s = V2(1 + (math_fabs(math_sin(t * 5)) * 3), 1);
f32 skew = t * PI / 10;
(UNUSED)og;
(UNUSED)r;
(UNUSED)s;
@ -1228,29 +1229,24 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
og = v2_add(og, ent->test_start_local_xform.og);
r += xform_get_rotation(ent->test_start_local_xform);
s = v2_add(s, xform_get_scale(ent->test_start_local_xform));
skew += xform_get_skew(ent->test_start_local_xform);
struct xform xf = entity_get_local_xform(ent);
xf.og = og;
xf = xform_rotated_to(xf, r);
xf = xform_scaled_to(xf, s);
xf = xform_skewed_to(xf, skew);
entity_set_local_xform(ent, xf);
#else
f32 t = (f32)time;
struct v2 og = v2_mul(V2(math_cos(t), math_sin(t)), 3);
f32 rot = t * PI / 3;
struct v2 scale = V2(1 + (math_fabs(math_sin(t * 5)) * 3), 1);
f32 skew = t * PI / 10;
(UNUSED)og;
(UNUSED)rot;
(UNUSED)scale;
(UNUSED)skew;
struct xform xf = entity_get_local_xform(ent);
//xf = xform_rotated_to(xf, rot);
//xf = xform_scaled_to(xf, scale);
xf = xform_skewed_to(xf, skew);
entity_set_local_xform(ent, xf);
#endif
}

View File

@ -874,8 +874,6 @@ 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 struct v2 xform_get_scale(struct xform xf);
INLINE f32 xform_get_skew(struct xform xf);
INLINE struct xform xform_skewed_to(struct xform xf, f32 s);
INLINE f32 xform_get_rotation(struct xform xf);
INLINE b32 xform_eq(struct xform xf1, struct xform xf2)
@ -930,14 +928,13 @@ INLINE struct xform xform_scaled(struct xform xf, struct v2 v)
INLINE struct xform xform_rotated_to(struct xform xf, f32 r)
{
/* TODO: Maintain skew/shear? */
struct v2 scale = xform_get_scale(xf);
f32 skew = xform_get_skew(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);
xf = xform_skewed_to(xf, skew);
return xf;
}
@ -979,12 +976,10 @@ INLINE struct xform xform_lerp(struct xform a, struct xform b, f32 t)
struct v2 og = v2_lerp(a.og, b.og, t);
f32 rot = math_lerp_angle(xform_get_rotation(a), xform_get_rotation(b), t);
struct v2 scale = v2_lerp(xform_get_scale(a), xform_get_scale(b), t);
f32 skew = math_lerp_angle(xform_get_skew(a), xform_get_skew(b), t);
struct xform res = xform_from_pos(og);
res = xform_rotated(res, rot);
res = xform_scaled(res, scale);
res = xform_skewed_to(res, skew);
return res;
}
@ -1061,18 +1056,6 @@ INLINE f32 xform_get_determinant(struct xform xf)
return v2_wedge(xf.bx, xf.by);
}
INLINE f32 xform_get_skew(struct xform xf)
{
return v2_angle_from_dirs(v2_norm(xf.bx), v2_norm(xf.by)) - PI / 2;
}
INLINE struct xform xform_skewed_to(struct xform xf, f32 s)
{
f32 angle = v2_angle(xf.bx) + s + (PI / 2);
xf.by = v2_mul(v2_from_angle(angle), v2_len(xf.by));
return xf;
}
INLINE struct v2 xform_get_right(struct xform xf)
{
return xf.bx;

View File

@ -362,13 +362,10 @@ INTERNAL void pubilsh_game_cmds(struct game_cmd_list *list)
* ========================== */
/* TODO: remove this (testing) */
INTERNAL void debug_draw_xform(struct xform xf)
INTERNAL void debug_draw_xform(struct xform xf, u32 color_x, u32 color_y)
{
f32 thickness = 2.f;
f32 arrowhead_len = 15.f;
u32 color = RGBA_32_F(0, 1, 1, 0.3);
u32 color_x = RGBA_32_F(1, 0, 0, 0.3);
u32 color_y = RGBA_32_F(0, 1, 0, 0.3);
struct v2 pos = xform_mul_v2(G.world_view, xf.og);
struct v2 x_ray = xform_basis_mul_v2(G.world_view, xform_get_right(xf));
@ -378,12 +375,13 @@ INTERNAL void debug_draw_xform(struct xform xf)
x_ray = v2_mul(x_ray, ray_scale);
y_ray = v2_mul(y_ray, ray_scale);
struct quad quad = quad_from_rect(RECT(0, 0, 1, -1));
quad = xform_mul_quad(xf, quad_scale(quad, 0.075f));
draw_solid_arrow_ray(G.viewport_canvas, pos, x_ray, thickness, arrowhead_len, color_x);
draw_solid_arrow_ray(G.viewport_canvas, pos, y_ray, thickness, arrowhead_len, color_y);
draw_solid_quad(G.viewport_canvas, quad, color);
//u32 color_quad = RGBA_32_F(0, 1, 1, 0.3);
//struct quad quad = quad_from_rect(RECT(0, 0, 1, -1));
//quad = xform_mul_quad(xf, quad_scale(quad, 0.075f));
//draw_solid_quad(G.viewport_canvas, quad, color);
}
/* TODO: remove this (testing) */
@ -835,8 +833,8 @@ INTERNAL void user_update(void)
struct xform parent_xf = entity_get_xform(parent);
b32 skip_debug_draw = !G.debug_camera && ent == active_camera;
//b32 skip_debug_draw_transform = entity_has_prop(ent, ENTITY_PROP_CAMERA);
b32 skip_debug_draw_transform = true;
b32 skip_debug_draw_transform = entity_has_prop(ent, ENTITY_PROP_CAMERA);
//b32 skip_debug_draw_transform = true;
struct xform sprite_xform = xf;
@ -870,7 +868,8 @@ INTERNAL void user_update(void)
#endif
/* Draw sprite */
if (!sprite_tag_is_nil(sprite) && ((false))) {
if ((false)) {
//if (!sprite_tag_is_nil(sprite)) {
/* Calculate sprite xform */
sprite_xform = xform_mul(xf, ent->sprite_local_xform);
@ -934,7 +933,9 @@ INTERNAL void user_update(void)
}
if (!skip_debug_draw_transform) {
debug_draw_xform(xf);
u32 color_x = RGBA_32_F(1, 0, 0, 0.3);
u32 color_y = RGBA_32_F(0, 1, 0, 0.3);
debug_draw_xform(xf, color_x, color_y);
}
#if 0