use midpoint of clipped gjk contact faces
This commit is contained in:
parent
14958a8449
commit
1d7f9be8b4
26
src/entity.h
26
src/entity.h
@ -60,6 +60,9 @@ struct entity_store {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct entity {
|
||||
/* ====================================================================== */
|
||||
/* Metadata */
|
||||
@ -98,9 +101,7 @@ struct entity {
|
||||
struct v2 pendir;
|
||||
b32 solved;
|
||||
|
||||
struct v2 point0;
|
||||
struct v2 point1;
|
||||
b32 has_2nd_point;
|
||||
struct v2 point;
|
||||
|
||||
b32 test_torque_applied;
|
||||
b32 test_collided;
|
||||
@ -112,6 +113,25 @@ struct entity {
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
/* ====================================================================== */
|
||||
/* Contact */
|
||||
|
||||
struct entity *contact_e0;
|
||||
struct entity *contact_e1;
|
||||
struct gjk_contact_pair contact_pairs[4];
|
||||
u32 num_contact_pairs;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
26
src/game.c
26
src/game.c
@ -910,11 +910,8 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
||||
}
|
||||
|
||||
b32 colliding = false;
|
||||
struct v2 pair0p0 = V2(0, 0);
|
||||
struct v2 pair0p1 = V2(0, 0);
|
||||
struct v2 pair1p0 = V2(0, 0);
|
||||
struct v2 pair1p1 = V2(0, 0);
|
||||
b32 has_2nd_pair = false;
|
||||
struct v2 p0 = V2(0, 0);
|
||||
struct v2 p1 = V2(0, 0);
|
||||
struct entity *colliding_with = entity_nil();
|
||||
struct gjk_simplex simplex = { 0 };
|
||||
struct gjk_prototype prototype = { 0 };
|
||||
@ -944,11 +941,8 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
||||
struct gjk_contact_points_result res = gjk_contact_points(e0_poly, e1_poly);
|
||||
|
||||
colliding = res.colliding;
|
||||
pair0p0 = res.pair0p0;
|
||||
pair0p1 = res.pair0p1;
|
||||
pair1p0 = res.pair1p0;
|
||||
pair1p1 = res.pair1p1;
|
||||
has_2nd_pair = res.has_2nd_pair;
|
||||
p0 = res.p0;
|
||||
p1 = res.p1;
|
||||
colliding_with = e1;
|
||||
simplex = res.simplex;
|
||||
prototype = res.prototype;
|
||||
@ -957,9 +951,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
||||
|
||||
e0->colliding = colliding;
|
||||
e0->colliding_with = colliding_with->handle;
|
||||
e0->point0 = pair0p0;
|
||||
e0->point1 = pair1p0;
|
||||
e0->has_2nd_point = has_2nd_pair;
|
||||
e0->point = p0;
|
||||
e0->simplex = simplex;
|
||||
e0->prototype = prototype;
|
||||
e0->pendir = velocity;
|
||||
@ -968,13 +960,11 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
||||
if (colliding_with->valid) {
|
||||
colliding_with->colliding = colliding;
|
||||
colliding_with->colliding_with = e0->handle;
|
||||
colliding_with->point0 = pair0p1;
|
||||
colliding_with->point1 = pair1p1;
|
||||
colliding_with->has_2nd_point = has_2nd_pair;
|
||||
colliding_with->point = p1;
|
||||
}
|
||||
|
||||
{
|
||||
#if 0
|
||||
#if 1
|
||||
if (colliding) {
|
||||
struct entity *e1 = colliding_with;
|
||||
struct xform e1_xf = entity_get_xform(e1);
|
||||
@ -999,7 +989,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
||||
|
||||
#if 1
|
||||
f32 bias_factor = 0.2;
|
||||
f32 bias_slop = 0.005;
|
||||
f32 bias_slop = 0.001;
|
||||
|
||||
f32 bias = (bias_factor / dt) * max((v2_len(pen) - bias_slop), 0);
|
||||
#else
|
||||
|
||||
76
src/gjk.c
76
src/gjk.c
@ -146,6 +146,9 @@ struct v2_array cloud(struct arena *arena, struct v2_array poly0, struct v2_arra
|
||||
|
||||
|
||||
|
||||
|
||||
/* TODO: Update this function to only calculate contact pairs if colliding. Will allow for shortcut-style GJK.
|
||||
* `colliding` & `has_2nd_pair` become "num_pairs", where 0 = no collision. */
|
||||
struct gjk_contact_points_result gjk_contact_points(struct v2_array shape0, struct v2_array shape1)
|
||||
{
|
||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||
@ -158,11 +161,8 @@ struct gjk_contact_points_result gjk_contact_points(struct v2_array shape0, stru
|
||||
struct gjk_menkowski_point *proto = NULL;
|
||||
u32 proto_count = 0;
|
||||
|
||||
struct v2 pair0p0 = { 0 };
|
||||
struct v2 pair0p1 = { 0 };
|
||||
struct v2 pair1p0 = { 0 };
|
||||
struct v2 pair1p1 = { 0 };
|
||||
b32 has_2nd_pair = false;
|
||||
struct v2 p0 = { 0 };
|
||||
struct v2 p1 = { 0 };
|
||||
|
||||
#if GJK_DEBUG
|
||||
u32 dbg_step = 0;
|
||||
@ -370,36 +370,14 @@ struct gjk_contact_points_result gjk_contact_points(struct v2_array shape0, stru
|
||||
|
||||
/* Resolve points */
|
||||
if (s.len == 1) {
|
||||
pair0p0 = s.a.p0;
|
||||
pair0p1 = s.a.p1;
|
||||
} else if (s.len == 2) {
|
||||
|
||||
/* TODO: Epsilon */
|
||||
if (v2_eq(s.a.p0, s.b.p0) || v2_eq(s.a.p1, s.b.p1)) {
|
||||
/* FIXME: Winding order dependent? */
|
||||
ASSERT(s.len == 2);
|
||||
f32 ratio;
|
||||
{
|
||||
/* Determine ratio between edge a & b that projected origin lies */
|
||||
struct v2 vab = v2_sub(s.b.p, s.a.p);
|
||||
struct v2 vao = v2_neg(s.a.p);
|
||||
ratio = clamp_f32(v2_dot(vab, vao) / v2_dot(vab, vab), 0, 1);
|
||||
}
|
||||
/* Shape 0 */
|
||||
pair0p0 = v2_sub(s.b.p0, s.a.p0);
|
||||
pair0p0 = v2_mul(pair0p0, ratio);
|
||||
pair0p0 = v2_add(pair0p0, s.a.p0);
|
||||
/* Shape 1 */
|
||||
pair0p1 = v2_sub(s.b.p1, s.a.p1);
|
||||
pair0p1 = v2_mul(pair0p1, ratio);
|
||||
pair0p1 = v2_add(pair0p1, s.a.p1);
|
||||
} else {
|
||||
/* Face -> face, need 2nd pair */
|
||||
|
||||
has_2nd_pair = true;
|
||||
|
||||
/* TODO: Rename abcd variables */
|
||||
|
||||
p0 = s.a.p0;
|
||||
p1 = s.a.p1;
|
||||
} else {
|
||||
ASSERT(s.len == 2);
|
||||
b32 p0_is_on_edge = !v2_eq(s.a.p0, s.b.p0);
|
||||
b32 p1_is_on_edge = !v2_eq(s.a.p1, s.b.p1);
|
||||
if (p0_is_on_edge && p1_is_on_edge) {
|
||||
/* Closest features are both faces, use midpoint of clipped faces to represent contact points */
|
||||
struct v2 a = s.a.p0;
|
||||
struct v2 b = s.b.p0;
|
||||
struct v2 c = s.a.p1;
|
||||
@ -416,10 +394,23 @@ struct gjk_contact_points_result gjk_contact_points(struct v2_array shape0, stru
|
||||
f32 inv_vab_len_sq = 1.f / v2_len_sq(vab);
|
||||
f32 inv_vcd_len_sq = 1.f / v2_len_sq(vcd);
|
||||
|
||||
pair0p0 = v2_add(a, v2_mul(vab, clamp_f32(v2_dot(vab, vac) * inv_vab_len_sq, 0, 1)));
|
||||
pair1p0 = v2_add(a, v2_mul(vab, clamp_f32(v2_dot(vab, vad) * inv_vab_len_sq, 0, 1)));
|
||||
pair0p1 = v2_add(c, v2_mul(vcd, clamp_f32(v2_dot(vcd, vca) * inv_vcd_len_sq, 0, 1)));
|
||||
pair1p1 = v2_add(c, v2_mul(vcd, clamp_f32(v2_dot(vcd, vcb) * inv_vcd_len_sq, 0, 1)));
|
||||
f32 ab_clip_c = clamp_f32(v2_dot(vab, vac) * inv_vab_len_sq, 0, 1);
|
||||
f32 ab_clip_d = clamp_f32(v2_dot(vab, vad) * inv_vab_len_sq, 0, 1);
|
||||
f32 cd_clip_a = clamp_f32(v2_dot(vcd, vca) * inv_vcd_len_sq, 0, 1);
|
||||
f32 cd_clip_b = clamp_f32(v2_dot(vcd, vcb) * inv_vcd_len_sq, 0, 1);
|
||||
|
||||
p0 = v2_add(a, v2_mul(vab, (ab_clip_c + ab_clip_d) * 0.5f));
|
||||
p1 = v2_add(c, v2_mul(vcd, (cd_clip_a + cd_clip_b) * 0.5f));
|
||||
} else {
|
||||
/* Determine ratio between edge a & b that projected origin lies */
|
||||
f32 ratio;
|
||||
{
|
||||
struct v2 vab = v2_sub(s.b.p, s.a.p);
|
||||
struct v2 vao = v2_neg(s.a.p);
|
||||
ratio = clamp_f32(v2_dot(vab, vao) / v2_dot(vab, vab), 0, 1);
|
||||
}
|
||||
p0 = v2_add(s.a.p0, v2_mul(v2_sub(s.b.p0, s.a.p0), ratio));
|
||||
p1 = v2_add(s.a.p1, v2_mul(v2_sub(s.b.p1, s.a.p1), ratio));
|
||||
}
|
||||
}
|
||||
|
||||
@ -443,11 +434,8 @@ abort:
|
||||
res.prototype.len = s.len;
|
||||
}
|
||||
res.colliding = colliding;
|
||||
res.pair0p0 = pair0p0;
|
||||
res.pair0p1 = pair0p1;
|
||||
res.pair1p0 = pair1p0;
|
||||
res.pair1p1 = pair1p1;
|
||||
res.has_2nd_pair = has_2nd_pair;
|
||||
res.p0 = p0;
|
||||
res.p1 = p1;
|
||||
res.simplex = s;
|
||||
scratch_end(scratch);
|
||||
return res;
|
||||
|
||||
@ -24,11 +24,8 @@ b32 gjk_boolean(struct v2_array shape0, struct v2_array shape1);
|
||||
struct gjk_prototype { struct v2 points[64]; u32 len; };
|
||||
struct gjk_contact_points_result {
|
||||
b32 colliding;
|
||||
|
||||
|
||||
struct v2 pair0p0, pair0p1;
|
||||
struct v2 pair1p0, pair1p1;
|
||||
b32 has_2nd_pair;
|
||||
struct v2 p0;
|
||||
struct v2 p1;
|
||||
|
||||
/* For debugging */
|
||||
b32 solved;
|
||||
|
||||
@ -1118,14 +1118,16 @@ INTERNAL void user_update(void)
|
||||
f32 radius = 5;
|
||||
{
|
||||
u32 color = entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED) ? RGBA_32_F(1, 0, 0, 0.75) : RGBA_32_F(0, 1, 1, 0.75);
|
||||
struct v2 point = xform_mul_v2(G.world_view, ent->point0);
|
||||
struct v2 point = xform_mul_v2(G.world_view, ent->point);
|
||||
draw_solid_circle(G.viewport_canvas, point, radius, color, 10);
|
||||
}
|
||||
#if 0
|
||||
if (ent->has_2nd_point) {
|
||||
u32 color = entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED) ? RGBA_32_F(1, 1, 0, 0.75) : RGBA_32_F(1, 0, 1, 0.75);
|
||||
struct v2 point = xform_mul_v2(G.world_view, ent->point1);
|
||||
draw_solid_circle(G.viewport_canvas, point, radius, color, 10);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user