From 3b19e1260e3b5ec23842e6b0979343b2735ca1c8 Mon Sep 17 00:00:00 2001 From: jacob Date: Sat, 17 May 2025 07:59:54 -0500 Subject: [PATCH] call collision callbacks during contact creation loop --- src/phys.c | 83 +++++++++++++++++++------------------------------- src/phys.h | 9 +----- src/sim_step.c | 36 ++++++++++------------ 3 files changed, 49 insertions(+), 79 deletions(-) diff --git a/src/phys.c b/src/phys.c index 46f54ca1..08e85000 100644 --- a/src/phys.c +++ b/src/phys.c @@ -40,14 +40,14 @@ struct phys_startup_receipt phys_startup(void) * Contact * ========================== */ -struct phys_collision_data_array phys_create_and_update_contacts(struct arena *arena, struct phys_step_ctx *ctx, f32 elapsed_dt, u64 phys_iteration) +void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt, u64 phys_iteration) { __prof; - struct phys_collision_data_array res = ZI; - res.a = arena_dry_push(arena, struct phys_collision_data); - struct sim_snapshot *ss = ctx->sim_step_ctx->world; - struct space *space = ctx->sim_step_ctx->accel->space; + struct sim_step_ctx *sim_step_ctx = ctx->sim_step_ctx; + struct sim_snapshot *ss = sim_step_ctx->world; + struct space *space = sim_step_ctx->accel->space; struct sim_ent_id local_player = ss->local_player; + phys_collision_callback_func *collision_callback = ctx->collision_callback; struct sim_ent *root = sim_ent_from_id(ss, SIM_ENT_ROOT_ID); u64 tick = ss->tick; @@ -187,24 +187,21 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a #endif } - /* Push collision data */ - /* TODO: Analyze benefits of calling callback here directly rather than deferring */ - if (ctx->collision_callback) { - struct phys_collision_data *data = arena_push(arena, struct phys_collision_data); - ++res.count; - data->constraint = &constraint_ent->contact_constraint_data; - data->e0 = e0->id; - data->e1 = e1->id; - data->normal = collider_res.normal; - data->is_start = is_start; - data->dt = elapsed_dt; + /* Run collision callback */ + if (collision_callback) { + struct phys_collision_data data = ZI; + data.e0 = e0->id; + data.e1 = e1->id; + data.normal = collider_res.normal; + data.is_start = is_start; + data.dt = elapsed_dt; /* Calculate point */ struct v2 point = collider_res.points[0].point; if (collider_res.num_points > 1) { point = v2_add(point, v2_mul(v2_sub(collider_res.points[1].point, point), 0.5f)); } - data->point = point; + data.point = point; /* Calculate relative velocity */ struct v2 vrel; @@ -219,7 +216,21 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a struct v2 vel1 = v2_add(v1, v2_perp_mul(vcp1, w1)); vrel = v2_sub(vel0, vel1); } - data->vrel = vrel; + data.vrel = vrel; + + /* Collision data from e1's perspective */ + struct phys_collision_data data_inverted = data; + data_inverted.e0 = data.e1; + data_inverted.e1 = data.e0; + data_inverted.normal = v2_neg(data.normal); + data_inverted.vrel = v2_neg(data.vrel); + + /* Run callback twice for both e0 & e1 */ + b32 skip_solve0 = collision_callback(&data, sim_step_ctx); + b32 skip_solve1 = collision_callback(&data_inverted, sim_step_ctx); + if (skip_solve0 || skip_solve1) { + constraint->skip_solve = true; + } } } else if (constraint_ent->valid) { constraint_ent->contact_constraint_data.num_points = 0; @@ -263,7 +274,6 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a } space_iter_end(&iter); } - return res; } void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration) @@ -307,7 +317,7 @@ void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration) f32 scale = math_fabs(xform_get_determinant(e1_xf)); f32 scaled_mass = e1->mass_unscaled * scale; f32 scaled_inertia = e1->inertia_unscaled * scale; - inv_m1 = 1.f / scaled_mass; + inv_m1 = 1.f / scaled_mass; inv_i1 = 1.f / scaled_inertia; } @@ -1044,30 +1054,6 @@ void phys_update_aabbs(struct phys_step_ctx *ctx) * Step * ========================== */ -INTERNAL void run_collision_callbacks(struct phys_step_ctx *ctx, phys_collision_callback_func *callback, struct phys_collision_data_array collision_data) -{ - __prof; - struct sim_step_ctx *sim_step_ctx = ctx->sim_step_ctx; - for (u64 i = 0; i < collision_data.count; ++i) { - /* Collision data from e0's perspective */ - struct phys_collision_data *data = &collision_data.a[i]; - - /* Collision data from e1's perspective */ - struct phys_collision_data data_inverted = *data; - data_inverted.e0 = data->e1; - data_inverted.e1 = data->e0; - data_inverted.normal = v2_neg(data->normal); - data_inverted.vrel = v2_neg(data->vrel); - - /* Run callback twice for both e0 & e1 */ - b32 skip_solve0 = callback(data, sim_step_ctx); - b32 skip_solve1 = callback(&data_inverted, sim_step_ctx); - if (skip_solve0 || skip_solve1) { - data->constraint->skip_solve = true; - } - } -} - /* Returns phys iteration to be fed into next step. Supplied iteration must be > 0. */ void phys_step(struct phys_step_ctx *ctx, f32 timestep) { @@ -1099,16 +1085,12 @@ void phys_step(struct phys_step_ctx *ctx, f32 timestep) } remaining_dt -= step_dt; - struct phys_collision_data_array collision_data = phys_create_and_update_contacts(scratch.arena, ctx, timestep - remaining_dt, phys_iteration); + phys_create_and_update_contacts(ctx, timestep - remaining_dt, phys_iteration); phys_prepare_contacts(ctx, phys_iteration); phys_prepare_motor_joints(ctx); phys_prepare_mouse_joints(ctx); - if (ctx->collision_callback) { - run_collision_callbacks(ctx, ctx->collision_callback, collision_data); - } - f32 substep_dt = step_dt / SIM_PHYSICS_SUBSTEPS; for (u32 i = 0; i < SIM_PHYSICS_SUBSTEPS; ++i) { __profscope(substep); @@ -1130,14 +1112,13 @@ void phys_step(struct phys_step_ctx *ctx, f32 timestep) /* Integrate */ phys_integrate_velocities(ctx, substep_dt); - phys_update_aabbs(ctx); - /* Relaxation solve */ #if SIM_PHYSICS_ENABLE_COLLISION && SIM_PHYSICS_ENABLE_RELAXATION phys_solve_contacts(ctx, substep_dt, false); #endif } + phys_update_aabbs(ctx); scratch_end(scratch); } diff --git a/src/phys.h b/src/phys.h index d09198ac..adbc554a 100644 --- a/src/phys.h +++ b/src/phys.h @@ -10,8 +10,6 @@ struct sim_step_ctx; struct phys_contact_constraint; struct phys_collision_data { - /* NOTE: e0 & e1 can be opposite of e0 & e1 contained in constraint when passed to collision callbacks */ - struct phys_contact_constraint *constraint; struct sim_ent_id e0; struct sim_ent_id e1; struct v2 point; @@ -21,11 +19,6 @@ struct phys_collision_data { 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 occurred) */ }; -struct phys_collision_data_array { - struct phys_collision_data *a; - u64 count; -}; - /* Callback can return true to prevent the physics system from resolving */ #define PHYS_COLLISION_CALLBACK_FUNC_DEF(name, arg_collision_data, arg_sim_step_ctx) b32 name(struct phys_collision_data *arg_collision_data, struct sim_step_ctx *arg_sim_step_ctx) typedef PHYS_COLLISION_CALLBACK_FUNC_DEF(phys_collision_callback_func, collision_data, ctx); @@ -102,7 +95,7 @@ struct phys_collision_debug { struct xform xf1; }; -struct phys_collision_data_array phys_create_and_update_contacts(struct arena *arena, struct phys_step_ctx *ctx, f32 elapsed_dt, u64 phys_iteration); +void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt, u64 phys_iteration); void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration); void phys_warm_start_contacts(struct phys_step_ctx *ctx); void phys_solve_contacts(struct phys_step_ctx *ctx, f32 dt, b32 apply_bias); diff --git a/src/sim_step.c b/src/sim_step.c index 8c9f1338..833e4d46 100644 --- a/src/sim_step.c +++ b/src/sim_step.c @@ -77,8 +77,8 @@ INTERNAL struct sim_ent *spawn_test_chucker(struct sim_ent *parent) chucker->layer = SIM_LAYER_RELATIVE_WEAPON; sim_ent_enable_prop(chucker, SEPROP_WEAPON_CHUCKER); - chucker->primary_fire_delay = 1.0f / 10.0f; - chucker->secondary_fire_delay = 1.0f / 10.0f; + //chucker->primary_fire_delay = 1.0f / 10.0f; + //chucker->secondary_fire_delay = 1.0f / 10.0f; /* Chucker zone */ { @@ -378,6 +378,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx) struct xform victim_xf = sim_ent_get_xform(victim); struct collider_closest_points_result closest_points = collider_closest_points(&origin_collider, &victim->local_collider, xf, victim_xf); struct v2 dir = v2_sub(closest_points.p1, closest_points.p0); + struct v2 point = closest_points.p1; f32 distance = v2_len(dir); #if 0 if (closest_points.colliding) { @@ -387,6 +388,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx) #else if (v2_dot(data->normal, dir) < 0) { dir = v2_neg(dir); + point = xf.og; distance = 0; } #endif @@ -398,7 +400,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx) const f32 falloff_curve = 3; /* Cubic falloff */ f32 strength_factor = math_pow(1 - distance/radius, falloff_curve); struct v2 impulse = v2_with_len(dir, strength_center * strength_factor); - sim_ent_apply_linear_impulse(victim, impulse, closest_points.p1); + sim_ent_apply_linear_impulse(victim, impulse, point); } } @@ -607,9 +609,7 @@ void sim_step(struct sim_step_ctx *ctx) } } if (flags & SIM_CONTROL_FLAG_CLEAR_ALL) { - if (is_master && !(old_control.flags & SIM_CONTROL_FLAG_CLEAR_ALL)) { - test_clear_level(ctx); - } + test_clear_level(ctx); } if (flags & SIM_CONTROL_FLAG_SPAWN1_TEST) { logf_info("Spawn1 (test)"); @@ -622,22 +622,18 @@ void sim_step(struct sim_step_ctx *ctx) } } if (flags & SIM_CONTROL_FLAG_SPAWN2_TEST) { - if (!(old_control.flags & SIM_CONTROL_FLAG_SPAWN2_TEST)) { - logf_info("Spawn1 (test)"); - u32 count = 1; - f32 spread = 0; - for (u32 j = 0; j < count; ++j) { - struct v2 pos = player->player_cursor_pos; - pos.y += (((f32)j / (f32)count) - 0.5) * spread; - spawn_test_entities2(root, pos); - } + logf_info("Spawn1 (test)"); + u32 count = 1; + f32 spread = 0; + for (u32 j = 0; j < count; ++j) { + struct v2 pos = player->player_cursor_pos; + pos.y += (((f32)j / (f32)count) - 0.5) * spread; + spawn_test_entities2(root, pos); } } if (flags & SIM_CONTROL_FLAG_EXPLODE_TEST) { - if (!(old_control.flags & SIM_CONTROL_FLAG_EXPLODE_TEST)) { - logf_info("Explosion (test)"); - spawn_test_explosion(root, player->player_cursor_pos, 100, 2); - } + logf_info("Explosion (test)"); + spawn_test_explosion(root, player->player_cursor_pos, 100, 2); } } @@ -1036,7 +1032,7 @@ void sim_step(struct sim_step_ctx *ctx) if (secondary_triggered) { struct sim_ent *zone = sim_ent_from_id(world, ent->chucker_zone); struct sim_ent *target = sim_ent_from_id(world, zone->chucker_zone_ent); - if (sim_ent_is_valid_and_active(target)) { + if (sim_ent_is_valid_and_active(target) && zone->chucker_zone_ent_tick == world->tick - 1) { sim_ent_enable_prop(target, SEPROP_RELEASE); } }