update collider debug logic so it works again. add debug teleport

This commit is contained in:
jacob 2025-05-16 10:32:07 -05:00
parent 1fbe42b3b9
commit 0b3767df3a
9 changed files with 68 additions and 52 deletions

View File

@ -30,7 +30,7 @@ INTERNAL void _dbgbreakable(void)
goto abort; \ goto abort; \
} else if (dbg_step >= collider_debug_steps - 1) { \ } else if (dbg_step >= collider_debug_steps - 1) { \
_dbgbreakable(); \ _dbgbreakable(); \
} } (void)0
#else #else
#define DBGSTEP #define DBGSTEP
#endif #endif

View File

@ -61,8 +61,8 @@
#define SIM_MAX_ANGULAR_VELOCITY (TAU * 20) #define SIM_MAX_ANGULAR_VELOCITY (TAU * 20)
#define COLLIDER_DEBUG 0 #define COLLIDER_DEBUG 0
#define COLLIDER_DEBUG_DETAILED 0 #define COLLIDER_DEBUG_DETAILED 1
#define COLLIDER_DEBUG_DETAILED_DRAW_MENKOWSKI 0 #define COLLIDER_DEBUG_DETAILED_DRAW_MENKOWSKI 1
/* If enabled, bitbuffs will insert/verify magic numbers & length for each read & write */ /* If enabled, bitbuffs will insert/verify magic numbers & length for each read & write */
#define BITBUFF_DEBUG 0 #define BITBUFF_DEBUG 0

View File

@ -225,23 +225,18 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a
/* TODO: Remove this (debugging) */ /* TODO: Remove this (debugging) */
#if COLLIDER_DEBUG && COLLIDER_DEBUG_DETAILED #if COLLIDER_DEBUG && COLLIDER_DEBUG_DETAILED
{ {
struct sim_ent *dbg_ent = sim_ent_nil(); struct sim_ent_id dbg_ent_id = sim_ent_collision_debug_id_from_ids(local_player, e0->id, e1->id);
struct sim_lookup_entry *dbg_entry = sim_lookup_get(debug_lookup, key); struct sim_ent *dbg_ent = sim_ent_from_id(ss, dbg_ent_id);
if (dbg_entry) {
dbg_ent = sim_ent_from_id(ss, dbg_entry->entity);
}
if (!dbg_ent->valid) { if (!dbg_ent->valid) {
/* FIXME: Entity never released */ /* FIXME: Entity never released */
dbg_ent = sim_ent_alloc_local(root); dbg_ent = sim_ent_alloc_local_with_id(root, dbg_ent_id);
sim_ent_enable_prop(dbg_ent, SEPROP_COLLISION_DEBUG); sim_ent_enable_prop(dbg_ent, SEPROP_COLLISION_DEBUG);
sim_lookup_set(debug_lookup, key, dbg_ent->handle);
} }
struct phys_collision_debug *dbg = &dbg_ent->collision_debug_data; struct phys_collision_debug *dbg = &dbg_ent->collision_debug_data;
dbg->e0 = e0->handle; dbg->e0 = e0->id;
dbg->e1 = e1->handle; dbg->e1 = e1->id;
dbg->res = collider_res; dbg->res = collider_res;
if (constraint) { if (constraint) {
@ -368,8 +363,9 @@ void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration)
} }
} }
#if 0
#if COLLIDER_DEBUG #if COLLIDER_DEBUG
struct sim_lookup *debug_lookup = ctx->debug_lookup; /* Remove collision debug ents */
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
struct sim_ent *dbg_ent = &ss->ents[sim_ent_index]; struct sim_ent *dbg_ent = &ss->ents[sim_ent_index];
if (!sim_ent_should_simulate(dbg_ent)) continue; if (!sim_ent_should_simulate(dbg_ent)) continue;
@ -379,26 +375,16 @@ void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration)
struct sim_ent *e0 = sim_ent_from_id(ss, dbg->e0); struct sim_ent *e0 = sim_ent_from_id(ss, dbg->e0);
struct sim_ent *e1 = sim_ent_from_id(ss, dbg->e1); struct sim_ent *e1 = sim_ent_from_id(ss, dbg->e1);
if (!sim_ent_should_simulate(e0) || !sim_ent_should_simulate(e1) if (!sim_ent_should_simulate(e0) || !sim_ent_should_simulate(e1)
|| !(sim_ent_has_prop(e0, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e0, SEPROP_PHYSICAL_KINEMATIC) || !sim_ent_has_prop(e0, SEPROP_SENSOR)) || !(sim_ent_has_prop(e0, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e0, SEPROP_PHYSICAL_KINEMATIC) || !sim_ent_has_prop(e0, SEPROP_SENSOR))
|| !(sim_ent_has_prop(e1, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e1, SEPROP_PHYSICAL_KINEMATIC) || !sim_ent_has_prop(e1, SEPROP_SENSOR))) { || !(sim_ent_has_prop(e1, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e1, SEPROP_PHYSICAL_KINEMATIC) || !sim_ent_has_prop(e1, SEPROP_SENSOR))) {
/* Mark dbg ent for removal */ /* Mark dbg ent for removal */
sim_ent_disable_prop(dbg_ent, SEPROP_ACTIVE); sim_ent_disable_prop(dbg_ent, SEPROP_ACTIVE);
sim_ent_enable_prop(dbg_ent, SEPROP_RELEASE); sim_ent_enable_prop(dbg_ent, SEPROP_RELEASE);
/* Remove from lookup */
struct sim_lookup_key key = sim_lookup_key_from_two_handles(dbg->e0, dbg->e1);
struct sim_lookup_entry *entry = sim_lookup_get(debug_lookup, key);
if (entry) {
sim_lookup_remove(debug_lookup, entry);
} else {
ASSERT(false); /* This should always exist */
}
} }
} }
#endif #endif
#endif
} }
void phys_warm_start_contacts(struct phys_step_ctx *ctx) void phys_warm_start_contacts(struct phys_step_ctx *ctx)

