spherecast predictions
authorhgn <hgodden00@gmail.com>
Sat, 10 Dec 2022 02:39:15 +0000 (02:39 +0000)
committerhgn <hgodden00@gmail.com>
Sat, 10 Dec 2022 02:39:15 +0000 (02:39 +0000)
distq.h
maps_src/mp_mtzero.mdl
player.h
player_physics.h
skaterift.c

diff --git a/distq.h b/distq.h
index 623010f97928dc51d332d44b920e802c88ad3d0e..1ae543690f9065e169f514b5bf240f63623d2171 100644 (file)
--- a/distq.h
+++ b/distq.h
@@ -3,299 +3,5 @@
 
 #include "vg_m.h"
 
 
 #include "vg_m.h"
 
-enum contact_type
-{
-   k_contact_type_default,
-   k_contact_type_disabled,
-   k_contact_type_edge
-};
-
-/*
- * -----------------------------------------------------------------------------
- *                        Closest point functions
- * -----------------------------------------------------------------------------
- */
-
-/* 
- * These closest point tests were learned from Real-Time Collision Detection by 
- * Christer Ericson 
- */
-VG_STATIC float closest_segment_segment( v3f p1, v3f q1, v3f p2, v3f q2, 
-   float *s, float *t, v3f c1, v3f c2)
-{
-   v3f d1,d2,r;
-   v3_sub( q1, p1, d1 );
-   v3_sub( q2, p2, d2 );
-   v3_sub( p1, p2, r );
-
-   float a = v3_length2( d1 ),
-         e = v3_length2( d2 ),
-         f = v3_dot( d2, r );
-
-   const float kEpsilon = 0.0001f;
-
-   if( a <= kEpsilon && e <= kEpsilon )
-   {
-      *s = 0.0f;
-      *t = 0.0f;
-      v3_copy( p1, c1 );
-      v3_copy( p2, c2 );
-
-      v3f v0;
-      v3_sub( c1, c2, v0 );
-
-      return v3_length2( v0 );
-   }
-   
-   if( a<= kEpsilon )
-   {
-      *s = 0.0f;
-      *t = vg_clampf( f / e, 0.0f, 1.0f );
-   }
-   else
-   {
-      float c = v3_dot( d1, r );
-      if( e <= kEpsilon )
-      {
-         *t = 0.0f;
-         *s = vg_clampf( -c / a, 0.0f, 1.0f );
-      }
-      else
-      {
-         float b = v3_dot(d1,d2),
-               d = a*e-b*b;
-
-         if( d != 0.0f )
-         {
-            *s = vg_clampf((b*f - c*e)/d, 0.0f, 1.0f);
-         }
-         else
-         {
-            *s = 0.0f;
-         }
-
-         *t = (b*(*s)+f) / e;
-
-         if( *t < 0.0f )
-         {
-            *t = 0.0f;
-            *s = vg_clampf( -c / a, 0.0f, 1.0f );
-         }
-         else if( *t > 1.0f )
-         {
-            *t = 1.0f;
-            *s = vg_clampf((b-c)/a,0.0f,1.0f);
-         }
-      }
-   }
-
-   v3_muladds( p1, d1, *s, c1 );
-   v3_muladds( p2, d2, *t, c2 );
-
-   v3f v0;
-   v3_sub( c1, c2, v0 );
-   return v3_length2( v0 );
-}
-
-VG_STATIC void closest_point_aabb( v3f p, boxf box, v3f dest )
-{
-   v3_maxv( p, box[0], dest );
-   v3_minv( dest, box[1], dest );
-}
-
-VG_STATIC void closest_point_obb( v3f p, boxf box, 
-                                  m4x3f mtx, m4x3f inv_mtx, v3f dest )
-{
-   v3f local;
-   m4x3_mulv( inv_mtx, p, local );
-   closest_point_aabb( local, box, local );
-   m4x3_mulv( mtx, local, dest );
-}
-
-VG_STATIC float closest_point_segment( v3f a, v3f b, v3f point, v3f dest )
-{
-   v3f v0, v1;
-   v3_sub( b, a, v0 );
-   v3_sub( point, a, v1 );
-
-   float t = v3_dot( v1, v0 ) / v3_length2(v0);
-   t = vg_clampf(t,0.0f,1.0f);
-   v3_muladds( a, v0, t, dest );
-   return t;
-}
-
-VG_STATIC void closest_on_triangle( v3f p, v3f tri[3], v3f dest )
-{
-   v3f ab, ac, ap;
-   float d1, d2;
-
-   /* Region outside A */
-   v3_sub( tri[1], tri[0], ab );
-   v3_sub( tri[2], tri[0], ac );
-   v3_sub( p, tri[0], ap );
-   
-   d1 = v3_dot(ab,ap);
-   d2 = v3_dot(ac,ap);
-   if( d1 <= 0.0f && d2 <= 0.0f ) 
-   {
-      v3_copy( tri[0], dest );
-      v3_copy( (v3f){INFINITY,INFINITY,INFINITY}, dest );
-      return;
-   }
-
-   /* Region outside B */
-   v3f bp;
-   float d3, d4;
-
-   v3_sub( p, tri[1], bp );
-   d3 = v3_dot( ab, bp );
-   d4 = v3_dot( ac, bp );
-
-   if( d3 >= 0.0f && d4 <= d3 )
-   {
-      v3_copy( tri[1], dest );
-      v3_copy( (v3f){INFINITY,INFINITY,INFINITY}, dest );
-      return;
-   }
-   
-   /* Edge region of AB */
-   float vc = d1*d4 - d3*d2;
-   if( vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f )
-   {
-      float v = d1 / (d1-d3);
-      v3_muladds( tri[0], ab, v, dest );
-      v3_copy( (v3f){INFINITY,INFINITY,INFINITY}, dest );
-      return;
-   }
-
-   /* Region outside C */
-   v3f cp;
-   float d5, d6;
-   v3_sub( p, tri[2], cp );
-   d5 = v3_dot(ab, cp);
-   d6 = v3_dot(ac, cp);
-   
-   if( d6 >= 0.0f && d5 <= d6 )
-   {
-      v3_copy( tri[2], dest );
-      v3_copy( (v3f){INFINITY,INFINITY,INFINITY}, dest );
-      return;
-   }
-
-   /* Region of AC */
-   float vb = d5*d2 - d1*d6;
-   if( vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f )
-   {
-      float w = d2 / (d2-d6);
-      v3_muladds( tri[0], ac, w, dest );
-      v3_copy( (v3f){INFINITY,INFINITY,INFINITY}, dest );
-      return;
-   }
-
-   /* Region of BC */
-   float va = d3*d6 - d5*d4;
-   if( va <= 0.0f && (d4-d3) >= 0.0f && (d5-d6) >= 0.0f )
-   {
-      float w = (d4-d3) / ((d4-d3) + (d5-d6));
-      v3f bc;
-      v3_sub( tri[2], tri[1], bc );
-      v3_muladds( tri[1], bc, w, dest );
-      v3_copy( (v3f){INFINITY,INFINITY,INFINITY}, dest );
-      return;
-   }
-
-   /* P inside region, Q via barycentric coordinates uvw */
-   float d = 1.0f/(va+vb+vc),
-         v = vb*d,
-         w = vc*d;
-
-   v3_muladds( tri[0], ab, v, dest );
-   v3_muladds( dest, ac, w, dest );
-}
-
-VG_STATIC enum contact_type closest_on_triangle_1( v3f p, v3f tri[3], v3f dest )
-{
-   v3f ab, ac, ap;
-   float d1, d2;
-
-   /* Region outside A */
-   v3_sub( tri[1], tri[0], ab );
-   v3_sub( tri[2], tri[0], ac );
-   v3_sub( p, tri[0], ap );
-   
-   d1 = v3_dot(ab,ap);
-   d2 = v3_dot(ac,ap);
-   if( d1 <= 0.0f && d2 <= 0.0f ) 
-   {
-      v3_copy( tri[0], dest );
-      return k_contact_type_default;
-   }
-
-   /* Region outside B */
-   v3f bp;
-   float d3, d4;
-
-   v3_sub( p, tri[1], bp );
-   d3 = v3_dot( ab, bp );
-   d4 = v3_dot( ac, bp );
-
-   if( d3 >= 0.0f && d4 <= d3 )
-   {
-      v3_copy( tri[1], dest );
-      return k_contact_type_edge;
-   }
-   
-   /* Edge region of AB */
-   float vc = d1*d4 - d3*d2;
-   if( vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f )
-   {
-      float v = d1 / (d1-d3);
-      v3_muladds( tri[0], ab, v, dest );
-      return k_contact_type_edge;
-   }
-
-   /* Region outside C */
-   v3f cp;
-   float d5, d6;
-   v3_sub( p, tri[2], cp );
-   d5 = v3_dot(ab, cp);
-   d6 = v3_dot(ac, cp);
-   
-   if( d6 >= 0.0f && d5 <= d6 )
-   {
-      v3_copy( tri[2], dest );
-      return k_contact_type_edge;
-   }
-
-   /* Region of AC */
-   float vb = d5*d2 - d1*d6;
-   if( vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f )
-   {
-      float w = d2 / (d2-d6);
-      v3_muladds( tri[0], ac, w, dest );
-      return k_contact_type_edge;
-   }
-
-   /* Region of BC */
-   float va = d3*d6 - d5*d4;
-   if( va <= 0.0f && (d4-d3) >= 0.0f && (d5-d6) >= 0.0f )
-   {
-      float w = (d4-d3) / ((d4-d3) + (d5-d6));
-      v3f bc;
-      v3_sub( tri[2], tri[1], bc );
-      v3_muladds( tri[1], bc, w, dest );
-      return k_contact_type_edge;
-   }
-
-   /* P inside region, Q via barycentric coordinates uvw */
-   float d = 1.0f/(va+vb+vc),
-         v = vb*d,
-         w = vc*d;
-
-   v3_muladds( tri[0], ab, v, dest );
-   v3_muladds( dest, ac, w, dest );
-
-   return k_contact_type_default;
-}
 
 #endif /* DISTQ_H */
 
 #endif /* DISTQ_H */
