call collision callbacks during contact creation loop
This commit is contained in:
parent
2c6dc93167
commit
3b19e1260e
83
src/phys.c
83
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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user