power_play/src/pp/pp_phys.h
2025-11-02 16:50:56 -06:00

267 lines
6.9 KiB
C

////////////////////////////////////////////////////////////
//~ 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);