index 45891c30aecae7dd58f30f547dbdfa7e5fbf2ca1..33fda35b581b56a505aa69267691b06a0740ec9c 100644 (file)
Binary files a/maps_src/mp_mtzero.mdl and b/maps_src/mp_mtzero.mdl differ
index cb36975a266bec614e2ccd53b99b7f377f3f53cd..8e4ae82b99d0ff547c8aa61d874359d395e9b7e9 100644 (file)
--- a/player.h
+++ b/player.h
@@ -69,7 +69,7 @@ VG_STATIC struct gplayer
 
       /* Utility */
       float vswitch, slip, slip_last, reverse;
 
       /* Utility */
       float vswitch, slip, slip_last, reverse;
-      float grab, jump, pushing, push_time;
+      float grab, jump, pushing, push_time, rise;
       v2f grab_mouse_delta;
 
       int lift_frames;
       v2f grab_mouse_delta;
 
       int lift_frames;
@@ -88,16 +88,25 @@ VG_STATIC struct gplayer
    int is_dead, death_tick_allowance, rewinding;
    int rewind_sound_wait;
 
    int is_dead, death_tick_allowance, rewinding;
    int rewind_sound_wait;
 
-   v3f land_target;
-
-   struct land_log
+   struct land_prediction
    {
    {
-      v3f positions[50];
-      u32 colour;
-      int count;
-   } 
-   land_log[22];
-   int land_log_count;
+      v3f   log[50];
+      v3f   n;
+      u32   log_length;
+      float score;
+
+      enum prediction_type
+      {
+         k_prediction_none,
+         k_prediction_land,
+         k_prediction_grind
+      }
+      type;
+
+      u32   colour;
+   }
+   predictions[22];
+   u32 prediction_count;
 
    v3f handl_target, handr_target,
        handl, handr;
 
    v3f handl_target, handr_target,
        handl, handr;
