diff --git a/src/phys.c b/src/phys.c index 734afe7a..46f54ca1 100644 --- a/src/phys.c +++ b/src/phys.c @@ -115,7 +115,9 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a struct phys_contact_constraint *constraint = NULL; if (collider_res.num_points > 0) { + b32 is_start = false; if (!constraint_ent->valid) { + is_start = true; /* Create constraint */ constraint_ent = sim_ent_alloc_local_with_id(root, constraint_id); constraint_ent->contact_constraint_data.e0 = e0->id; @@ -128,40 +130,6 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a /* TODO: Should we recalculate normal as more contact points are added? */ sim_ent_enable_prop(constraint_ent, SEPROP_CONTACT_CONSTRAINT); sim_ent_activate(constraint_ent, tick); - - /* 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->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; - - /* Calculate relative velocity */ - struct v2 vrel; - { - struct v2 v0 = e0->linear_velocity; - struct v2 v1 = e1->linear_velocity; - f32 w0 = e0->angular_velocity; - f32 w1 = e1->angular_velocity; - struct v2 vcp0 = v2_sub(point, e0_xf.og); - struct v2 vcp1 = v2_sub(point, e1_xf.og); - struct v2 vel0 = v2_add(v0, v2_perp_mul(vcp0, w0)); - struct v2 vel1 = v2_add(v1, v2_perp_mul(vcp1, w1)); - vrel = v2_sub(vel0, vel1); - } - data->vrel = vrel; - } } constraint = &constraint_ent->contact_constraint_data; constraint->normal = collider_res.normal; @@ -218,6 +186,41 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a contact->dbg_pt = point; #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; + + /* 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; + + /* Calculate relative velocity */ + struct v2 vrel; + { + struct v2 v0 = e0->linear_velocity; + struct v2 v1 = e1->linear_velocity; + f32 w0 = e0->angular_velocity; + f32 w1 = e1->angular_velocity; + struct v2 vcp0 = v2_sub(point, e0_xf.og); + struct v2 vcp1 = v2_sub(point, e1_xf.og); + struct v2 vel0 = v2_add(v0, v2_perp_mul(vcp0, w0)); + struct v2 vel1 = v2_add(v1, v2_perp_mul(vcp1, w1)); + vrel = v2_sub(vel0, vel1); + } + data->vrel = vrel; + } } else if (constraint_ent->valid) { constraint_ent->contact_constraint_data.num_points = 0; } @@ -304,7 +307,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; } diff --git a/src/phys.h b/src/phys.h index ea250c56..d09198ac 100644 --- a/src/phys.h +++ b/src/phys.h @@ -17,6 +17,7 @@ struct phys_collision_data { struct v2 point; struct v2 normal; /* Normal of the collision from e0 to e1 */ struct v2 vrel; /* Relative velocity at point of collision */ + b32 is_start; /* Did this collision just begin */ 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) */ }; diff --git a/src/sim_ent.h b/src/sim_ent.h index 0b6bd1b3..3d1b8052 100644 --- a/src/sim_ent.h +++ b/src/sim_ent.h @@ -50,6 +50,8 @@ enum sim_ent_prop { SEPROP_WEAPON_LAUNCHER, SEPROP_WEAPON_CHUCKER, + SEPROP_CHUCKER_ZONE, + SEPROP_EXPLOSION, SEPROP_TRACER, @@ -281,6 +283,21 @@ struct sim_ent { struct sim_ent_id equipped; + /* ====================================================================== */ + /* Chucker */ + + /* SEPROP_WEAPON_CHUCKER */ + + struct sim_ent_id chucker_zone; + + /* ====================================================================== */ + /* Chucker zone */ + + /* SEPROP_CHUCKER_ZONE */ + + struct sim_ent_id chucker_zone_ent; + u64 chucker_zone_ent_tick; + /* ====================================================================== */ /* Triggerable */ diff --git a/src/sim_step.c b/src/sim_step.c index 06d90a0a..8c9f1338 100644 --- a/src/sim_step.c +++ b/src/sim_step.c @@ -80,18 +80,23 @@ INTERNAL struct sim_ent *spawn_test_chucker(struct sim_ent *parent) chucker->primary_fire_delay = 1.0f / 10.0f; chucker->secondary_fire_delay = 1.0f / 10.0f; - /* Chucker sensor */ + /* Chucker zone */ { - struct sim_ent *sensor = sim_ent_alloc_sync_src(chucker); + struct sim_ent *zone = sim_ent_alloc_sync_src(chucker); - sim_ent_enable_prop(sensor, SEPROP_ATTACHED); - sensor->attach_slice = LIT("out"); + sim_ent_enable_prop(zone, SEPROP_CHUCKER_ZONE); - sim_ent_enable_prop(sensor, SEPROP_SENSOR); + sim_ent_enable_prop(zone, SEPROP_ATTACHED); + zone->attach_slice = LIT("out"); + + sim_ent_enable_prop(zone, SEPROP_SENSOR); struct collider_shape collider = ZI; - collider.count = 1; + collider.count = 2; + collider.points[1] = V2(0, -0.5); collider.radius = 0.1; - sensor->local_collider = collider; + zone->local_collider = collider; + + chucker->chucker_zone = zone->id; } return chucker; @@ -396,6 +401,14 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx) sim_ent_apply_linear_impulse(victim, impulse, closest_points.p1); } } + + /* Chucker zone */ + if (sim_ent_has_prop(e0, SEPROP_CHUCKER_ZONE)) { + if (!sim_ent_id_eq(e0->top, e1->top) && sim_ent_has_prop(e1, SEPROP_SOLID)) { + e0->chucker_zone_ent = e1->id; + e0->chucker_zone_ent_tick = world->tick; + } + } } return skip_solve; @@ -1020,6 +1033,13 @@ void sim_step(struct sim_step_ctx *ctx) if (sim_ent_has_prop(ent, SEPROP_WEAPON_CHUCKER)) { if (primary_triggered) { } + 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)) { + sim_ent_enable_prop(target, SEPROP_RELEASE); + } + } } }