X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=player_physics.h;h=f395953932e19003e93cac528d76c538cb99531e;hb=a1adba47558099cab82aa6d10abdc1dca11d3342;hp=52c51da75257e6a4f92b41d4f48879d53bf4b67b;hpb=147ecb98ce2d6a2b24b0d86436913a46888dea84;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/player_physics.h b/player_physics.h index 52c51da..f395953 100644 --- a/player_physics.h +++ b/player_physics.h @@ -14,6 +14,51 @@ VG_STATIC void apply_gravity( v3f vel, float const timestep ) v3_muladds( vel, gravity, timestep, vel ); } +VG_STATIC struct +grind_edge *player_grind_collect_edge( v3f p0, v3f p1, + v3f c0, v3f c1, float max_dist ) +{ + struct player_phys *phys = &player.phys; + + bh_iter it; + bh_iter_init( 0, &it ); + + boxf region; + + box_init_inf( region ); + box_addpt( region, p0 ); + box_addpt( region, p1 ); + + float k_r = max_dist; + 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] ); + + float closest = k_r*k_r; + struct grind_edge *closest_edge = NULL; + + int idx; + while( bh_next( world.grind_bh, &it, region, &idx ) ) + { + 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 ); + } + } + + return closest_edge; +} + /* * Called when launching into the air to predict and adjust trajectories */ @@ -34,6 +79,10 @@ VG_STATIC void player_start_air(void) for( int m=-3;m<=12; m++ ) { + struct land_log *log = &player.land_log[ player.land_log_count ++ ]; + log->count = 0; + log->colour = 0xff000000; + float vmod = ((float)m / 15.0f)*0.09f; v3f pco, pco1, pv; @@ -55,6 +104,9 @@ VG_STATIC void player_start_air(void) m3x3_mulv( vr, pv, pv ); v3_muladds( pco, pv, pstep, pco ); + struct grind_edge *best_grind = NULL; + float closest_grind = INFINITY; + for( int i=0; i<50; i++ ) { v3_copy( pco, pco1 ); @@ -70,6 +122,20 @@ VG_STATIC void player_start_air(void) contact.dist = v3_length( vdir ); v3_divs( vdir, contact.dist, vdir); + v3f c0, c1; + struct grind_edge *ge = player_grind_collect_edge( pco, pco1, + c0, c1, 0.4f ); + + if( ge && (v3_dot((v3f){0.0f,1.0f,0.0f},vdir) < -0.2f ) ) + { + float d2 = v3_dist2( c0, c1 ); + if( d2 < closest_grind ) + { + closest_grind = d2; + best_grind = ge; + } + } + if( ray_world( pco1, vdir, &contact )) { float land_delta = v3_dot( pv, contact.normal ); @@ -94,14 +160,27 @@ VG_STATIC void player_start_air(void) q_m3x3( vr_q, phys->vr ); } - v3_copy( contact.pos, - player.land_target_log[player.land_log_count] ); - player.land_target_colours[player.land_log_count] = - 0xff000000 | scolour; + v3_copy( contact.pos, log->positions[ log->count ++ ] ); + log->colour = 0xff000000 | scolour; + break; + } - player.land_log_count ++; + v3_copy( pco, log->positions[ log->count ++ ] ); + } - break; + if( best_grind ) + { + log->colour = 0xff0000ff; + + float score = -closest_grind * 0.05f; + + if( score > best_velocity_delta ) + { + best_velocity_delta = score; + + m3x3_copy( vr, phys->vr_pstep ); + q_axis_angle( vr_q, axis, vmod*0.1f ); + q_m3x3( vr_q, phys->vr ); } } } @@ -605,50 +684,18 @@ VG_STATIC int player_update_grind_collision( rb_ct *contact ) { struct player_phys *phys = &player.phys; - 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 ); - 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 ); + struct grind_edge *closest_edge = player_grind_collect_edge( p0, p1, + c0, c1, k_r ); - float closest = k_r*k_r; - struct grind_edge *closest_edge = NULL; - int idx; - while( bh_next( world.grind_bh, &it, region, &idx ) ) - { - 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 ); - } - } + vg_line( p0, p1, 0xff0000ff ); if( closest_edge ) { @@ -684,37 +731,6 @@ VG_STATIC int player_update_grind_collision( rb_ct *contact ) } 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 } /* Manifold must be able to hold at least 64 elements */ @@ -957,38 +973,70 @@ VG_STATIC void player_do_motion(void) int len = player_update_collision_manifold( manifold ); int grind_col = player_update_grind_collision( &manifold[len] ); + static int _grind_col_pre = 0; + 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 ) { + v3f axis; + v3_cross( phys->rb.up, up, axis ); + 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 ); + float const DOWNFORCE = -k_downforce*1.2f*VG_TIMESTEP_FIXED; + v3_muladds( phys->rb.v, manifold[len].n, DOWNFORCE, phys->rb.v ); + m3x3_identity( phys->vr ); + m3x3_identity( phys->vr_pstep ); + + if( !_grind_col_pre ) + { + 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_board[5] ); + audio_unlock(); + } } else { phys->grind = 0; player_adhere_ground( manifold, len ); + + if( _grind_col_pre ) + { + 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_board[6] ); + audio_unlock(); + } } + _grind_col_pre = grind_col; + 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 ) + { + phys->in_air = 0; player_physics_control_grind(); + } else { if( phys->in_air ) @@ -1083,8 +1131,8 @@ VG_STATIC void player_freecam(void) v3f lookdir = { 0.0f, 0.0f, -1.0f }, sidedir = { 1.0f, 0.0f, 0.0f }; - m3x3_mulv( camera_mtx, lookdir, lookdir ); - m3x3_mulv( camera_mtx, sidedir, sidedir ); + m3x3_mulv( main_camera.transform, lookdir, lookdir ); + m3x3_mulv( main_camera.transform, sidedir, sidedir ); static v3f move_vel = { 0.0f, 0.0f, 0.0f }; @@ -1146,6 +1194,13 @@ VG_STATIC int reset_player( int argc, char const *argv[] ) if( !rp ) { vg_error( "No spawn found\n" ); + vg_info( "Player position: %f %f %f\n", player.phys.rb.co[0], + player.phys.rb.co[1], + player.phys.rb.co[2] ); + vg_info( "Player velocity: %f %f %f\n", player.phys.rb.v[0], + player.phys.rb.v[1], + player.phys.rb.v[2] ); + if( !world.spawn_count ) return 0;