View File

@ -142,11 +142,13 @@ enum sim_control_flag {
SIM_CONTROL_FLAG_SPAWN_TEST = 1 << 3, SIM_CONTROL_FLAG_SPAWN_TEST = 1 << 3,
SIM_CONTROL_FLAG_TILE_TEST = 1 << 4, SIM_CONTROL_FLAG_TILE_TEST = 1 << 4,
SIM_CONTROL_FLAG_EXPLODE_TEST = 1 << 5, SIM_CONTROL_FLAG_EXPLODE_TEST = 1 << 5,
SIM_CONTROL_FLAG_TELEPORT_TEST = 1 << 6,
}; };
struct sim_control { struct sim_control {
struct v2 move; /* Movement direction vector (speed of 0 -> 1) */ struct v2 move; /* Movement direction vector (speed of 0 -> 1) */
struct v2 focus; /* Focus direction vector (where does the controller want to look) */ struct v2 focus; /* Focus direction vector (where does the controller want to look) */
struct v2 dbg_cursor; /* Where is the user's cursor in the world (used for things like editing the world) */
u32 flags; u32 flags;
}; };

View File

@ -7,6 +7,7 @@
/* Id magic number constants (to be used in conjunction with ent ids in deterministic id combinations) */ /* Id magic number constants (to be used in conjunction with ent ids in deterministic id combinations) */
#define SIM_ENT_CONTACT_BASIS_UID (UID(0x6a2a5d2dbecf534f, 0x0a8ca7c372a015af)) #define SIM_ENT_CONTACT_BASIS_UID (UID(0x6a2a5d2dbecf534f, 0x0a8ca7c372a015af))
#define SIM_ENT_COLLISION_DEBUG_BASIS_UID (UID(0x302c01182013bb02, 0x570bd270399d11a5))
#define SIM_ENT_TILE_CHUNK_BASIS_UID (UID(0x3ce42de071dd226b, 0x9b566f7df30c813a)) #define SIM_ENT_TILE_CHUNK_BASIS_UID (UID(0x3ce42de071dd226b, 0x9b566f7df30c813a))
INTERNAL u32 index_from_ent(struct sim_snapshot *ss, struct sim_ent *ent) INTERNAL u32 index_from_ent(struct sim_snapshot *ss, struct sim_ent *ent)
@ -283,6 +284,17 @@ struct sim_ent_id sim_ent_contact_constraint_id_from_contacting_ids(struct sim_e
return res; return res;
} }
/* Returns the deterministic id of the debug contact constraint ent id that should be produced from e0 & e1 colliding */
struct sim_ent_id sim_ent_collision_debug_id_from_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1)
{
struct sim_ent_id res = ZI;
res.uid = SIM_ENT_COLLISION_DEBUG_BASIS_UID;
res.uid = uid_combine(res.uid, player_id.uid);
res.uid = uid_combine(res.uid, id0.uid);
res.uid = uid_combine(res.uid, id1.uid);
return res;
}
/* Returns the deterministic id of the tile chunk that should be produced at chunk pos */ /* Returns the deterministic id of the tile chunk that should be produced at chunk pos */
struct sim_ent_id sim_ent_chunk_id_from_chunk_pos(struct sim_ent_id player_id, struct v2i32 chunk_pos) struct sim_ent_id sim_ent_chunk_id_from_chunk_pos(struct sim_ent_id player_id, struct v2i32 chunk_pos)
{ {

View File

@ -211,7 +211,7 @@ struct sim_ent {
/* SEPROP_CONTROLLED */ /* SEPROP_CONTROLLED */
struct sim_ent_id controlling_client; struct sim_ent_id controlling_player;
f32 control_force; /* How much force is applied to achieve desired control movement */ f32 control_force; /* How much force is applied to achieve desired control movement */
f32 control_force_max_speed; /* Maximum linear velocity achieved by force (m/s) */ f32 control_force_max_speed; /* Maximum linear velocity achieved by force (m/s) */
@ -470,6 +470,7 @@ void sim_ent_set_id(struct sim_ent *ent, struct sim_ent_id id);
struct sim_ent *sim_ent_from_id(struct sim_snapshot *ss, struct sim_ent_id id); struct sim_ent *sim_ent_from_id(struct sim_snapshot *ss, struct sim_ent_id id);
struct sim_ent_id sim_ent_random_id(void); struct sim_ent_id sim_ent_random_id(void);
struct sim_ent_id sim_ent_contact_constraint_id_from_contacting_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1); struct sim_ent_id sim_ent_contact_constraint_id_from_contacting_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1);
struct sim_ent_id sim_ent_collision_debug_id_from_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1);
struct sim_ent_id sim_ent_chunk_id_from_chunk_pos(struct sim_ent_id player_id, struct v2i32 chunk_pos); struct sim_ent_id sim_ent_chunk_id_from_chunk_pos(struct sim_ent_id player_id, struct v2i32 chunk_pos);
/* Query */ /* Query */

