add collision props that are separate from dynamic & kinematic props

This commit is contained in:
jacob 2025-05-16 17:17:37 -05:00
parent e24591c13c
commit e4a4e33232
6 changed files with 145 additions and 136 deletions

View File

@ -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));
/* 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);
}
/* 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);
}

View File

@ -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

View File

@ -501,6 +501,7 @@ 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)
{
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));
@ -510,33 +511,42 @@ void sim_ent_apply_linear_impulse(struct sim_ent *ent, struct v2 impulse, struct
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)
{
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)));
}
}
void sim_ent_apply_force_to_center(struct sim_ent *ent, struct v2 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)
{
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)
{
if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
ent->torque += torque;
}
}
/* ========================== *

View File

@ -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;
/* ====================================================================== */

View File

@ -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;

View File

@ -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);
}