From e8bc83df3acd4f3e4f013ef53c7938170a74ebae Mon Sep 17 00:00:00 2001 From: jacob Date: Fri, 13 Sep 2024 12:12:57 -0500 Subject: [PATCH] revert to returning contact pairs from gjk --- res/graphics/tim.ase | 2 +- src/entity.h | 5 +++-- src/game.c | 25 +++++++++++++++---------- src/gjk.c | 38 ++++++++++++++++++++++---------------- src/gjk.h | 10 +++++++--- src/math.h | 1 + src/user.c | 14 ++++++-------- 7 files changed, 55 insertions(+), 40 deletions(-) diff --git a/res/graphics/tim.ase b/res/graphics/tim.ase index b4948e9b..438b0c85 100644 --- a/res/graphics/tim.ase +++ b/res/graphics/tim.ase @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:539310432433eac66ab2bbe633d8e1ab6a1849a58c180842a6c4e9f5330fb805 +oid sha256:ec0a7a4b08a43993c8f8745e08057db4e2f04aa1b83ee109e395a838e897d87e size 4191 diff --git a/src/entity.h b/src/entity.h index c1788473..ed408e00 100644 --- a/src/entity.h +++ b/src/entity.h @@ -94,14 +94,15 @@ struct entity { /* TODO: Remove this (testing) */ - b32 colliding; struct entity_handle colliding_with; struct gjk_simplex simplex; struct gjk_prototype prototype; struct v2 pendir; b32 solved; - struct v2 point; + struct v2 point0; + struct v2 point1; + u32 num_points; b32 test_torque_applied; b32 test_collided; diff --git a/src/game.c b/src/game.c index f3276a56..55ec433a 100644 --- a/src/game.c +++ b/src/game.c @@ -910,8 +910,9 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) } b32 colliding = false; - struct v2 p0 = V2(0, 0); - struct v2 p1 = V2(0, 0); + struct gjk_contact_pair pair0 = { 0 }; + struct gjk_contact_pair pair1 = { 0 }; + u32 num_pairs = 0; struct entity *colliding_with = entity_nil(); struct gjk_simplex simplex = { 0 }; struct gjk_prototype prototype = { 0 }; @@ -940,31 +941,35 @@ 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; - p0 = res.p0; - p1 = res.p1; + num_pairs = res.num_pairs; + colliding = num_pairs > 0; + pair0 = res.pairs[0]; + pair1 = res.pairs[1]; colliding_with = e1; simplex = res.simplex; prototype = res.prototype; solved = res.solved; } - e0->colliding = colliding; e0->colliding_with = colliding_with->handle; - e0->point = p0; + e0->point0 = pair0.p0; + e0->point1 = pair1.p0; + e0->num_points = num_pairs; e0->simplex = simplex; e0->prototype = prototype; e0->pendir = velocity; e0->solved = solved; if (colliding_with->valid) { - colliding_with->colliding = colliding; colliding_with->colliding_with = e0->handle; - colliding_with->point = p1; + colliding_with->point0 = pair0.p1; + colliding_with->point1 = pair1.p1; + colliding_with->num_points = num_pairs; } + (UNUSED)colliding; { -#if 1 +#if 0 if (colliding) { struct entity *e1 = colliding_with; struct xform e1_xf = entity_get_xform(e1); diff --git a/src/gjk.c b/src/gjk.c index d8867fde..8166459a 100644 --- a/src/gjk.c +++ b/src/gjk.c @@ -161,8 +161,9 @@ 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 p0 = { 0 }; - struct v2 p1 = { 0 }; + struct gjk_contact_pair pair0 = { 0 }; + struct gjk_contact_pair pair1 = { 0 }; + u32 num_pairs = 0; #if GJK_DEBUG u32 dbg_step = 0; @@ -370,14 +371,16 @@ struct gjk_contact_points_result gjk_contact_points(struct v2_array shape0, stru /* Resolve points */ if (s.len == 1) { - p0 = s.a.p0; - p1 = s.a.p1; + pair0.p0 = s.a.p0; + pair0.p1 = s.a.p1; + num_pairs = 1; } 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 */ + num_pairs = 2; struct v2 a = s.a.p0; struct v2 b = s.b.p0; struct v2 c = s.a.p1; @@ -394,28 +397,31 @@ 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); - 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)); + pair0.p0 = v2_add(a, v2_mul(vab, clamp_f32(v2_dot(vab, vac) * inv_vab_len_sq, 0, 1))); + pair0.p1 = v2_add(c, v2_mul(vcd, clamp_f32(v2_dot(vcd, vcb) * inv_vcd_len_sq, 0, 1))); + pair1.p0 = v2_add(a, v2_mul(vab, clamp_f32(v2_dot(vab, vad) * inv_vab_len_sq, 0, 1))); + pair1.p1 = v2_add(c, v2_mul(vcd, clamp_f32(v2_dot(vcd, vca) * inv_vcd_len_sq, 0, 1))); } else { /* Determine ratio between edge a & b that projected origin lies */ + num_pairs = 1; 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)); + pair0.p0 = v2_add(s.a.p0, v2_mul(v2_sub(s.b.p0, s.a.p0), ratio)); + pair0.p1 = v2_add(s.a.p1, v2_mul(v2_sub(s.b.p1, s.a.p1), ratio)); } } res.solved = true; abort: + + + /* TODO: Remove this */ + if (!colliding) num_pairs = 0; + if (proto_count > 0) { for (u32 i = 0; i < min_u32(proto_count, ARRAY_COUNT(res.prototype.points)); ++i) { res.prototype.points[i] = proto[i].p; @@ -433,9 +439,9 @@ abort: } res.prototype.len = s.len; } - res.colliding = colliding; - res.p0 = p0; - res.p1 = p1; + res.pairs[0] = pair0; + res.pairs[1] = pair1; + res.num_pairs = num_pairs; res.simplex = s; scratch_end(scratch); return res; diff --git a/src/gjk.h b/src/gjk.h index 6fa0b07e..62736ac6 100644 --- a/src/gjk.h +++ b/src/gjk.h @@ -21,11 +21,15 @@ struct gjk_simplex { /* Returns simple true or false indicating shape collision */ b32 gjk_boolean(struct v2_array shape0, struct v2_array shape1); +struct gjk_contact_pair { + struct v2 p0, p1; +}; + struct gjk_prototype { struct v2 points[64]; u32 len; }; struct gjk_contact_points_result { - b32 colliding; - struct v2 p0; - struct v2 p1; + + struct gjk_contact_pair pairs[2]; + u32 num_pairs; /* For debugging */ b32 solved; diff --git a/src/math.h b/src/math.h index 7ebab470..875d04bf 100644 --- a/src/math.h +++ b/src/math.h @@ -667,6 +667,7 @@ INLINE struct v2 v2_norm(struct v2 a) { f32 l = a.x * a.x + a.y * a.y; if (l != 0) { + /* TODO: Benchmark with math_rqsrt(l) */ f32 denom = 1.f / math_sqrt(l); a.x *= denom; a.y *= denom; diff --git a/src/user.c b/src/user.c index d9f8789f..d2ff60d0 100644 --- a/src/user.c +++ b/src/user.c @@ -888,6 +888,7 @@ INTERNAL void user_update(void) /* Debug draw info */ if (G.debug_draw && !skip_debug_draw) { struct temp_arena temp = arena_temp_begin(scratch.arena); + b32 colliding = ent->num_points > 0; #if 0 struct font *disp_font = font_load_async(STR("res/fonts/fixedsys.ttf"), 12.0f); @@ -953,7 +954,7 @@ INTERNAL void user_update(void) u32 point_color = RGBA_32_F(1, 0, 0, 1); u32 ray_color = RGBA_32_F(1, 0, 0.5, 1); - if (ent->colliding) { + if (colliding) { quad_color = RGBA_32_F(1, 1, 1, 1); } @@ -988,7 +989,6 @@ INTERNAL void user_update(void) /* Draw collision */ if (ent->is_top) { - b32 colliding = ent->colliding; struct entity *e1 = entity_from_handle(store, ent->colliding_with); (UNUSED)e1; (UNUSED)colliding; @@ -1116,18 +1116,16 @@ INTERNAL void user_update(void) /* Draw points */ { 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); { - 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->point); + struct v2 point = xform_mul_v2(G.world_view, ent->point0); 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); + if (!v2_is_zero(ent->point1)) { + //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 } }