@@ -232,7 +241,7 @@ VG_STATIC void player_mouseview(void);
  * -----------------------------------------------------------------------------
  */
 
  * -----------------------------------------------------------------------------
  */
 
-VG_STATIC void player_init(void)                                            /* 1 */
+VG_STATIC void player_init(void)                                         /* 1 */
 {
    player.input_js1h = vg_create_named_input( "steer-h", k_input_type_axis );
    player.input_js1v = vg_create_named_input( "steer-v", k_input_type_axis );
 {
    player.input_js1h = vg_create_named_input( "steer-h", k_input_type_axis );
    player.input_js1v = vg_create_named_input( "steer-v", k_input_type_axis );
@@ -436,6 +445,34 @@ VG_STATIC void player_update_pre(void)
 {
    struct player_phys *phys = &player.phys;
 
 {
    struct player_phys *phys = &player.phys;
 
+
+   {
+      v3f ra, rb, rx;
+      v3_copy( main_camera.pos, ra );
+      v3_muladds( ra, main_camera.transform[2], -10.0f, rb );
+
+      float t;
+      if( spherecast_world( ra, rb, 0.4f, &t, rx ) != -1 )
+      {
+         m4x3f mtx;
+         m3x3_identity( mtx );
+         v3_lerp( ra, rb, t, mtx[3] );
+
+         debug_sphere( mtx, 0.4f, 0xff00ff00 );
+
+         v3f x1;
+         v3_muladds( mtx[3], rx, 0.4f, x1 );
+         vg_line( mtx[3], x1, 0xffffffff );
+      }
+   }
+
+
+
+
+
+
+
+
    if( player.rewinding )
       return;
 
    if( player.rewinding )
       return;
 
@@ -551,14 +588,18 @@ VG_STATIC void player_update_fixed(void)                                 /* 2 */
 
 VG_STATIC void player_update_post(void)
 {
 
 VG_STATIC void player_update_post(void)
 {
-   for( int i=0; i<player.land_log_count; i++ )
+   for( int i=0; i<player.prediction_count; i++ )
    {
    {
-      struct land_log *log = &player.land_log[i];
+      struct land_prediction *p = &player.predictions[i];
       
       
-      for( int j=0; j<log->count - 1; j ++ )
-         vg_line( log->positions[j], log->positions[j+1], log->colour );
+      for( int j=0; j<p->log_length - 1; j ++ )
+         vg_line( p->log[j], p->log[j+1], p->colour );
+
+      vg_line_cross( p->log[p->log_length-1], p->colour, 0.25f );
 
 
-      vg_line_cross( log->positions[log->count-1], log->colour, 0.25f );
+      v3f p1;
+      v3_add( p->log[p->log_length-1], p->n, p1 );
+      vg_line( p->log[p->log_length-1], p1, 0xffffffff );
    }
 
    if( player.is_dead )
    }
 
    if( player.is_dead )
index 56698f87e2ecdfd65fd44e083eed6b522d386c88..50ea62e41951db888036ef5f427bb1db69d1b71c 100644 (file)
@@ -59,6 +59,164 @@ grind_edge *player_grind_collect_edge( v3f p0, v3f p1,
    return closest_edge;
 }
 
    return closest_edge;
 }
 
+/*
+ * Cast a sphere from a to b and see what time it hits
+ */
+VG_STATIC int spherecast_world( v3f pa, v3f pb, float r, float *t, v3f n )
+{
+   struct player_phys *phys = &player.phys;
+
+   bh_iter it;
+   bh_iter_init( 0, &it );
+
+   boxf region;
+   box_init_inf( region );
+   box_addpt( region, pa );
+   box_addpt( region, pb );
+   
+   v3_add( (v3f){ r, r, r}, region[1], region[1] );
+   v3_add( (v3f){-r,-r,-r}, region[0], region[0] );
+
+   v3f dir;
+   v3_sub( pb, pa, dir );
+
+   int hit = -1;
+   float min_t = 1.0f;
+
+   int idx;
+   while( bh_next( world.geo_bh, &it, region, &idx ) )
+   {
+      u32 *ptri = &world.scene_geo->arrindices[ idx*3 ];
+      v3f tri[3];
+
+      boxf box;
+      box_init_inf( box );
+
+      for( int j=0; j<3; j++ )
+      {
+         v3_copy( world.scene_geo->arrvertices[ptri[j]].co, tri[j] );
+         box_addpt( box, tri[j] );
+      }
+
+      v3_add( (v3f){ r, r, r}, box[1], box[1] );
+      v3_add( (v3f){-r,-r,-r}, box[0], box[0] );
+      if( !ray_aabb( box, pa, dir, 1.0f ) )
+         continue;
+      
+      float t;
+      v3f n1;
+      if( spherecast_triangle( tri, pa, dir, r, &t, n1 ) )
+      {
+         if( t < min_t )
+         {
+            min_t = t;
+            hit = idx;
+            v3_copy( n1, n );
+         }
+      }
+   }
+
+   *t = min_t;
+   return hit;
+}
+
+/* 
+ * Trace a path given a velocity rotation.
+ * Closest to 0 is best.
+ */
+VG_STATIC void player_predict_land( m3x3f vr, 
+                                    struct land_prediction *prediction )
+{
+   struct player_phys *phys = &player.phys;
+
+   float pstep  = VG_TIMESTEP_FIXED * 10.0f;
+   float k_bias = 0.96f;
+
+   v3f pco, pco1, pv;
+   v3_copy( phys->rb.co, pco );
+   v3_muls( phys->rb.v, k_bias, pv );
+
+   m3x3_mulv( vr, pv, pv );
+   v3_muladds( pco, pv, pstep, pco );
+
+   struct grind_edge *best_grind = NULL;
+   float closest_grind = INFINITY;
+
+   float grind_score   = INFINITY,
+         air_score     = INFINITY;
+
+   prediction->log_length = 0;
+
+   for( int i=0; i<vg_list_size(prediction->log); i++ )
+   {
+      v3_copy( pco, pco1 );
+      apply_gravity( pv, pstep );
+
+      m3x3_mulv( vr, pv, pv );
+      v3_muladds( pco, pv, pstep, pco );
+      
+      v3f vdir;
+
+      v3_sub( pco, pco1, vdir );
+
+      float l = v3_length( vdir );
+      v3_muls( vdir, 1.0f/l, 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;
+            grind_score = closest_grind * 0.05f;
+         }
+      }
+
+      v3f n1;
+
+      float t1;
+      int idx = spherecast_world( pco1, pco, 0.4f, &t1, n1 );
+      if( idx != -1 )
+      {
+         v3_copy( n1, prediction->n );
+         air_score = -v3_dot( pv, n1 );
+         
+         u32 vert_index = world.scene_geo->arrindices[ idx*3 ];
+         struct world_material *mat = world_tri_index_material( vert_index );
+
+         /* Bias prediction towords ramps */
+         if( mat->info.flags & k_material_flag_skate_surface )
+            air_score *= 0.1f;
+
+         v3_lerp( pco1, pco, t1, prediction->log[ prediction->log_length ++ ] ); 
+         break;
+      }
+
+      v3_copy( pco, prediction->log[ prediction->log_length ++ ] );
+   }
+
+   if( grind_score < air_score )
+   {
+      prediction->score = grind_score; 
+      prediction->type = k_prediction_grind;
+   }
+   else if( air_score < INFINITY )
+   {
+      prediction->score = air_score;
+      prediction->type = k_prediction_land;
+   }
+   else
+   {
+      prediction->score = INFINITY;
+      prediction->type = k_prediction_none;
+   }
+}
+
 /*
  * Called when launching into the air to predict and adjust trajectories
  */
 /*
  * Called when launching into the air to predict and adjust trajectories
  */
@@ -68,121 +226,79 @@ VG_STATIC void player_start_air(void)
 
    float pstep = VG_TIMESTEP_FIXED * 10.0f;
    float best_velocity_delta = -9999.9f;
 
    float pstep = VG_TIMESTEP_FIXED * 10.0f;
    float best_velocity_delta = -9999.9f;
-   float k_bias = 0.96f;
 
    v3f axis;
    v3_cross( phys->rb.up, phys->rb.v, axis );
    v3_normalize( axis );
 
    v3f axis;
    v3_cross( phys->rb.up, phys->rb.v, axis );
    v3_normalize( axis );
-   player.land_log_count = 0;
+   player.prediction_count = 0;
    
    m3x3_identity( phys->vr );
 
    
    m3x3_identity( phys->vr );
 
+   float 
+         best_vmod   = 0.0f,
+         min_score   =  INFINITY,
+         max_score   = -INFINITY;
+
+   /*
+    * Search a broad selection of futures
+    */
    for( int m=-3;m<=12; m++ )
    {
    for( int m=-3;m<=12; m++ )
    {
-      struct land_log *log = &player.land_log[ player.land_log_count ++ ];
-      log->count = 0;
-      log->colour = 0xff000000;
+      struct land_prediction *p = 
+         &player.predictions[ player.prediction_count ++ ];
 
       float vmod = ((float)m / 15.0f)*0.09f;
 
 
       float vmod = ((float)m / 15.0f)*0.09f;
 
-      v3f pco, pco1, pv;
-      v3_copy( phys->rb.co, pco );
-      v3_muls( phys->rb.v, k_bias, pv );
-
-      /* 
-       * Try different 'rotations' of the velocity to find the best possible
-       * landing normal. This conserves magnitude at the expense of slightly
-       * unrealistic results
-       */
-
       m3x3f vr;
       v4f vr_q;
 
       q_axis_angle( vr_q, axis, vmod );
       q_m3x3( vr_q, vr );
 
       m3x3f vr;
       v4f vr_q;
 
       q_axis_angle( vr_q, axis, vmod );
       q_m3x3( vr_q, vr );
 
-      m3x3_mulv( vr, pv, pv );
-      v3_muladds( pco, pv, pstep, pco );
-
-      struct grind_edge *best_grind = NULL;
-      float closest_grind = INFINITY;
+      player_predict_land( vr, p );
 
 
-      for( int i=0; i<50; i++ )
+      if( p->type != k_prediction_none )
       {
       {
-         v3_copy( pco, pco1 );
-         apply_gravity( pv, pstep );
-
-         m3x3_mulv( vr, pv, pv );
-         v3_muladds( pco, pv, pstep, pco );
-         
-         ray_hit contact;
-         v3f vdir;
-
-         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 ) )
+         if( p->score < min_score )
          {
          {
-            float d2 = v3_dist2( c0, c1 );
-            if( d2 < closest_grind )
-            {
-               closest_grind = d2;
-               best_grind = ge;
-            }
+            min_score = p->score;
+            best_vmod = vmod;
          }
 
          }
 
-         if( ray_world( pco1, vdir, &contact ))
-         {
-            float land_delta = v3_dot( pv, contact.normal );
-            u32 scolour = (u8)(vg_minf(-land_delta * 2.0f, 255.0f));
+         if( p->score > max_score )
+            max_score = p->score;
+      }
+   }
 
 
-            /* Bias prediction towords ramps */
-            if( ray_hit_material( &contact )->info.flags 
-                  & k_material_flag_skate_surface )
-            {
-               land_delta *= 0.1f;
-               scolour |= 0x0000a000;
-            }
+   v4f vr_q;
+   q_axis_angle( vr_q, axis, best_vmod*0.1f );
+   q_m3x3( vr_q, phys->vr );
 
 
-            if( (land_delta < 0.0f) && (land_delta > best_velocity_delta) )
-            {
-               best_velocity_delta = land_delta;
+   q_axis_angle( vr_q, axis, best_vmod );
+   q_m3x3( vr_q, phys->vr_pstep );
 
 
-               v3_copy( contact.pos, player.land_target );
-               
-               m3x3_copy( vr, phys->vr_pstep );
-               q_axis_angle( vr_q, axis, vmod*0.1f );
-               q_m3x3( vr_q, phys->vr );
-            }
+   /*
+    * Logging
+    */
+   for( int i=0; i<player.prediction_count; i ++ )
+   {
+      struct land_prediction *p = &player.predictions[i];
 
 
-            v3_copy( contact.pos, log->positions[ log->count ++ ] );
-            log->colour = 0xff000000 | scolour;
-            break;
-         }
+      float l = p->score;
 
 
-         v3_copy( pco, log->positions[ log->count ++ ] );
+      if( l < 0.0f )
+      {
+         vg_error( "negative score! (%f)\n", l );
       }
 
       }
 
-      if( best_grind )
-      {
-         log->colour = 0xff0000ff;
-         
-         float score = -closest_grind * 0.05f;
+      l -= min_score;
+      l /= (max_score-min_score);
+      l  = 1.0f - l;
+      l *= 255.0f;
 
 
-         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 );
-         }
-      }
+      p->colour = l;
+      p->colour <<= 8;
+      p->colour |= 0xff000000;
    }
 }
 
    }
 }
 
