sort hit events by dt to prevent out of order bullet hit processing

This commit is contained in:
jacob 2025-01-11 15:09:14 -06:00
parent 5d6835ece3
commit bbd11d2526
4 changed files with 53 additions and 32 deletions

View File

@ -229,7 +229,6 @@ struct entity {
struct v2 bullet_src_pos; struct v2 bullet_src_pos;
struct v2 bullet_src_dir; struct v2 bullet_src_dir;
f32 bullet_impulse; f32 bullet_impulse;
b32 bullet_has_hit; /* Has the bullet hit a target this tick */
/* ====================================================================== */ /* ====================================================================== */
/* Testing */ /* Testing */

View File

@ -944,14 +944,38 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
/* ========================== * /* ========================== *
* Respond to hit events * Respond to hit events
* ========================== */ * ========================== */
{
struct temp_arena temp = arena_temp_begin(scratch.arena);
/* Sort hit events by dt (to ensure early time of impact collisions are processed first) */
struct phys_hit_event_node *first_sorted = NULL;
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 (!entity_is_valid_and_active(ent)) continue; if (!entity_is_valid_and_active(ent)) continue;
if (!entity_has_prop(ent, ENTITY_PROP_HIT_EVENT)) continue; if (!entity_has_prop(ent, ENTITY_PROP_HIT_EVENT)) continue;
struct phys_hit_event *e = &ent->hit_event;
struct phys_hit_event_node *next = first_sorted;
struct phys_hit_event_node *prev = NULL;
while (next) {
if (e->dt < next->e->dt) {
break;
}
prev = next;
next = next->next;
}
struct phys_hit_event_node *n = arena_push_zero(temp.arena, struct phys_hit_event_node);
n->e = e;
n->next = next;
if (prev) {
prev->next = n;
} else {
first_sorted = n;
}
}
struct phys_hit_event *event = &ent->hit_event; /* Process events */
for (struct phys_hit_event_node *n = first_sorted; n; n = n->next) {
struct phys_hit_event *event = n->e;
struct entity *e0 = entity_from_handle(store, event->e0); struct entity *e0 = entity_from_handle(store, event->e0);
struct entity *e1 = entity_from_handle(store, event->e1); struct entity *e1 = entity_from_handle(store, event->e1);
@ -960,22 +984,11 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
if (entity_has_prop(e0, ENTITY_PROP_BULLET) || entity_has_prop(e1, ENTITY_PROP_BULLET)) { if (entity_has_prop(e0, ENTITY_PROP_BULLET) || entity_has_prop(e1, ENTITY_PROP_BULLET)) {
struct entity *bullet = entity_has_prop(e0, ENTITY_PROP_BULLET) ? e0 : e1; struct entity *bullet = entity_has_prop(e0, ENTITY_PROP_BULLET) ? e0 : e1;
struct entity *target = e0 == bullet ? e1 : e0; struct entity *target = e0 == bullet ? e1 : e0;
if (!bullet->bullet_has_hit) {
bullet->bullet_has_hit = true;
(UNUSED)bullet; (UNUSED)bullet;
(UNUSED)target; (UNUSED)target;
#if 0
{
/* Set bullet position to hit position */
struct xform xf = entity_get_xform(bullet);
xf.og = event->point;
entity_set_xform(bullet, xf);
/* Release after publish so user sees bullet in final postiion */
entity_enable_prop(bullet, ENTITY_PROP_RELEASE_AFTER_PUBLISH);
}
#else
entity_enable_prop(bullet, ENTITY_PROP_RELEASE_BEFORE_PUBLISH); entity_enable_prop(bullet, ENTITY_PROP_RELEASE_BEFORE_PUBLISH);
#endif entity_disable_prop(bullet, ENTITY_PROP_ACTIVE);
/* Create test blood */ /* Create test blood */
/* TODO: Remove this */ /* TODO: Remove this */
@ -992,6 +1005,8 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
} }
} }
} }
arena_temp_end(temp);
} }
/* ========================== * /* ========================== *

View File

@ -37,7 +37,7 @@ struct phys_startup_receipt phys_startup(void)
* Contact * Contact
* ========================== */ * ========================== */
void phys_create_contacts(struct phys_ctx *ctx) void phys_create_contacts(struct phys_ctx *ctx, f32 elapsed_dt)
{ {
u64 tick_id = ctx->tick_id; u64 tick_id = ctx->tick_id;
struct entity_lookup *contact_lookup = ctx->contact_lookup; struct entity_lookup *contact_lookup = ctx->contact_lookup;
@ -121,6 +121,7 @@ void phys_create_contacts(struct phys_ctx *ctx)
event->hit_event.e0 = e0->handle; event->hit_event.e0 = e0->handle;
event->hit_event.e1 = e1->handle; event->hit_event.e1 = e1->handle;
event->hit_event.normal = collider_res.normal; event->hit_event.normal = collider_res.normal;
event->hit_event.dt = elapsed_dt;
entity_enable_prop(event, ENTITY_PROP_RELEASE_BEFORE_PUBLISH); entity_enable_prop(event, ENTITY_PROP_RELEASE_BEFORE_PUBLISH);
entity_enable_prop(event, ENTITY_PROP_ACTIVE); entity_enable_prop(event, ENTITY_PROP_ACTIVE);
@ -1120,13 +1121,14 @@ void phys_step(struct phys_ctx *ctx, f32 timestep)
const u32 max_iterations = 16; const u32 max_iterations = 16;
f32 earliest_toi = max_f32(phys_determine_earliest_toi_for_bullets(ctx, step_dt, tolerance, max_iterations), min_toi); f32 earliest_toi = max_f32(phys_determine_earliest_toi_for_bullets(ctx, step_dt, tolerance, max_iterations), min_toi);
step_dt = remaining_dt * earliest_toi; step_dt = remaining_dt * earliest_toi;
remaining_dt -= step_dt;
#else #else
(UNUSED)toi; (UNUSED)toi;
(UNUSED)determine_earliest_toi_for_bullets; (UNUSED)determine_earliest_toi_for_bullets;
#endif #endif
} }
phys_create_contacts(ctx); phys_create_contacts(ctx, timestep - remaining_dt);
phys_create_mouse_joints(ctx); phys_create_mouse_joints(ctx);
phys_prepare_contacts(ctx); phys_prepare_contacts(ctx);
@ -1153,6 +1155,5 @@ void phys_step(struct phys_ctx *ctx, f32 timestep)
phys_solve_contacts(ctx, substep_dt, false); /* Relaxation */ phys_solve_contacts(ctx, substep_dt, false); /* Relaxation */
#endif #endif
} }
remaining_dt -= step_dt;
} }
} }

View File

@ -25,6 +25,12 @@ struct phys_hit_event {
struct v2 point; struct v2 point;
struct v2 normal; struct v2 normal;
struct v2 vrel; /* Relative velocity */ struct v2 vrel; /* Relative velocity */
f32 dt; /* How much time elapsed in the step when this event occurred (this will equal the physics timestep unless an early time of impact collision occurred) */
};
struct phys_hit_event_node {
struct phys_hit_event *e;
struct phys_hit_event_node *next;
}; };
/* ========================== * /* ========================== *
@ -91,7 +97,7 @@ struct phys_collision_debug {
struct xform xf1; struct xform xf1;
}; };
void phys_create_contacts(struct phys_ctx *ctx); void phys_create_contacts(struct phys_ctx *ctx, f32 elapsed_dt);
void phys_prepare_contacts(struct phys_ctx *ctx); void phys_prepare_contacts(struct phys_ctx *ctx);
void phys_warm_start_contacts(struct phys_ctx *ctx); void phys_warm_start_contacts(struct phys_ctx *ctx);
void phys_solve_contacts(struct phys_ctx *ctx, f32 dt, b32 apply_bias); void phys_solve_contacts(struct phys_ctx *ctx, f32 dt, b32 apply_bias);