View File

@ -94,10 +94,8 @@ INTERNAL struct sim_ent *spawn_test_employee(struct sim_step_ctx *ctx)
sim_ent_set_xform(e, xf); sim_ent_set_xform(e, xf);
#if 0
e->linear_ground_friction = 250; e->linear_ground_friction = 250;
e->angular_ground_friction = 200; e->angular_ground_friction = 200;
#endif
e->friction = 0; e->friction = 0;
@ -153,12 +151,12 @@ INTERNAL struct sim_ent *spawn_test_camera(struct sim_snapshot *world, struct si
return camera_ent; return camera_ent;
} }
INTERNAL struct sim_ent *spawn_test_explosion(struct sim_snapshot *world, struct v2 point, f32 radius) INTERNAL struct sim_ent *spawn_test_explosion(struct sim_snapshot *world, struct v2 pos, f32 radius)
{ {
struct sim_ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID); struct sim_ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
struct sim_ent *ent = sim_ent_alloc_sync_src(root); struct sim_ent *ent = sim_ent_alloc_sync_src(root);
sim_ent_set_xform(ent, XFORM_POS(point)); sim_ent_set_xform(ent, XFORM_POS(pos));
sim_ent_enable_prop(ent, SEPROP_EXPLOSION); sim_ent_enable_prop(ent, SEPROP_EXPLOSION);
ent->explosion_radius = radius; ent->explosion_radius = radius;
@ -170,6 +168,14 @@ INTERNAL struct sim_ent *spawn_test_explosion(struct sim_snapshot *world, struct
return ent; return ent;
} }
INTERNAL void test_teleport(struct sim_ent *ent, struct v2 pos)
{
++ent->continuity_gen;
struct xform xf = sim_ent_get_xform(ent);
xf.og = pos;
sim_ent_set_xform(ent, xf);
}
INTERNAL void spawn_test_entities(struct sim_step_ctx *ctx, struct v2 offset) INTERNAL void spawn_test_entities(struct sim_step_ctx *ctx, struct v2 offset)
{ {
struct sim_snapshot *world = ctx->world; struct sim_snapshot *world = ctx->world;
@ -350,7 +356,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
struct sim_ent *victim = e1; struct sim_ent *victim = e1;
exp->explosion_tick = world->tick; exp->explosion_tick = world->tick;
sim_ent_disable_prop(exp, SEPROP_SENSOR); //sim_ent_disable_prop(exp, SEPROP_SENSOR);
struct xform xf = sim_ent_get_xform(exp); struct xform xf = sim_ent_get_xform(exp);
@ -560,6 +566,7 @@ void sim_step(struct sim_step_ctx *ctx)
struct sim_control *control = &player->player_control; struct sim_control *control = &player->player_control;
*control = cmd_ent->cmd_control; *control = cmd_ent->cmd_control;
{ {
player->player_cursor_pos = control->dbg_cursor;
player->player_dbg_drag_start = false; player->player_dbg_drag_start = false;
player->player_dbg_drag_stop = false; player->player_dbg_drag_stop = false;
@ -568,16 +575,6 @@ void sim_step(struct sim_step_ctx *ctx)
control->move = v2_norm(control->move); control->move = v2_norm(control->move);
} }
/* Determine cursor pos from focus */
{
struct sim_ent_id player_control_ent_id = player->player_control_ent;
struct sim_ent *player_control_ent = sim_ent_from_id(world, player_control_ent_id);
if (player_control_ent->valid || sim_ent_id_is_nil(player_control_ent_id)) {
/* Only update cursor pos if focus ent is valid (or nil) */
player->player_cursor_pos = v2_add(sim_ent_get_xform(player_control_ent).og, player->player_control.focus);
}
}
player->player_hovered_ent = cmd_ent->cmd_control_hovered_ent; player->player_hovered_ent = cmd_ent->cmd_control_hovered_ent;
u32 flags = control->flags; u32 flags = control->flags;
@ -613,6 +610,15 @@ void sim_step(struct sim_step_ctx *ctx)
spawn_test_explosion(world, player->player_cursor_pos, 1); spawn_test_explosion(world, player->player_cursor_pos, 1);
} }
} }
if (flags & SIM_CONTROL_FLAG_TELEPORT_TEST) {
if (!(old_control.flags & SIM_CONTROL_FLAG_TELEPORT_TEST)) {
logf_info("Teleport (test)");
struct sim_ent *ent = sim_ent_from_id(world, player->player_control_ent);
if (ent->valid) {
test_teleport(ent, player->player_cursor_pos);
}
}
}
if (flags & SIM_CONTROL_FLAG_TILE_TEST) { if (flags & SIM_CONTROL_FLAG_TILE_TEST) {
#if 0 #if 0
@ -693,7 +699,7 @@ void sim_step(struct sim_step_ctx *ctx)
control_ent->predictor = ent->id; control_ent->predictor = ent->id;
sim_ent_enable_prop(control_ent, SEPROP_CONTROLLED); sim_ent_enable_prop(control_ent, SEPROP_CONTROLLED);
ent->player_control_ent = control_ent->id; ent->player_control_ent = control_ent->id;
control_ent->controlling_client = ent->id; control_ent->controlling_player = ent->id;
} }
struct sim_ent *camera_ent = sim_ent_from_id(world, ent->player_camera_ent); struct sim_ent *camera_ent = sim_ent_from_id(world, ent->player_camera_ent);
if (!camera_ent->valid) { if (!camera_ent->valid) {
@ -714,7 +720,7 @@ void sim_step(struct sim_step_ctx *ctx)
if (!sim_ent_should_simulate(ent)) continue; if (!sim_ent_should_simulate(ent)) continue;
if (sim_ent_has_prop(ent, SEPROP_CONTROLLED)) { if (sim_ent_has_prop(ent, SEPROP_CONTROLLED)) {
struct sim_ent *player = sim_ent_from_id(world, ent->controlling_client); struct sim_ent *player = sim_ent_from_id(world, ent->controlling_player);
if (player->valid) { if (player->valid) {
ent->control = player->player_control; ent->control = player->player_control;
/* TODO: Move this */ /* TODO: Move this */

View File

@ -123,7 +123,7 @@ GLOBAL struct {
struct v2 ui_center; struct v2 ui_center;
struct v2 ui_cursor; struct v2 ui_cursor;
struct v2 world_cursor; struct v2 world_cursor;
struct v2 world_cursor_send; struct v2 focus_send;
} G = ZI, DEBUG_ALIAS(G, G_user); } G = ZI, DEBUG_ALIAS(G, G_user);
/* ========================== * /* ========================== *
@ -146,6 +146,7 @@ GLOBAL READONLY enum user_bind_kind g_binds[SYS_BTN_COUNT] = {
[SYS_BTN_M2] = USER_BIND_KIND_DEBUG_DRAG, [SYS_BTN_M2] = USER_BIND_KIND_DEBUG_DRAG,
[SYS_BTN_F] = USER_BIND_KIND_DEBUG_EXPLODE, [SYS_BTN_F] = USER_BIND_KIND_DEBUG_EXPLODE,
[SYS_BTN_T] = USER_BIND_KIND_DEBUG_TELEPORT,
[SYS_BTN_C] = USER_BIND_KIND_DEBUG_CLEAR, [SYS_BTN_C] = USER_BIND_KIND_DEBUG_CLEAR,
[SYS_BTN_V] = USER_BIND_KIND_DEBUG_SPAWN, [SYS_BTN_V] = USER_BIND_KIND_DEBUG_SPAWN,
[SYS_BTN_N] = USER_BIND_KIND_DEBUG_STEP, [SYS_BTN_N] = USER_BIND_KIND_DEBUG_STEP,
@ -1577,14 +1578,17 @@ INTERNAL void user_update(void)
input_move_dir = v2_mul(v2_norm(input_move_dir), move_speed); input_move_dir = v2_mul(v2_norm(input_move_dir), move_speed);
} }
G.world_cursor_send = G.world_cursor; if (!G.debug_camera) {
struct v2 input_aim_dir = v2_sub(G.world_cursor_send, sim_ent_get_xform(local_control).og); G.focus_send = v2_sub(G.world_cursor, sim_ent_get_xform(local_control).og);
}
struct v2 input_aim_dir = G.focus_send;
/* Queue player control cmd */ /* Queue player control cmd */
{ {
struct sim_control control = ZI; struct sim_control control = ZI;
control.move = input_move_dir; control.move = input_move_dir;
control.focus = input_aim_dir; control.focus = input_aim_dir;
control.dbg_cursor = G.world_cursor;
struct bind_state fire_state = G.bind_states[USER_BIND_KIND_FIRE]; struct bind_state fire_state = G.bind_states[USER_BIND_KIND_FIRE];
struct bind_state drag_state = G.bind_states[USER_BIND_KIND_DEBUG_DRAG]; struct bind_state drag_state = G.bind_states[USER_BIND_KIND_DEBUG_DRAG];
@ -1594,6 +1598,7 @@ INTERNAL void user_update(void)
struct bind_state step_state = G.bind_states[USER_BIND_KIND_DEBUG_STEP]; struct bind_state step_state = G.bind_states[USER_BIND_KIND_DEBUG_STEP];
struct bind_state tile_state = G.bind_states[USER_BIND_KIND_TILE_TEST]; struct bind_state tile_state = G.bind_states[USER_BIND_KIND_TILE_TEST];
struct bind_state explode_state = G.bind_states[USER_BIND_KIND_DEBUG_EXPLODE]; struct bind_state explode_state = G.bind_states[USER_BIND_KIND_DEBUG_EXPLODE];
struct bind_state teleport_state = G.bind_states[USER_BIND_KIND_DEBUG_TELEPORT];
if (fire_state.num_presses || fire_state.is_held) { if (fire_state.num_presses || fire_state.is_held) {
control.flags |= SIM_CONTROL_FLAG_FIRE; control.flags |= SIM_CONTROL_FLAG_FIRE;
@ -1601,18 +1606,21 @@ INTERNAL void user_update(void)
if (drag_state.num_presses || drag_state.is_held) { if (drag_state.num_presses || drag_state.is_held) {
control.flags |= SIM_CONTROL_FLAG_DRAG; control.flags |= SIM_CONTROL_FLAG_DRAG;
} }
if (clear_state.num_presses) { if (clear_state.num_presses_and_repeats) {
control.flags |= SIM_CONTROL_FLAG_CLEAR_ALL; control.flags |= SIM_CONTROL_FLAG_CLEAR_ALL;
} }
if (spawn_state.num_presses) { if (spawn_state.num_presses_and_repeats) {
control.flags |= SIM_CONTROL_FLAG_SPAWN_TEST; control.flags |= SIM_CONTROL_FLAG_SPAWN_TEST;
} }
if (tile_state.num_presses) { if (tile_state.num_presses_and_repeats) {
control.flags |= SIM_CONTROL_FLAG_TILE_TEST; control.flags |= SIM_CONTROL_FLAG_TILE_TEST;
} }
if (explode_state.num_presses) { if (explode_state.num_presses_and_repeats) {
control.flags |= SIM_CONTROL_FLAG_EXPLODE_TEST; control.flags |= SIM_CONTROL_FLAG_EXPLODE_TEST;
} }
if (teleport_state.num_presses_and_repeats) {
control.flags |= SIM_CONTROL_FLAG_TELEPORT_TEST;
}
if (pause_state.num_presses) { if (pause_state.num_presses) {
atomic_i32_eval_xor(&G.user_paused, 1); atomic_i32_eval_xor(&G.user_paused, 1);

View File

@ -36,6 +36,7 @@ enum user_bind_kind {
USER_BIND_KIND_DEBUG_PAUSE, USER_BIND_KIND_DEBUG_PAUSE,
USER_BIND_KIND_DEBUG_STEP, USER_BIND_KIND_DEBUG_STEP,
USER_BIND_KIND_DEBUG_DRAG, USER_BIND_KIND_DEBUG_DRAG,
USER_BIND_KIND_DEBUG_TELEPORT,
USER_BIND_KIND_DEBUG_EXPLODE, USER_BIND_KIND_DEBUG_EXPLODE,
USER_BIND_KIND_FULLSCREEN, USER_BIND_KIND_FULLSCREEN,
USER_BIND_KIND_ZOOM_IN, USER_BIND_KIND_ZOOM_IN,