252 lines
6.6 KiB
C
252 lines
6.6 KiB
C
typedef struct CollisionData CollisionData;
|
|
struct CollisionData {
|
|
EntId e0;
|
|
EntId 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 */
|
|
typedef struct SimStepCtx 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)
|
|
typedef PHYS_COLLISION_CALLBACK_FUNC_DEF(phys_collision_callback_func, collision_data, ctx);
|
|
|
|
/* Structure containing data used for a single physics step */
|
|
typedef struct PhysStepCtx PhysStepCtx;
|
|
struct PhysStepCtx {
|
|
SimStepCtx *sim_step_ctx;
|
|
phys_collision_callback_func *collision_callback;
|
|
};
|
|
|
|
/* ========================== *
|
|
* Contact
|
|
* ========================== */
|
|
|
|
typedef struct ContactPoint ContactPoint;
|
|
struct 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
|
|
};
|
|
|
|
typedef struct ContactConstraint ContactConstraint;
|
|
struct ContactConstraint {
|
|
u64 last_phys_iteration; /* To avoid checking collisions for the same constraint twice in one tick */
|
|
b32 skip_solve;
|
|
b32 wrong_dir;
|
|
EntId e0;
|
|
EntId 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;
|
|
ContactPoint points[2];
|
|
u32 num_points;
|
|
|
|
f32 friction;
|
|
|
|
f32 pushout_velocity;
|
|
};
|
|
|
|
typedef struct CollisionDebugData CollisionDebugData;
|
|
struct CollisionDebugData {
|
|
EntId e0;
|
|
EntId e1;
|
|
CLD_CollisionResult res;
|
|
|
|
ContactPoint points[2];
|
|
u32 num_points;
|
|
|
|
Vec2 closest0;
|
|
Vec2 closest1;
|
|
|
|
Xform xf0;
|
|
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);
|
|
void phys_warm_start_contacts(PhysStepCtx *ctx);
|
|
void phys_solve_contacts(PhysStepCtx *ctx, f32 dt, b32 apply_bias);
|
|
|
|
/* ========================== *
|
|
* Motor joint
|
|
* ========================== */
|
|
|
|
typedef struct MotorJointDesc MotorJointDesc;
|
|
struct MotorJointDesc {
|
|
EntId e0;
|
|
EntId e1;
|
|
f32 correction_rate;
|
|
f32 max_force;
|
|
f32 max_torque;
|
|
};
|
|
|
|
typedef struct MotorJoint MotorJoint;
|
|
struct MotorJoint {
|
|
EntId e0;
|
|
EntId 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;
|
|
};
|
|
|
|
MotorJointDesc phys_motor_joint_def_init(void);
|
|
MotorJoint phys_motor_joint_from_def(MotorJointDesc def);
|
|
void phys_prepare_motor_joints(PhysStepCtx *ctx);
|
|
void phys_warm_start_motor_joints(PhysStepCtx *ctx);
|
|
void phys_solve_motor_joints(PhysStepCtx *ctx, f32 dt);
|
|
|
|
/* ========================== *
|
|
* Mouse joint
|
|
* ========================== */
|
|
|
|
typedef struct MouseJointDesc MouseJointDesc;
|
|
struct MouseJointDesc {
|
|
EntId 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;
|
|
};
|
|
|
|
typedef struct MouseJoint MouseJoint;
|
|
struct MouseJoint {
|
|
EntId 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;
|
|
};
|
|
|
|
MouseJointDesc phys_mouse_joint_def_init(void);
|
|
MouseJoint phys_mouse_joint_from_def(MouseJointDesc def);
|
|
void phys_prepare_mouse_joints(PhysStepCtx *ctx);
|
|
void phys_warm_start_mouse_joints(PhysStepCtx *ctx);
|
|
void phys_solve_mouse_joints(PhysStepCtx *ctx, f32 dt);
|
|
|
|
/* ========================== *
|
|
* Weld joint
|
|
* ========================== */
|
|
|
|
typedef struct WeldJointDesc WeldJointDesc;
|
|
struct WeldJointDesc {
|
|
EntId e0;
|
|
EntId 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;
|
|
};
|
|
|
|
typedef struct WeldJoint WeldJoint;
|
|
struct WeldJoint {
|
|
EntId e0;
|
|
EntId 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;
|
|
};
|
|
|
|
WeldJointDesc phys_weld_joint_def_init(void);
|
|
WeldJoint phys_weld_joint_from_def(WeldJointDesc def);
|
|
void phys_prepare_weld_joints(PhysStepCtx *ctx);
|
|
void phys_warm_start_weld_joints(PhysStepCtx *ctx);
|
|
void phys_solve_weld_joints(PhysStepCtx *ctx, f32 dt);
|
|
|
|
/* ========================== *
|
|
* Integration
|
|
* ========================== */
|
|
|
|
void phys_integrate_forces(PhysStepCtx *ctx, f32 dt);
|
|
void phys_integrate_velocities(PhysStepCtx *ctx, f32 dt);
|
|
|
|
/* ========================== *
|
|
* Earliest time of impact
|
|
* ========================== */
|
|
|
|
f32 phys_determine_earliest_toi(PhysStepCtx *ctx, f32 step_dt, f32 tolerance, u32 max_iterations);
|
|
|
|
/* ========================== *
|
|
* Space
|
|
* ========================== */
|
|
|
|
void phys_update_aabbs(PhysStepCtx *ctx);
|
|
|
|
/* ========================== *
|
|
* Step
|
|
* ========================== */
|
|
|
|
void phys_step(PhysStepCtx *ctx, f32 timestep);
|