prelim tricks
authorhgn <hgodden00@gmail.com>
Mon, 6 Feb 2023 05:15:59 +0000 (05:15 +0000)
committerhgn <hgodden00@gmail.com>
Mon, 6 Feb 2023 05:15:59 +0000 (05:15 +0000)
player.c
player_skate.c
player_skate.h
player_walk.c

index c898e6d83958eaf4315bf3de3a92f828c6fd336b..85cf9166f25ff00b2690e56add842c5917291827 100644 (file)
--- a/player.c
+++ b/player.c
@@ -265,18 +265,16 @@ PLAYER_API void player__im_gui( player_instance *player )
 
    vg_uictx.cursor[0] = vg.window_x;
 
+#if 0
    player__debugtext( 1, "%.2f %.2f %.2f", player->cam.pos[0],
                                            player->cam.pos[1],
                                            player->cam.pos[2] );
+#endif
    player__debugtext( 1, "%.2f %.2f %.2f (%.2f)", 
                                            player->cam.angles[0],
                                            player->cam.angles[1],
                                            player->cam.angles[2],
                                            player->cam.fov);
-   player__debugtext( 1, "C/K %.2f %.2f (%.2f)", 
-                              player->cam_velocity_coefficient_smooth,
-                              player->cam_velocity_constant_smooth,
-                              player->cam_velocity_influence_smooth );
 
    if( _player_im_gui[ player->subsystem ] )
       _player_im_gui[ player->subsystem ]( player );
index d71e3cb89b7a93e3b1c7dd60d02af294d444a657..788bf0bff2adc7d54c0c3648bb5d13c507b69058 100644 (file)
@@ -712,6 +712,71 @@ VG_STATIC void skate_apply_interface_model( player_instance *player,
    }
 }
 
+VG_STATIC void skate_apply_trick_model( player_instance *player )
+{
+   struct player_skate *s = &player->_skate;
+
+   v3f Fd, Fs, F;
+   v3f strength = { 3.7f, 3.6f, 8.0f };
+
+   v3_muls( s->board_trick_residualv, -4.0f , Fd );
+   v3_muls( s->board_trick_residuald, -10.0f, Fs );
+   v3_add( Fd, Fs, F );
+   v3_mul( strength, F, F );
+
+   v3_muladds( s->board_trick_residualv, F, k_rb_delta, 
+               s->board_trick_residualv );
+   v3_muladds( s->board_trick_residuald, s->board_trick_residualv,
+               k_rb_delta, s->board_trick_residuald );
+
+   if( s->state.activity == k_skate_activity_air )
+   {
+      if( v3_length2( s->state.trick_vel ) < 0.0001f )
+         return;
+
+      int carry_on = player->input_jump->button.value;
+
+      /* we assume velocities share a common divisor, in which case the 
+       * interval is the minimum value (if not zero) */
+
+      float min_rate = 99999.0f;
+
+      for( int i=0; i<3; i++ )
+      {
+         float v = s->state.trick_vel[i];
+         if( (v > 0.0f) && (v < min_rate) )
+            min_rate = v;
+      }
+
+      float interval = 1.0f / min_rate,
+            current  = floorf( s->state.trick_time / interval ),
+            next_end = (current+1.0f) * interval;
+
+
+      /* integrate trick velocities */
+      v3_muladds( s->state.trick_euler, s->state.trick_vel, k_rb_delta,
+                  s->state.trick_euler );
+
+      if( !carry_on && (s->state.trick_time + k_rb_delta >= next_end) )
+      {
+         s->state.trick_time = 0.0f;
+         s->state.trick_euler[0] = roundf( s->state.trick_euler[0] );
+         s->state.trick_euler[1] = roundf( s->state.trick_euler[1] );
+         s->state.trick_euler[2] = roundf( s->state.trick_euler[2] );
+         v3_copy( s->state.trick_vel, s->board_trick_residualv );
+         v3_zero( s->state.trick_vel );
+      }
+
+      s->state.trick_time += k_rb_delta;
+   }
+   else
+   {
+      if( s->state.lift_frames == 0 )
+      {
+      }
+   }
+}
+
 VG_STATIC void skate_apply_grab_model( player_instance *player )
 {
    struct player_skate *s = &player->_skate;
@@ -855,6 +920,12 @@ VG_STATIC void skate_apply_jump_model( player_instance *player )
       s->state.steery_s = -steer[0] * maxspin;
       s->state.steerx = s->state.steerx_s;
 
+      v3_zero( s->state.trick_vel );
+      s->state.trick_vel[0] = 3.0f;
+      s->state.trick_vel[2] = 6.0f;
+      s->state.trick_time = 0.0f;
+      s->state.lift_frames ++;
+
       /* FIXME audio events */
 #if 0
       audio_lock();
@@ -1163,6 +1234,7 @@ VG_STATIC void player__skate_update( player_instance *player )
    skate_apply_friction_model( player );
    skate_apply_jump_model( player );
    skate_apply_air_model( player );
+   skate_apply_trick_model( player );
 
    skate_integrate( player );
 
@@ -1208,16 +1280,24 @@ VG_STATIC void player__skate_im_gui( player_instance *player )
                                                 player->rb.w[1],
                                                 player->rb.w[2] );
 
