From 0b69490b7ced300b028240fe0606b10b39fe08a2 Mon Sep 17 00:00:00 2001 From: hgn Date: Tue, 7 Feb 2023 09:43:58 +0000 Subject: [PATCH] CCD! --- maps_src/mp_gridmap.mdl | Bin 1415664 -> 1423568 bytes player_skate.c | 190 +++++++++++++++++++++++++++++++++------- player_skate.h | 6 +- 3 files changed, 162 insertions(+), 34 deletions(-) diff --git a/maps_src/mp_gridmap.mdl b/maps_src/mp_gridmap.mdl index 7efdc8a2322305c47ddc4001be9ac5a397e9354d..676155a61d3ae5d944bd35154a1a14d29d199fa2 100644 GIT binary patch delta 12037 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.co, player->rb.to_world[2], 0.5f, p0 ); v3_muladds( player->rb.co, player->rb.to_world[2], -0.5f, p1 ); - v3_muladds( p0, player->rb.to_world[1], 0.125f-0.15f, p0 ); - v3_muladds( p1, player->rb.to_world[1], 0.125f-0.15f, p1 ); + v3_muladds( p0, player->rb.to_world[1], 0.08f, p0 ); + v3_muladds( p1, player->rb.to_world[1], 0.08f, p1 ); float const k_r = 0.25f; struct grind_edge *closest_edge = skate_collect_grind_edge( p0, p1, @@ -615,6 +615,8 @@ VG_STATIC int skate_simulate_spring( player_instance *player, /* * Handles connection between the player and the ground + * + * TODO: Must save original velocity to use here */ VG_STATIC void skate_apply_interface_model( player_instance *player, rb_ct *manifold, int len ) @@ -701,6 +703,7 @@ VG_STATIC void skate_apply_interface_model( player_instance *player, float angle = v3_dot( player->rb.to_world[1], projected ); v3_cross( player->rb.to_world[1], projected, axis ); +#if 0 if( fabsf(angle) < 0.9999f ) { v4f correction; @@ -708,6 +711,7 @@ VG_STATIC void skate_apply_interface_model( player_instance *player, acosf(angle)*4.0f*VG_TIMESTEP_FIXED ); q_mul( correction, player->rb.q, player->rb.q ); } +#endif } } } @@ -1061,10 +1065,12 @@ VG_STATIC void skate_collision_response( player_instance *player, */ float wy = v3_dot( player->rb.to_world[1], impulse ) * 0.8f, - wx = v3_dot( player->rb.to_world[0], impulse ) * 1.0f; + wx = v3_dot( player->rb.to_world[0], impulse ) * 1.0f, + wz = v3_dot( player->rb.to_world[2], impulse ) * 2.0f; v3_muladds( player->rb.w, player->rb.to_world[1], wy, player->rb.w ); v3_muladds( player->rb.w, player->rb.to_world[0], wx, player->rb.w ); + v3_muladds( player->rb.w, player->rb.to_world[2], wz, player->rb.w ); } } } @@ -1074,9 +1080,11 @@ VG_STATIC void skate_integrate( player_instance *player ) struct player_skate *s = &player->_skate; /* integrate rigidbody velocities */ +#ifndef SKATE_CCD v3f gravity = { 0.0f, -9.6f, 0.0f }; v3_muladds( player->rb.v, gravity, k_rb_delta, player->rb.v ); v3_muladds( player->rb.co, player->rb.v, k_rb_delta, player->rb.co ); +#endif float decay_rate = 0.5f*0.125f; @@ -1088,6 +1096,7 @@ VG_STATIC void skate_integrate( player_instance *player ) v3_lerp( player->rb.w, (v3f){0.0f,0.0f,0.0f}, decay_rate, player->rb.w ); +#ifndef SKATE_CCD if( v3_length2( player->rb.w ) > 0.0f ) { v4f rotation; @@ -1099,6 +1108,7 @@ VG_STATIC void skate_integrate( player_instance *player ) q_axis_angle( rotation, axis, mag*k_rb_delta ); q_mul( rotation, player->rb.q, player->rb.q ); } +#endif /* integrate steering velocities */ v4f rotate; @@ -1203,72 +1213,186 @@ VG_STATIC void player__skate_update( player_instance *player ) v3_copy( player->rb.co, s->state.prev_pos ); s->state.activity_prev = s->state.activity; - /* Setup colliders */ - m4x3f mtx_front, mtx_back; - m3x3_identity( mtx_front ); - m3x3_identity( mtx_back ); + float l = k_board_length, + w = 0.13f; + + v3f wheel_positions[] = + { + { -w, 0.0f, -l }, + { w, 0.0f, -l }, + { -w, 0.0f, l }, + { w, 0.0f, l }, + }; + + rb_sphere collider; + collider.radius = 0.07f; + + s->substep = k_rb_delta; + +begin_collision:; + +#ifdef SKATE_CCD + + /* calculate transform one step into future */ + v3f future_co; + v4f future_q; + v3_muladds( player->rb.co, player->rb.v, s->substep, future_co ); + + if( v3_length2( player->rb.w ) > 0.0f ) + { + v4f rotation; + v3f axis; + v3_copy( player->rb.w, axis ); + + float mag = v3_length( axis ); + v3_divs( axis, mag, axis ); + q_axis_angle( rotation, axis, mag*s->substep ); + q_mul( rotation, player->rb.q, future_q ); + q_normalize( future_q ); + } + + /* calculate the minimum time we can move */ + float max_time = s->substep, + cast_radius = collider.radius - 0.05f; + + for( int i=0; i<4; i++ ) + { + v3f current, future; + q_mulv( future_q, wheel_positions[i], future ); + v3_add( future, future_co, future ); - skate_get_board_points( player, mtx_front[3], mtx_back[3] ); + q_mulv( player->rb.q, wheel_positions[i], current ); + v3_add( current, player->rb.co, current ); + + float t; /* TODO: ignore lightly grazing normals? */ + v3f n; + if( spherecast_world( current, future, cast_radius, &t, n ) != -1) + { + max_time = vg_minf( max_time, t * s->substep ); + } + } + + /* clamp to a fraction of delta, to prevent locking */ + max_time = vg_minf( vg_maxf( max_time, k_rb_delta*0.025f ), s->substep ); + s->substep_delta = max_time; + + /* integrate */ + v3_muladds( player->rb.co, player->rb.v, s->substep_delta, player->rb.co ); + if( v3_length2( player->rb.w ) > 0.0f ) + { + v4f rotation; + v3f axis; + v3_copy( player->rb.w, axis ); + + float mag = v3_length( axis ); + v3_divs( axis, mag, axis ); + q_axis_angle( rotation, axis, mag*s->substep_delta ); + q_mul( rotation, player->rb.q, player->rb.q ); + } + + rb_update_transform( &player->rb ); + + v3f gravity = { 0.0f, -9.6f, 0.0f }; + v3_muladds( player->rb.v, gravity, s->substep_delta, player->rb.v ); + +#else + + s->substep_delta = k_rb_delta; + +#endif + + s->substep -= s->substep_delta; - s->sphere_back.radius = 0.3f; - s->sphere_front.radius = 0.3f; /* create manifold(s) */ - rb_ct manifold[72], - *interface_manifold = NULL, - *grind_manifold = NULL; + rb_ct manifold[128]; + + int manifold_len = 0, + manifold_front = 0, + manifold_back = 0, + manifold_interface = 0; + + rb_ct *cmanifold = manifold; + + for( int i=0; i<4; i++ ) + { + m4x3f mtx; + m3x3_identity( mtx ); + + m4x3_mulv( player->rb.to_world, wheel_positions[i], mtx[3] ); + + int l = skate_collide_smooth( player, mtx, &collider, cmanifold ); - int - len_front = skate_collide_smooth( player, mtx_front, - &s->sphere_front, manifold ), - len_back = skate_collide_smooth( player, mtx_back, - &s->sphere_back, &manifold[len_front] ), - interface_len = len_front + len_back; + cmanifold += l; + manifold_len += l; + manifold_interface += l; + + if( i<=1 ) + manifold_front ++; + else + manifold_back ++; + } /* try to slap both wheels onto the ground when landing to prevent mega * angular velocities being added */ - if( (s->state.activity == k_skate_activity_air) && (len_front != len_back) ) + if( (s->state.activity == k_skate_activity_air) && + (manifold_front != manifold_back ) ) { v3f trace_from, trace_dir; v3_muls( player->rb.to_world[1], -1.0f, trace_dir ); - if( len_front ) - v3_copy( mtx_back[3], trace_from ); + if( manifold_front ) + v3_copy( (v3f){0.0f,0.0f, k_board_length}, trace_from ); else - v3_copy( mtx_front[3], trace_from ); + v3_copy( (v3f){0.0f,0.0f,-k_board_length}, trace_from ); + m4x3_mulv( player->rb.to_world, trace_from, trace_from ); ray_hit ray; ray.dist = 0.6f; if( ray_world( trace_from, trace_dir, &ray ) ) { - rb_ct *ct = &manifold[ interface_len ]; + rb_ct *ct = cmanifold; v3_copy( ray.pos, ct->co ); v3_copy( ray.normal, ct->n ); ct->p = 0.0f; - interface_len ++; + manifold_len ++; + manifold_interface ++; } } - interface_manifold = manifold; - grind_manifold = manifold + interface_len; - - int grind_len = skate_grind_collide( player, grind_manifold ); + int grind_len = skate_grind_collide( player, cmanifold ); + manifold_len += grind_len; - for( int i=0; ibias = -0.2f * + (s->substep_delta * 3600.0f) + * vg_minf( 0.0f, -ct->p+k_penetration_slop ); + rb_tangent_basis( ct->n, ct->t[0], ct->t[1] ); + ct->norm_impulse = 0.0f; + ct->tangent_impulse[0] = 0.0f; + ct->tangent_impulse[1] = 0.0f; +#else rb_prepare_contact( &manifold[i] ); +#endif rb_debug_contact( &manifold[i] ); } - skate_apply_grind_model( player, grind_manifold, grind_len ); - skate_apply_interface_model( player, manifold, interface_len ); + skate_collision_response( player, manifold, manifold_len ); + + if( s->substep >= 0.0001f ) + goto begin_collision; + + skate_apply_grind_model( player, &manifold[manifold_interface], grind_len ); + skate_apply_interface_model( player, manifold, manifold_interface ); skate_apply_pump_model( player ); skate_apply_cog_model( player ); - skate_collision_response( player, manifold, interface_len + grind_len ); skate_apply_grab_model( player ); skate_apply_friction_model( player ); diff --git a/player_skate.h b/player_skate.h index 1833062..6ace410 100644 --- a/player_skate.h +++ b/player_skate.h @@ -3,6 +3,8 @@ #include "player_api.h" +#define SKATE_CCD + struct player_skate { struct @@ -86,7 +88,6 @@ struct player_skate *anim_push, *anim_push_reverse, *anim_ollie, *anim_ollie_reverse, *anim_grabs, *anim_stop; - rb_sphere sphere_front, sphere_back; v3f board_offset, board_trick_residualv, board_trick_residuald; @@ -101,6 +102,9 @@ struct player_skate blend_jump, blend_airdir; + float substep, + substep_delta; + v2f wobble; float debug_normal_pressure; -- 2.25.1