From 147ecb98ce2d6a2b24b0d86436913a46888dea84 Mon Sep 17 00:00:00 2001 From: hgn Date: Sat, 26 Nov 2022 20:11:58 +0000 Subject: [PATCH 1/1] grind phys --- maps_src/mp_gridmap.mdl | Bin 644192 -> 690960 bytes player.h | 16 +- player_animation.h | 18 +- player_physics.h | 445 +++++++++++++++++++++++++++------------- 4 files changed, 330 insertions(+), 149 deletions(-) diff --git a/maps_src/mp_gridmap.mdl b/maps_src/mp_gridmap.mdl index 2b2d2e56f23c3528cf55f2e22dfbfebe2fba881f..04238034f13e29f12ba4ac066ed1cf9f5555b084 100644 GIT binary patch delta 55058 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 Pxqxz~Pu(1TxY+*zth4$< delta 7117 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, phys->rb.v, 0.05f, phys->vl ); + player.fgrind = vg_lerpf( player.fgrind, phys->grind, vg.time_delta ); + float yaw = atan2f( phys->vl[0], -phys->vl[2] ), - pitch = atan2f( -phys->vl[1], - sqrtf( - phys->vl[0]*phys->vl[0] + phys->vl[2]*phys->vl[2] - )) * 0.7f; + pitch = atan2f + ( + -phys->vl[1], + sqrtf + ( + phys->vl[0]*phys->vl[0] + phys->vl[2]*phys->vl[2] + ) + ) + * 0.7f + vg_lerpf( 0.30f, 0.90f, player.fgrind ); player.angles[0] = yaw; - player.angles[1] = vg_lerpf( player.angles[1], pitch + 0.30f, - player.fonboard ); + player.angles[1] = vg_lerpf( player.angles[1], pitch, player.fonboard ); /* Camera shake */ static v2f shake_damp = {0.0f,0.0f}; diff --git a/player_physics.h b/player_physics.h index 41adc1e..52c51da 100644 --- a/player_physics.h +++ b/player_physics.h @@ -21,11 +21,6 @@ VG_STATIC void player_start_air(void) { struct player_phys *phys = &player.phys; - if( phys->in_air ) - return; - - phys->in_air = 1; - float pstep = VG_TIMESTEP_FIXED * 10.0f; float best_velocity_delta = -9999.9f; float k_bias = 0.96f; @@ -112,6 +107,33 @@ VG_STATIC void player_start_air(void) } } + +VG_STATIC void player_physics_control_passive(void) +{ + struct player_phys *phys = &player.phys; + float grabt = player.input_grab->axis.value; + + if( grabt > 0.5f ) + { + v2_muladds( phys->grab_mouse_delta, vg.mouse_delta, 0.02f, + phys->grab_mouse_delta ); + v2_normalize_clamp( phys->grab_mouse_delta ); + } + else + v2_zero( phys->grab_mouse_delta ); + + phys->grab = vg_lerpf( phys->grab, grabt, 0.14f ); + player.phys.pushing = 0.0f; + + if( !phys->jump_charge || phys->in_air ) + { + phys->jump -= k_jump_charge_speed * VG_TIMESTEP_FIXED; + } + + phys->jump_charge = 0; + phys->jump = vg_clampf( phys->jump, 0.0f, 1.0f ); +} + /* * Main friction interface model */ @@ -186,6 +208,60 @@ VG_STATIC void player_physics_control(void) steer_scaled = vg_signf(steer) * powf(steer,2.0f) * k_steer_ground; phys->iY -= steer_scaled * VG_TIMESTEP_FIXED; + + if( !phys->jump_charge && phys->jump > 0.2f ) + { + v3f jumpdir; + + /* Launch more up if alignment is up else improve velocity */ + float aup = fabsf(v3_dot( (v3f){0.0f,1.0f,0.0f}, phys->rb.up )), + mod = 0.5f, + dir = mod + aup*(1.0f-mod); + + v3_copy( phys->rb.v, jumpdir ); + v3_normalize( jumpdir ); + v3_muls( jumpdir, 1.0f-dir, jumpdir ); + v3_muladds( jumpdir, phys->rb.up, dir, jumpdir ); + v3_normalize( jumpdir ); + + float force = k_jump_force*phys->jump; + v3_muladds( phys->rb.v, jumpdir, force, phys->rb.v ); + phys->jump = 0.0f; + + player.jump_time = vg.time; + + /* TODO: Move to audio file */ + audio_lock(); + audio_player_set_flags( &audio_player_extra, AUDIO_FLAG_SPACIAL_3D ); + audio_player_set_position( &audio_player_extra, phys->rb.co ); + audio_player_set_vol( &audio_player_extra, 20.0f ); + audio_player_playclip( &audio_player_extra, &audio_jumps[rand()%2] ); + audio_unlock(); + } +} + +VG_STATIC void player_physics_control_grind(void) +{ + struct player_phys *phys = &player.phys; + v2f steer = { player.input_js1h->axis.value, + player.input_js1v->axis.value }; + + float l2 = v2_length2( steer ); + if( l2 > 1.0f ) + v2_muls( steer, 1.0f/sqrtf(l2), steer ); + + phys->iY -= steer[0] * k_steer_air * VG_TIMESTEP_FIXED; + + float iX = steer[1] * phys->reverse * k_steer_air * VG_TIMESTEP_FIXED; + + static float siX = 0.0f; + siX = vg_lerpf( siX, iX, k_steer_air_lerp ); + + v4f rotate; + q_axis_angle( rotate, phys->rb.right, siX ); + q_mul( rotate, phys->rb.q, phys->rb.q ); + + phys->slip = 0.0f; } /* @@ -239,7 +315,7 @@ VG_STATIC void player_physics_control_air(void) limiter *= limiter; limiter = 1.0f-limiter; - if( angle < 0.99f ) + if( fabsf(angle) < 0.99f ) { v4f correction; q_axis_angle( correction, axis, @@ -515,38 +591,137 @@ VG_STATIC void player_grind(void) vg_line_cross( closest, 0xff000000, 0.3f ); vg_line( edge->p0, edge->p1, 0xff000000 ); - return; + v3f grind_delta; + v3_sub( closest, phys->rb.co, grind_delta ); + + float p = v3_dot( phys->rb.forward, grind_delta ); + v3_muladds( grind_delta, phys->rb.forward, -p, grind_delta ); + + float a = vg_maxf( 0.0f, 4.0f-v3_dist2( closest, phys->rb.co ) ); + v3_muladds( phys->rb.v, grind_delta, a*0.2f, phys->rb.v ); +} + +VG_STATIC int player_update_grind_collision( rb_ct *contact ) +{ + struct player_phys *phys = &player.phys; - idx = bh_closest_point( world.geo_bh, phys->rb.co, closest, INFINITY ); - vg_line( phys->rb.co, closest, 0xff000000 ); - vg_line_cross( closest, 0xff000000, 0.3f ); + bh_iter it; + bh_iter_init( 0, &it ); + + boxf region; + + v3f p0, p1, c0, c1; + v3_muladds( phys->rb.co, phys->rb.forward, 0.5f, p0 ); + v3_muladds( phys->rb.co, phys->rb.forward, -0.5f, p1 ); + v3_muladds( p0, phys->rb.up, 0.125f, p0 ); + v3_muladds( p1, phys->rb.up, 0.125f, p1 ); + + box_init_inf( region ); + box_addpt( region, p0 ); + box_addpt( region, p1 ); - idx = world.scene_geo->arrindices[ idx * 3 ]; - struct world_material *mat = world_tri_index_material( idx ); + float const k_r = 0.25f; + v3_add( (v3f){ k_r, k_r, k_r}, region[1], region[1] ); + v3_add( (v3f){-k_r,-k_r,-k_r}, region[0], region[0] ); + + vg_line( p0, p1, 0xff0000ff ); + vg_line_boxf( region, 0xff0000ff ); - if( mat->info.flags & k_material_flag_grind_surface ) + float closest = k_r*k_r; + struct grind_edge *closest_edge = NULL; + + int idx; + while( bh_next( world.grind_bh, &it, region, &idx ) ) { - v3f grind_delta; - v3_sub( closest, phys->rb.co, grind_delta ); - - float p = v3_dot( phys->rb.forward, grind_delta ); - v3_muladds( grind_delta, phys->rb.forward, -p, grind_delta ); - - float a = vg_maxf( 0.0f, 4.0f-v3_dist2( closest, phys->rb.co ) ); - v3_muladds( phys->rb.v, grind_delta, a*0.2f, phys->rb.v ); + struct grind_edge *edge = &world.grind_edges[ idx ]; + + float s,t; + v3f pa, pb; + + float d2 = + closest_segment_segment( p0, p1, edge->p0, edge->p1, &s,&t, pa, pb ); + + if( d2 < closest ) + { + closest = d2; + closest_edge = edge; + v3_copy( pa, c0 ); + v3_copy( pb, c1 ); + } } + + if( closest_edge ) + { + vg_line_cross( c0, 0xff000000, 0.1f ); + vg_line_cross( c1, 0xff000000, 0.1f ); + vg_line( c0, c1, 0xff000000 ); + + v3f delta; + v3_sub( c1, c0, delta ); + + if( v3_dot( delta, phys->rb.up ) > 0.0f ) + { + v3_copy( delta, contact->n ); + float l = v3_length( contact->n ); + v3_muls( contact->n, 1.0f/l, contact->n ); + contact->p = l; + contact->type = k_contact_type_edge; + contact->element_id = 0; + v3_copy( c1, contact->co ); + contact->rba = &player.phys.rb; + contact->rbb = &world.rb_geo; + + v3f edge_dir, axis_dir; + v3_sub( closest_edge->p1, closest_edge->p0, edge_dir ); + v3_normalize( edge_dir ); + v3_cross( (v3f){0.0f,1.0f,0.0f}, edge_dir, axis_dir ); + v3_cross( edge_dir, axis_dir, contact->n ); + + return 1; + } + else + return -1; + } + + return 0; + +#if 0 + v3f closest; + int idx = bh_closest_point( world.grind_bh, phys->rb.co, closest, INFINITY ); + if( idx != -1 ) + { + struct grind_edge *edge = &world.grind_edges[ idx ]; + + vg_line( phys->rb.co, closest, 0xff000000 ); + vg_line_cross( closest, 0xff000000, 0.3f ); + vg_line( edge->p0, edge->p1, 0xff000000 ); + + v3f delta; + v3_sub( closest, phys->rb.co, delta ); + + if( v3_length2(delta) < 0.5f*0.5f ) + { + v3_copy( closest, phys->rb.co ); + + v3f line_dir; + v3_sub( edge->p1, edge->p0, line_dir ); + v3_normalize( line_dir ); + + float p = v3_dot( phys->rb.v, line_dir ); + v3_muls( line_dir, p, phys->rb.v ); + phys->grind = 1; + } + else + phys->grind = 0; + } +#endif } -/* - * Physics collision detection, and control - */ -VG_STATIC void player_physics(void) +/* Manifold must be able to hold at least 64 elements */ +VG_STATIC int player_update_collision_manifold( rb_ct *manifold ) { struct player_phys *phys = &player.phys; - /* - * Update collision fronts - */ - + rigidbody *rbf = &player.collide_front, *rbb = &player.collide_back; @@ -570,7 +745,6 @@ VG_STATIC void player_physics(void) rb_debug( rbf, 0xff00ffff ); rb_debug( rbb, 0xffffff00 ); - rb_ct manifold[64]; int len_f = 0, len_b = 0; @@ -595,14 +769,7 @@ VG_STATIC void player_physics(void) } len_b = rb_manifold_apply_filtered( man_b, len_b ); - int len = len_f+len_b; - - player_grind(); - - boxf bax; - v3_sub( phys->rb.co, (v3f){2.0f,2.0f,2.0f}, bax[0] ); - v3_add( phys->rb.co, (v3f){2.0f,2.0f,2.0f}, bax[1] ); - +#if 0 /* * Preprocess collision points, and create a surface picture. * we want contacts that are within our 'capsule's internal line to be @@ -623,33 +790,79 @@ VG_STATIC void player_physics(void) v3_normalize( manifold[i].n ); } } +#endif - rb_presolve_contacts( manifold, len ); - v3f surface_avg = {0.0f, 0.0f, 0.0f}; + return len_f + len_b; +} + +VG_STATIC void player_adhere_ground( rb_ct *manifold, int len ) +{ + struct player_phys *phys = &player.phys; + int was_in_air = phys->in_air; - if( !len ) + v3f surface_avg; + v3_zero( surface_avg ); + + if( len == 0 ) { - player_start_air(); + phys->lift_frames ++; + + if( phys->lift_frames >= 8 ) + phys->in_air = 1; } else { for( int i=0; irb.v, surface_avg ) > 0.5f ) + + if( v3_dot( phys->rb.v, surface_avg ) > 0.7f ) { - player_start_air(); + phys->lift_frames ++; + + if( phys->lift_frames >= 8 ) + phys->in_air = 1; } else { phys->in_air = 0; + phys->lift_frames = 0; + v3f projected, axis; + + float const DOWNFORCE = -k_downforce*VG_TIMESTEP_FIXED; + v3_muladds( phys->rb.v, phys->rb.up, DOWNFORCE, phys->rb.v ); + + float d = v3_dot( phys->rb.forward, surface_avg ); + v3_muladds( surface_avg, phys->rb.forward, -d, projected ); + v3_normalize( projected ); + + float angle = v3_dot( phys->rb.up, projected ); + v3_cross( phys->rb.up, projected, axis ); + + v3f p0, p1; + v3_add( phys->rb.co, projected, p0 ); + v3_add( phys->rb.co, phys->rb.up, p1 ); + vg_line( phys->rb.co, p0, 0xff00ff00 ); + vg_line( phys->rb.co, p1, 0xff000fff ); + + if( fabsf(angle) < 0.999f ) + { + v4f correction; + q_axis_angle( correction, axis, + acosf(angle)*4.0f*VG_TIMESTEP_FIXED ); + q_mul( correction, phys->rb.q, phys->rb.q ); + } } } + if( !was_in_air && phys->in_air ) + player_start_air(); +} + +VG_STATIC void player_collision_response( rb_ct *manifold, int len ) +{ + struct player_phys *phys = &player.phys; + for( int j=0; j<5; j++ ) { for( int i=0; irb.up, impulse ), - wx = v3_dot( phys->rb.right, impulse )*1.5f; + wx = v3_dot( phys->rb.right, impulse )*1.8f; v3_muladds( phys->rb.w, phys->rb.up, wy, phys->rb.w ); v3_muladds( phys->rb.w, phys->rb.right, wx, phys->rb.w ); } } - - float grabt = player.input_grab->axis.value; - - if( grabt > 0.5f ) - { - v2_muladds( phys->grab_mouse_delta, vg.mouse_delta, 0.02f, - phys->grab_mouse_delta ); - v2_normalize_clamp( phys->grab_mouse_delta ); - } - else - v2_zero( phys->grab_mouse_delta ); - - phys->grab = vg_lerpf( phys->grab, grabt, 0.14f ); - player.phys.pushing = 0.0f; - - if( !phys->in_air ) - { - v3f projected, axis; - - float d = v3_dot( phys->rb.forward, surface_avg ); - v3_muladds( surface_avg, phys->rb.forward, -d, projected ); - v3_normalize( projected ); - - float angle = v3_dot( phys->rb.up, projected ); - v3_cross( phys->rb.up, projected, axis ); - - v3f p0, p1; - v3_add( phys->rb.co, projected, p0 ); - v3_add( phys->rb.co, phys->rb.up, p1 ); - vg_line( phys->rb.co, p0, 0xff00ff00 ); - vg_line( phys->rb.co, p1, 0xff000fff ); - - if( fabsf(angle) < 0.999f ) - { - v4f correction; - q_axis_angle( correction, axis, acosf(angle)*4.0f*VG_TIMESTEP_FIXED ); - q_mul( correction, phys->rb.q, phys->rb.q ); - } - - float const DOWNFORCE = -k_downforce*VG_TIMESTEP_FIXED; - v3_muladds( phys->rb.v, phys->rb.up, DOWNFORCE, phys->rb.v ); - - player_physics_control(); - - if( !phys->jump_charge && phys->jump > 0.2f ) - { - v3f jumpdir; - - /* Launch more up if alignment is up else improve velocity */ - float aup = fabsf(v3_dot( (v3f){0.0f,1.0f,0.0f}, phys->rb.up )), - mod = 0.5f, - dir = mod + aup*(1.0f-mod); - - v3_copy( phys->rb.v, jumpdir ); - v3_normalize( jumpdir ); - v3_muls( jumpdir, 1.0f-dir, jumpdir ); - v3_muladds( jumpdir, phys->rb.up, dir, jumpdir ); - v3_normalize( jumpdir ); - - float force = k_jump_force*phys->jump; - v3_muladds( phys->rb.v, jumpdir, force, phys->rb.v ); - phys->jump = 0.0f; - - player.jump_time = vg.time; - - /* TODO: Move to audio file */ - audio_lock(); - audio_player_set_flags( &audio_player_extra, AUDIO_FLAG_SPACIAL_3D ); - audio_player_set_position( &audio_player_extra, phys->rb.co ); - audio_player_set_vol( &audio_player_extra, 20.0f ); - audio_player_playclip( &audio_player_extra, &audio_jumps[rand()%2] ); - audio_unlock(); - } - } - else - { - player_physics_control_air(); - } - - if( !phys->jump_charge ) - { - phys->jump -= k_jump_charge_speed * VG_TIMESTEP_FIXED; - } - - phys->jump_charge = 0; - phys->jump = vg_clampf( phys->jump, 0.0f, 1.0f ); } VG_STATIC void player_save_frame(void) @@ -821,13 +948,55 @@ VG_STATIC void player_do_motion(void) } } - v3f prevco; v3_copy( phys->rb.co, prevco ); if( phys->on_board ) { - player_physics(); + rb_ct manifold[72]; + int len = player_update_collision_manifold( manifold ); + int grind_col = player_update_grind_collision( &manifold[len] ); + + if( grind_col ) + { + phys->grind = 1; + v3f up = { 0.0f, 1.0f, 0.0f }; + float angle = v3_dot( phys->rb.up, up ); + v3f axis; + v3_cross( phys->rb.up, up, axis ); + + if( fabsf(angle) < 0.99f ) + { + v4f correction; + q_axis_angle( correction, axis, + VG_TIMESTEP_FIXED * 10.0f * acosf(angle) ); + q_mul( correction, phys->rb.q, phys->rb.q ); + } + + float const DOWNFORCE = -k_downforce*2.0f*VG_TIMESTEP_FIXED; + v3_muladds( phys->rb.v, phys->rb.up, DOWNFORCE, phys->rb.v ); + } + else + { + phys->grind = 0; + player_adhere_ground( manifold, len ); + } + + rb_presolve_contacts( manifold, len+ VG_MAX(0,grind_col) ); + player_collision_response( manifold, len+ VG_MAX(0,grind_col) ); + + player_physics_control_passive(); + + if( grind_col ) + player_physics_control_grind(); + else + { + if( phys->in_air ) + player_physics_control_air(); + else + player_physics_control(); + } + player_integrate(); } else -- 2.25.1