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;
|
struct entity *entities;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO: Remove this (testing) */
|
||||||
|
struct simplex {
|
||||||
|
struct v2 a, b, c;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct entity {
|
struct entity {
|
||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
/* Metadata */
|
/* Metadata */
|
||||||
|
|||||||
108
src/game.c
108
src/game.c
@ -170,7 +170,7 @@ INTERNAL void spawn_test_entities(void)
|
|||||||
|
|
||||||
/* Box */
|
/* Box */
|
||||||
{
|
{
|
||||||
struct v2 pos = V2(1, -1);
|
struct v2 pos = V2(0.5, -0.5);
|
||||||
struct v2 size = V2(1, 1);
|
struct v2 size = V2(1, 1);
|
||||||
f32 rot = 0;
|
f32 rot = 0;
|
||||||
struct entity *e = entity_alloc(root);
|
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)));
|
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)
|
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)));
|
struct v2 dir = v2_norm(v2_perp_cw(v2_sub(end, start)));
|
||||||
#if 1
|
i32 sign = 1 - ((v2_dot(dir, v2_sub(p, start)) < 0) << 1);
|
||||||
if (v2_dot(dir, v2_sub(p, start)) < 0) {
|
return v2_mul(dir, sign);
|
||||||
dir = v2_neg(dir);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
dir = v2_mul(dir, 1 - ((v2_dot(dir, v2_sub(p, start)) > 0) << 1));
|
|
||||||
#endif
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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 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);
|
struct v2 q1_center = v2_div(v2_add(q1.p4, v2_add(q1.p3, v2_add(q1.p2, q1.p1))), 4);
|
||||||
|
|
||||||
/* Simplex */
|
/* Simplex */
|
||||||
struct v2 s[3] = { 0 };
|
struct simplex s = { 0 };
|
||||||
u32 s_len = 0;
|
u32 s_len = 0;
|
||||||
|
|
||||||
/* Append first point to simplex */
|
/* Append first point to simplex */
|
||||||
struct v2 dir = v2_norm(v2_sub(q1_center, q0_center));
|
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;
|
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) {
|
while (true) {
|
||||||
/* Determine support point */
|
/* Determine support point */
|
||||||
struct v2 p = quad_support_point(q0, q1, dir);
|
struct v2 p = quad_support_point(q0, q1, dir);
|
||||||
if (v2_dot(dir, p) < 0) {
|
if (v2_dot(dir, p) < 0) {
|
||||||
/* Point did not cross origin */
|
/* Point did not cross origin */
|
||||||
return false;
|
colliding = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s_len == 1) {
|
if (s_len < 3) {
|
||||||
s[1] = p;
|
|
||||||
++s_len;
|
|
||||||
} else if (s_len == 2) {
|
|
||||||
/* Line case */
|
/* Line case */
|
||||||
/* Next dir is line normal towards origin */
|
/* 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;
|
++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 {
|
} else {
|
||||||
s[0] = s[1];
|
|
||||||
s[1] = s[2];
|
|
||||||
s[2] = p;
|
|
||||||
|
|
||||||
/* Triangle case */
|
/* Triangle case */
|
||||||
struct v2 a = s[2];
|
s.c = s.b;
|
||||||
struct v2 b = s[1];
|
s.b = s.a;
|
||||||
struct v2 c = s[0];
|
s.a = p;
|
||||||
|
|
||||||
dir = v2_neg(normal_towards_point(a, b, c)); /* Normal dir of ab pointing away from c */
|
/* Ensure point is unique */
|
||||||
if (v2_dot(dir, v2_neg(a)) >= 0) {
|
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 */
|
/* Point is in region ab, remove c from simplex */
|
||||||
} else {
|
} else {
|
||||||
dir = v2_neg(normal_towards_point(a, c, b)); /* Normal dir of ac pointing away from b */
|
dir = v2_neg(normal_towards_point(s.a, s.c, s.b)); /* Normal dir of ac pointing away from b */
|
||||||
if (v2_dot(dir, v2_neg(a)) >= 0) {
|
if (v2_dot(dir, a_to_origin_rel) >= 0) {
|
||||||
/* Point is in region ac, remove b from simplex */
|
/* Point is in region ac, remove b from simplex */
|
||||||
s[1] = s[0];
|
s.b = s.c;
|
||||||
} else {
|
} else {
|
||||||
/* Point must be in simplex */
|
/* 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 *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);
|
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;
|
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 *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);
|
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;
|
colliding = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user