time of impact seemingly working

This commit is contained in:
jacob 2025-01-06 12:20:06 -06:00
parent 1e81a7ea41
commit dd4b05cbd1
3 changed files with 124 additions and 37 deletions

View File

@ -10,7 +10,9 @@ u32 collider_debug_steps = U32_MAX;
INTERNAL void _dbgbreakable(void)
{
#if RTC
DEBUGBREAKABLE;
#endif
}
#define DBGSTEP \

View File

@ -36,7 +36,7 @@
#define GAME_PHYSICS_ENABLE_WARM_STARTING 1
#define GAME_PHYSICS_ENABLE_RELAXATION 1
#define USER_DRAW_MENKOWSKI 1
#define USER_DRAW_MENKOWSKI 0
#define GAME_PHYSICS_ENABLE_COLLISION 1
#define GAME_SPAWN_TESTENT 0
#define GAME_PLAYER_AIM 1
@ -53,8 +53,7 @@
#define USER_INTERP_OFFSET_TICK_RATIO 1.1
#define USER_INTERP_ENABLED 1
//#define COLLIDER_DEBUG RTC
#define COLLIDER_DEBUG 1
#define COLLIDER_DEBUG RTC
/* ========================== *
* Settings

View File

@ -291,7 +291,9 @@ INTERNAL void reset_world(void)
/* Release world */
world_release(&G.tick);
/* Release bookkeeping */
#if COLLIDER_DEBUG
arena_release(&G.collision_debug_lookup.arena);
#endif
contact_lookup_release(&G.contact_lookup);
}
@ -1462,12 +1464,9 @@ INTERNAL void integrate_positions_from_velocities(f32 dt)
* TESTING TOI
* ========================== */
#if 0
/* Takes 2 shapes and their xforms at t=0 and t=1.
* Returns time of impact in range [0, 1]. */
INTERNAL f32 toi(struct collider_shape c0, struct collider_shape c1,
INTERNAL f32 toi(struct collider_shape *c0, struct collider_shape *c1,
struct xform xf0_t0, struct xform xf1_t0,
struct xform xf0_t1, struct xform xf1_t1,
f32 tolerance)
@ -1476,7 +1475,7 @@ INTERNAL f32 toi(struct collider_shape c0, struct collider_shape c1,
struct v2 dir;
struct v2 dir_neg;
{
struct collider_closest_points_result closest_points_res = collider_closest_points(&c0, &c1, xf0_t0, xf1_t0);
struct collider_closest_points_result closest_points_res = collider_closest_points(c0, c1, xf0_t0, xf1_t0);
if (closest_points_res.colliding) {
/* Shapes are penetrating at t=0 */
return 0;
@ -1488,8 +1487,8 @@ INTERNAL f32 toi(struct collider_shape c0, struct collider_shape c1,
/* Safety check that shapes penetrate at t=1 */
f32 sep;
{
struct v2 p0 = collider_support_point(&c0, xf0_t1, dir);
struct v2 p1 = collider_support_point(&c1, xf1_t1, dir_neg);
struct v2 p0 = collider_support_point(c0, xf0_t1, dir);
struct v2 p1 = collider_support_point(c1, xf1_t1, dir_neg);
sep = v2_dot(dir, v2_sub(p1, p0));
if (sep > tolerance) {
/* Shapes are not penetrating at t=1 */
@ -1505,8 +1504,8 @@ INTERNAL f32 toi(struct collider_shape c0, struct collider_shape c1,
struct xform xf0 = xform_lerp(xf0_t0, xf0_t1, t);
struct xform xf1 = xform_lerp(xf1_t0, xf1_t1, t);
struct v2 p0 = collider_support_point(&c0, xf0, dir);
struct v2 p1 = collider_support_point(&c1, xf1, dir_neg);
struct v2 p0 = collider_support_point(c0, xf0, dir);
struct v2 p1 = collider_support_point(c1, xf1, dir_neg);
sep = v2_dot(dir, v2_sub(p1, p0));
@ -1516,12 +1515,90 @@ INTERNAL f32 toi(struct collider_shape c0, struct collider_shape c1,
} else {
t1 = t;
}
t = (t1 - t0) / 2.0;
t = (t1 + t0) / 2.0;
}
return t;
}
#endif
INTERNAL f32 determine_earliest_toi(f32 dt, f32 tolerance)
{
__prof;
f32 smallest_t = 1;
struct entity_store *store = G.tick.entity_store;
//struct entity *root = G.root;
for (u64 e0_index = 0; e0_index < store->reserved; ++e0_index) {
struct entity *e0 = &store->entities[e0_index];
if (!entity_is_valid_and_active(e0)) continue;
if (!(entity_has_prop(e0, ENTITY_PROP_PHYSICAL_DYNAMIC) || entity_has_prop(e0, ENTITY_PROP_PHYSICAL_KINEMATIC))) continue;
if (e0->local_collider.count <= 0) continue;
struct collider_shape e0_collider = e0->local_collider;
struct xform e0_xf_t0 = entity_get_xform(e0);
struct xform e0_xf_t1 = e0_xf_t0;
{
/* Calculate xform at t=1 */
struct v2 linear_velocity = v2_clamp_len(e0->linear_velocity, GAME_MAX_LINEAR_VELOCITY);
f32 angular_velocity = clamp_f32(e0->angular_velocity, -GAME_MAX_ANGULAR_VELOCITY, GAME_MAX_ANGULAR_VELOCITY);
struct v2 tick_linear_velocity = v2_mul(linear_velocity, dt);
f32 tick_angular_velocity = angular_velocity * dt;
e0_xf_t1.og = v2_add(e0_xf_t1.og, tick_linear_velocity);
e0_xf_t1 = xform_basis_rotated_world(e0_xf_t1, tick_angular_velocity);
}
/* Start e1 index at e0 index + 1 to prevent redundant checks */
for (u64 e1_index = e0_index + 1; e1_index < store->reserved; ++e1_index) {
struct entity *e1 = &store->entities[e1_index];
if (e1 == e0) continue;
if (!entity_is_valid_and_active(e1)) continue;
if (!(entity_has_prop(e1, ENTITY_PROP_PHYSICAL_DYNAMIC) || entity_has_prop(e1, ENTITY_PROP_PHYSICAL_KINEMATIC))) continue;
if (e1->local_collider.count <= 0) continue;
struct collider_shape e1_collider = e1->local_collider;
struct xform e1_xf_t0 = entity_get_xform(e1);
struct xform e1_xf_t1 = e1_xf_t0;
{
/* Calculate xform at t=1 */
struct v2 linear_velocity = v2_clamp_len(e1->linear_velocity, GAME_MAX_LINEAR_VELOCITY);
f32 angular_velocity = clamp_f32(e1->angular_velocity, -GAME_MAX_ANGULAR_VELOCITY, GAME_MAX_ANGULAR_VELOCITY);
struct v2 tick_linear_velocity = v2_mul(linear_velocity, dt);
f32 tick_angular_velocity = angular_velocity * dt;
e1_xf_t1.og = v2_add(e1_xf_t1.og, tick_linear_velocity);
e1_xf_t1 = xform_basis_rotated_world(e1_xf_t1, tick_angular_velocity);
}
f32 t = toi(&e0_collider, &e1_collider, e0_xf_t0, e1_xf_t0, e0_xf_t1, e1_xf_t1, tolerance);
if (t != 0 && t < smallest_t) {
smallest_t = t;
}
}
}
return smallest_t;
}
@ -1672,7 +1749,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
{
struct sprite_sheet_span span = sprite_sheet_get_span(sheet, ent->sprite_span_name);
f64 time_in_frame = ent->animation_time_in_frame + G.tick.dt;
f64 time_in_frame = ent->animation_time_in_frame + dt;
u64 frame_index = ent->animation_frame;
if (frame_index < span.start || frame_index > span.end) {
frame_index = span.start;
@ -2140,7 +2217,14 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
(UNUSED)integrate_positions_from_velocities;
#if 1
{
integrate_velocities_from_forces(dt);
f32 remaining_dt = dt;
while (remaining_dt > 0) {
f32 min_toi = 0.00001f;
f32 tolerance = 0.0001f;
f32 earliest_toi = max_f32(determine_earliest_toi(remaining_dt, tolerance), min_toi);
f32 step_dt = remaining_dt * earliest_toi;
integrate_velocities_from_forces(step_dt);
create_contacts();
create_mouse_joints(game_cmds);
@ -2148,25 +2232,27 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
prepare_motor_joints();
prepare_mouse_joints();
f32 substep_dt = dt / GAME_PHYSICS_SUBSTEPS;
f32 substep_dt = step_dt / GAME_PHYSICS_SUBSTEPS;
for (u32 i = 0; i < GAME_PHYSICS_SUBSTEPS; ++i) {
#if GAME_PHYSICS_ENABLE_WARM_STARTING
#if GAME_PHYSICS_ENABLE_WARM_STARTING
warm_start_contacts();
warm_start_motor_joints();
warm_start_mouse_joints();
#endif
#endif
#if GAME_PHYSICS_ENABLE_COLLISION
#if GAME_PHYSICS_ENABLE_COLLISION
solve_contacts(substep_dt, true);
#endif
#endif
solve_motor_joints(substep_dt);
solve_mouse_joints(substep_dt);
integrate_positions_from_velocities(substep_dt);
#if GAME_PHYSICS_ENABLE_COLLISION && GAME_PHYSICS_ENABLE_RELAXATION
#if GAME_PHYSICS_ENABLE_COLLISION && GAME_PHYSICS_ENABLE_RELAXATION
solve_contacts(substep_dt, false); /* Relaxation */
#endif
#endif
}
remaining_dt -= step_dt;
}
}
#endif