pp refactor progress

This commit is contained in:
jacob 2025-08-05 16:34:02 -05:00
parent 1f27a0fe1e
commit eabefaa16d
6 changed files with 180 additions and 175 deletions

View File

@ -1412,7 +1412,7 @@ void UpdateUser(P_Window *window)
#if COLLIDER_DEBUG #if COLLIDER_DEBUG
if (HasProp(ent, Prop_CollisionDebug)) if (HasProp(ent, Prop_CollisionDebug))
{ {
CollisionDebugData *data = &ent->collision_debug_data; ContactDebugData *data = &ent->collision_debug_data;
CLD_CollisionData collision_reuslt = data->collision_result; CLD_CollisionData collision_reuslt = data->collision_result;
Entity *e0 = EntityFromId(g->ss_blended, data->e0); Entity *e0 = EntityFromId(g->ss_blended, data->e0);
Entity *e1 = EntityFromId(g->ss_blended, data->e1); Entity *e1 = EntityFromId(g->ss_blended, data->e1);

View File

@ -185,7 +185,7 @@ Struct(Entity)
CLD_Shape local_collider; CLD_Shape local_collider;
#if COLLIDER_DEBUG #if COLLIDER_DEBUG
CollisionDebugData collision_debug_data; ContactDebugData collision_debug_data;
#endif #endif
SpaceEntryHandle space_handle; SpaceEntryHandle space_handle;

View File

@ -1,11 +1,7 @@
#define CONTACT_SPRING_HZ 25 ////////////////////////////////
#define CONTACT_SPRING_DAMP 10 //~ Contact
/* ========================== * b32 CanEntitiesContact(Entity *e0, Entity *e1)
* Contact
* ========================== */
internal b32 can_contact(Entity *e0, Entity *e1)
{ {
b32 result = 0; b32 result = 0;
result = e0 != e1 && result = e0 != e1 &&
@ -14,14 +10,14 @@ internal b32 can_contact(Entity *e0, Entity *e1)
return result; return result;
} }
void phys_create_and_update_contacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteration) void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteration)
{ {
__prof; __prof;
SimStepCtx *sim_step_ctx = ctx->sim_step_ctx; SimStepCtx *sim_step_ctx = ctx->sim_step_ctx;
Snapshot *ss = sim_step_ctx->world; Snapshot *ss = sim_step_ctx->world;
Space *space = sim_step_ctx->accel->space; Space *space = sim_step_ctx->accel->space;
EntityId local_player = ss->local_player; EntityId local_player = ss->local_player;
phys_collision_callback_func *collision_callback = ctx->collision_callback; CollisionCallbackFunc *collision_callback = ctx->collision_callback;
Entity *root = EntityFromId(ss, RootEntityId); Entity *root = EntityFromId(ss, RootEntityId);
u64 tick = ss->tick; u64 tick = ss->tick;
@ -43,7 +39,7 @@ void phys_create_and_update_contacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_
if (!IsValidAndActive(check1)) continue; if (!IsValidAndActive(check1)) continue;
if (!(HasProp(check1, Prop_Solid) || HasProp(check1, Prop_Sensor))) continue; if (!(HasProp(check1, Prop_Solid) || HasProp(check1, Prop_Sensor))) continue;
if (check1->local_collider.count <= 0) continue; if (check1->local_collider.count <= 0) continue;
if (!can_contact(check0, check1)) continue; if (!CanEntitiesContact(check0, check1)) continue;
/* Deterministic order based on entity id */ /* Deterministic order based on entity id */
Entity *e0; Entity *e0;
@ -236,7 +232,7 @@ void phys_create_and_update_contacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_
EnableProp(dbg_ent, Prop_CollisionDebug); EnableProp(dbg_ent, Prop_CollisionDebug);
} }
CollisionDebugData *dbg = &dbg_ent->collision_debug_data; ContactDebugData *dbg = &dbg_ent->collision_debug_data;
dbg->e0 = e0->id; dbg->e0 = e0->id;
dbg->e1 = e1->id; dbg->e1 = e1->id;
@ -265,7 +261,7 @@ void phys_create_and_update_contacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_
} }
} }
void phys_prepare_contacts(PhysStepCtx *ctx, u64 phys_iteration) void PrepareContacts(PhysStepCtx *ctx, u64 phys_iteration)
{ {
__prof; __prof;
Snapshot *ss = ctx->sim_step_ctx->world; Snapshot *ss = ctx->sim_step_ctx->world;
@ -359,7 +355,7 @@ void phys_prepare_contacts(PhysStepCtx *ctx, u64 phys_iteration)
if (!ShouldSimulate(dbg_ent)) continue; if (!ShouldSimulate(dbg_ent)) continue;
if (!HasProp(dbg_ent, Prop_CollisionDebug)) continue; if (!HasProp(dbg_ent, Prop_CollisionDebug)) continue;
CollisionDebugData *dbg = &dbg_ent->collision_debug_data; ContactDebugData *dbg = &dbg_ent->collision_debug_data;
Entity *e0 = EntityFromId(ss, dbg->e0); Entity *e0 = EntityFromId(ss, dbg->e0);
Entity *e1 = EntityFromId(ss, dbg->e1); Entity *e1 = EntityFromId(ss, dbg->e1);
@ -375,7 +371,7 @@ void phys_prepare_contacts(PhysStepCtx *ctx, u64 phys_iteration)
#endif #endif
} }
void phys_warm_start_contacts(PhysStepCtx *ctx) void WarmStartContacts(PhysStepCtx *ctx)
{ {
__prof; __prof;
Snapshot *ss = ctx->sim_step_ctx->world; Snapshot *ss = ctx->sim_step_ctx->world;
@ -427,7 +423,7 @@ void phys_warm_start_contacts(PhysStepCtx *ctx)
} }
} }
void phys_solve_contacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias) void SolveContacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias)
{ {
__prof; __prof;
Snapshot *ss = ctx->sim_step_ctx->world; Snapshot *ss = ctx->sim_step_ctx->world;
@ -477,7 +473,7 @@ void phys_solve_contacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias)
velocity_bias = separation / dt; velocity_bias = separation / dt;
} else if (apply_bias) { } else if (apply_bias) {
/* Soft constraint */ /* Soft constraint */
SoftSpring softness = MakeSpring(CONTACT_SPRING_HZ, CONTACT_SPRING_DAMP, dt); SoftSpring softness = MakeSpring(ContactSpringHz, ContactSpringDamp, dt);
f32 pushout_velocity = constraint->pushout_velocity; f32 pushout_velocity = constraint->pushout_velocity;
mass_scale = softness.mass_scale; mass_scale = softness.mass_scale;
impulse_scale = softness.impulse_scale; impulse_scale = softness.impulse_scale;
@ -544,17 +540,16 @@ void phys_solve_contacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias)
} }
} }
/* ========================== * ////////////////////////////////
* Motor joint //~ Motor joint
* ========================== */
MotorJointDesc phys_motor_joint_def_init(void) MotorJointDesc CreateMotorJointDef(void)
{ {
MotorJointDesc def = ZI; MotorJointDesc def = ZI;
return def; return def;
} }
MotorJoint phys_motor_joint_from_def(MotorJointDesc def) MotorJoint MotorJointFromDef(MotorJointDesc def)
{ {
MotorJoint result = ZI; MotorJoint result = ZI;
result.e0 = def.e0; result.e0 = def.e0;
@ -565,7 +560,7 @@ MotorJoint phys_motor_joint_from_def(MotorJointDesc def)
return result; return result;
} }
void phys_prepare_motor_joints(PhysStepCtx *ctx) void PrepareMotorJoints(PhysStepCtx *ctx)
{ {
__prof; __prof;
Snapshot *ss = ctx->sim_step_ctx->world; Snapshot *ss = ctx->sim_step_ctx->world;
@ -629,7 +624,7 @@ void phys_prepare_motor_joints(PhysStepCtx *ctx)
} }
} }
void phys_warm_start_motor_joints(PhysStepCtx *ctx) void WarmStartMotorJoints(PhysStepCtx *ctx)
{ {
__prof; __prof;
Snapshot *ss = ctx->sim_step_ctx->world; Snapshot *ss = ctx->sim_step_ctx->world;
@ -661,7 +656,7 @@ void phys_warm_start_motor_joints(PhysStepCtx *ctx)
} }
} }
void phys_solve_motor_joints(PhysStepCtx *ctx, f32 dt) void SolveMotorJoints(PhysStepCtx *ctx, f32 dt)
{ {
__prof; __prof;
Snapshot *ss = ctx->sim_step_ctx->world; Snapshot *ss = ctx->sim_step_ctx->world;
@ -738,11 +733,10 @@ void phys_solve_motor_joints(PhysStepCtx *ctx, f32 dt)
} }
} }
/* ========================== * ////////////////////////////////
* Mouse joint //~ Mouse joint
* ========================== */
MouseJointDesc phys_mouse_joint_def_init(void) MouseJointDesc CreateMouseJointDef(void)
{ {
MouseJointDesc def = ZI; MouseJointDesc def = ZI;
def.linear_spring_hz = 5.0f; def.linear_spring_hz = 5.0f;
@ -753,7 +747,7 @@ MouseJointDesc phys_mouse_joint_def_init(void)
return def; return def;
} }
MouseJoint phys_mouse_joint_from_def(MouseJointDesc def) MouseJoint MouseJointFromDef(MouseJointDesc def)
{ {
MouseJoint result = ZI; MouseJoint result = ZI;
result.target = def.target; result.target = def.target;
@ -767,7 +761,7 @@ MouseJoint phys_mouse_joint_from_def(MouseJointDesc def)
return result; return result;
} }
void phys_prepare_mouse_joints(PhysStepCtx *ctx) void PrepareMouseJoints(PhysStepCtx *ctx)
{ {
__prof; __prof;
Snapshot *ss = ctx->sim_step_ctx->world; Snapshot *ss = ctx->sim_step_ctx->world;
@ -814,7 +808,7 @@ void phys_prepare_mouse_joints(PhysStepCtx *ctx)
} }
} }
void phys_warm_start_mouse_joints(PhysStepCtx *ctx) void WarmStartMouseJoints(PhysStepCtx *ctx)
{ {
__prof; __prof;
Snapshot *ss = ctx->sim_step_ctx->world; Snapshot *ss = ctx->sim_step_ctx->world;
@ -836,7 +830,7 @@ void phys_warm_start_mouse_joints(PhysStepCtx *ctx)
} }
} }
void phys_solve_mouse_joints(PhysStepCtx *ctx, f32 dt) void SolveMouseJoints(PhysStepCtx *ctx, f32 dt)
{ {
__prof; __prof;
Snapshot *ss = ctx->sim_step_ctx->world; Snapshot *ss = ctx->sim_step_ctx->world;
@ -905,11 +899,10 @@ void phys_solve_mouse_joints(PhysStepCtx *ctx, f32 dt)
} }
} }
/* ========================== * ////////////////////////////////
* Weld joint //~ Weld joint
* ========================== */
WeldJointDesc phys_weld_joint_def_init(void) WeldJointDesc CreateWeldJointDef(void)
{ {
WeldJointDesc def = ZI; WeldJointDesc def = ZI;
def.linear_spring_hz = 50; def.linear_spring_hz = 50;
@ -919,7 +912,7 @@ WeldJointDesc phys_weld_joint_def_init(void)
return def; return def;
} }
WeldJoint phys_weld_joint_from_def(WeldJointDesc def) WeldJoint WeldJointFromDef(WeldJointDesc def)
{ {
WeldJoint result = ZI; WeldJoint result = ZI;
result.e0 = def.e0; result.e0 = def.e0;
@ -932,7 +925,7 @@ WeldJoint phys_weld_joint_from_def(WeldJointDesc def)
return result; return result;
} }
void phys_prepare_weld_joints(PhysStepCtx *ctx) void PrepareWeldJoints(PhysStepCtx *ctx)
{ {
__prof; __prof;
Snapshot *ss = ctx->sim_step_ctx->world; Snapshot *ss = ctx->sim_step_ctx->world;
@ -981,7 +974,7 @@ void phys_prepare_weld_joints(PhysStepCtx *ctx)
} }
} }
void phys_warm_start_weld_joints(PhysStepCtx *ctx) void WarmStartWeldJoints(PhysStepCtx *ctx)
{ {
__prof; __prof;
Snapshot *ss = ctx->sim_step_ctx->world; Snapshot *ss = ctx->sim_step_ctx->world;
@ -1018,7 +1011,7 @@ void phys_warm_start_weld_joints(PhysStepCtx *ctx)
} }
} }
void phys_solve_weld_joints(PhysStepCtx *ctx, f32 dt) void SolveWeldJoints(PhysStepCtx *ctx, f32 dt)
{ {
__prof; __prof;
Snapshot *ss = ctx->sim_step_ctx->world; Snapshot *ss = ctx->sim_step_ctx->world;
@ -1082,11 +1075,10 @@ void phys_solve_weld_joints(PhysStepCtx *ctx, f32 dt)
} }
} }
/* ========================== * ////////////////////////////////
* Integration //~ Integration
* ========================== */
internal Xform get_derived_xform(Entity *ent, f32 dt) Xform GetDerivedEntityXform(Entity *ent, f32 dt)
{ {
Xform xf = XformFromEntity(ent); Xform xf = XformFromEntity(ent);
@ -1098,7 +1090,7 @@ internal Xform get_derived_xform(Entity *ent, f32 dt)
return xf; return xf;
} }
void phys_integrate_forces(PhysStepCtx *ctx, f32 dt) void IntegrateForces(PhysStepCtx *ctx, f32 dt)
{ {
__prof; __prof;
Snapshot *ss = ctx->sim_step_ctx->world; Snapshot *ss = ctx->sim_step_ctx->world;
@ -1140,7 +1132,7 @@ void phys_integrate_forces(PhysStepCtx *ctx, f32 dt)
} }
} }
void phys_integrate_velocities(PhysStepCtx *ctx, f32 dt) void IntegrateVelocities(PhysStepCtx *ctx, f32 dt)
{ {
__prof; __prof;
Snapshot *ss = ctx->sim_step_ctx->world; Snapshot *ss = ctx->sim_step_ctx->world;
@ -1149,16 +1141,15 @@ void phys_integrate_velocities(PhysStepCtx *ctx, f32 dt)
if (!ShouldSimulate(ent)) continue; if (!ShouldSimulate(ent)) continue;
if (!HasProp(ent, Prop_Dynamic) && !HasProp(ent, Prop_Kinematic)) continue; if (!HasProp(ent, Prop_Dynamic) && !HasProp(ent, Prop_Kinematic)) continue;
Xform xf = get_derived_xform(ent, dt); Xform xf = GetDerivedEntityXform(ent, dt);
SetXform(ent, xf); SetXform(ent, xf);
} }
} }
/* ========================== * ////////////////////////////////
* Earliest time of impact //~ Earliest time of impact
* ========================== */
f32 phys_determine_earliest_toi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u32 max_iterations) f32 DetermineEarliestToi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u32 max_iterations)
{ {
__prof; __prof;
Snapshot *ss = ctx->sim_step_ctx->world; Snapshot *ss = ctx->sim_step_ctx->world;
@ -1174,7 +1165,7 @@ f32 phys_determine_earliest_toi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u3
CLD_Shape e0_collider = e0->local_collider; CLD_Shape e0_collider = e0->local_collider;
Xform e0_xf_t0 = XformFromEntity(e0); Xform e0_xf_t0 = XformFromEntity(e0);
Xform e0_xf_t1 = get_derived_xform(e0, step_dt); Xform e0_xf_t1 = GetDerivedEntityXform(e0, step_dt);
/* TODO: Use swept aabb rather than combined aabb. This should prevent spikes from bullets returning 0 positive TOIs with irrelevant entities. */ /* TODO: Use swept aabb rather than combined aabb. This should prevent spikes from bullets returning 0 positive TOIs with irrelevant entities. */
Aabb aabb_t0 = CLD_AabbFromShape(&e0_collider, e0_xf_t0); Aabb aabb_t0 = CLD_AabbFromShape(&e0_collider, e0_xf_t0);
@ -1188,11 +1179,11 @@ f32 phys_determine_earliest_toi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u3
if (!ShouldSimulate(e1)) continue; if (!ShouldSimulate(e1)) continue;
if (!(HasProp(e1, Prop_Solid) || HasProp(e1, Prop_Sensor))) continue; if (!(HasProp(e1, Prop_Solid) || HasProp(e1, Prop_Sensor))) continue;
if (e1->local_collider.count <= 0) continue; if (e1->local_collider.count <= 0) continue;
if (!can_contact(e0, e1)) continue; if (!CanEntitiesContact(e0, e1)) continue;
CLD_Shape e1_collider = e1->local_collider; CLD_Shape e1_collider = e1->local_collider;
Xform e1_xf_t0 = XformFromEntity(e1); Xform e1_xf_t0 = XformFromEntity(e1);
Xform e1_xf_t1 = get_derived_xform(e1, step_dt); Xform e1_xf_t1 = GetDerivedEntityXform(e1, step_dt);
f32 t = CLD_TimeOfImpact(&e0_collider, &e1_collider, e0_xf_t0, e1_xf_t0, e0_xf_t1, e1_xf_t1, tolerance, max_iterations); f32 t = CLD_TimeOfImpact(&e0_collider, &e1_collider, e0_xf_t0, e1_xf_t0, e0_xf_t1, e1_xf_t1, tolerance, max_iterations);
if (t != 0 && t < smallest_t) { if (t != 0 && t < smallest_t) {
@ -1205,11 +1196,10 @@ f32 phys_determine_earliest_toi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u3
return smallest_t; return smallest_t;
} }
/* ========================== * ////////////////////////////////
* Space //~ Spatial
* ========================== */
void phys_update_aabbs(PhysStepCtx *ctx) void UpdateAabbs(PhysStepCtx *ctx)
{ {
__prof; __prof;
Snapshot *ss = ctx->sim_step_ctx->world; Snapshot *ss = ctx->sim_step_ctx->world;
@ -1230,19 +1220,18 @@ void phys_update_aabbs(PhysStepCtx *ctx)
} }
} }
/* ========================== * ////////////////////////////////
* Step //~ Step
* ========================== */
/* Returns phys iteration to be fed into next step. Supplied iteration must be > 0. */ /* Returns phys iteration to be fed into next step. Supplied iteration must be > 0. */
void phys_step(PhysStepCtx *ctx, f32 timestep) void StepPhys(PhysStepCtx *ctx, f32 timestep)
{ {
__prof; __prof;
phys_integrate_forces(ctx, timestep); IntegrateForces(ctx, timestep);
Snapshot *ss = ctx->sim_step_ctx->world; Snapshot *ss = ctx->sim_step_ctx->world;
u64 phys_iteration = ss->phys_iteration; u64 phys_iteration = ss->phys_iteration;
phys_update_aabbs(ctx); UpdateAabbs(ctx);
f32 remaining_dt = timestep; f32 remaining_dt = timestep;
while (remaining_dt > 0) { while (remaining_dt > 0) {
@ -1257,20 +1246,20 @@ void phys_step(PhysStepCtx *ctx, f32 timestep)
const f32 min_toi = 0.000001f; const f32 min_toi = 0.000001f;
const f32 tolerance = 0.0001f; const f32 tolerance = 0.0001f;
const u32 max_iterations = 16; const u32 max_iterations = 16;
f32 earliest_toi = MaxF32(phys_determine_earliest_toi(ctx, step_dt, tolerance, max_iterations), min_toi); f32 earliest_toi = MaxF32(DetermineEarliestToi(ctx, step_dt, tolerance, max_iterations), min_toi);
step_dt = remaining_dt * earliest_toi; step_dt = remaining_dt * earliest_toi;
#else #else
LAX phys_determine_earliest_toi; LAX DetermineEarliestToi;
#endif #endif
} }
remaining_dt -= step_dt; remaining_dt -= step_dt;
phys_create_and_update_contacts(ctx, timestep - remaining_dt, phys_iteration); CreateAndUpdateContacts(ctx, timestep - remaining_dt, phys_iteration);
phys_prepare_contacts(ctx, phys_iteration); PrepareContacts(ctx, phys_iteration);
phys_prepare_motor_joints(ctx); PrepareMotorJoints(ctx);
phys_prepare_mouse_joints(ctx); PrepareMouseJoints(ctx);
phys_prepare_weld_joints(ctx); PrepareWeldJoints(ctx);
f32 substep_dt = step_dt / SIM_PHYSICS_SUBSTEPS; f32 substep_dt = step_dt / SIM_PHYSICS_SUBSTEPS;
for (u32 i = 0; i < SIM_PHYSICS_SUBSTEPS; ++i) { for (u32 i = 0; i < SIM_PHYSICS_SUBSTEPS; ++i) {
@ -1278,30 +1267,30 @@ void phys_step(PhysStepCtx *ctx, f32 timestep)
/* Warm start */ /* Warm start */
#if SIM_PHYSICS_ENABLE_WARM_STARTING #if SIM_PHYSICS_ENABLE_WARM_STARTING
phys_warm_start_contacts(ctx); WarmStartContacts(ctx);
phys_warm_start_motor_joints(ctx); WarmStartMotorJoints(ctx);
phys_warm_start_mouse_joints(ctx); WarmStartMouseJoints(ctx);
phys_warm_start_weld_joints(ctx); WarmStartWeldJoints(ctx);
#endif #endif
/* Solve */ /* Solve */
#if SIM_PHYSICS_ENABLE_COLLISION #if SIM_PHYSICS_ENABLE_COLLISION
phys_solve_contacts(ctx, substep_dt, 1); SolveContacts(ctx, substep_dt, 1);
#endif #endif
phys_solve_motor_joints(ctx, substep_dt); SolveMotorJoints(ctx, substep_dt);
phys_solve_mouse_joints(ctx, substep_dt); SolveMouseJoints(ctx, substep_dt);
phys_solve_weld_joints(ctx, substep_dt); SolveWeldJoints(ctx, substep_dt);
/* Integrate */ /* Integrate */
phys_integrate_velocities(ctx, substep_dt); IntegrateVelocities(ctx, substep_dt);
/* Relaxation solve */ /* Relaxation solve */
#if SIM_PHYSICS_ENABLE_COLLISION && SIM_PHYSICS_ENABLE_RELAXATION #if SIM_PHYSICS_ENABLE_COLLISION && SIM_PHYSICS_ENABLE_RELAXATION
phys_solve_contacts(ctx, substep_dt, 0); SolveContacts(ctx, substep_dt, 0);
#endif #endif
} }
phys_update_aabbs(ctx); UpdateAabbs(ctx);
EndScratch(scratch); EndScratch(scratch);
} }

