209 lines
5.5 KiB
C
209 lines
5.5 KiB
C
#ifndef PHYS_H
|
|
#define PHYS_H
|
|
|
|
#include "collider.h"
|
|
#include "math.h"
|
|
|
|
struct space;
|
|
struct entity_store;
|
|
struct entity_lookup;
|
|
|
|
struct phys_contact_constraint;
|
|
struct phys_collision_data {
|
|
struct phys_contact_constraint *constraint;
|
|
struct entity_handle e0;
|
|
struct entity_handle e1;
|
|
struct v2 point;
|
|
struct v2 normal; /* Normal of the collision from e0 to e1 */
|
|
struct v2 vrel; /* Relative velocity at point of collision */
|
|
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) */
|
|
};
|
|
|
|
struct phys_collision_data_array {
|
|
struct phys_collision_data *a;
|
|
u64 count;
|
|
};
|
|
|
|
struct phys_collision_data;
|
|
#define PHYS_COLLISION_CALLBACK_FUNC_DEF(name, arg) void name(struct phys_collision_data_array arg)
|
|
typedef PHYS_COLLISION_CALLBACK_FUNC_DEF(phys_collision_callback_func, data);
|
|
|
|
/* Structure containing data used for a single physics step */
|
|
struct phys_ctx {
|
|
u64 tick_id;
|
|
struct space *space;
|
|
struct entity_store *store;
|
|
struct entity_lookup *contact_lookup;
|
|
|
|
phys_collision_callback_func *pre_solve_callback;
|
|
phys_collision_callback_func *post_solve_callback;
|
|
|
|
struct entity_lookup *debug_lookup;
|
|
struct v2 dbg_cursor_pos;
|
|
b32 dbg_start_dragging;
|
|
b32 dbg_stop_dragging;
|
|
|
|
};
|
|
|
|
/* ========================== *
|
|
* Startup
|
|
* ========================== */
|
|
|
|
struct phys_startup_receipt { i32 _; };
|
|
struct phys_startup_receipt phys_startup(void);
|
|
|
|
/* ========================== *
|
|
* Contact
|
|
* ========================== */
|
|
|
|
struct phys_contact_point {
|
|
/* Contact point in local space of each entity */
|
|
struct v2 point_local_e0;
|
|
struct v2 point_local_e1;
|
|
|
|
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 */
|
|
struct v2 dbg_pt;
|
|
};
|
|
|
|
struct phys_contact_constraint {
|
|
u64 last_phys_iteration; /* To avoid checking collisions for the same constraint twice in one tick */
|
|
b32 skip_solve;
|
|
struct entity_handle e0;
|
|
struct entity_handle e1;
|
|
f32 inv_m0;
|
|
f32 inv_m1;
|
|
f32 inv_i0;
|
|
f32 inv_i1;
|
|
|
|
struct v2 normal; /* Normal vector of collision from e0 -> e1 */
|
|
u64 last_iteration;
|
|
struct phys_contact_point points[2];
|
|
u32 num_points;
|
|
|
|
f32 friction;
|
|
|
|
struct math_spring_result softness;
|
|
f32 pushout_velocity;
|
|
};
|
|
|
|
struct phys_collision_debug {
|
|
struct entity_handle e0;
|
|
struct entity_handle e1;
|
|
struct collider_collision_points_result res;
|
|
|
|
struct phys_contact_point points[2];
|
|
u32 num_points;
|
|
|
|
struct v2 closest0;
|
|
struct v2 closest1;
|
|
|
|
struct xform xf0;
|
|
struct xform xf1;
|
|
};
|
|
|
|
struct phys_collision_data_array phys_create_and_update_contacts(struct arena *arena, struct phys_ctx *ctx, f32 elapsed_dt, u64 phys_iteration);
|
|
void phys_prepare_contacts(struct phys_ctx *ctx, u64 phys_iteration);
|
|
void phys_warm_start_contacts(struct phys_ctx *ctx);
|
|
void phys_solve_contacts(struct phys_ctx *ctx, f32 dt, b32 apply_bias);
|
|
|
|
/* ========================== *
|
|
* Motor joint
|
|
* ========================== */
|
|
|
|
struct phys_motor_joint_def {
|
|
struct entity_handle e0;
|
|
struct entity_handle e1;
|
|
f32 correction_rate;
|
|
f32 max_force;
|
|
f32 max_torque;
|
|
};
|
|
|
|
struct phys_motor_joint {
|
|
struct entity_handle e0;
|
|
struct entity_handle e1;
|
|
f32 correction_rate;
|
|
f32 max_force;
|
|
f32 max_torque;
|
|
|
|
f32 inv_m0;
|
|
f32 inv_m1;
|
|
f32 inv_i0;
|
|
f32 inv_i1;
|
|
|
|
struct v2 linear_impulse;
|
|
f32 angular_impulse;
|
|
|
|
struct v2 point_local_e0;
|
|
struct v2 point_local_e1;
|
|
|
|
struct xform linear_mass_xf;
|
|
f32 angular_mass;
|
|
};
|
|
|
|
struct phys_motor_joint motor_joint_from_def(struct phys_motor_joint_def def);
|
|
void phys_prepare_motor_joints(struct phys_ctx *ctx);
|
|
void phys_warm_start_motor_joints(struct phys_ctx *ctx);
|
|
void phys_solve_motor_joints(struct phys_ctx *ctx, f32 dt);
|
|
|
|
/* ========================== *
|
|
* Mouse joint
|
|
* ========================== */
|
|
|
|
struct phys_mouse_joint {
|
|
struct entity_handle target;
|
|
struct v2 point_local_start;
|
|
struct v2 point_local_end;
|
|
struct math_spring_result linear_softness;
|
|
struct math_spring_result angular_softness;
|
|
f32 max_force;
|
|
|
|
f32 inv_m;
|
|
f32 inv_i;
|
|
|
|
struct v2 linear_impulse;
|
|
f32 angular_impulse;
|
|
|
|
struct xform linear_mass_xf;
|
|
};
|
|
|
|
void phys_create_mouse_joints(struct phys_ctx *ctx);
|
|
void phys_prepare_mouse_joints(struct phys_ctx *ctx);
|
|
void phys_warm_start_mouse_joints(struct phys_ctx *ctx);
|
|
void phys_solve_mouse_joints(struct phys_ctx *ctx, f32 dt);
|
|
|
|
/* ========================== *
|
|
* Integration
|
|
* ========================== */
|
|
|
|
void phys_integrate_forces(struct phys_ctx *ctx, f32 dt);
|
|
void phys_integrate_velocities(struct phys_ctx *ctx, f32 dt);
|
|
|
|
/* ========================== *
|
|
* Earliest time of impact
|
|
* ========================== */
|
|
|
|
f32 phys_determine_earliest_toi_for_bullets(struct phys_ctx *ctx, f32 step_dt, f32 tolerance, u32 max_iterations);
|
|
|
|
/* ========================== *
|
|
* Space
|
|
* ========================== */
|
|
|
|
void phys_update_aabbs(struct phys_ctx *ctx);
|
|
|
|
/* ========================== *
|
|
* Step
|
|
* ========================== */
|
|
|
|
/* Returns phys iteration to be fed into next step. Supplied iteration must be > 0. */
|
|
u64 phys_step(struct phys_ctx *ctx, f32 timestep, u64 phys_iteration);
|
|
|
|
#endif
|