@@ -354,18 +470,19 @@ VG_STATIC void player_physics_control_air(void)
    struct player_phys *phys = &player.phys;
 
    m3x3_mulv( phys->vr, phys->rb.v, phys->rb.v );
    struct player_phys *phys = &player.phys;
 
    m3x3_mulv( phys->vr, phys->rb.v, phys->rb.v );
-   vg_line_cross( player.land_target, 0xff0000ff, 0.25f );
+   //vg_line_cross( player.land_target, 0xff0000ff, 0.25f );
 
    ray_hit hit;
 
    /* 
     * Prediction 
     */
 
    ray_hit hit;
 
    /* 
     * Prediction 
     */
-   float pstep = VG_TIMESTEP_FIXED * 10.0f;
+   float pstep  = VG_TIMESTEP_FIXED * 1.0f;
+   float k_bias = 0.98f;
 
    v3f pco, pco1, pv;
    v3_copy( phys->rb.co, pco );
 
    v3f pco, pco1, pv;
    v3_copy( phys->rb.co, pco );
-   v3_copy( phys->rb.v, pv );
+   v3_muls( phys->rb.v, 1.0f, pv );
    
    float time_to_impact = 0.0f;
    float limiter = 1.0f;
    
    float time_to_impact = 0.0f;
    float limiter = 1.0f;
