allow reset on death
[carveJwlIkooP6JGAAIwe30JlM.git] / player_physics.h
index 80a07b2d450f54cd2d5e03c85e534d702ad8c0ad..db7105d1ed246bbfe95947a7612243dee5ca7541 100644 (file)
@@ -197,6 +197,9 @@ VG_STATIC void player_physics_control_passive(void)
       v2_muladds( phys->grab_mouse_delta, vg.mouse_delta, 0.02f, 
                   phys->grab_mouse_delta );
       v2_normalize_clamp( phys->grab_mouse_delta );
+
+      if( freecam )
+         v2_zero( phys->grab_mouse_delta );
    }
    else
       v2_zero( phys->grab_mouse_delta );
@@ -367,6 +370,12 @@ VG_STATIC void player_physics_control_air(void)
    float time_to_impact = 0.0f;
    float limiter = 1.0f;
 
+   struct grind_edge *best_grind = NULL;
+   float closest_grind = INFINITY;
+
+   v3f target_normal = { 0.0f, 1.0f, 0.0f };
+   int has_target = 0;
+
    for( int i=0; i<50; i++ )
    {
       v3_copy( pco, pco1 );
@@ -380,34 +389,51 @@ VG_STATIC void player_physics_control_air(void)
       v3_sub( pco, pco1, vdir );
       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 ) )
+      {
+         vg_line( ge->p0, ge->p1, 0xff0000ff );
+         vg_line_cross( pco, 0xff0000ff, 0.25f );
+         has_target = 1;
+         break;
+      }
       
       float orig_dist = contact.dist;
-      if( ray_world( pco1, vdir, &contact ))
+      if( ray_world( pco1, vdir, &contact ) )
       {
-         float angle = v3_dot( phys->rb.up, contact.normal );
-         v3f axis; 
-         v3_cross( phys->rb.up, contact.normal, axis );
-
+         v3_copy( contact.normal, target_normal );
+         has_target = 1;
          time_to_impact += (contact.dist/orig_dist)*pstep;
-         limiter = vg_minf( 5.0f, time_to_impact )/5.0f;
-         limiter = 1.0f-limiter;
-         limiter *= limiter;
-         limiter = 1.0f-limiter;
-
-         if( fabsf(angle) < 0.99f )
-         {
-            v4f correction;
-            q_axis_angle( correction, axis, 
-                  acosf(angle)*(1.0f-limiter)*3.0f*VG_TIMESTEP_FIXED );
-            q_mul( correction, phys->rb.q, phys->rb.q );
-         }
-
          vg_line_cross( contact.pos, 0xffff0000, 0.25f );
          break;
       }
       time_to_impact += pstep;
    }
 
+   if( has_target )
+   {
+      float angle = v3_dot( phys->rb.up, target_normal );
+      v3f axis; 
+      v3_cross( phys->rb.up, target_normal, axis );
+
+      limiter = vg_minf( 5.0f, time_to_impact )/5.0f;
+      limiter = 1.0f-limiter;
+      limiter *= limiter;
+      limiter = 1.0f-limiter;
+
+      if( fabsf(angle) < 0.99f )
+      {
+         v4f correction;
+         q_axis_angle( correction, axis, 
+                        acosf(angle)*(1.0f-limiter)*3.0f*VG_TIMESTEP_FIXED );
+         q_mul( correction, phys->rb.q, phys->rb.q );
+      }
+   }
+
    v2f steer = { player.input_js1h->axis.value,
                  player.input_js1v->axis.value };
 
@@ -479,6 +505,9 @@ VG_STATIC void player_walk_physics(void)
 
    v2f walk = { player.input_walkh->axis.value,
                 player.input_walkv->axis.value };
+
+   if( freecam )
+      v2_zero( walk );
    
    if( v2_length2(walk) > 0.001f )
       v2_normalize_clamp( walk );
@@ -706,12 +735,9 @@ VG_STATIC int player_update_grind_collision( rb_ct *contact )
       v3f delta;
       v3_sub( c1, c0, delta );
 
-      if( v3_dot( delta, phys->rb.up ) > 0.0f )
+      if( v3_dot( delta, phys->rb.up ) > 0.0001f )
       {
-         v3_copy( delta, contact->n );
-         float l = v3_length( contact->n );
-         v3_muls( contact->n, 1.0f/l, contact->n );
-         contact->p = l;
+         contact->p = v3_length( delta );
          contact->type = k_contact_type_edge;
          contact->element_id = 0;
          v3_copy( c1, contact->co );
@@ -724,6 +750,8 @@ VG_STATIC int player_update_grind_collision( rb_ct *contact )
          v3_cross( (v3f){0.0f,1.0f,0.0f}, edge_dir, axis_dir );
          v3_cross( edge_dir, axis_dir, contact->n );
 
+         vg_info( "%f %f\n", v3_length( contact->n ), contact->p );
+
          return 1;
       }
       else
@@ -973,33 +1001,60 @@ 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) );
 
@@ -1065,6 +1120,15 @@ VG_STATIC void player_do_motion(void)
          m3x3_mulv( gate->transport, phys->m, phys->m );
          m3x3_mulv( gate->transport, phys->bob, phys->bob );
 
+         /* Pre-emptively edit the camera matrices so that the motion vectors 
+          * are correct */
+         m4x3f transport_i;
+         m4x4f transport_4;
+         m4x3_invert_affine( gate->transport, transport_i );
+         m4x3_expand( transport_i, transport_4 );
+         m4x4_mul( main_camera.mtx.pv, transport_4, main_camera.mtx.pv );
+         m4x4_mul( main_camera.mtx.v, transport_4, main_camera.mtx.v );
+
          v4f transport_rotation;
          m3x3_q( gate->transport, transport_rotation );
          q_mul( transport_rotation, phys->rb.q, phys->rb.q );
@@ -1100,26 +1164,20 @@ VG_STATIC void player_freecam(void)
 {
    player_mouseview();
 
-   float movespeed = fc_speed;
+   float movespeed = fc_speed * VG_TIMESTEP_FIXED;
    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 };
 
-   /* TODO */
-#if 0
-   if( vg_get_button( "forward" ) )
-      v3_muladds( move_vel, lookdir, VG_TIMESTEP_FIXED * movespeed, move_vel );
-   if( vg_get_button( "back" ) )
-      v3_muladds( move_vel, lookdir, VG_TIMESTEP_FIXED *-movespeed, move_vel );
-   if( vg_get_button( "left" ) )
-      v3_muladds( move_vel, sidedir, VG_TIMESTEP_FIXED *-movespeed, move_vel );
-   if( vg_get_button( "right" ) )
-      v3_muladds( move_vel, sidedir, VG_TIMESTEP_FIXED * movespeed, move_vel );
-#endif
+   v2f steer = { player.input_js1h->axis.value,
+                 player.input_js1v->axis.value };
+
+   v3_muladds( move_vel, sidedir,  movespeed*steer[0], move_vel );
+   v3_muladds( move_vel, lookdir, -movespeed*steer[1], move_vel );
 
    v3_muls( move_vel, 0.7f, move_vel );
    v3_add( move_vel, player.camera_pos, player.camera_pos );
@@ -1167,6 +1225,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;