fix collision issue between capsule rounded edge & corners, and with reverse-winding shapes

This commit is contained in:
jacob 2025-01-03 18:42:46 -06:00
parent 33df739cc6
commit 2260b1bc36
2 changed files with 82 additions and 29 deletions

View File

@ -425,18 +425,32 @@ struct collider_collision_points_result collider_collision_points(struct collide
f32 vap_wedge = v2_wedge(vap, normal);
f32 vpb_wedge = v2_wedge(vpb, normal);
if (count0 > 2 && v2_winding(vap, vpb) > 0) {
/* Winding is reversed, swap */
b32 reversed = count0 > 1 && v2_winding(vap, vpb) < 0;
if (reversed) {
/* Winding is reversed, swap vap & vpb wedge */
f32 t = vap_wedge;
vap_wedge = vpb_wedge;
vpb_wedge = t;
}
if (vap_wedge > (vpb_wedge + wedge_epsilon)) {
if (vap_wedge < (vpb_wedge + wedge_epsilon)) {
if (reversed) {
id_a0 = p_i;
id_b0 = a_i;
a0 = p;
b0 = a;
} else {
id_a0 = a_i;
id_b0 = p_i;
a0 = a;
b0 = p;
}
} else {
if (reversed) {
id_a0 = b_i;
id_b0 = p_i;
a0 = b;
b0 = p;
} else {
id_a0 = p_i;
id_b0 = b_i;
@ -444,12 +458,13 @@ struct collider_collision_points_result collider_collision_points(struct collide
b0 = b;
}
}
}
{
struct v2 neg_normal = v2_neg(normal);
u32 p_i = collider_support_point_index(shape1, xf1, neg_normal);
u32 a_i = ((p_i + 1) < count1) ? (p_i + 1) : 0;
u32 b_i = (p_i > 0) ? (p_i - 1) : (count1 - 1);
u32 a_i = (p_i > 0) ? (p_i - 1) : (count1 - 1);
u32 b_i = ((p_i + 1) < count1) ? (p_i + 1) : 0;
struct v2 p = xform_mul_v2(xf1, points1[p_i]);
struct v2 a = xform_mul_v2(xf1, points1[a_i]);
@ -460,23 +475,38 @@ struct collider_collision_points_result collider_collision_points(struct collide
f32 vap_wedge = v2_wedge(vap, normal);
f32 vpb_wedge = v2_wedge(vpb, normal);
if (count1 > 2 && v2_winding(vap, vpb) < 0) {
/* Winding is reversed, swap */
b32 reversed = count1 > 1 && v2_winding(vap, vpb) < 0;
if (reversed) {
/* Winding is reversed, swapvap & vpb wedge*/
f32 t = vap_wedge;
vap_wedge = vpb_wedge;
vpb_wedge = t;
}
if (vap_wedge > (vpb_wedge + wedge_epsilon)) {
if (reversed) {
id_a1 = a_i;
id_b1 = p_i;
a1 = a;
b1 = p;
} else {
id_a1 = p_i;
id_b1 = a_i;
a1 = p;
b1 = a;
}
} else {
if (reversed) {
id_a1 = p_i;
id_b1 = b_i;
a1 = p;
b1 = b;
} else {
id_a1 = b_i;
id_b1 = p_i;
a1 = b;
b1 = p;
}
}
}

View File

@ -399,6 +399,29 @@ INTERNAL void spawn_test_entities(void)
e->angular_ground_friction = 200;
}
/* Box */
#if 0
{
struct entity *e = entity_alloc(root);
struct v2 pos = V2(1, -0.5);
f32 r = 0;
struct v2 size = V2(0.5, 0.25);
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
entity_set_xform(e, xf);
e->sprite = sprite_tag_from_path(STR("res/graphics/box.ase"));
e->sprite_collider_slice = STR("shape");
entity_enable_prop(e, ENTITY_PROP_PHYSICAL_DYNAMIC);
e->mass_unscaled = 10;
e->inertia_unscaled = 10;
e->linear_ground_friction = 250;
e->angular_ground_friction = 5;
}
#endif
/* Player weapon */
if (player_ent->valid) {
struct entity *e = entity_alloc(player_ent);
@ -1654,13 +1677,13 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
#elif 1
#if 0
/* "Bad" winding order */
ent->local_collider.points[0] = V2(-0.5, 0.5);
ent->local_collider.points[1] = V2(0.5, 0.5);
ent->local_collider.points[2] = V2(0, -0.5);
ent->local_collider.points[0] = V2(-0.15, 0.15);
ent->local_collider.points[1] = V2(0.15, 0.15);
ent->local_collider.points[2] = V2(0, -0.15);
#else
ent->local_collider.points[0] = V2(0, -0.5);
ent->local_collider.points[1] = V2(0.5, 0.5);
ent->local_collider.points[2] = V2(-0.5, 0.5);
ent->local_collider.points[0] = V2(0, -0.15);
ent->local_collider.points[1] = V2(0.15, 0.15);
ent->local_collider.points[2] = V2(-0.15, 0.15);
#endif
ent->local_collider.count = 3;
ent->local_collider.radius = 0.25;