re-add/enable gjk debug visualization

This commit is contained in:
jacob 2024-09-04 10:26:04 -05:00
parent 8c36552659
commit f608000b85
6 changed files with 117 additions and 96 deletions

View File

@ -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;

View File

@ -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

View File

@ -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
View File

@ -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;
} }

View File

@ -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

View File

@ -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