//////////////////////////////////////////////////////////// //~ Collision data types #define PP_ContactSpringHz 25 #define PP_ContactSpringDamp 10 Struct(PP_CollisionData) { PP_EntKey e0; PP_EntKey e1; Vec2 point; Vec2 normal; /* Normal of the collision from e0 to e1 */ Vec2 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) */ }; /* Callback can return 1 to prevent the physics system from resolving */ struct PP_SimStepCtx; #define PP_CollisionCallbackFuncDef(name, arg_collision_data, arg_sim_step_ctx) b32 name(PP_CollisionData *arg_collision_data, struct PP_SimStepCtx *arg_sim_step_ctx) typedef PP_CollisionCallbackFuncDef(PP_CollisionCallbackFunc, collision_data, ctx); //////////////////////////////////////////////////////////// //~ Step ctx /* Structure containing data used for a single physics step */ Struct(PP_PhysStepCtx) { struct PP_SimStepCtx *sim_step_ctx; PP_CollisionCallbackFunc *collision_callback; }; //////////////////////////////////////////////////////////// //~ Contact types Struct(PP_ContactPoint) { /* Contact point relative to the center of each entity. * * NOTE: We use fixed (non-rotated) points relative to the entities * rather than points fully in local space because contact manifolds * shouldn't really be affected by rotation accross substeps * (imagine re-building the manifold of a rotated shape, it would still be * on the same side of the shape that it originally occured on) */ Vec2 vcp0; Vec2 vcp1; u32 id; /* ID generated during clipping */ f32 starting_separation; /* How far are original points along normal */ f32 normal_impulse; /* Accumulated impulse along normal */ f32 tangent_impulse; /* Accumulated impulse along tangent */ f32 inv_normal_mass; f32 inv_tangent_mass; /* Debugging */ #if DeveloperIsEnabled Vec2 dbg_pt; #endif }; Struct(PP_ContactConstraint) { u64 last_phys_iteration; /* To avoid checking collisions for the same constraint twice in one tick */ b32 skip_solve; b32 wrong_dir; PP_EntKey e0; PP_EntKey e1; f32 inv_m0; f32 inv_m1; f32 inv_i0; f32 inv_i1; Vec2 normal; /* Normal vector of collision from e0 -> e1 */ u64 last_iteration; PP_ContactPoint points[2]; u32 num_points; f32 friction; f32 pushout_velocity; }; Struct(PP_ContactDebugData) { PP_EntKey e0; PP_EntKey e1; CLD_CollisionData collision_result; PP_ContactPoint points[2]; u32 num_points; Vec2 closest0; Vec2 closest1; Xform xf0; Xform xf1; }; //////////////////////////////////////////////////////////// //~ Motor joint types Struct(PP_MotorJointDesc) { PP_EntKey e0; PP_EntKey e1; f32 correction_rate; f32 max_force; f32 max_torque; }; Struct(PP_MotorJoint) { PP_EntKey e0; PP_EntKey e1; f32 correction_rate; f32 max_force; f32 max_torque; f32 inv_m0; f32 inv_m1; f32 inv_i0; f32 inv_i1; Vec2 linear_impulse; f32 angular_impulse; Vec2 point_local_e0; Vec2 point_local_e1; Xform linear_mass_xf; f32 angular_mass; }; //////////////////////////////////////////////////////////// //~ Mouse joint types Struct(PP_MouseJointDesc) { PP_EntKey target; Vec2 point_local_start; Vec2 point_end; f32 linear_spring_hz; f32 linear_spring_damp; f32 angular_spring_hz; f32 angular_spring_damp; f32 max_force; }; Struct(PP_MouseJoint) { PP_EntKey target; Vec2 point_local_start; Vec2 point_end; f32 linear_spring_hz; f32 linear_spring_damp; f32 angular_spring_hz; f32 angular_spring_damp; f32 max_force; f32 inv_m; f32 inv_i; Vec2 linear_impulse; f32 angular_impulse; Xform linear_mass_xf; }; //////////////////////////////////////////////////////////// //~ Weld joint types Struct(PP_WeldJointDesc) { PP_EntKey e0; PP_EntKey e1; /* The xform that transforms a point in e0's space into the desired e1 space * (IE `xf` * VEC2(0, 0) should evaluate to the local point that e1's origin will lie) */ Xform xf; f32 linear_spring_hz; f32 linear_spring_damp; f32 angular_spring_hz; f32 angular_spring_damp; }; Struct(PP_WeldJoint) { PP_EntKey e0; PP_EntKey e1; Xform xf0_to_xf1; f32 linear_spring_hz; f32 linear_spring_damp; f32 angular_spring_hz; f32 angular_spring_damp; f32 inv_m0; f32 inv_m1; f32 inv_i0; f32 inv_i1; Vec2 linear_impulse0; Vec2 linear_impulse1; f32 angular_impulse0; f32 angular_impulse1; }; //////////////////////////////////////////////////////////// //~ Contact operations b32 PP_CanEntsContact(struct PP_Ent *e0, struct PP_Ent *e1); void PP_CreateAndUpdateContacts(PP_PhysStepCtx *ctx, f32 elapsed_dt, u64 phys_iteration); void PP_PrepareContacts(PP_PhysStepCtx *ctx, u64 phys_iteration); void PP_WarmStartContacts(PP_PhysStepCtx *ctx); void PP_SolveContacts(PP_PhysStepCtx *ctx, f32 dt, b32 apply_bias); //////////////////////////////////////////////////////////// //~ Motor joint operations PP_MotorJointDesc PP_CreateMotorJointDef(void); PP_MotorJoint PP_MotorJointFromDef(PP_MotorJointDesc def); void PP_PrepareMotorJoints(PP_PhysStepCtx *ctx); void PP_WarmStartMotorJoints(PP_PhysStepCtx *ctx); void PP_SolveMotorJoints(PP_PhysStepCtx *ctx, f32 dt); //////////////////////////////////////////////////////////// //~ Mouse joint operations PP_MouseJointDesc PP_CreateMouseJointDef(void); PP_MouseJoint PP_MouseJointFromDef(PP_MouseJointDesc def); void PP_PrepareMouseJoints(PP_PhysStepCtx *ctx); void PP_WarmStartMouseJoints(PP_PhysStepCtx *ctx); void PP_SolveMouseJoints(PP_PhysStepCtx *ctx, f32 dt); //////////////////////////////////////////////////////////// //~ Weld joint operations PP_WeldJointDesc PP_CreateWeldJointDef(void); PP_WeldJoint PP_WeldJointFromDef(PP_WeldJointDesc def); void PP_PrepareWeldJoints(PP_PhysStepCtx *ctx); void PP_WarmStartWeldJoints(PP_PhysStepCtx *ctx); void PP_SolveWeldJoints(PP_PhysStepCtx *ctx, f32 dt); //////////////////////////////////////////////////////////// //~ Integration operations Xform PP_GetDerivedEntXform(struct PP_Ent *ent, f32 dt); void PP_IntegrateForces(PP_PhysStepCtx *ctx, f32 dt); void PP_IntegrateVelocities(PP_PhysStepCtx *ctx, f32 dt); //////////////////////////////////////////////////////////// //~ Time of impact operations f32 PP_DetermineEarliestToi(PP_PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u32 max_iterations); //////////////////////////////////////////////////////////// //~ Spatial operations void PP_UpdateAabbs(PP_PhysStepCtx *ctx); //////////////////////////////////////////////////////////// //~ Step void PP_StepPhys(PP_PhysStepCtx *ctx, f32 timestep);