diff --git a/src/phys.c b/src/phys.c index ec90b2d9..734afe7a 100644 --- a/src/phys.c +++ b/src/phys.c @@ -55,7 +55,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a for (u64 check0_index = 0; check0_index < ss->num_ents_reserved; ++check0_index) { struct sim_ent *check0 = &ss->ents[check0_index]; if (!sim_ent_is_valid_and_active(check0)) continue; - if (!(sim_ent_has_prop(check0, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(check0, SEPROP_PHYSICAL_KINEMATIC) || sim_ent_has_prop(check0, SEPROP_SENSOR))) continue; + if (!(sim_ent_has_prop(check0, SEPROP_SOLID) || sim_ent_has_prop(check0, SEPROP_SENSOR))) continue; if (check0->local_collider.count <= 0) continue; struct xform check0_xf = sim_ent_get_xform(check0); @@ -68,7 +68,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a struct sim_ent *check1 = sim_ent_from_id(ss, space_entry->ent); if (check1 == check0) continue; if (!sim_ent_is_valid_and_active(check1)) continue; - if (!(sim_ent_has_prop(check1, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(check1, SEPROP_PHYSICAL_KINEMATIC) || sim_ent_has_prop(check1, SEPROP_SENSOR))) continue; + if (!(sim_ent_has_prop(check1, SEPROP_SOLID) || sim_ent_has_prop(check1, SEPROP_SENSOR))) continue; if (check1->local_collider.count <= 0) continue; /* Deterministic order based on entity id */ @@ -117,21 +117,21 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a if (collider_res.num_points > 0) { if (!constraint_ent->valid) { /* Create constraint */ - { - constraint_ent = sim_ent_alloc_local_with_id(root, constraint_id); - constraint_ent->contact_constraint_data.e0 = e0->id; - constraint_ent->contact_constraint_data.e1 = e1->id; - constraint_ent->contact_constraint_data.skip_solve = sim_ent_has_prop(e0, SEPROP_SENSOR) || sim_ent_has_prop(e1, SEPROP_SENSOR) - || !(sim_ent_has_prop(e0, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e1, SEPROP_PHYSICAL_DYNAMIC)); - sim_ent_enable_prop(constraint_ent, SEPROP_ACTIVE); + constraint_ent = sim_ent_alloc_local_with_id(root, constraint_id); + constraint_ent->contact_constraint_data.e0 = e0->id; + constraint_ent->contact_constraint_data.e1 = e1->id; + /* Both entities must be solid and one must be dynamic for a solve to be necessary. */ + constraint_ent->contact_constraint_data.skip_solve = !sim_ent_has_prop(e0, SEPROP_SOLID) || !sim_ent_has_prop(e1, SEPROP_SOLID) || + !(sim_ent_has_prop(e0, SEPROP_DYNAMIC) || sim_ent_has_prop(e1, SEPROP_DYNAMIC)); + sim_ent_enable_prop(constraint_ent, SEPROP_ACTIVE); - /* 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); - } + /* 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 */ - if (ctx->pre_solve_callback || ctx->post_solve_callback) { + /* 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; @@ -287,29 +287,25 @@ void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration) /* TODO: Cache this */ /* Calculate masses */ - f32 inv_m0; - f32 inv_m1; - f32 inv_i0; - f32 inv_i1; + f32 inv_m0 = 0; + f32 inv_m1 = 0; + f32 inv_i0 = 0; + f32 inv_i1 = 0; { - if (sim_ent_should_simulate(e0)) { - f32 scale0 = math_fabs(xform_get_determinant(e0_xf)); - inv_m0 = 1.f / (e0->mass_unscaled * scale0); - inv_i0 = 1.f / (e0->inertia_unscaled * scale0); - } else { - /* e0 is not simulated locally, pretend it has infinite mass for this contact */ - inv_m0 = 0; - inv_i0 = 0; + /* If not simulated locally or ent is not dynamic, pretend contact mass is infinite */ + if (sim_ent_should_simulate(e0) && sim_ent_has_prop(e0, SEPROP_DYNAMIC)) { + f32 scale = math_fabs(xform_get_determinant(e0_xf)); + f32 scaled_mass = e0->mass_unscaled * scale; + f32 scaled_inertia = e0->inertia_unscaled * scale; + inv_m0 = 1.f / scaled_mass; + inv_i0 = 1.f / scaled_inertia; } - - if (sim_ent_should_simulate(e1)) { - f32 scale1 = math_fabs(xform_get_determinant(e1_xf)); - inv_m1 = 1.f / (e1->mass_unscaled * scale1); - inv_i1 = 1.f / (e1->inertia_unscaled * scale1); - } else { - /* e0 is not simulated locally, pretend it has infinite mass for this contact */ - inv_m1 = 0; - inv_i1 = 0; + if (sim_ent_should_simulate(e1) && sim_ent_has_prop(e1, SEPROP_DYNAMIC)) { + 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_i1 = 1.f / scaled_inertia; } } @@ -318,15 +314,6 @@ void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration) constraint->inv_i0 = inv_i0; constraint->inv_i1 = inv_i1; - if (!sim_ent_has_prop(e0, SEPROP_PHYSICAL_DYNAMIC)) { - constraint->inv_m0 = 0; - constraint->inv_i0 = 0; - } - if (!sim_ent_has_prop(e1, SEPROP_PHYSICAL_DYNAMIC)) { - constraint->inv_m1 = 0; - constraint->inv_i1 = 0; - } - /* Update / insert returned contacts */ for (u32 i = 0; i < num_points; ++i) { struct phys_contact_point *contact = &constraint->points[i]; @@ -375,9 +362,9 @@ 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 *e1 = sim_ent_from_id(ss, dbg->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(e1, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e1, SEPROP_PHYSICAL_KINEMATIC) || !sim_ent_has_prop(e1, SEPROP_SENSOR))) { + if (!(sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) || + !(sim_ent_has_prop(e0, SEPROP_SOLID) || sim_ent_has_prop(e0, SEPROP_SENSOR)) || + !(sim_ent_has_prop(e1, SEPROP_SOLID) || sim_ent_has_prop(e1, SEPROP_SENSOR))) { /* Mark dbg ent for removal */ sim_ent_disable_prop(dbg_ent, SEPROP_ACTIVE); sim_ent_enable_prop(dbg_ent, SEPROP_RELEASE); @@ -926,8 +913,8 @@ void phys_integrate_forces(struct phys_step_ctx *ctx, f32 dt) struct sim_ent *ent = &ss->ents[sim_ent_index]; if (!sim_ent_should_simulate(ent)) continue; - b32 is_dynamic = sim_ent_has_prop(ent, SEPROP_PHYSICAL_DYNAMIC); - b32 is_kinematic = sim_ent_has_prop(ent, SEPROP_PHYSICAL_KINEMATIC); + b32 is_dynamic = sim_ent_has_prop(ent, SEPROP_DYNAMIC); + b32 is_kinematic = sim_ent_has_prop(ent, SEPROP_KINEMATIC); if (is_dynamic || is_kinematic) { struct v2 linear_velocity = ent->linear_velocity; f32 angular_velocity = ent->angular_velocity; @@ -967,7 +954,7 @@ void phys_integrate_velocities(struct phys_step_ctx *ctx, f32 dt) for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { struct sim_ent *ent = &ss->ents[sim_ent_index]; if (!sim_ent_should_simulate(ent)) continue; - if (!sim_ent_has_prop(ent, SEPROP_PHYSICAL_DYNAMIC) && !sim_ent_has_prop(ent, SEPROP_PHYSICAL_KINEMATIC)) continue; + if (!sim_ent_has_prop(ent, SEPROP_DYNAMIC) && !sim_ent_has_prop(ent, SEPROP_KINEMATIC)) continue; struct xform xf = get_derived_xform(ent, dt); sim_ent_set_xform(ent, xf); @@ -978,7 +965,7 @@ void phys_integrate_velocities(struct phys_step_ctx *ctx, f32 dt) * Earliest time of impact * ========================== */ -f32 phys_determine_earliest_toi_for_bullets(struct phys_step_ctx *ctx, f32 step_dt, f32 tolerance, u32 max_iterations) +f32 phys_determine_earliest_toi(struct phys_step_ctx *ctx, f32 step_dt, f32 tolerance, u32 max_iterations) { __prof; struct sim_snapshot *ss = ctx->sim_step_ctx->world; @@ -988,8 +975,8 @@ f32 phys_determine_earliest_toi_for_bullets(struct phys_step_ctx *ctx, f32 step_ for (u64 e0_index = 0; e0_index < ss->num_ents_reserved; ++e0_index) { struct sim_ent *e0 = &ss->ents[e0_index]; if (!sim_ent_should_simulate(e0)) continue; - if (!(sim_ent_has_prop(e0, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e0, SEPROP_PHYSICAL_KINEMATIC) || sim_ent_has_prop(e0, SEPROP_SENSOR))) continue; - if (!sim_ent_has_prop(e0, SEPROP_BULLET)) continue; + if (!(sim_ent_has_prop(e0, SEPROP_SOLID) || sim_ent_has_prop(e0, SEPROP_SENSOR))) continue; + if (!sim_ent_has_prop(e0, SEPROP_TOI)) continue; if (e0->local_collider.count <= 0) continue; struct collider_shape e0_collider = e0->local_collider; @@ -1007,7 +994,7 @@ f32 phys_determine_earliest_toi_for_bullets(struct phys_step_ctx *ctx, f32 step_ struct sim_ent *e1 = sim_ent_from_id(ss, entry->ent); if (e1 == e0) continue; if (!sim_ent_should_simulate(e1)) continue; - if (!(sim_ent_has_prop(e1, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e1, SEPROP_PHYSICAL_KINEMATIC) || sim_ent_has_prop(e1, SEPROP_SENSOR))) continue; + if (!(sim_ent_has_prop(e1, SEPROP_SOLID) || sim_ent_has_prop(e1, SEPROP_SENSOR))) continue; if (e1->local_collider.count <= 0) continue; struct collider_shape e1_collider = e1->local_collider; @@ -1056,6 +1043,7 @@ void phys_update_aabbs(struct phys_step_ctx *ctx) 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 */ @@ -1069,8 +1057,11 @@ INTERNAL void run_collision_callbacks(struct phys_step_ctx *ctx, phys_collision_ data_inverted.vrel = v2_neg(data->vrel); /* Run callback twice for both e0 & e1 */ - callback(data, sim_step_ctx); - callback(&data_inverted, sim_step_ctx); + 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; + } } } @@ -1097,10 +1088,10 @@ void phys_step(struct phys_step_ctx *ctx, f32 timestep) const f32 min_toi = 0.000001f; const f32 tolerance = 0.0001f; 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(ctx, step_dt, tolerance, max_iterations), min_toi); step_dt = remaining_dt * earliest_toi; #else - (UNUSED)phys_determine_earliest_toi_for_bullets; + (UNUSED)phys_determine_earliest_toi; #endif } remaining_dt -= step_dt; @@ -1111,9 +1102,8 @@ void phys_step(struct phys_step_ctx *ctx, f32 timestep) phys_prepare_motor_joints(ctx); phys_prepare_mouse_joints(ctx); - if (ctx->pre_solve_callback) { - __profscope(pre_solve_callback); - run_collision_callbacks(ctx, ctx->pre_solve_callback, collision_data); + if (ctx->collision_callback) { + run_collision_callbacks(ctx, ctx->collision_callback, collision_data); } f32 substep_dt = step_dt / SIM_PHYSICS_SUBSTEPS; @@ -1145,11 +1135,6 @@ void phys_step(struct phys_step_ctx *ctx, f32 timestep) #endif } - if (ctx->post_solve_callback) { - __profscope(post_solve_callback); - run_collision_callbacks(ctx, ctx->post_solve_callback, collision_data); - } - scratch_end(scratch); } diff --git a/src/phys.h b/src/phys.h index b8861aa0..ea250c56 100644 --- a/src/phys.h +++ b/src/phys.h @@ -25,15 +25,14 @@ struct phys_collision_data_array { u64 count; }; -struct phys_collision_data; -#define PHYS_COLLISION_CALLBACK_FUNC_DEF(name, arg_collision_data, arg_sim_step_ctx) void name(struct phys_collision_data *arg_collision_data, struct sim_step_ctx *arg_sim_step_ctx) +/* 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); /* Structure containing data used for a single physics step */ struct phys_step_ctx { struct sim_step_ctx *sim_step_ctx; - phys_collision_callback_func *pre_solve_callback; - phys_collision_callback_func *post_solve_callback; + phys_collision_callback_func *collision_callback; }; /* ========================== * @@ -190,7 +189,7 @@ void phys_integrate_velocities(struct phys_step_ctx *ctx, f32 dt); * Earliest time of impact * ========================== */ -f32 phys_determine_earliest_toi_for_bullets(struct phys_step_ctx *ctx, f32 step_dt, f32 tolerance, u32 max_iterations); +f32 phys_determine_earliest_toi(struct phys_step_ctx *ctx, f32 step_dt, f32 tolerance, u32 max_iterations); /* ========================== * * Space diff --git a/src/sim_ent.c b/src/sim_ent.c index dd5c2a69..cbdae81c 100644 --- a/src/sim_ent.c +++ b/src/sim_ent.c @@ -501,42 +501,52 @@ void sim_ent_set_local_xform(struct sim_ent *ent, struct xform xf) void sim_ent_apply_linear_impulse(struct sim_ent *ent, struct v2 impulse, struct v2 point) { - struct xform xf = sim_ent_get_xform(ent); - struct v2 center = xf.og; - f32 scale = math_fabs(xform_get_determinant(xf)); - f32 inv_mass = 1.f / (ent->mass_unscaled * scale); - f32 inv_inertia = 1.f / (ent->inertia_unscaled * scale); + if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) { + struct xform xf = sim_ent_get_xform(ent); + struct v2 center = xf.og; + f32 scale = math_fabs(xform_get_determinant(xf)); + f32 inv_mass = 1.f / (ent->mass_unscaled * scale); + f32 inv_inertia = 1.f / (ent->inertia_unscaled * scale); - struct v2 vcp = v2_sub(point, center); - sim_ent_set_linear_velocity(ent, v2_add(ent->linear_velocity, v2_mul(impulse, inv_mass))); - sim_ent_set_angular_velocity(ent, v2_wedge(vcp, impulse) * inv_inertia); + struct v2 vcp = v2_sub(point, center); + sim_ent_set_linear_velocity(ent, v2_add(ent->linear_velocity, v2_mul(impulse, inv_mass))); + sim_ent_set_angular_velocity(ent, v2_wedge(vcp, impulse) * inv_inertia); + } } void sim_ent_apply_linear_impulse_to_center(struct sim_ent *ent, struct v2 impulse) { - struct xform xf = sim_ent_get_xform(ent); - f32 scale = math_fabs(xform_get_determinant(xf)); - f32 inv_mass = 1.f / (ent->mass_unscaled * scale); + if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) { + struct xform xf = sim_ent_get_xform(ent); + f32 scale = math_fabs(xform_get_determinant(xf)); + f32 inv_mass = 1.f / (ent->mass_unscaled * scale); - sim_ent_set_linear_velocity(ent, v2_add(ent->linear_velocity, v2_mul(impulse, inv_mass))); + sim_ent_set_linear_velocity(ent, v2_add(ent->linear_velocity, v2_mul(impulse, inv_mass))); + } } void sim_ent_apply_force_to_center(struct sim_ent *ent, struct v2 force) { - ent->force = v2_add(ent->force, force); + if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) { + ent->force = v2_add(ent->force, force); + } } void sim_ent_apply_angular_impulse(struct sim_ent *ent, f32 impulse) { - struct xform xf = sim_ent_get_xform(ent); - f32 scale = math_fabs(xform_get_determinant(xf)); - f32 inv_inertia = 1.f / (ent->inertia_unscaled * scale); - sim_ent_set_angular_velocity(ent, ent->angular_velocity + impulse * inv_inertia); + if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) { + struct xform xf = sim_ent_get_xform(ent); + f32 scale = math_fabs(xform_get_determinant(xf)); + f32 inv_inertia = 1.f / (ent->inertia_unscaled * scale); + sim_ent_set_angular_velocity(ent, ent->angular_velocity + impulse * inv_inertia); + } } void sim_ent_apply_torque(struct sim_ent *ent, f32 torque) { - ent->torque += torque; + if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) { + ent->torque += torque; + } } /* ========================== * diff --git a/src/sim_ent.h b/src/sim_ent.h index 4a23041c..4116308d 100644 --- a/src/sim_ent.h +++ b/src/sim_ent.h @@ -16,8 +16,8 @@ enum sim_ent_prop { SEPROP_ACTIVE, SEPROP_RELEASE, - SEPROP_SYNC_SRC, /* This entity should be networked to other clients */ - SEPROP_SYNC_DST, /* This entity is not locally created, and should sync with incoming net src ents */ + SEPROP_SYNC_SRC, /* This entity is networked to other clients */ + SEPROP_SYNC_DST, /* This entity is not locally created, and will sync with incoming net src ents */ SEPROP_PLAYER, SEPROP_PLAYER_IS_MASTER, @@ -26,8 +26,14 @@ enum sim_ent_prop { SEPROP_TILE_CHUNK, - SEPROP_PHYSICAL_DYNAMIC, - SEPROP_PHYSICAL_KINEMATIC, + /* Physics collision */ + SEPROP_SENSOR, /* This entity's collisions generate contacts */ + SEPROP_SOLID, /* This entity's collisions generate contacts to be solved by the physics system (overrides SEPROP_SENSOR) */ + SEPROP_TOI, /* This entity's collisions are processed using TOI (time of impact) for precise collisions */ + + /* Physics movement */ + SEPROP_KINEMATIC, /* This entity reacts to velocity */ + SEPROP_DYNAMIC, /* This entity reacts to velocity and forces (overrides SEPROP_KINEMATIC) */ SEPROP_CONTROLLED, @@ -35,11 +41,11 @@ enum sim_ent_prop { SEPROP_CONTACT_CONSTRAINT, SEPROP_MOTOR_JOINT, SEPROP_MOUSE_JOINT, - SEPROP_SENSOR, SEPROP_CAMERA, SEPROP_CAMERA_ACTIVE, + SEPROP_BULLET, SEPROP_WEAPON_SMG, SEPROP_WEAPON_LAUNCHER, @@ -49,7 +55,6 @@ enum sim_ent_prop { SEPROP_EXPLOSION, - SEPROP_BULLET, SEPROP_TRACER, SEPROP_QUAKE, @@ -226,7 +231,7 @@ struct sim_ent { /* ====================================================================== */ /* Physics */ - /* SEPROP_PHYSICAL_DYNAMIC */ + /* SEPROP_DYNAMIC */ //f32 density; /* Density in kg/m^2 */ @@ -293,10 +298,10 @@ struct sim_ent { struct sim_ent_id bullet_tracer; struct v2 bullet_src_pos; struct v2 bullet_src_dir; - f32 bullet_impulse; + f32 bullet_launch_velocity; f32 bullet_knockback; - f32 bullet_impact_explosion_strength; - f32 bullet_impact_explosion_radius; + f32 bullet_explosion_strength; + f32 bullet_explosion_radius; b32 bullet_has_hit; /* ====================================================================== */ diff --git a/src/sim_step.c b/src/sim_step.c index 75fc053c..63c3c4a5 100644 --- a/src/sim_step.c +++ b/src/sim_step.c @@ -106,7 +106,8 @@ INTERNAL struct sim_ent *spawn_test_employee(struct sim_step_ctx *ctx) //e->control_torque = 5000; e->control_torque = F32_INFINITY; - sim_ent_enable_prop(e, SEPROP_PHYSICAL_DYNAMIC); + sim_ent_enable_prop(e, SEPROP_DYNAMIC); + sim_ent_enable_prop(e, SEPROP_SOLID); employee = e; } @@ -218,7 +219,9 @@ INTERNAL void spawn_test_entities2(struct sim_step_ctx *ctx, struct v2 pos) e->sprite_collider_slice = LIT("shape"); e->layer = SIM_LAYER_SHOULDERS; - sim_ent_enable_prop(e, SEPROP_PHYSICAL_DYNAMIC); + sim_ent_enable_prop(e, SEPROP_SOLID); + + sim_ent_enable_prop(e, SEPROP_DYNAMIC); e->mass_unscaled = 100; e->inertia_unscaled = 50; e->linear_ground_friction = 100; @@ -240,7 +243,9 @@ INTERNAL void spawn_test_entities2(struct sim_step_ctx *ctx, struct v2 pos) e->sprite_collider_slice = LIT("shape"); e->layer = SIM_LAYER_SHOULDERS; - sim_ent_enable_prop(e, SEPROP_PHYSICAL_DYNAMIC); + sim_ent_enable_prop(e, SEPROP_SOLID); + + sim_ent_enable_prop(e, SEPROP_DYNAMIC); e->mass_unscaled = 0.5; e->inertia_unscaled = 1000; e->linear_ground_friction = 0.001; @@ -269,6 +274,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx) struct sim_ent *e0 = sim_ent_from_id(world, data->e0); struct sim_ent *e1 = sim_ent_from_id(world, data->e1); struct sim_ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID); + b32 skip_solve = false; if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) { /* Bullet impact */ @@ -281,7 +287,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx) struct sim_ent *src = sim_ent_from_id(world, bullet->bullet_src); /* Process collision if bullet already spent or * target share same top level parent */ - if (!bullet->bullet_has_hit && !sim_ent_id_eq(src->top, target->top)) { + if (!bullet->bullet_has_hit && !sim_ent_id_eq(src->top, target->top) && sim_ent_has_prop(target, SEPROP_SOLID)) { struct v2 point = data->point; /* Update tracer */ @@ -314,7 +320,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx) f32 angular_velocity_range = 5; f32 angular_velocity = rand_f64_from_seed(&step_ctx->rand, -angular_velocity_range, angular_velocity_range); - sim_ent_enable_prop(decal, SEPROP_PHYSICAL_KINEMATIC); + sim_ent_enable_prop(decal, SEPROP_KINEMATIC); sim_ent_set_linear_velocity(decal, linear_velocity); sim_ent_set_angular_velocity(decal, angular_velocity); @@ -323,8 +329,8 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx) } /* Create explosion */ - if (bullet->bullet_impact_explosion_radius > 0) { - spawn_test_explosion(world, point, bullet->bullet_impact_explosion_strength, bullet->bullet_impact_explosion_radius); + if (bullet->bullet_explosion_strength > 0) { + spawn_test_explosion(world, point, bullet->bullet_explosion_strength, bullet->bullet_explosion_radius); } /* Update bullet */ @@ -347,12 +353,17 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx) 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); f32 distance = v2_len(dir); +#if 0 if (closest_points.colliding) { dir = v2_neg(dir); - distance = 0; - } else { - distance = v2_len(dir); + //distance = 0; } +#else + if (v2_dot(data->normal, dir) < 0) { + dir = v2_neg(dir); + distance = 0; + } +#endif /* TODO: Blast obstruction */ f32 radius = exp->explosion_radius; @@ -365,6 +376,8 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx) } } } + + return skip_solve; } /* ========================== * @@ -948,14 +961,13 @@ void sim_step(struct sim_step_ctx *ctx) { bullet = sim_ent_alloc_sync_src(root); + sim_ent_enable_prop(bullet, SEPROP_BULLET); bullet->bullet_src = ent->id; bullet->bullet_src_pos = rel_pos; bullet->bullet_src_dir = rel_dir; - //bullet->bullet_impulse = 0.75f; - bullet->bullet_impulse = 2.0f; + //bullet->bullet_launch_velocity = 0.75f; + bullet->bullet_launch_velocity = 50.0f; bullet->bullet_knockback = 10; - bullet->mass_unscaled = 0.04f; - bullet->inertia_unscaled = 0.00001f; bullet->layer = SIM_LAYER_BULLETS; #if 1 @@ -966,9 +978,6 @@ void sim_step(struct sim_step_ctx *ctx) bullet->sprite = sprite_tag_from_path(LIT("res/graphics/bullet.ase")); bullet->sprite_collider_slice = LIT("shape"); #endif - - sim_ent_enable_prop(bullet, SEPROP_BULLET); - sim_ent_enable_prop(bullet, SEPROP_SENSOR); } /* Spawn tracer */ @@ -997,16 +1006,15 @@ void sim_step(struct sim_step_ctx *ctx) { bullet = sim_ent_alloc_sync_src(root); + sim_ent_enable_prop(bullet, SEPROP_BULLET); bullet->bullet_src = ent->id; bullet->bullet_src_pos = rel_pos; bullet->bullet_src_dir = rel_dir; - //bullet->bullet_impulse = 0.75f; - bullet->bullet_impulse = 0.75; - bullet->bullet_knockback = 10; - bullet->bullet_impact_explosion_strength = 200; - bullet->bullet_impact_explosion_radius = 4.0; - bullet->mass_unscaled = 0.04f; - bullet->inertia_unscaled = 0.00001f; + //bullet->bullet_launch_velocity = 0.75f; + bullet->bullet_launch_velocity = 15; + bullet->bullet_knockback = 50; + bullet->bullet_explosion_strength = 100; + bullet->bullet_explosion_radius = 4; bullet->layer = SIM_LAYER_BULLETS; /* Point collider */ @@ -1014,8 +1022,6 @@ void sim_step(struct sim_step_ctx *ctx) bullet->local_collider.count = 1; bullet->local_collider.radius = 0.05; - sim_ent_enable_prop(bullet, SEPROP_BULLET); - sim_ent_enable_prop(bullet, SEPROP_SENSOR); } /* Spawn tracer */ @@ -1085,7 +1091,7 @@ void sim_step(struct sim_step_ctx *ctx) joint_ent->predictor = ent->predictor; joint_ent->mass_unscaled = F32_INFINITY; joint_ent->inertia_unscaled = F32_INFINITY; - sim_ent_enable_prop(joint_ent, SEPROP_PHYSICAL_KINEMATIC); /* Since we'll be setting velocity manually */ + sim_ent_enable_prop(joint_ent, SEPROP_KINEMATIC); /* Since we'll be setting velocity manually */ sim_ent_enable_prop(joint_ent, SEPROP_MOTOR_JOINT); sim_ent_enable_prop(joint_ent, SEPROP_ACTIVE); ent->aim_joint = joint_ent->id; @@ -1171,7 +1177,7 @@ void sim_step(struct sim_step_ctx *ctx) for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { struct sim_ent *ent = &world->ents[ent_index]; if (!sim_ent_should_simulate(ent)) continue; - if (!sim_ent_has_prop(ent, SEPROP_PHYSICAL_DYNAMIC)) continue; + if (!sim_ent_has_prop(ent, SEPROP_DYNAMIC)) continue; struct sim_ent *joint_ent = sim_ent_from_id(world, ent->ground_friction_joint); @@ -1253,7 +1259,7 @@ void sim_step(struct sim_step_ctx *ctx) { struct phys_step_ctx phys = ZI; phys.sim_step_ctx = ctx; - phys.pre_solve_callback = on_collision; + phys.collision_callback = on_collision; phys_step(&phys, sim_dt); } @@ -1267,7 +1273,7 @@ void sim_step(struct sim_step_ctx *ctx) if (!sim_ent_has_prop(ent, SEPROP_EXPLOSION)) continue; /* Explosion doesn't need to generate any more collisions after initial physics step */ - //sim_ent_disable_prop(ent, SEPROP_SENSOR); + sim_ent_disable_prop(ent, SEPROP_SENSOR); } /* ========================== * @@ -1307,9 +1313,13 @@ void sim_step(struct sim_step_ctx *ctx) struct sim_ent *src = sim_ent_from_id(world, ent->bullet_src); struct xform src_xf = sim_ent_get_xform(src); + /* Activate collision */ + sim_ent_enable_prop(ent, SEPROP_SENSOR); + sim_ent_enable_prop(ent, SEPROP_TOI); + struct v2 pos = xform_mul_v2(src_xf, ent->bullet_src_pos); - struct v2 impulse = xform_basis_mul_v2(src_xf, ent->bullet_src_dir); - impulse = v2_with_len(impulse, ent->bullet_impulse); + struct v2 vel = xform_basis_mul_v2(src_xf, ent->bullet_src_dir); + vel = v2_with_len(vel, ent->bullet_launch_velocity); #if 0 /* Add shooter velocity to bullet */ @@ -1320,17 +1330,17 @@ void sim_step(struct sim_step_ctx *ctx) } #endif - struct xform xf = XFORM_TRS(.t = pos, .r = v2_angle(impulse) + PI / 2); + struct xform xf = XFORM_TRS(.t = pos, .r = v2_angle(vel) + PI / 2); sim_ent_set_xform(ent, xf); - sim_ent_enable_prop(ent, SEPROP_PHYSICAL_KINEMATIC); - sim_ent_apply_linear_impulse_to_center(ent, impulse); + sim_ent_enable_prop(ent, SEPROP_KINEMATIC); + sim_ent_set_linear_velocity(ent, vel); /* Initialize tracer */ struct sim_ent *tracer = sim_ent_from_id(world, ent->bullet_tracer); if (sim_ent_should_simulate(tracer)) { sim_ent_set_xform(tracer, xf); - sim_ent_enable_prop(tracer, SEPROP_PHYSICAL_KINEMATIC); + sim_ent_enable_prop(tracer, SEPROP_KINEMATIC); sim_ent_set_linear_velocity(tracer, ent->linear_velocity); tracer->tracer_start = pos; tracer->tracer_start_velocity = ent->linear_velocity; diff --git a/src/user.c b/src/user.c index 51c57af1..fee8dbdc 100644 --- a/src/user.c +++ b/src/user.c @@ -1102,7 +1102,7 @@ INTERNAL void user_update(void) if (G.debug_draw && !skip_debug_draw) { struct temp_arena temp = arena_temp_begin(scratch.arena); - if (sim_ent_has_prop(ent, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(ent, SEPROP_PHYSICAL_KINEMATIC)) { + if (sim_ent_has_prop(ent, SEPROP_DYNAMIC) || sim_ent_has_prop(ent, SEPROP_KINEMATIC)) { debug_draw_movement(ent); }