@@ -376,10 +493,10 @@ VG_STATIC void player_physics_control_air(void)
    v3f target_normal = { 0.0f, 1.0f, 0.0f };
    int has_target = 0;
 
    v3f target_normal = { 0.0f, 1.0f, 0.0f };
    int has_target = 0;
 
-   for( int i=0; i<50; i++ )
+   for( int i=0; i<250; i++ )
    {
       v3_copy( pco, pco1 );
    {
       v3_copy( pco, pco1 );
-      m3x3_mulv( phys->vr_pstep, pv, pv );
+      m3x3_mulv( phys->vr, pv, pv );
       apply_gravity( pv, pstep );
       v3_muladds( pco, pv, pstep, pco );
       
       apply_gravity( pv, pstep );
       v3_muladds( pco, pv, pstep, pco );
       
@@ -750,7 +867,9 @@ 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 );
 
          v3_cross( (v3f){0.0f,1.0f,0.0f}, edge_dir, axis_dir );
          v3_cross( edge_dir, axis_dir, contact->n );
 
+#if 0
          vg_info( "%f %f\n", v3_length( contact->n ), contact->p );
          vg_info( "%f %f\n", v3_length( contact->n ), contact->p );
+#endif
 
          return 1;
       }
 
          return 1;
       }
@@ -766,6 +885,9 @@ VG_STATIC int player_update_collision_manifold( rb_ct *manifold )
 {
    struct player_phys *phys = &player.phys;
 
 {
    struct player_phys *phys = &player.phys;
 
+   phys->rise = vg_lerpf( phys->rise, phys->in_air? -0.25f: 0.0f, 
+                          VG_TIMESTEP_FIXED );
+
    rigidbody *rbf = &player.collide_front,
              *rbb = &player.collide_back;
 
    rigidbody *rbf = &player.collide_front,
              *rbb = &player.collide_back;
 
@@ -773,7 +895,7 @@ VG_STATIC int player_update_collision_manifold( rb_ct *manifold )
    m3x3_copy( phys->rb.to_world, player.collide_back.to_world );
    
    player.air_blend = vg_lerpf( player.air_blend, phys->in_air, 0.1f );
    m3x3_copy( phys->rb.to_world, player.collide_back.to_world );
    
    player.air_blend = vg_lerpf( player.air_blend, phys->in_air, 0.1f );
-   float h = player.air_blend*0.2f;
+   float h = player.air_blend*0.0f;
 
    m4x3_mulv( phys->rb.to_world, (v3f){0.0f,h,-k_board_length}, rbf->co );
    v3_copy( rbf->co, rbf->to_world[3] );
 
    m4x3_mulv( phys->rb.to_world, (v3f){0.0f,h,-k_board_length}, rbf->co );
    v3_copy( rbf->co, rbf->to_world[3] );
index 2e117cf33ecc351f3ca1cbe622754d1d7b1c94cd..5f2f7066a3d6ca9475031c1d87535fb40626b52b 100644 (file)
@@ -96,7 +96,7 @@ VG_STATIC void vg_load(void)
 
    /* 'systems' are completely loaded now */
    strcpy( world.world_name, "maps/mp_mtzero.mdl" );
 
    /* 'systems' are completely loaded now */
    strcpy( world.world_name, "maps/mp_mtzero.mdl" );
-   //strcpy( world.world_name, "maps/mp_gridmap.mdl" );
+   strcpy( world.world_name, "maps/mp_gridmap.mdl" );
    world_load();
    vg_console_load_autos();
 }
    world_load();
    vg_console_load_autos();
 }