re-add/enable gjk debug visualization
This commit is contained in:
parent
8c36552659
commit
f608000b85
@ -56,7 +56,8 @@ struct entity_store {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO: Remove this */
|
||||||
|
#include "gjk.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -95,6 +96,7 @@ struct entity {
|
|||||||
b32 colliding;
|
b32 colliding;
|
||||||
struct entity_handle colliding_with;
|
struct entity_handle colliding_with;
|
||||||
struct v2 point;
|
struct v2 point;
|
||||||
|
struct gjk_simplex simplex;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
47
src/game.c
47
src/game.c
@ -27,11 +27,6 @@ GLOBAL struct {
|
|||||||
struct atomic_u64 prev_tick_id;
|
struct atomic_u64 prev_tick_id;
|
||||||
struct world prev_tick;
|
struct world prev_tick;
|
||||||
struct world tick;
|
struct world tick;
|
||||||
|
|
||||||
#if RTC
|
|
||||||
u32 gjk_steps;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} G = { 0 }, DEBUG_ALIAS(G, G_game);
|
} G = { 0 }, DEBUG_ALIAS(G, G_game);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -49,10 +44,6 @@ struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr,
|
|||||||
(UNUSED)sheet_sr;
|
(UNUSED)sheet_sr;
|
||||||
(UNUSED)sound_sr;
|
(UNUSED)sound_sr;
|
||||||
|
|
||||||
#if RTC
|
|
||||||
G.gjk_steps = U32_MAX;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Initialize game cmd storage */
|
/* Initialize game cmd storage */
|
||||||
G.game_cmds_mutex = sys_mutex_alloc();
|
G.game_cmds_mutex = sys_mutex_alloc();
|
||||||
G.game_cmds_arena = arena_alloc(GIGABYTE(64));
|
G.game_cmds_arena = arena_alloc(GIGABYTE(64));
|
||||||
@ -287,13 +278,6 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
spawn_test_entities();
|
spawn_test_entities();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
#if RTC
|
|
||||||
/* Debug */
|
|
||||||
case GAME_CMD_KIND_SET_GJK_STEPS: {
|
|
||||||
G.gjk_steps = cmd.gjk_steps;
|
|
||||||
} break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -779,6 +763,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
struct v2 point0 = V2(0, 0);
|
struct v2 point0 = V2(0, 0);
|
||||||
struct v2 point1 = V2(0, 0);
|
struct v2 point1 = V2(0, 0);
|
||||||
struct entity *colliding_with = entity_nil();
|
struct entity *colliding_with = entity_nil();
|
||||||
|
struct gjk_simplex simplex = { 0 };
|
||||||
for (u64 e1_index = 0; e1_index < store->reserved; ++e1_index) {
|
for (u64 e1_index = 0; e1_index < store->reserved; ++e1_index) {
|
||||||
struct entity *e1 = &store->entities[e1_index];
|
struct entity *e1 = &store->entities[e1_index];
|
||||||
if (e1 == e0) continue;
|
if (e1 == e0) continue;
|
||||||
@ -799,7 +784,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
struct v2 e0_velocity = v2_div(v2_sub(e0_xf.og, e0->verlet_xform.og), dt);
|
struct v2 e0_velocity = v2_div(v2_sub(e0_xf.og, e0->verlet_xform.og), dt);
|
||||||
struct v2 e1_velocity = v2_div(v2_sub(e1_xf.og, e1->verlet_xform.og), dt);
|
struct v2 e1_velocity = v2_div(v2_sub(e1_xf.og, e1->verlet_xform.og), dt);
|
||||||
struct v2 pendir = v2_sub(e0_velocity, e1_velocity); /* What if both point in opposite directions? */
|
struct v2 pendir = v2_sub(e0_velocity, e1_velocity); /* What if both point in opposite directions? */
|
||||||
@ -815,32 +800,21 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
point0 = res.p0;
|
point0 = res.p0;
|
||||||
point1 = res.p1;
|
point1 = res.p1;
|
||||||
colliding_with = e1;
|
colliding_with = e1;
|
||||||
//final_simplex = res.simplex;
|
simplex = res.simplex;
|
||||||
|
|
||||||
if (colliding) {
|
if (colliding) {
|
||||||
|
|
||||||
|
#if 1
|
||||||
struct v2 pen = v2_sub(point1, point0);
|
struct v2 pen = v2_sub(point1, point0);
|
||||||
|
/* Pen movement test */
#if 0
|
||||||
#if 0
|
f32 epsilon = 0.000;
pen = v2_add(pen, v2_mul(v2_norm(pen), epsilon));
|
||||||
/* Pen movement test */
|
#endif
|
||||||
f32 e0_ratio = v2_dot(pendir, e0_velocity);
|
|
||||||
//f32 e1_ratio = v2_dot(pendir, e1_velocity);
|
|
||||||
f32 e1_ratio = v2_dot(pendir, e1_velocity);
|
|
||||||
{
|
|
||||||
struct v2 pen = v2_mul(e0_velocity, e0_ratio);
|
|
||||||
|
|
||||||
struct xform xf = e0_xf;
|
struct xform xf = e0_xf;
|
||||||
xf.og = v2_add(xf.og, pen);
|
xf.og = v2_add(xf.og, pen);
|
||||||
entity_set_xform(e0, xf);
|
entity_set_xform(e0, xf);
|
||||||
|
|
||||||
//e0->verlet_xform.og = v2_add(e0->verlet_xform.og, pen);
|
//e0->verlet_xform.og = v2_add(e0->verlet_xform.og, pen);
|
||||||
}
|
e0->verlet_xform.og = xf.og;
|
||||||
#else
f32 epsilon = 0.0001;
pen = v2_add(pen, v2_mul(v2_norm(pen), epsilon));
|
|
||||||
|
|
||||||
struct xform xf = e0_xf;
|
|
||||||
xf.og = v2_add(xf.og, pen);
|
|
||||||
entity_set_xform(e0, xf);
|
|
||||||
e0->verlet_xform.og = v2_add(e0->verlet_xform.og, pen);
|
|
||||||
//e0->verlet_xform.og = xf.og;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -848,6 +822,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
e0->colliding = colliding;
|
e0->colliding = colliding;
|
||||||
e0->colliding_with = colliding_with->handle;
|
e0->colliding_with = colliding_with->handle;
|
||||||
e0->point = point0;
|
e0->point = point0;
|
||||||
|
e0->simplex = simplex;
|
||||||
|
|
||||||
if (colliding_with->valid) {
|
if (colliding_with->valid) {
|
||||||
colliding_with->colliding = colliding;
|
colliding_with->colliding = colliding;
|
||||||
@ -862,6 +837,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
* Player aim
|
* Player aim
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
|
#if 0
|
||||||
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
|
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
|
||||||
struct entity *ent = &store->entities[entity_index];
|
struct entity *ent = &store->entities[entity_index];
|
||||||
if (!(ent->valid && entity_has_prop(ent, ENTITY_PROP_ACTIVE))) continue;
|
if (!(ent->valid && entity_has_prop(ent, ENTITY_PROP_ACTIVE))) continue;
|
||||||
@ -924,6 +900,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
entity_set_xform(ent, xf);
|
entity_set_xform(ent, xf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Initialize bullet kinematics from sources
|
* Initialize bullet kinematics from sources
|
||||||
|
|||||||
@ -24,11 +24,6 @@ enum game_cmd_kind {
|
|||||||
GAME_CMD_KIND_PAUSE,
|
GAME_CMD_KIND_PAUSE,
|
||||||
GAME_CMD_KIND_STEP,
|
GAME_CMD_KIND_STEP,
|
||||||
|
|
||||||
#if RTC
|
|
||||||
/* Debug */
|
|
||||||
GAME_CMD_KIND_SET_GJK_STEPS,
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GAME_CMD_KIND_COUNT
|
GAME_CMD_KIND_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
104
src/gjk.c
104
src/gjk.c
@ -3,16 +3,11 @@
|
|||||||
#include "arena.h"
|
#include "arena.h"
|
||||||
#include "scratch.h"
|
#include "scratch.h"
|
||||||
|
|
||||||
struct menkowski_point {
|
#if GJK_DEBUG
|
||||||
struct v2 p0; /* Support point of first shape in dir */
|
u32 gjk_debug_steps = U32_MAX;
|
||||||
struct v2 p1; /* Support point of second shape in -dir */
|
#endif
|
||||||
struct v2 p; /* Menkowski difference point */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct simplex {
|
#define DBGSTEP if (dbg_step++ >= gjk_debug_steps) goto abort
|
||||||
u32 len;
|
|
||||||
struct menkowski_point a, b, c;
|
|
||||||
};
|
|
||||||
|
|
||||||
INTERNAL struct v2 poly_support(struct v2_array a, struct v2 dir)
|
INTERNAL struct v2 poly_support(struct v2_array a, struct v2 dir)
|
||||||
{
|
{
|
||||||
@ -35,9 +30,9 @@ INTERNAL struct v2 menkowski_point(struct v2_array poly0, struct v2_array shape1
|
|||||||
return v2_sub(poly_support(poly0, dir), poly_support(shape1, v2_neg(dir)));
|
return v2_sub(poly_support(poly0, dir), poly_support(shape1, v2_neg(dir)));
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct menkowski_point menkowski_point_extended(struct v2_array poly0, struct v2_array poly1, struct v2 dir)
|
INTERNAL struct gjk_menkowski_point menkowski_point_extended(struct v2_array poly0, struct v2_array poly1, struct v2 dir)
|
||||||
{
|
{
|
||||||
struct menkowski_point res;
|
struct gjk_menkowski_point res;
|
||||||
res.p0 = poly_support(poly0, dir);
|
res.p0 = poly_support(poly0, dir);
|
||||||
res.p1 = poly_support(poly1, v2_neg(dir));
|
res.p1 = poly_support(poly1, v2_neg(dir));
|
||||||
res.p = v2_sub(res.p0, res.p1);
|
res.p = v2_sub(res.p0, res.p1);
|
||||||
@ -93,24 +88,34 @@ b32 gjk_boolean(struct v2_array shape0, struct v2_array shape1)
|
|||||||
|
|
||||||
struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array shape1, struct v2 penetration_dir)
|
struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array shape1, struct v2 penetration_dir)
|
||||||
{
|
{
|
||||||
|
struct temp_arena scratch = scratch_begin_no_conflict();
|
||||||
struct gjk_extended_result res = { 0 };
|
struct gjk_extended_result res = { 0 };
|
||||||
|
|
||||||
/* TODO: Verify epsilon */
|
/* TODO: Verify epsilon */
|
||||||
f32 unique_epsilon = 0.00001;
|
f32 unique_epsilon = 0.00001;
|
||||||
b32 use_penetration_dir = false;
|
b32 use_penetration_dir = false;
|
||||||
struct simplex s = { 0 };
|
struct gjk_simplex s = { 0 };
|
||||||
|
b32 colliding = false;
|
||||||
|
struct v2 shape0_p = { 0 };
|
||||||
|
struct v2 shape1_p = { 0 };
|
||||||
|
|
||||||
|
#if GJK_DEBUG
|
||||||
|
u32 dbg_step = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* GJK collision check
|
* GJK collision check
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct v2 dir = { 0 };
|
struct v2 dir = { 0 };
|
||||||
struct menkowski_point m = { 0 };
|
struct gjk_menkowski_point m = { 0 };
|
||||||
{
|
{
|
||||||
|
DBGSTEP;
|
||||||
/* First point is support point in shape's general directions to eachother */
|
/* First point is support point in shape's general directions to eachother */
|
||||||
s.a = menkowski_point_extended(shape0, shape1, v2_sub(shape1.points[0], shape0.points[0]));
|
s.a = menkowski_point_extended(shape0, shape1, v2_sub(shape1.points[0], shape0.points[0]));
|
||||||
s.len = 1;
|
s.len = 1;
|
||||||
|
|
||||||
|
DBGSTEP;
|
||||||
/* Second point is support point towards origin */
|
/* Second point is support point towards origin */
|
||||||
dir = v2_neg(s.a.p);
|
dir = v2_neg(s.a.p);
|
||||||
m = menkowski_point_extended(shape0, shape1, dir);
|
m = menkowski_point_extended(shape0, shape1, dir);
|
||||||
@ -120,6 +125,7 @@ struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array
|
|||||||
s.len = 2;
|
s.len = 2;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
DBGSTEP;
|
||||||
/* Third point is support point in direction of line normal towards origin */
|
/* Third point is support point in direction of line normal towards origin */
|
||||||
dir = v2_perp_towards_dir(v2_sub(s.b.p, s.a.p), v2_neg(s.a.p));
|
dir = v2_perp_towards_dir(v2_sub(s.b.p, s.a.p), v2_neg(s.a.p));
|
||||||
m = menkowski_point_extended(shape0, shape1, dir);
|
m = menkowski_point_extended(shape0, shape1, dir);
|
||||||
@ -133,6 +139,7 @@ struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array
|
|||||||
s.a = m;
|
s.a = m;
|
||||||
s.len = 3;
|
s.len = 3;
|
||||||
|
|
||||||
|
DBGSTEP;
|
||||||
dir = v2_perp_towards_dir(v2_sub(s.b.p, s.a.p), v2_neg(v2_sub(s.c.p, s.a.p))); /* Normal of ab pointing away from c */
|
dir = v2_perp_towards_dir(v2_sub(s.b.p, s.a.p), v2_neg(v2_sub(s.c.p, s.a.p))); /* Normal of ab pointing away from c */
|
||||||
struct v2 a_to_origin = v2_neg(s.a.p);
|
struct v2 a_to_origin = v2_neg(s.a.p);
|
||||||
if (v2_dot(dir, a_to_origin) >= 0) {
|
if (v2_dot(dir, a_to_origin) >= 0) {
|
||||||
@ -146,7 +153,7 @@ struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array
|
|||||||
s.b = s.c;
|
s.b = s.c;
|
||||||
s.len = 2;
|
s.len = 2;
|
||||||
} else {
|
} else {
|
||||||
res.colliding = true;
|
colliding = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,7 +161,7 @@ struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.colliding) {
|
if (colliding) {
|
||||||
use_penetration_dir = !v2_eq(penetration_dir, V2(0, 0));
|
use_penetration_dir = !v2_eq(penetration_dir, V2(0, 0));
|
||||||
if (use_penetration_dir) {
|
if (use_penetration_dir) {
|
||||||
|
|
||||||
@ -165,6 +172,7 @@ struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array
|
|||||||
while (true) {
|
while (true) {
|
||||||
/* Second point is support point towards penetration_dir */
|
/* Second point is support point towards penetration_dir */
|
||||||
if (s.len == 1) {
|
if (s.len == 1) {
|
||||||
|
DBGSTEP;
|
||||||
dir = v2_sub(v2_mul(penetration_dir, v2_dot(penetration_dir, s.a.p) / v2_dot(penetration_dir, penetration_dir)), s.a.p);
|
dir = v2_sub(v2_mul(penetration_dir, v2_dot(penetration_dir, s.a.p) / v2_dot(penetration_dir, penetration_dir)), s.a.p);
|
||||||
m = menkowski_point_extended(shape0, shape1, dir);
|
m = menkowski_point_extended(shape0, shape1, dir);
|
||||||
if (v2_eq(m.p, s.a.p)) {
|
if (v2_eq(m.p, s.a.p)) {
|
||||||
@ -178,6 +186,7 @@ struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (s.len == 2) {
|
if (s.len == 2) {
|
||||||
|
DBGSTEP;
|
||||||
m = menkowski_point_extended(shape0, shape1, dir);
|
m = menkowski_point_extended(shape0, shape1, dir);
|
||||||
if (math_fabs(v2_wedge(v2_sub(s.b.p, s.a.p), v2_sub(m.p, s.a.p))) < unique_epsilon) {
|
if (math_fabs(v2_wedge(v2_sub(s.b.p, s.a.p), v2_sub(m.p, s.a.p))) < unique_epsilon) {
|
||||||
/* New point is already on the current line */
|
/* New point is already on the current line */
|
||||||
@ -189,6 +198,7 @@ struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array
|
|||||||
s.len = 3;
|
s.len = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DBGSTEP;
|
||||||
i32 a_wedgesign = math_fsign(v2_wedge(penetration_dir, s.a.p));
|
i32 a_wedgesign = math_fsign(v2_wedge(penetration_dir, s.a.p));
|
||||||
i32 b_wedgesign = math_fsign(v2_wedge(penetration_dir, s.b.p));
|
i32 b_wedgesign = math_fsign(v2_wedge(penetration_dir, s.b.p));
|
||||||
i32 c_wedgesign = math_fsign(v2_wedge(penetration_dir, s.c.p));
|
i32 c_wedgesign = math_fsign(v2_wedge(penetration_dir, s.c.p));
|
||||||
@ -212,17 +222,15 @@ struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array
|
|||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Expand simplex towards closest edge (EPA)
|
* Expand simplex towards closest edge to origin inside menkowski (EPA)
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct temp_arena scratch = scratch_begin_no_conflict();
|
struct gjk_menkowski_point *proto = arena_dry_push(scratch.arena, struct gjk_menkowski_point);
|
||||||
|
|
||||||
struct menkowski_point *proto = arena_dry_push(scratch.arena, struct menkowski_point);
|
|
||||||
u32 proto_count = 0;
|
u32 proto_count = 0;
|
||||||
|
|
||||||
{
|
{
|
||||||
ASSERT(s.len == 3);
|
ASSERT(s.len == 3);
|
||||||
struct menkowski_point *tmp = arena_push_array(scratch.arena, struct menkowski_point, 3);
|
struct gjk_menkowski_point *tmp = arena_push_array(scratch.arena, struct gjk_menkowski_point, 3);
|
||||||
tmp[0] = s.a;
|
tmp[0] = s.a;
|
||||||
tmp[1] = s.b;
|
tmp[1] = s.b;
|
||||||
tmp[2] = s.c;
|
tmp[2] = s.c;
|
||||||
@ -230,6 +238,7 @@ struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
DBGSTEP;
|
||||||
struct v2 pen = V2(0, 0);
|
struct v2 pen = V2(0, 0);
|
||||||
f32 pen_len_sq = F32_INFINITY;
|
f32 pen_len_sq = F32_INFINITY;
|
||||||
|
|
||||||
@ -258,6 +267,11 @@ struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: Move to break (debugging) */
|
||||||
|
s.a = proto[pen_ps_index];
|
||||||
|
s.b = proto[pen_pe_index];
|
||||||
|
s.len = 2;
|
||||||
|
|
||||||
/* Find new point in dir */
|
/* Find new point in dir */
|
||||||
m = menkowski_point_extended(shape0, shape1, pen);
|
m = menkowski_point_extended(shape0, shape1, pen);
|
||||||
|
|
||||||
@ -274,9 +288,6 @@ struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!unique) {
|
if (!unique) {
|
||||||
s.a = proto[pen_ps_index];
|
|
||||||
s.b = proto[pen_pe_index];
|
|
||||||
s.len = 2;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -292,13 +303,11 @@ struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array
|
|||||||
}
|
}
|
||||||
proto[pen_pe_index] = m;
|
proto[pen_pe_index] = m;
|
||||||
}
|
}
|
||||||
|
|
||||||
scratch_end(scratch);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Move simplex towards closest edge to origin
|
* Move simplex towards closest edge to origin outside menkowski
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
if (s.len == 2) {
|
if (s.len == 2) {
|
||||||
@ -309,6 +318,7 @@ struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array
|
|||||||
while (true) {
|
while (true) {
|
||||||
/* Second point is support point towards origin */
|
/* Second point is support point towards origin */
|
||||||
if (s.len == 1) {
|
if (s.len == 1) {
|
||||||
|
DBGSTEP;
|
||||||
m = menkowski_point_extended(shape0, shape1, v2_neg(s.a.p));
|
m = menkowski_point_extended(shape0, shape1, v2_neg(s.a.p));
|
||||||
if (v2_eq(m.p, s.a.p) || v2_eq(m.p, V2(0, 0))) {
|
if (v2_eq(m.p, s.a.p) || v2_eq(m.p, V2(0, 0))) {
|
||||||
break;
|
break;
|
||||||
@ -323,6 +333,7 @@ struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (s.len == 2) {
|
if (s.len == 2) {
|
||||||
|
DBGSTEP;
|
||||||
m = menkowski_point_extended(shape0, shape1, dir);
|
m = menkowski_point_extended(shape0, shape1, dir);
|
||||||
if (math_fabs(v2_wedge(v2_sub(s.b.p, s.a.p), v2_sub(m.p, s.a.p))) < unique_epsilon || v2_eq(m.p, V2(0, 0))) {
|
if (math_fabs(v2_wedge(v2_sub(s.b.p, s.a.p), v2_sub(m.p, s.a.p))) < unique_epsilon || v2_eq(m.p, V2(0, 0))) {
|
||||||
/* New point is already on the current line */
|
/* New point is already on the current line */
|
||||||
@ -334,6 +345,7 @@ struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array
|
|||||||
s.len = 3;
|
s.len = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DBGSTEP;
|
||||||
/* Remove point or edge and determine next direction based on voronoi regions */
|
/* Remove point or edge and determine next direction based on voronoi regions */
|
||||||
struct v2 rab_dir = v2_perp_towards_dir(v2_sub(s.b.p, s.a.p), v2_neg(v2_sub(s.c.p, s.a.p)));
|
struct v2 rab_dir = v2_perp_towards_dir(v2_sub(s.b.p, s.a.p), v2_neg(v2_sub(s.c.p, s.a.p)));
|
||||||
struct v2 rac_dir = v2_perp_towards_dir(v2_sub(s.c.p, s.a.p), v2_neg(v2_sub(s.b.p, s.a.p)));
|
struct v2 rac_dir = v2_perp_towards_dir(v2_sub(s.c.p, s.a.p), v2_neg(v2_sub(s.b.p, s.a.p)));
|
||||||
@ -374,9 +386,10 @@ struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Resolve points */
|
/* Resolve points */
|
||||||
|
DBGSTEP;
|
||||||
if (s.len == 1) {
|
if (s.len == 1) {
|
||||||
res.p0 = s.a.p0;
|
shape0_p = s.a.p0;
|
||||||
res.p1 = s.a.p1;
|
shape1_p = s.a.p1;
|
||||||
} else if (s.len == 2) {
|
} else if (s.len == 2) {
|
||||||
/* FIXME: Winding order dependent? */
|
/* FIXME: Winding order dependent? */
|
||||||
f32 ratio;
|
f32 ratio;
|
||||||
@ -392,14 +405,37 @@ struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array
|
|||||||
ratio = clamp_f32(v2_dot(vab, vao) / v2_dot(vab, vab), 0, 1);
|
ratio = clamp_f32(v2_dot(vab, vao) / v2_dot(vab, vab), 0, 1);
|
||||||
}
|
}
|
||||||
/* Shape 0 */
|
/* Shape 0 */
|
||||||
res.p0 = v2_sub(s.b.p0, s.a.p0);
|
shape0_p = v2_sub(s.b.p0, s.a.p0);
|
||||||
res.p0 = v2_mul(res.p0, ratio);
|
shape0_p = v2_mul(shape0_p, ratio);
|
||||||
res.p0 = v2_add(res.p0, s.a.p0);
|
shape0_p = v2_add(shape0_p, s.a.p0);
|
||||||
/* Shape 1 */
|
/* Shape 1 */
|
||||||
res.p1 = v2_sub(s.b.p1, s.a.p1);
|
shape1_p = v2_sub(s.b.p1, s.a.p1);
|
||||||
res.p1 = v2_mul(res.p1, ratio);
|
shape1_p = v2_mul(shape1_p, ratio);
|
||||||
res.p1 = v2_add(res.p1, s.a.p1);
|
shape1_p = v2_add(shape1_p, s.a.p1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abort:
|
||||||
|
res.colliding = colliding;
|
||||||
|
res.p0 = shape0_p;
|
||||||
|
res.p1 = shape1_p;
|
||||||
|
res.simplex = s;
|
||||||
|
scratch_end(scratch);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Remove this (debugging) */
|
||||||
|
struct v2_array menkowski(struct arena *arena, struct v2_array poly0, struct v2_array poly1)
|
||||||
|
{
|
||||||
|
struct v2_array res = { .points = arena_dry_push(arena, struct v2) };
|
||||||
|
u64 rays = 500;
|
||||||
|
for (u64 i = 0; i < rays; ++i) {
|
||||||
|
f32 angle = ((f32)i / rays) * (2 * PI);
|
||||||
|
struct v2 dir = v2_from_angle(angle);
|
||||||
|
struct v2 p = menkowski_point_extended(poly0, poly1, dir).p;
|
||||||
|
if (res.count == 0 || !v2_eq(p, res.points[res.count - 1])) {
|
||||||
|
*arena_push(arena, struct v2) = p;
|
||||||
|
++res.count;
|
||||||
|
}
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
22
src/gjk.h
22
src/gjk.h
@ -1,9 +1,29 @@
|
|||||||
#ifndef GJK_H
|
#ifndef GJK_H
|
||||||
#define GJK_H
|
#define GJK_H
|
||||||
|
|
||||||
|
#define GJK_DEBUG RTC
|
||||||
|
|
||||||
|
#if GJK_DEBUG
|
||||||
|
extern u32 gjk_debug_steps;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct gjk_menkowski_point {
|
||||||
|
struct v2 p0; /* Support point of first shape in dir */
|
||||||
|
struct v2 p1; /* Support point of second shape in -dir */
|
||||||
|
struct v2 p; /* Menkowski difference point */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gjk_simplex {
|
||||||
|
u32 len;
|
||||||
|
struct gjk_menkowski_point a, b, c;
|
||||||
|
};
|
||||||
|
|
||||||
struct gjk_extended_result {
|
struct gjk_extended_result {
|
||||||
b32 colliding;
|
b32 colliding;
|
||||||
struct v2 p0, p1; /* Closest points (or penetrating points if colliding) on each shape */
|
struct v2 p0, p1; /* Closest points (or penetrating points if colliding) on each shape */
|
||||||
|
|
||||||
|
/* For debugging */
|
||||||
|
struct gjk_simplex simplex;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Returns simple true or false indicating shape collision */
|
/* Returns simple true or false indicating shape collision */
|
||||||
@ -17,4 +37,6 @@ b32 gjk_boolean(struct v2_array shape0, struct v2_array shape1);
|
|||||||
* supplied direction. */
|
* supplied direction. */
|
||||||
struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array shape1, struct v2 penetration_dir);
|
struct gjk_extended_result gjk_extended(struct v2_array shape0, struct v2_array shape1, struct v2 penetration_dir);
|
||||||
|
|
||||||
|
struct v2_array menkowski(struct arena *arena, struct v2_array poly0, struct v2_array poly1);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
29
src/user.c
29
src/user.c
@ -69,10 +69,6 @@ GLOBAL struct {
|
|||||||
struct v2 viewport_center;
|
struct v2 viewport_center;
|
||||||
struct v2 viewport_cursor;
|
struct v2 viewport_cursor;
|
||||||
struct v2 world_cursor;
|
struct v2 world_cursor;
|
||||||
|
|
||||||
#if RTC
|
|
||||||
u32 gjk_steps;
|
|
||||||
#endif
|
|
||||||
} G = { 0 }, DEBUG_ALIAS(G, G_user);
|
} G = { 0 }, DEBUG_ALIAS(G, G_user);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -148,9 +144,6 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
|
|||||||
G.viewport_bg_canvas = renderer_canvas_alloc();
|
G.viewport_bg_canvas = renderer_canvas_alloc();
|
||||||
G.viewport_canvas = renderer_canvas_alloc();
|
G.viewport_canvas = renderer_canvas_alloc();
|
||||||
G.window = window;
|
G.window = window;
|
||||||
#if RTC
|
|
||||||
G.gjk_steps = U32_MAX;
|
|
||||||
#endif
|
|
||||||
sys_window_register_event_callback(G.window, &window_event_callback);
|
sys_window_register_event_callback(G.window, &window_event_callback);
|
||||||
|
|
||||||
G.user_thread = sys_thread_alloc(&user_thread_entry_point, NULL, STR("[P1] User thread"));
|
G.user_thread = sys_thread_alloc(&user_thread_entry_point, NULL, STR("[P1] User thread"));
|
||||||
@ -997,7 +990,7 @@ INTERNAL void user_update(void)
|
|||||||
(UNUSED)e1;
|
(UNUSED)e1;
|
||||||
(UNUSED)colliding;
|
(UNUSED)colliding;
|
||||||
|
|
||||||
#if 0
|
#if 1
|
||||||
/* Draw menkowski */
|
/* Draw menkowski */
|
||||||
if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) {
|
if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) {
|
||||||
struct quad ent_quad;
|
struct quad ent_quad;
|
||||||
@ -1046,7 +1039,7 @@ INTERNAL void user_update(void)
|
|||||||
draw_solid_circle(G.viewport_canvas, point, thickness, color, 10);
|
draw_solid_circle(G.viewport_canvas, point, thickness, color, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 1
|
||||||
/* Draw simplex */
|
/* Draw simplex */
|
||||||
{
|
{
|
||||||
f32 thickness = 2;
|
f32 thickness = 2;
|
||||||
@ -1076,7 +1069,9 @@ INTERNAL void user_update(void)
|
|||||||
draw_solid_poly_line(G.viewport_canvas, simplex_array, simplex.len > 2, thickness, line_color);
|
draw_solid_poly_line(G.viewport_canvas, simplex_array, simplex.len > 2, thickness, line_color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Draw pen */
|
/* Draw pen */
|
||||||
if (colliding) {
|
if (colliding) {
|
||||||
f32 thickness = 2;
|
f32 thickness = 2;
|
||||||
@ -1148,7 +1143,8 @@ INTERNAL void user_update(void)
|
|||||||
|
|
||||||
{
|
{
|
||||||
/* Queue player move cmd */
|
/* Queue player move cmd */
|
||||||
f32 move_speed = G.bind_states[USER_BIND_KIND_WALK].is_held ? 0.25f : 1.0f;
|
const f32 walk_ratio = 0.25f;
|
||||||
|
f32 move_speed = G.bind_states[USER_BIND_KIND_WALK].is_held ? walk_ratio : 1.0f;
|
||||||
struct v2 input_move_dir = { 0 };
|
struct v2 input_move_dir = { 0 };
|
||||||
{
|
{
|
||||||
for (enum user_bind_kind bind = 0; bind < (i32)ARRAY_COUNT(G.bind_states); ++bind) {
|
for (enum user_bind_kind bind = 0; bind < (i32)ARRAY_COUNT(G.bind_states); ++bind) {
|
||||||
@ -1199,20 +1195,13 @@ INTERNAL void user_update(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if RTC
|
#if RTC
|
||||||
/* Queue debug cmds */
|
|
||||||
|
|
||||||
/* Gjk steps */
|
/* Gjk steps */
|
||||||
{
|
{
|
||||||
i64 new_steps = (i64)G.gjk_steps;
|
i64 new_steps = gjk_debug_steps;
|
||||||
new_steps += G.bind_states[USER_BIND_KIND_INCR_GJK_STEPS].num_presses_and_repeats;
|
new_steps += G.bind_states[USER_BIND_KIND_INCR_GJK_STEPS].num_presses_and_repeats;
|
||||||
new_steps -= G.bind_states[USER_BIND_KIND_DECR_GJK_STEPS].num_presses_and_repeats;
|
new_steps -= G.bind_states[USER_BIND_KIND_DECR_GJK_STEPS].num_presses_and_repeats;
|
||||||
if (G.bind_states[USER_BIND_KIND_RESET_GJK_STEPS].num_presses_and_repeats > 0) new_steps = 0;
|
if (G.bind_states[USER_BIND_KIND_RESET_GJK_STEPS].num_presses_and_repeats > 0) new_steps = 0;
|
||||||
G.gjk_steps = (u32)clamp_i64(new_steps, 0, U32_MAX);
|
gjk_debug_steps = (u32)clamp_i64(new_steps, 0, U32_MAX);
|
||||||
queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) {
|
|
||||||
.kind = GAME_CMD_KIND_SET_GJK_STEPS,
|
|
||||||
.state = 1,
|
|
||||||
.gjk_steps = G.gjk_steps
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -1272,7 +1261,7 @@ INTERNAL void user_update(void)
|
|||||||
pos.y += spacing;
|
pos.y += spacing;
|
||||||
|
|
||||||
#if RTC
|
#if RTC
|
||||||
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("gjk steps: %F"), FMT_UINT(G.gjk_steps)));
|
draw_text(G.viewport_canvas, font, pos, string_format(temp.arena, STR("gjk steps: %F"), FMT_UINT(gjk_debug_steps)));
|
||||||
pos.y += spacing;
|
pos.y += spacing;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user