working gjk test
This commit is contained in:
parent
86f1f1f6e0
commit
8bcc0bd356
BIN
res/graphics/box.ase
(Stored with Git LFS)
BIN
res/graphics/box.ase
(Stored with Git LFS)
Binary file not shown.
23
src/entity.h
23
src/entity.h
@ -50,6 +50,29 @@ struct entity_store {
|
||||
struct entity *entities;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* TODO: Remove this (testing) */
|
||||
struct simplex {
|
||||
struct v2 a, b, c;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct entity {
|
||||
/* ====================================================================== */
|
||||
/* Metadata */
|
||||
|
||||
108
src/game.c
108
src/game.c
@ -170,7 +170,7 @@ INTERNAL void spawn_test_entities(void)
|
||||
|
||||
/* Box */
|
||||
{
|
||||
struct v2 pos = V2(1, -1);
|
||||
struct v2 pos = V2(0.5, -0.5);
|
||||
struct v2 size = V2(1, 1);
|
||||
f32 rot = 0;
|
||||
struct entity *e = entity_alloc(root);
|
||||
@ -223,91 +223,92 @@ INTERNAL struct v2 quad_support_point(struct quad q0, struct quad q1, struct v2
|
||||
return v2_sub(quad_furthest_point(q0, dir), quad_furthest_point(q1, v2_neg(dir)));
|
||||
}
|
||||
|
||||
#if 0
|
||||
INTERNAL struct v2 normal_towards_origin(struct v2 p0, struct v2 p1)
|
||||
{
|
||||
struct v2 dir = v2_norm(v2_perp_cw(v2_sub(p1, p0)));
|
||||
#if 1
|
||||
if (v2_dot(dir, p0) > 0) {
|
||||
dir = v2_neg(dir);
|
||||
}
|
||||
#else
|
||||
dir = v2_mul(dir, 1 - ((v2_dot(dir, p0) > 0) << 1));
|
||||
#endif
|
||||
return dir;
|
||||
}
|
||||
#else
|
||||
INTERNAL struct v2 normal_towards_point(struct v2 start, struct v2 end, struct v2 p)
|
||||
{
|
||||
struct v2 dir = v2_norm(v2_perp_cw(v2_sub(end, start)));
|
||||
#if 1
|
||||
if (v2_dot(dir, v2_sub(p, start)) < 0) {
|
||||
dir = v2_neg(dir);
|
||||
}
|
||||
#else
|
||||
dir = v2_mul(dir, 1 - ((v2_dot(dir, v2_sub(p, start)) > 0) << 1));
|
||||
#endif
|
||||
return dir;
|
||||
}
|
||||
#endif
|
||||
i32 sign = 1 - ((v2_dot(dir, v2_sub(p, start)) < 0) << 1);
|
||||
return v2_mul(dir, sign);
|
||||
|
||||
INTERNAL b32 quad_collision_test(struct quad q0, struct quad q1)
|
||||
}
|
||||
|
||||
struct gjk_result {
|
||||
b32 colliding;
|
||||
struct simplex final_simplex;
|
||||
};
|
||||
|
||||
INTERNAL struct gjk_result gjk(struct quad q0, struct quad q1)
|
||||
{
|
||||
struct v2 q0_center = v2_div(v2_add(q0.p4, v2_add(q0.p3, v2_add(q0.p2, q0.p1))), 4);
|
||||
struct v2 q1_center = v2_div(v2_add(q1.p4, v2_add(q1.p3, v2_add(q1.p2, q1.p1))), 4);
|
||||
|
||||
/* Simplex */
|
||||
struct v2 s[3] = { 0 };
|
||||
struct simplex s = { 0 };
|
||||
u32 s_len = 0;
|
||||
|
||||
/* Append first point to simplex */
|
||||
struct v2 dir = v2_norm(v2_sub(q1_center, q0_center));
|
||||
s[0] = quad_support_point(q0, q1, dir);
|
||||
s.c = quad_support_point(q0, q1, dir);
|
||||
s_len = 1;
|
||||
|
||||
dir = v2_norm(v2_neg(s[0])); /* Next point is towards origin */
|
||||
dir = v2_norm(v2_neg(s.c)); /* Next point is towards origin */
|
||||
|
||||
b32 colliding = false;
|
||||
while (true) {
|
||||
/* Determine support point */
|
||||
struct v2 p = quad_support_point(q0, q1, dir);
|
||||
if (v2_dot(dir, p) < 0) {
|
||||
/* Point did not cross origin */
|
||||
return false;
|
||||
colliding = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (s_len == 1) {
|
||||
s[1] = p;
|
||||
++s_len;
|
||||
} else if (s_len == 2) {
|
||||
if (s_len < 3) {
|
||||
/* Line case */
|
||||
/* Next dir is line normal towards origin */
|
||||
s[2] = p;
|
||||
if (s_len == 1) {
|
||||
s.b = p;
|
||||
} else if (s_len == 2) {
|
||||
s.a = p;
|
||||
}
|
||||
++s_len;
|
||||
dir = normal_towards_point(s[0], s[1], V2(0, 0));
|
||||
dir = normal_towards_point(s.a, s.b, V2(0, 0));
|
||||
} else {
|
||||
s[0] = s[1];
|
||||
s[1] = s[2];
|
||||
s[2] = p;
|
||||
|
||||
/* Triangle case */
|
||||
struct v2 a = s[2];
|
||||
struct v2 b = s[1];
|
||||
struct v2 c = s[0];
|
||||
s.c = s.b;
|
||||
s.b = s.a;
|
||||
s.a = p;
|
||||
|
||||
dir = v2_neg(normal_towards_point(a, b, c)); /* Normal dir of ab pointing away from c */
|
||||
if (v2_dot(dir, v2_neg(a)) >= 0) {
|
||||
/* Ensure point is unique */
|
||||
if (v2_eq(s.a, s.b)
|
||||
|| v2_eq(s.b, s.c)
|
||||
|| v2_eq(s.a, s.c)) {
|
||||
colliding = false;
|
||||
break;
|
||||
}
|
||||
|
||||
struct v2 a_to_origin_rel = v2_neg(s.a);
|
||||
|
||||
dir = v2_neg(normal_towards_point(s.a, s.b, s.c)); /* Normal dir of ab pointing away from c */
|
||||
if (v2_dot(dir, a_to_origin_rel) >= 0) {
|
||||
/* Point is in region ab, remove c from simplex */
|
||||
} else {
|
||||
dir = v2_neg(normal_towards_point(a, c, b)); /* Normal dir of ac pointing away from b */
|
||||
if (v2_dot(dir, v2_neg(a)) >= 0) {
|
||||
dir = v2_neg(normal_towards_point(s.a, s.c, s.b)); /* Normal dir of ac pointing away from b */
|
||||
if (v2_dot(dir, a_to_origin_rel) >= 0) {
|
||||
/* Point is in region ac, remove b from simplex */
|
||||
s[1] = s[0];
|
||||
s.b = s.c;
|
||||
} else {
|
||||
/* Point must be in simplex */
|
||||
return true;
|
||||
colliding = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (struct gjk_result) {
|
||||
.colliding = colliding,
|
||||
.final_simplex = s
|
||||
};
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
@ -747,7 +748,8 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
||||
{
|
||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, e0->sprite);
|
||||
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("shape"), e0->animation_frame);
|
||||
e0_quad = xform_mul_quad(e0_xf, quad_from_rect(slice.rect));
|
||||
e0_quad = xform_mul_quad(e0->sprite_local_xform, quad_from_rect(slice.rect));
|
||||
e0_quad = xform_mul_quad(e0_xf, e0_quad);
|
||||
}
|
||||
|
||||
b32 colliding = false;
|
||||
@ -762,10 +764,12 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
||||
{
|
||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, e1->sprite);
|
||||
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("shape"), e1->animation_frame);
|
||||
e1_quad = xform_mul_quad(e1_xf, quad_from_rect(slice.rect));
|
||||
e1_quad = xform_mul_quad(e1->sprite_local_xform, quad_from_rect(slice.rect));
|
||||
e1_quad = xform_mul_quad(e1_xf, e1_quad);
|
||||
}
|
||||
|
||||
if (quad_collision_test(e0_quad, e1_quad)) {
|
||||
struct gjk_result res = gjk(e0_quad, e1_quad);
|
||||
if (res.colliding) {
|
||||
colliding = true;
|
||||
break;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user