-   player__debugtext( 1, "activity: %s\n",
+   player__debugtext( 1, "activity: %s",
                            (const char *[]){ "k_skate_activity_air",
                                              "k_skate_activity_ground",
                                              "k_skate_activity_grind }" }
                                              [s->state.activity] );
-   player__debugtext( 1, "steer_s: %5.2f %5.2f [%.2f %.2f]\n",
+   player__debugtext( 1, "steer_s: %5.2f %5.2f [%.2f %.2f]",
                         s->state.steerx_s, s->state.steery_s,
                         k_steer_ground, k_steer_air );
-   player__debugtext( 1, "flip: %.4f %.4f\n", s->state.flip_rate, 
+   player__debugtext( 1, "flip: %.4f %.4f", s->state.flip_rate, 
                                              s->state.flip_time );
+   player__debugtext( 1, "trickv: %.2f %.2f %.2f", 
+                           s->state.trick_vel[0],
+                           s->state.trick_vel[1],
+                           s->state.trick_vel[2] );
+   player__debugtext( 1, "tricke: %.2f %.2f %.2f", 
+                           s->state.trick_euler[0],
+                           s->state.trick_euler[1],
+                           s->state.trick_euler[2] );
 }
 
 VG_STATIC void player__skate_animate( player_instance *player,
@@ -1395,20 +1475,58 @@ VG_STATIC void player__skate_animate( player_instance *player,
       v3_add( bo, kf_foot_l->co, kf_foot_l->co );
       v3_add( bo, kf_foot_r->co, kf_foot_r->co );
 
+#if 0
       m3x3f c;
       q_m3x3( s->board_rotation, c );
+#endif
+
+      v4f qtotal;
+
+      v4f qtrickr, qyawr, qpitchr, qrollr;
+      v3f eulerr;
+
+      
+
+      v3_muls( s->board_trick_residuald, VG_TAUf, eulerr );
+
+      q_axis_angle( qyawr,   (v3f){0.0f,1.0f,0.0f}, eulerr[0] * 0.5f );
+      q_axis_angle( qpitchr, (v3f){1.0f,0.0f,0.0f}, eulerr[1] );
+      q_axis_angle( qrollr,  (v3f){0.0f,0.0f,1.0f}, eulerr[2] );
+
+      q_mul( qpitchr, qrollr, qtrickr );
+      q_mul( qyawr, qtrickr, qtrickr );
+      q_mul( s->board_rotation, qtrickr, qtotal );
+      q_normalize( qtotal );
+
+      q_mul( qtotal, kf_board->q, kf_board->q );
+
 
       v3f d;
       v3_sub( kf_foot_l->co, bo, d );
-      m3x3_mulv( c, d, d );
+      q_mulv( qtotal, d, d );
       v3_add( bo, d, kf_foot_l->co );
       
       v3_sub( kf_foot_r->co, bo, d );
-      m3x3_mulv( c, d, d );
+      q_mulv( qtotal, d, d );
       v3_add( bo, d, kf_foot_r->co );
 
       q_mul( s->board_rotation, kf_board->q, kf_board->q );
       q_normalize( kf_board->q );
+
+
+      /* trick rotation */
+      v4f qtrick, qyaw, qpitch, qroll;
+      v3f euler;
+      v3_muls( s->state.trick_euler, VG_TAUf, euler );
+
+      q_axis_angle( qyaw,   (v3f){0.0f,1.0f,0.0f}, euler[0] * 0.5f );
+      q_axis_angle( qpitch, (v3f){1.0f,0.0f,0.0f}, euler[1] );
+      q_axis_angle( qroll,  (v3f){0.0f,0.0f,1.0f}, euler[2] );
+
+      q_mul( qpitch, qroll, qtrick );
+      q_mul( qyaw, qtrick, qtrick );
+      q_mul( qtrick, kf_board->q, kf_board->q );
+      q_normalize( kf_board->q );
    }
 
    /* transform */
index f0efcf8ac3df169f6d911648c110968620980cba..1833062d0bef5939966d2878f461c13cd30031c6 100644 (file)
@@ -23,10 +23,15 @@ struct player_skate
             reverse,
             slip;
 
+      /* tricks */
       v3f   flip_axis;
       float flip_time,
             flip_rate;
 
+      v3f   trick_vel,     /* measured in units of TAU/s */
+            trick_euler;   /* measured in units of TAU */
+      float trick_time;
+
       m3x3f velocity_bias,
             velocity_bias_pstep;
       v3f apex;
@@ -82,7 +87,9 @@ struct player_skate
                         *anim_ollie, *anim_ollie_reverse,
                         *anim_grabs, *anim_stop;
    rb_sphere sphere_front, sphere_back;
-   v3f board_offset;
+   v3f board_offset,
+       board_trick_residualv,
+       board_trick_residuald;
    v4f board_rotation;
 
    float blend_slide,
index 0503f48fde51853c300f8cccfaf868ca7c42d2b1..0a6a4856e9e40f6c525d65a17a4a5f0e5973acfa 100644 (file)
@@ -49,6 +49,7 @@ VG_STATIC void player_walk_generic_to_skate( player_instance *player,
    player__skate_reset_animator( player );
    player__skate_clear_mechanics( player );
    rb_update_transform( &player->rb );
+   v3_copy( (v3f){0.0f,0.0f,0.0f}, s->state.trick_euler );
 
    if( init == k_skate_activity_air )
       player__approximate_best_trajectory( player );
@@ -74,6 +75,33 @@ VG_STATIC void player_walk_drop_in_to_skate( player_instance *player )
    v3_copy( init_velocity, s->state.cog_v );
    v3_copy( init_velocity, player->rb.v );
    v3_copy( init_velocity, player->cam_velocity_smooth );
+   v3_copy( (v3f){1.0f,0.0f,0.0f}, s->state.trick_euler );
+}
+
+VG_STATIC void player_walk_drop_in_overhang_transform( player_instance *player,
+                                                       float t,
+                                                       v3f co, v4f q )
+{
+   struct player_walk *w = &player->_walk;
+
+   v3f axis;
+   v3_cross( (v3f){0.0f,1.0f,0.0f}, w->state.drop_in_normal, axis );
+   v3_normalize( axis );
+
+   float a = acosf( w->state.drop_in_normal[1] ) * t;
+
+   q_axis_angle( q, axis, a );
+
+   float l = t * 0.5f,
+         heading_angle = w->state.drop_in_angle;
+
+   v3f overhang;
+   overhang[0] = sinf( heading_angle ) * l;
+   overhang[1] = 0.28f * l;
+   overhang[2] = cosf( heading_angle ) * l;
+
+   q_mulv( q, overhang, overhang );
+   v3_add( w->state.drop_in_target, overhang, co );
 }
 
 VG_STATIC int player_walk_scan_for_drop_in( player_instance *player )
@@ -153,6 +181,48 @@ VG_STATIC int player_walk_scan_for_drop_in( player_instance *player )
       {
          v3_copy( edge, w->state.drop_in_target );
          v3_copy( s1->normal, w->state.drop_in_normal );
+         v3_copy( player->rb.co, w->state.drop_in_start );
+
+         w->state.drop_in_start_angle = player_get_heading_yaw( player );
+         w->state.drop_in_angle = atan2f( w->state.drop_in_normal[0],
+                                          w->state.drop_in_normal[2] );
+
+         /* TODO: scan multiple of these? */
+         v3f oco;
+         v4f oq;
+         player_walk_drop_in_overhang_transform( player, 1.0f, oco, oq );
+
+         v3f va = {0.0f,0.0f,-k_board_length - 0.3f},
+             vb = {0.0f,0.0f, k_board_length + 0.3f};
+
+         q_mulv( oq, va, va );
+         q_mulv( oq, vb, vb );
+         v3_add( oco, va, va );
+         v3_add( oco, vb, vb );
+
+         v3f v0;
+         v3_sub( vb, va, v0 );
+         v3_normalize( v0 );
+
+         ray_hit ray;
+         ray.dist = k_board_length*2.0f + 0.6f;
+         
+         if( ray_world( va, v0, &ray ) )
+         {
+            vg_line( va, vb, VG__RED );
+            vg_line_pt3( ray.pos, 0.1f, VG__RED );
+            vg_error( "invalidated\n" );
+            return 0;
+         }
+
+         v3_muls( v0, -1.0f, v0 );
+         if( ray_world( vb, v0, &ray ) )
+         {
+            vg_line( va, vb, VG__RED );
+            vg_line_pt3( ray.pos, 0.1f, VG__RED );
+            vg_error( "invalidated\n" );
+            return 0;
+         }
 
          player_walk_drop_in_vector( player, player->rb.v );
          return 1;
@@ -203,11 +273,6 @@ VG_STATIC void player__walk_pre_update( player_instance *player )
             w->state.outro_anim = w->anim_drop_in;
             w->state.outro_start_time = vg.time;
             w->state.activity = k_walk_activity_immobile;
-            v3_copy( player->rb.co, w->state.drop_in_start );
-
-            w->state.drop_in_start_angle = player_get_heading_yaw( player );
-            w->state.drop_in_angle = atan2f( w->state.drop_in_normal[0],
-                                             w->state.drop_in_normal[2] );
 
             struct player_avatar *av = player->playeravatar;
             m4x3_mulv( av->sk.final_mtx[ av->id_ik_foot_r ], 
@@ -506,7 +571,7 @@ VG_STATIC void player__walk_post_update( player_instance *player )
    struct player_walk *w = &player->_walk;
 
    m4x3f mtx;
-   m3x3_identity( mtx );
+   m3x3_copy( player->rb.to_world, mtx );
    v3_add( player->rb.co, (v3f){0.0f, 1.0f, 0.0f}, mtx[3] );
 
    float substep = vg_clampf( vg.accumulator / k_rb_delta, 0.0f, 1.0f );
@@ -658,27 +723,10 @@ VG_STATIC void player__walk_animate( player_instance *player,
          if( step_t >= 1.0f )
          {
             v4f final_q;
-            v3f axis;
-            v3_cross( (v3f){0.0f,1.0f,0.0f}, w->state.drop_in_normal, axis );
-            v3_normalize( axis );
-
-            float a = acosf( w->state.drop_in_normal[1] ) * dop_t;
-
-            q_axis_angle( final_q, axis, a );
+            player_walk_drop_in_overhang_transform( player, dop_t, 
+                                                    player->rb.co, final_q );
             q_mul( final_q, dest->root_q, dest->root_q );
 
-            float l = dop_t * 0.5f,
-                  heading_angle = w->state.drop_in_angle;
-
-            v3f overhang;
-            overhang[0] = sinf( heading_angle ) * l;
-            overhang[1] = 0.28f * l;
-            overhang[2] = cosf( heading_angle ) * l;
-
-            q_mulv( final_q, overhang, overhang );
-
-            v3f overhang_pos;
-            v3_add( w->state.drop_in_target, overhang, player->rb.co );
             v4_copy( dest->root_q, player->rb.q );
             v3_muladds( dest->root_co, player->rb.to_world[1], 
                         -0.28f * dop_t, dest->root_co );