View File

@ -1,5 +1,11 @@
typedef struct CollisionData CollisionData; ////////////////////////////////
struct CollisionData { //~ Collision data types
#define ContactSpringHz 25
#define ContactSpringDamp 10
Struct(CollisionData)
{
EntityId e0; EntityId e0;
EntityId e1; EntityId e1;
Vec2 point; Vec2 point;
@ -10,23 +16,25 @@ struct CollisionData {
}; };
/* Callback can return 1 to prevent the physics system from resolving */ /* Callback can return 1 to prevent the physics system from resolving */
typedef struct SimStepCtx SimStepCtx; struct SimStepCtx;
#define PHYS_COLLISION_CALLBACK_FUNC_DEF(name, arg_collision_data, arg_sim_step_ctx) b32 name(CollisionData *arg_collision_data, SimStepCtx *arg_sim_step_ctx) #define CollisionCallbackFuncDef(name, arg_collision_data, arg_sim_step_ctx) b32 name(CollisionData *arg_collision_data, struct SimStepCtx *arg_sim_step_ctx)
typedef PHYS_COLLISION_CALLBACK_FUNC_DEF(phys_collision_callback_func, collision_data, ctx); typedef CollisionCallbackFuncDef(CollisionCallbackFunc, collision_data, ctx);
////////////////////////////////
//~ Step ctx
/* Structure containing data used for a single physics step */ /* Structure containing data used for a single physics step */
typedef struct PhysStepCtx PhysStepCtx; Struct(PhysStepCtx)
struct PhysStepCtx { {
SimStepCtx *sim_step_ctx; struct SimStepCtx *sim_step_ctx;
phys_collision_callback_func *collision_callback; CollisionCallbackFunc *collision_callback;
}; };
/* ========================== * ////////////////////////////////
* Contact //~ Contact types
* ========================== */
typedef struct ContactPoint ContactPoint; Struct(ContactPoint)
struct ContactPoint { {
/* Contact point relative to the center of each entity. /* Contact point relative to the center of each entity.
* *
* NOTE: We use fixed (non-rotated) points relative to the entities * NOTE: We use fixed (non-rotated) points relative to the entities
@ -51,8 +59,8 @@ struct ContactPoint {
#endif #endif
}; };
typedef struct ContactConstraint ContactConstraint; Struct(ContactConstraint)
struct ContactConstraint { {
u64 last_phys_iteration; /* To avoid checking collisions for the same constraint twice in one tick */ u64 last_phys_iteration; /* To avoid checking collisions for the same constraint twice in one tick */
b32 skip_solve; b32 skip_solve;
b32 wrong_dir; b32 wrong_dir;
@ -73,8 +81,8 @@ struct ContactConstraint {
f32 pushout_velocity; f32 pushout_velocity;
}; };
typedef struct CollisionDebugData CollisionDebugData; Struct(ContactDebugData)
struct CollisionDebugData { {
EntityId e0; EntityId e0;
EntityId e1; EntityId e1;
CLD_CollisionData collision_result; CLD_CollisionData collision_result;
@ -89,17 +97,11 @@ struct CollisionDebugData {
Xform xf1; Xform xf1;
}; };
void phys_create_and_update_contacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteration); ////////////////////////////////
void phys_prepare_contacts(PhysStepCtx *ctx, u64 phys_iteration); //~ Motor joint types
void phys_warm_start_contacts(PhysStepCtx *ctx);
void phys_solve_contacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias);
/* ========================== * Struct(MotorJointDesc)
* Motor joint {
* ========================== */
typedef struct MotorJointDesc MotorJointDesc;
struct MotorJointDesc {
EntityId e0; EntityId e0;
EntityId e1; EntityId e1;
f32 correction_rate; f32 correction_rate;
@ -107,8 +109,8 @@ struct MotorJointDesc {
f32 max_torque; f32 max_torque;
}; };
typedef struct MotorJoint MotorJoint; Struct(MotorJoint)
struct MotorJoint { {
EntityId e0; EntityId e0;
EntityId e1; EntityId e1;
f32 correction_rate; f32 correction_rate;
@ -130,18 +132,11 @@ struct MotorJoint {
f32 angular_mass; f32 angular_mass;
}; };
MotorJointDesc phys_motor_joint_def_init(void); ////////////////////////////////
MotorJoint phys_motor_joint_from_def(MotorJointDesc def); //~ Mouse joint types
void phys_prepare_motor_joints(PhysStepCtx *ctx);
void phys_warm_start_motor_joints(PhysStepCtx *ctx);
void phys_solve_motor_joints(PhysStepCtx *ctx, f32 dt);
/* ========================== * Struct(MouseJointDesc)
* Mouse joint {
* ========================== */
typedef struct MouseJointDesc MouseJointDesc;
struct MouseJointDesc {
EntityId target; EntityId target;
Vec2 point_local_start; Vec2 point_local_start;
Vec2 point_end; Vec2 point_end;
@ -152,8 +147,8 @@ struct MouseJointDesc {
f32 max_force; f32 max_force;
}; };
typedef struct MouseJoint MouseJoint; Struct(MouseJoint)
struct MouseJoint { {
EntityId target; EntityId target;
Vec2 point_local_start; Vec2 point_local_start;
Vec2 point_end; Vec2 point_end;
@ -172,18 +167,11 @@ struct MouseJoint {
Xform linear_mass_xf; Xform linear_mass_xf;
}; };
MouseJointDesc phys_mouse_joint_def_init(void); ////////////////////////////////
MouseJoint phys_mouse_joint_from_def(MouseJointDesc def); //~ Weld joint types
void phys_prepare_mouse_joints(PhysStepCtx *ctx);
void phys_warm_start_mouse_joints(PhysStepCtx *ctx);
void phys_solve_mouse_joints(PhysStepCtx *ctx, f32 dt);
/* ========================== * Struct(WeldJointDesc)
* Weld joint {
* ========================== */
typedef struct WeldJointDesc WeldJointDesc;
struct WeldJointDesc {
EntityId e0; EntityId e0;
EntityId e1; EntityId e1;
@ -197,8 +185,8 @@ struct WeldJointDesc {
f32 angular_spring_damp; f32 angular_spring_damp;
}; };
typedef struct WeldJoint WeldJoint; Struct(WeldJoint)
struct WeldJoint { {
EntityId e0; EntityId e0;
EntityId e1; EntityId e1;
Xform xf0_to_xf1; Xform xf0_to_xf1;
@ -219,33 +207,61 @@ struct WeldJoint {
f32 angular_impulse1; f32 angular_impulse1;
}; };
WeldJointDesc phys_weld_joint_def_init(void); ////////////////////////////////
WeldJoint phys_weld_joint_from_def(WeldJointDesc def); //~ Contact operations
void phys_prepare_weld_joints(PhysStepCtx *ctx);
void phys_warm_start_weld_joints(PhysStepCtx *ctx);
void phys_solve_weld_joints(PhysStepCtx *ctx, f32 dt);
/* ========================== * b32 CanEntitiesContact(struct Entity *e0, struct Entity *e1);
* Integration void CreateAndUpdateContacts(PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteration);
* ========================== */ void PrepareContacts(PhysStepCtx *ctx, u64 phys_iteration);
void WarmStartContacts(PhysStepCtx *ctx);
void SolveContacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias);
void phys_integrate_forces(PhysStepCtx *ctx, f32 dt); ////////////////////////////////
void phys_integrate_velocities(PhysStepCtx *ctx, f32 dt); //~ Motor joint operations
/* ========================== * MotorJointDesc CreateMotorJointDef(void);
* Earliest time of impact MotorJoint MotorJointFromDef(MotorJointDesc def);
* ========================== */ void PrepareMotorJoints(PhysStepCtx *ctx);
void WarmStartMotorJoints(PhysStepCtx *ctx);
void SolveMotorJoints(PhysStepCtx *ctx, f32 dt);
f32 phys_determine_earliest_toi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u32 max_iterations); ////////////////////////////////
//~ Mouse joint operations
/* ========================== * MouseJointDesc CreateMouseJointDef(void);
* Space MouseJoint MouseJointFromDef(MouseJointDesc def);
* ========================== */ void PrepareMouseJoints(PhysStepCtx *ctx);
void WarmStartMouseJoints(PhysStepCtx *ctx);
void SolveMouseJoints(PhysStepCtx *ctx, f32 dt);
void phys_update_aabbs(PhysStepCtx *ctx); ////////////////////////////////
//~ Weld joint operations
/* ========================== * WeldJointDesc CreateWeldJointDef(void);
* Step WeldJoint WeldJointFromDef(WeldJointDesc def);
* ========================== */ void PrepareWeldJoints(PhysStepCtx *ctx);
void WarmStartWeldJoints(PhysStepCtx *ctx);
void SolveWeldJoints(PhysStepCtx *ctx, f32 dt);
void phys_step(PhysStepCtx *ctx, f32 timestep); ////////////////////////////////
//~ Integration operations
struct Entity;
Xform GetDerivedEntityXform(struct Entity *ent, f32 dt);
void IntegrateForces(PhysStepCtx *ctx, f32 dt);
void IntegrateVelocities(PhysStepCtx *ctx, f32 dt);
////////////////////////////////
//~ Time of impact operations
f32 DetermineEarliestToi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u32 max_iterations);
////////////////////////////////
//~ Spatial operations
void UpdateAabbs(PhysStepCtx *ctx);
////////////////////////////////
//~ Step
void StepPhys(PhysStepCtx *ctx, f32 timestep);

View File

@ -689,7 +689,7 @@ void GenerateTestWalls(Snapshot *world)
//////////////////////////////// ////////////////////////////////
//~ On collision //~ On collision
PHYS_COLLISION_CALLBACK_FUNC_DEF(OnEntityCollision, data, step_ctx) CollisionCallbackFuncDef(OnEntityCollision, data, step_ctx)
{ {
Snapshot *world = step_ctx->world; Snapshot *world = step_ctx->world;
Entity *e0 = EntityFromId(world, data->e0); Entity *e0 = EntityFromId(world, data->e0);
@ -1423,7 +1423,7 @@ void StepSim(SimStepCtx *ctx)
Xform xf0_to_xf1 = MulXform(InvertXform(xf0), xf1); Xform xf0_to_xf1 = MulXform(InvertXform(xf0), xf1);
EnableProp(joint_ent, Prop_WeldJoint); EnableProp(joint_ent, Prop_WeldJoint);
WeldJointDesc def = phys_weld_joint_def_init(); WeldJointDesc def = CreateWeldJointDef();
def.e0 = ent->id; def.e0 = ent->id;
def.e1 = target->id; def.e1 = target->id;
def.xf = xf0_to_xf1; def.xf = xf0_to_xf1;
@ -1431,7 +1431,7 @@ void StepSim(SimStepCtx *ctx)
def.linear_spring_damp = 0.3f; def.linear_spring_damp = 0.3f;
def.angular_spring_hz = 10; def.angular_spring_hz = 10;
def.angular_spring_damp = 0.3f; def.angular_spring_damp = 0.3f;
joint_ent->weld_joint_data = phys_weld_joint_from_def(def); joint_ent->weld_joint_data = WeldJointFromDef(def);
ent->chucker_joint = joint_ent->id; ent->chucker_joint = joint_ent->id;
} }
} }
@ -1462,13 +1462,13 @@ void StepSim(SimStepCtx *ctx)
ent->move_joint = joint_ent->id; ent->move_joint = joint_ent->id;
EnableProp(joint_ent, Prop_MotorJoint); EnableProp(joint_ent, Prop_MotorJoint);
MotorJointDesc def = phys_motor_joint_def_init(); MotorJointDesc def = CreateMotorJointDef();
def.e0 = joint_ent->id; /* Re-using joint entity as e0 */ def.e0 = joint_ent->id; /* Re-using joint entity as e0 */
def.e1 = ent->id; def.e1 = ent->id;
def.correction_rate = 0; def.correction_rate = 0;
def.max_force = ent->control_force; def.max_force = ent->control_force;
def.max_torque = 0; def.max_torque = 0;
joint_ent->motor_joint_data = phys_motor_joint_from_def(def); joint_ent->motor_joint_data = MotorJointFromDef(def);
} }
if (ShouldSimulate(joint_ent)) { if (ShouldSimulate(joint_ent)) {
@ -1502,12 +1502,12 @@ void StepSim(SimStepCtx *ctx)
EnableProp(joint_ent, Prop_Active); EnableProp(joint_ent, Prop_Active);
ent->aim_joint = joint_ent->id; ent->aim_joint = joint_ent->id;
MotorJointDesc def = phys_motor_joint_def_init(); MotorJointDesc def = CreateMotorJointDef();
def.e0 = joint_ent->id; /* Re-using joint entity as e0 */ def.e0 = joint_ent->id; /* Re-using joint entity as e0 */
def.e1 = ent->id; def.e1 = ent->id;
def.max_force = 0; def.max_force = 0;
def.max_torque = ent->control_torque; def.max_torque = ent->control_torque;
joint_ent->motor_joint_data = phys_motor_joint_from_def(def); joint_ent->motor_joint_data = MotorJointFromDef(def);
} }
if (ShouldSimulate(joint_ent)) { if (ShouldSimulate(joint_ent)) {
@ -1586,7 +1586,7 @@ void StepSim(SimStepCtx *ctx)
Entity *joint_ent = EntityFromId(world, ent->ground_friction_joint); Entity *joint_ent = EntityFromId(world, ent->ground_friction_joint);
MotorJointDesc def = phys_motor_joint_def_init(); MotorJointDesc def = CreateMotorJointDef();
def.e0 = root->id; def.e0 = root->id;
def.e1 = ent->id; def.e1 = ent->id;
def.correction_rate = 0; def.correction_rate = 0;
@ -1598,7 +1598,7 @@ void StepSim(SimStepCtx *ctx)
joint_ent->predictor = ent->predictor; joint_ent->predictor = ent->predictor;
EnableProp(joint_ent, Prop_MotorJoint); EnableProp(joint_ent, Prop_MotorJoint);
EnableProp(joint_ent, Prop_Active); EnableProp(joint_ent, Prop_Active);
joint_ent->motor_joint_data = phys_motor_joint_from_def(def); joint_ent->motor_joint_data = MotorJointFromDef(def);
ent->ground_friction_joint = joint_ent->id; ent->ground_friction_joint = joint_ent->id;
} }
} }
@ -1639,7 +1639,7 @@ void StepSim(SimStepCtx *ctx)
} }
Xform xf = XformFromEntity(target_ent); Xform xf = XformFromEntity(target_ent);
MouseJointDesc def = phys_mouse_joint_def_init(); MouseJointDesc def = CreateMouseJointDef();
def.target = target_ent->id; def.target = target_ent->id;
if (EqId(joint_ent->mouse_joint_data.target, target_ent->id)) { if (EqId(joint_ent->mouse_joint_data.target, target_ent->id)) {
def.point_local_start = joint_ent->mouse_joint_data.point_local_start; def.point_local_start = joint_ent->mouse_joint_data.point_local_start;
@ -1652,7 +1652,7 @@ void StepSim(SimStepCtx *ctx)
def.linear_spring_damp = 0.7f; def.linear_spring_damp = 0.7f;
def.angular_spring_hz = 1; def.angular_spring_hz = 1;
def.angular_spring_damp = 0.1f; def.angular_spring_damp = 0.1f;
joint_ent->mouse_joint_data = phys_mouse_joint_from_def(def); joint_ent->mouse_joint_data = MouseJointFromDef(def);
} else if (IsValidAndActive(joint_ent)) { } else if (IsValidAndActive(joint_ent)) {
joint_ent->mouse_joint_data.target = target_ent->id; joint_ent->mouse_joint_data.target = target_ent->id;
} }
@ -1666,7 +1666,7 @@ void StepSim(SimStepCtx *ctx)
PhysStepCtx phys = ZI; PhysStepCtx phys = ZI;
phys.sim_step_ctx = ctx; phys.sim_step_ctx = ctx;
phys.collision_callback = OnEntityCollision; phys.collision_callback = OnEntityCollision;
phys_step(&phys, sim_dt); StepPhys(&phys, sim_dt);
} }

View File

@ -60,7 +60,7 @@ void GenerateTestWalls(Snapshot *world);
//////////////////////////////// ////////////////////////////////
//~ Collision response //~ Collision response
PHYS_COLLISION_CALLBACK_FUNC_DEF(OnEntityCollision, data, step_ctx); CollisionCallbackFuncDef(OnEntityCollision, data, step_ctx);
//////////////////////////////// ////////////////////////////////
//~ Step //~ Step