im making a note here, huge success
authorhgn <hgodden00@gmail.com>
Wed, 15 Feb 2023 21:08:31 +0000 (21:08 +0000)
committerhgn <hgodden00@gmail.com>
Wed, 15 Feb 2023 21:08:31 +0000 (21:08 +0000)
player_skate.c
player_skate.h

index 9609b7fa0fb9b7601740f9c474fcb78c381eef92..df3d42439671373fe1c77bfd2d6c2ca0e6822200 100644 (file)
@@ -596,258 +596,144 @@ VG_STATIC int skate_grind_scansq( player_instance *player, v3f pos,
 
 #endif
 
-/*
- *
- * Prediction system
- *
- *
- */
-
-/* 
- * Trace a path given a velocity rotation.
- *
- * TODO: this MIGHT be worth doing RK4 on the gravity field.
- */
-VG_STATIC void skate_score_biased_path( v3f co, v3f v, m3x3f vr, 
-                                        struct land_prediction *prediction )
+VG_STATIC 
+void player__approximate_best_trajectory( player_instance *player )
 {
-   float pstep  = VG_TIMESTEP_FIXED * 10.0f;
-   float k_bias = 0.96f;
-
-   v3f pco, pco1, pv;
-   v3_copy( co, pco );
-   v3_muls( 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;
+   struct player_skate *s = &player->_skate;
+   float k_trace_delta = k_rb_delta * 10.0f;
 
-   float grind_score    = INFINITY,
-         air_score      = INFINITY,
-         time_to_impact = 0.0f;
+   s->state.air_start = vg.time;
+   v3_copy( player->rb.v, s->state.air_init_v );
+   v3_copy( player->rb.co, s->state.air_init_co );
 
-   v3f ground_normal,
-       grind_normal;
+   s->prediction_count = 0;
 
-   v3_copy( (v3f){0.0f,1.0f,0.0f}, ground_normal );
-   v3_copy( (v3f){0.0f,1.0f,0.0f}, grind_normal );
+   v3f axis;
+   v3_cross( player->rb.v, player->rb.to_world[1], axis );
+   v3_normalize( axis );
 
-   prediction->log_length = 0;
-   v3_copy( pco, prediction->apex );
+   /* at high slopes, Y component is low */
+   float angle_begin = -(1.0f-fabsf( player->rb.to_world[1][1] )),
+         angle_end   =   1.0f;
 
-   for( int i=0; i<vg_list_size(prediction->log); i++ )
+   for( int m=0;m<=15; m++ )
    {
-      v3_copy( pco, pco1 );
-
-      pv[1] += -k_gravity * pstep;
+      struct land_prediction *p = &s->predictions[ s->prediction_count ++ ];
 
-      m3x3_mulv( vr, pv, pv );
-      v3_muladds( pco, pv, pstep, pco );
+      p->log_length = 0;
+      p->land_dist = 0.0f;
+      v3_zero( p->apex );
+      p->type = k_prediction_none;
 
-      if( pco[1] > prediction->apex[1] )
-         v3_copy( pco, prediction->apex );
-      
-      v3f vdir;
+      v3f launch_co, launch_v, co0, co1;
+      v3_copy( player->rb.co, launch_co );
+      v3_copy( player->rb.v,  launch_v );
+      v3_copy( launch_co, co0 );
 
-      v3_sub( pco, pco1, vdir );
+      float vt  = (float)m * (1.0f/15.0f),
+            ang = vg_lerpf( angle_begin, angle_end, vt ) * 0.15f;
 
-      float l = v3_length( vdir );
-      v3_muls( vdir, 1.0f/l, vdir );
+      v4f qbias;
+      q_axis_angle( qbias, axis, ang );
+      q_mulv( qbias, launch_v, launch_v );
+      v3_copy( launch_v, p->v );
 
-#if 0
-      v3f c0, c1;
-      struct grind_edge *ge = skate_collect_grind_edge( pco, pco1,
-                                                        c0, c1, 0.4f );
-
-      if( ge && (v3_dot((v3f){0.0f,1.0f,0.0f},vdir) < -0.2f ) )
+      for( int i=1; i<=50; i++ )
       {
-         float d2 = v3_dist2( c0, c1 );
-         if( d2 < closest_grind )
-         {
-            closest_grind = d2;
-            best_grind = ge;
-            grind_score = closest_grind * 0.05f;
-         }
-      }
-#endif
+         float t = (float)i * k_trace_delta;
 
-      /* TODO: binary search grind once we find it, do not need to
-       *       recompute scansq, or collision. only distance
-       */
+         v3_muls( launch_v, t, co1 );
+         co1[1] += -0.5f * k_gravity * t*t;
+         v3_add( launch_co, co1, co1 );
 
-      v3f closest;
-      if( bh_closest_point( world.geo_bh, pco, closest, k_board_length ) != -1 )
-      {
-         struct grind_info inf;
-         if( skate_grind_scansq( closest, vdir, 0.5f, &inf ) )
-         {
-            float score = -v3_dot( pv, inf.n ) * 0.06f;
+         float t1;
+         v3f n;
 
-            if( (score > 0.0f) && (score < grind_score) )
-            {
-               grind_score = score;
-            }
+         int idx = spherecast_world( co0, co1, k_board_radius, &t1, n );
+         if( idx != -1 )
+         {
+            v3_copy( n, p->n );
+            v3_lerp( co0, co1, t1, p->log[ p->log_length ++ ] ); 
+            p->type = k_prediction_land;
+
+            v3f ve;
+            v3_copy( launch_v, ve );
+            ve[1] -= k_gravity * t;
+            p->score = -v3_dot( ve, n );
+            p->land_dist = t + k_trace_delta * t1;
+            break;
          }
-      }
-
-      v3f n1;
 
-      float t1;
-      int idx = spherecast_world( pco1, pco, 0.4f, &t1, n1 );
-      if( idx != -1 )
-      {
-         v3_copy( n1, ground_normal );
-         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 ++ ] ); 
-         time_to_impact += t1 * pstep;
-         break;
+         v3_copy( co1, p->log[ p->log_length ++ ] ); 
+         v3_copy( co1, co0 );
       }
 
-      time_to_impact += pstep;
-      v3_copy( pco, prediction->log[ prediction->log_length ++ ] );
-   }
-
-   if( grind_score < air_score )
-   {
-      prediction->score = grind_score; 
-      prediction->type = k_prediction_grind;
-      v3_copy( grind_normal, prediction->n );
+      if( p->type == k_prediction_none )
+         s->prediction_count --;
    }
-   else if( air_score < INFINITY )
-   {
-      prediction->score = air_score;
-      prediction->type = k_prediction_land;
-      v3_copy( ground_normal, prediction->n );
-   }
-   else
-   {
-      prediction->score = INFINITY;
-      prediction->type = k_prediction_none;
-   }
-
-   prediction->land_dist = time_to_impact;
-}
 
-VG_STATIC 
-void player__approximate_best_trajectory( player_instance *player )
-{
-   struct player_skate *s = &player->_skate;
-
-   float pstep = VG_TIMESTEP_FIXED * 10.0f;
-   float best_velocity_delta = -9999.9f;
-
-   v3f axis;
-   v3_cross( player->rb.to_world[1], player->rb.v, axis );
-   v3_normalize( axis );
+   float score_min =  INFINITY,
+         score_max = -INFINITY;
 
-   s->prediction_count = 0;
-   m3x3_identity( s->state.velocity_bias );
-
-   float best_vmod   = 0.0f,
-         min_score   =  INFINITY,
-         max_score   = -INFINITY;
-
-   v3_zero( s->state.apex );
-   v3_copy( (v3f){0.0f,1.0f,0.0f}, s->land_normal );  
-         /* TODO: Make part of state */
+   struct land_prediction *best = NULL;
 
-   s->land_dist = 0.0f;
-
-   /*
-    * Search a broad selection of futures
-    */
-   for( int m=-3;m<=12; m++ )
+   for( int i=0; i<s->prediction_count; i ++ )
    {
-      struct land_prediction *p = &s->predictions[ s->prediction_count ++ ];
-
-      float vmod = ((float)m / 15.0f)*0.09f;
-
-      m3x3f bias;
-      v4f bias_q;
-
-      q_axis_angle( bias_q, axis, vmod );
-      q_m3x3( bias_q, bias );
-
-      skate_score_biased_path( player->rb.co, player->rb.v, bias, p );
-
-      if( p->type != k_prediction_none )
-      {
-         if( p->score < min_score )
-         {
-            min_score = p->score;
-            best_vmod = vmod;
-            s->land_dist = p->land_dist;
-            v3_copy( p->apex, s->state.apex );
-            v3_copy( p->n, s->land_normal );
+      struct land_prediction *p = &s->predictions[i];
 
-            /* TODO: Store this as pointer? */
-         }
+      if( p->score < score_min )
+         best = p;
 
-         if( p->score > max_score )
-            max_score = p->score;
-      }
+      score_min = vg_minf( score_min, p->score );
+      score_max = vg_maxf( score_max, p->score );
    }
 
-   v4f vr_q;
-   q_axis_angle( vr_q, axis, best_vmod*0.1f );
-   q_m3x3( vr_q, s->state.velocity_bias );
-
-   q_axis_angle( vr_q, axis, best_vmod );
-   q_m3x3( vr_q, s->state.velocity_bias_pstep );
-
-   /*
-    * Logging
-    */
    for( int i=0; i<s->prediction_count; i ++ )
    {
       struct land_prediction *p = &s->predictions[i];
+      float s = p->score;
 
-      float l = p->score;
+      s -= score_min;
+      s /= (score_max-score_min);
+      s  = 1.0f - s;
 
-      if( l < 0.0f )
-      {
-         vg_error( "negative score! (%f)\n", l );
-      }
-
-      l -= min_score;
-      l /= (max_score-min_score);
-      l  = 1.0f - l;
+      p->score = s;
+      p->colour = s * 255.0f;
 
-      p->score = l;
-      p->colour = l * 255.0f;
-
-      if( p->type == k_prediction_land )
+      if( p == best )
+         p->colour <<= 16;
+      else if( p->type == k_prediction_land )
          p->colour <<= 8;
       
       p->colour |= 0xff000000;
    }
 
+   if( best )
+   {
+      v3_copy( best->n, s->land_normal );
+      v3_copy( best->v, player->rb.v );
+      s->land_dist = best->land_dist;
 
-   v2f steer = { player->input_js1h->axis.value,
-                 player->input_js1v->axis.value };
-   v2_normalize_clamp( steer );
+      v2f steer = { player->input_js1h->axis.value,
+                    player->input_js1v->axis.value };
+      v2_normalize_clamp( steer );
 
-   if( (fabsf(steer[1]) > 0.5f) && (s->land_dist >= 1.0f) )
-   {
-      s->state.flip_rate = (1.0f/s->land_dist) * vg_signf(steer[1]) *
-                              s->state.reverse ;
-      s->state.flip_time = 0.0f;
-      v3_copy( player->rb.to_world[0], s->state.flip_axis );
+      if( (fabsf(steer[1]) > 0.5f) && (s->land_dist >= 1.5f) )
+      {
+         s->state.flip_rate = (1.0f/s->land_dist) * vg_signf(steer[1]) *
+                                 s->state.reverse ;
+         s->state.flip_time = 0.0f;
+         v3_copy( player->rb.to_world[0], s->state.flip_axis );
+      }
+      else
+      {
+         s->state.flip_rate = 0.0f;
+         v3_zero( s->state.flip_axis );
+      }
    }
    else
    {
-      s->state.flip_rate = 0.0f;
-      v3_zero( s->state.flip_axis );
+      v3_copy( (v3f){0.0f,1.0f,0.0f}, s->land_normal );
    }
 }
 
@@ -867,9 +753,9 @@ VG_STATIC void skate_apply_air_model( player_instance *player )
    if( s->state.activity_prev != k_skate_activity_air )
       player__approximate_best_trajectory( player );
 
+#if 0
    m3x3_mulv( s->state.velocity_bias, player->rb.v, player->rb.v );
 
-#if 0
    ray_hit hit;
    /* 
     * Prediction 
@@ -1063,6 +949,12 @@ VG_STATIC void skate_apply_steering_model( player_instance *player )
       top  = 1.5f;
    }
 
+   else if( s->state.manual_direction )
+   {
+      rate = 35.0f;
+      top  = 1.5f;
+   }
+
    else if( s->state.activity >= k_skate_activity_grind_any )
    {
       rate *= fabsf(steer_scaled);
@@ -1414,7 +1306,9 @@ VG_STATIC void player__skate_post_update( player_instance *player )
       vg_line_pt3( p->apex, 0.02f, 0xffffffff );
    }
 
+#if 0
    vg_line_pt3( s->state.apex, 0.030f, 0xff0000ff );
+#endif
 }
 
 /*
@@ -2243,13 +2137,10 @@ begin_collision:;
    }
 
    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 );
+   player->rb.v[1] += -k_gravity * s->substep_delta;
 
    s->substep -= s->substep_delta;
 
-
    rb_ct manifold[128];
    int manifold_len   = 0;
 
@@ -2259,7 +2150,6 @@ begin_collision:;
     */
    m4x3_mulv( player->rb.to_world, s->state.head_position, head_wp1 );
 
-#if 0
    float t;
    v3f n;
    if( (v3_dist2( head_wp0, head_wp1 ) > 0.001f) &&
@@ -2271,7 +2161,6 @@ begin_collision:;
       player__dead_transition( player );
       return;
    }
-#endif
 
    /*
     * Phase 1: Regular collision detection
@@ -2875,8 +2764,11 @@ VG_STATIC void player__skate_clear_mechanics( player_instance *player )
    s->state.slip           = 0.0f;
    v3_copy( player->rb.co, s->state.prev_pos );
 
+#if 0
    m3x3_identity( s->state.velocity_bias );
    m3x3_identity( s->state.velocity_bias_pstep );
+#endif
+
    v3_zero( s->state.throw_v );
    v3_zero( s->state.trick_vel );
    v3_zero( s->state.trick_euler );
index 37c90dc796326d06bedd9bdeead4cd25965b6107..e54754e570f5bf61fda3bb6a01066fbf6868c36a 100644 (file)
@@ -43,9 +43,12 @@ struct player_skate
             trick_euler;   /* measured in units of TAU */
       float trick_time;
 
+#if 0
       m3x3f velocity_bias,
             velocity_bias_pstep;
       v3f apex;
+#endif
+
       v3f up_dir;
 
       v3f head_position;
@@ -60,12 +63,17 @@ struct player_skate
 
       int charging_jump, jump_dir;
       float jump_charge;
-      double jump_time;
 
+      double jump_time;
       double start_push,
              cur_push;
 
       v3f prev_pos;
+
+      /* initial launch conditions */
+      double air_start;
+      v3f    air_init_v,
+             air_init_co;
    }
    state,
    state_gate_storage;
@@ -105,6 +113,8 @@ struct player_skate
       v3f   log[50];
       v3f   n;
       v3f   apex;
+      v3f   v;
+
       int   log_length;
       float score,
             land_dist;