move everything to animator based
authorhgn <hgodden00@gmail.com>
Tue, 18 Jul 2023 07:20:36 +0000 (08:20 +0100)
committerhgn <hgodden00@gmail.com>
Tue, 18 Jul 2023 07:20:36 +0000 (08:20 +0100)
14 files changed:
player.h
player_api.h
player_dead.c
player_dead.h
player_drive.c
player_drive.h
player_render.c
player_replay.c
player_replay.h
player_skate.c
player_skate.h
player_walk.c
player_walk.h
workshop.c

index cb60d049e09864278988f0f807f1309153179bc7..2d31e46e28aa8188bae035d5e591fba2c37446c1 100644 (file)
--- a/player.h
+++ b/player.h
@@ -153,7 +153,7 @@ VG_STATIC
 void( *_player_post_update[])( player_instance *player ) = {
    player__walk_post_update,
    player__skate_post_update,
-   NULL,
+   player__dead_post_update,
    player__drive_post_update
 };
 
@@ -174,7 +174,7 @@ void( *_player_animate[])( player_instance *player ) = {
 };
 
 VG_STATIC
-void( *_player_pose[] )( player_instance *player ) = {
+void( *_player_pose[] )( player_instance *player, player_pose *pose ) = {
    player__walk_pose,
    player__skate_pose,
    player__dead_pose,
index 01658418794d65949eb3df214e407797707bf334..2c2d18ece0cab214ebfb66c89a261dea1110c027 100644 (file)
@@ -11,8 +11,8 @@ typedef struct player_pose player_pose;
 
 struct player_pose{
    enum player_pose_type {
-      k_player_pose_type_fk,      /* regular FK animation */
-      k_player_pose_type_absolute /* decomposition of the final matrices */
+      k_player_pose_type_ik,      /* regular IK animation */
+      k_player_pose_type_fk_2,
    }
    type;
 
index b6312cb5273835dfbbdfc204c8157125e85a0cee..78cce2fb76614b6698cf01ed03bcaf11c63e295e 100644 (file)
@@ -8,30 +8,9 @@ VG_STATIC void player__dead_update      ( player_instance *player )
    player_ragdoll_iter( &player->ragdoll );
 }
 
-VG_STATIC void player__dead_animate    ( player_instance *player ){
-   /* nothing here */
-}
-
-VG_STATIC void player__dead_pose        ( player_instance *player ){
-   player_pose *pose = &player->pose;
-   v3_zero( pose->root_co );
-   q_identity( pose->root_q );
-   
-   for( int i=0; i<vg_list_size(pose->keyframes); i ++ ){
-      /* FUUUUTUUREEEE: squangle the rigidbodies back into OK keyframes */
-      v3_zero( pose->keyframes[i].co );
-      v3_fill( pose->keyframes[i].s, 1.0f );
-      q_identity( pose->keyframes[i].q );
-   }
-}
-
-VG_STATIC void player__dead_post_animate( player_instance *player ){
+VG_STATIC void player__dead_post_update( player_instance *player ){
+   struct player_dead *d  = &player->_dead;
    struct player_avatar *av = player->playeravatar;
-   struct player_dead   *d  = &player->_dead;
-
-   copy_ragdoll_pose_to_avatar( &player->ragdoll, player->playeravatar );
-   player->cam_velocity_influence = 1.0f;
-
    struct ragdoll_part *part = &player->ragdoll.parts[ av->id_hip-1 ];
 
    v3f ext_co;
@@ -47,6 +26,103 @@ VG_STATIC void player__dead_post_animate( player_instance *player ){
    v3_zero( player->rb.w );
 }
 
+VG_STATIC void player__dead_animate( player_instance *player ){
+   struct player_dead *d  = &player->_dead;
+   struct player_dead_animator *animator = &d->animator;
+   struct player_ragdoll *rd = &player->ragdoll;
+   struct player_avatar *av = player->playeravatar;
+   struct skeleton *sk = &av->sk;
+
+   m4x3f transforms[ 32 ];
+
+   /* root transform */
+   q_m3x3( player->rb.q, transforms[0] );
+   v3_copy( player->rb.co, transforms[0][3] );
+
+   v4_copy( player->rb.q, animator->transforms[0].q );
+   v3_copy( player->rb.co, animator->transforms[0].co );
+
+   /* colliders with bones transforms */
+   for( int i=0; i<rd->part_count; i++ ){
+      struct ragdoll_part *part = &rd->parts[i];
+
+      m4x3f mtx;
+
+      v4f q_int;
+      v3f co_int;
+
+      float substep = vg.time_fixed_extrapolate;
+      v3_lerp( part->prev_co, part->obj.rb.co, substep, co_int );
+      q_nlerp( part->prev_q, part->obj.rb.q, substep, q_int );
+      v4_copy( part->obj.rb.q, q_int );
+
+      q_m3x3( q_int, mtx );
+      v3_copy( co_int, mtx[3] );
+
+      m4x3_mul( mtx, part->inv_collider_mtx, transforms[part->bone_id] );
+   }
+
+   /* bones without colliders transforms */
+   for( u32 i=1; i<sk->bone_count; i++ ){
+      struct skeleton_bone *sb = &sk->bones[i];
+
+      if( sb->parent && !sb->collider ){
+         v3f delta;
+         v3_sub( sk->bones[i].co, sk->bones[sb->parent].co, delta );
+
+         m4x3f posemtx;
+         m3x3_identity( posemtx );
+         v3_copy( delta, posemtx[3] );
+
+         /* final matrix */
+         m4x3_mul( transforms[sb->parent], posemtx, transforms[i] );
+      }
+   }
+
+   /* measurements */
+   for( u32 i=1; i<sk->bone_count; i++ ){
+      struct skeleton_bone *sb = &sk->bones[i];
+
+      v3_zero( animator->transforms[i].co );
+      q_identity( animator->transforms[i].q );
+
+      m4x3f parent, inverse, local;
+      m3x3_identity( parent );
+      v3_sub( sk->bones[i].co, sk->bones[sb->parent].co, parent[3] );
+      m4x3_mul( transforms[ sb->parent ], parent, parent );
+      m4x3_invert_affine( parent, inverse );
+
+      v3f _s;
+      m4x3_mul( inverse, transforms[i], local );
+      m4x3_decompose( local, animator->transforms[i].co, 
+                             animator->transforms[i].q, _s );
+   }
+}
+
+VG_STATIC void player__dead_pose( player_instance *player, player_pose *pose ){
+   struct player_dead *d  = &player->_dead;
+   struct player_dead_animator *animator = &d->animator;
+   struct player_ragdoll *rd = &player->ragdoll;
+   struct player_avatar *av = player->playeravatar;
+   struct skeleton *sk = &av->sk;
+
+   pose->type = k_player_pose_type_fk_2;
+   pose->board.lean = 0.0f;
+
+   v3_copy( animator->transforms[0].co, pose->root_co );
+   v4_copy( animator->transforms[0].q, pose->root_q );
+
+   for( u32 i=1; i<sk->bone_count; i++ ){
+      v3_copy( animator->transforms[i].co, pose->keyframes[i-1].co );
+      v4_copy( animator->transforms[i].q, pose->keyframes[i-1].q );
+      v3_fill( pose->keyframes[i-1].s, 1.0f );
+   }
+}
+
+VG_STATIC void player__dead_post_animate( player_instance *player ){
+   player->cam_velocity_influence = 1.0f;
+}
+
 VG_STATIC void player__dead_im_gui      ( player_instance *player ){
 
 }
index 43f7574b738529da34a8a2959c0654e4be52d3c1..6a10bea118a29b3a3eabb735011d1295432a1c31 100644 (file)
@@ -5,11 +5,21 @@
 
 struct player_dead{
    v3f co_lpf, v_lpf, w_lpf;
+
+   struct player_dead_animator{
+      struct {
+         v3f co;
+         v4f q;
+      }
+      transforms[ 32 ];
+   }
+   animator;
 };
 
 VG_STATIC void player__dead_update      ( player_instance *player );
+VG_STATIC void player__dead_post_update ( player_instance *player );
 VG_STATIC void player__dead_animate     ( player_instance *player );
-VG_STATIC void player__dead_pose        ( player_instance *player );
+VG_STATIC void player__dead_pose( player_instance *player, player_pose *pose );
 
 VG_STATIC void player__dead_post_animate( player_instance *player );
 VG_STATIC void player__dead_im_gui      ( player_instance *player );
index 157ef4069842d0d8bdd34af8ad1dc233a559a44c..1c83205e0f5529fc65014d03984a216ba2063040 100644 (file)
@@ -31,10 +31,9 @@ VG_STATIC void player__drive_post_update( player_instance *player )
 
 VG_STATIC void player__drive_animate( player_instance *player ){}
 
-VG_STATIC void player__drive_pose( player_instance *player ){
+VG_STATIC void player__drive_pose( player_instance *player, player_pose *pose ){
    struct player_drive *drive = &player->_drive;
    struct skeleton *sk = &player->playeravatar->sk;
-   player_pose *pose = &player->pose;
 
    skeleton_sample_anim( sk, drive->anim_drive, 0.0f, pose->keyframes );
    v3_copy( player->rb.co, pose->root_co );
index dcf689eb04353eb2695226eeac9fdaa50725aee7..7e1bb984688d14af73843afc67c05192118632e9 100644 (file)
@@ -13,7 +13,7 @@ VG_STATIC void player__drive_pre_update( player_instance *player );
 VG_STATIC void player__drive_update( player_instance *player );
 VG_STATIC void player__drive_post_update( player_instance *player );
 VG_STATIC void player__drive_animate( player_instance *player );
-VG_STATIC void player__drive_pose( player_instance *player );
+VG_STATIC void player__drive_pose( player_instance *player, player_pose *pose );
 
 VG_STATIC void player__drive_post_animate( player_instance *player );
 VG_STATIC void player__drive_im_gui( player_instance *player );
index 283b2510e4f0db097d20cfc3ed343775e71b6c9a..d0d14a4c5617ff8470415ceb91c266fd0e1ecf31 100644 (file)
@@ -138,18 +138,36 @@ VG_STATIC void player_model_unload( struct player_model *board ){
    dynamic_model_unload( &board->mdl );
 }
 
+VG_STATIC void player_apply_pose_to_skeleton( player_instance *player ){
+   struct skeleton *sk = &player->playeravatar->sk;
+   player_pose *pose = &player->pose;
+
+   m4x3f transform;
+   q_m3x3( pose->root_q, transform );
+   v3_copy( pose->root_co, transform[3] );
+   
+   if( pose->type == k_player_pose_type_ik ){
+      skeleton_apply_pose( sk, pose->keyframes, k_anim_apply_defer_ik );
+      skeleton_apply_ik_pass( sk );
+      skeleton_apply_pose( sk, pose->keyframes, k_anim_apply_deffered_only );
+      skeleton_apply_inverses( sk );
+      skeleton_apply_transform( sk, transform );
+   }
+   else if( pose->type == k_player_pose_type_fk_2 ){
+      skeleton_apply_pose( sk, pose->keyframes, k_anim_apply_always );
+      skeleton_apply_inverses( sk );
+      skeleton_apply_transform( sk, transform );
+   }
+}
+
 VG_STATIC void player__animate( player_instance *player ){
    if( _player_animate[ player->subsystem ] && 
        _player_pose[ player->subsystem ] ){
       _player_animate[ player->subsystem ]( player );
-      _player_pose[ player->subsystem ]( player );
+      _player_pose[ player->subsystem ]( player, &player->pose );
 
       player_pose *pose = &player->pose;
 
-      m4x3f transform;
-      q_m3x3( pose->root_q, transform );
-      v3_copy( pose->root_co, transform[3] );
-
       struct skeleton *sk = &player->playeravatar->sk;
 
       if( player->holdout_time > 0.0f ){
@@ -159,17 +177,7 @@ VG_STATIC void player__animate( player_instance *player ){
          player->holdout_time -= vg.time_frame_delta * 2.0f;
       }
 
-      if( pose->type == k_player_pose_type_fk ){
-         skeleton_apply_pose( sk, pose->keyframes, k_anim_apply_defer_ik );
-         skeleton_apply_ik_pass( sk );
-         skeleton_apply_pose( sk, pose->keyframes, k_anim_apply_deffered_only );
-         skeleton_apply_inverses( sk );
-         skeleton_apply_transform( sk, transform );
-      }
-      else {
-         skeleton_apply_pose( sk, pose->keyframes, k_anim_apply_absolute );
-      }
-
+      player_apply_pose_to_skeleton( player );
       skeleton_debug( sk );
    }
 
@@ -179,36 +187,67 @@ VG_STATIC void player__animate( player_instance *player ){
    player__cam_iterate( player );
 }
 
+VG_STATIC void player_copy_frame_animator( player_instance *player,
+                                           replay_frame *frame ){
+   void *animator_src = replay_frame_data( frame, k_replay_framedata_animator );
+   u16 animator_size = frame->data_table[ k_replay_framedata_animator ][1];
+
+   if( frame->system == k_player_subsystem_walk ){
+      memcpy( &player->_walk.animator, animator_src, animator_size );
+   }
+   else if( frame->system == k_player_subsystem_dead ){
+      memcpy( &player->_dead.animator, animator_src, animator_size );
+   }
+   else if( frame->system == k_player_subsystem_skate ){
+      memcpy( &player->_skate.animator, animator_src, animator_size );
+   }
+   else if( frame->system == k_player_subsystem_drive ){
+      
+   }
+}
+
 VG_STATIC void player__animate_from_replay( player_instance *player,
                                             replay_buffer *replay ){
-   /* TODO: holdout blending (from when the game has to slow down) */
    replay_frame *frame = replay->cursor_frame,
                 *next = NULL;
-
-   player_pose *pose = &player->pose;
-
    if( frame ){
       next = frame->r;
 
       if( next ){
          f32 t = replay_subframe_time( replay );
 
+         player_pose pose0, pose1;
+
+         player_copy_frame_animator( player, frame );
+         _player_pose[ frame->system ]( player, &pose0 );
+
+         player_copy_frame_animator( player, next );
+         _player_pose[ next->system ]( player, &pose1 );
+
+         v3_lerp( pose0.root_co, pose1.root_co, t, player->pose.root_co );
+         q_nlerp( pose0.root_q,  pose1.root_q,  t, player->pose.root_q );
+         player->pose.type = pose0.type;
+         player->pose.board.lean = vg_lerpf( pose0.board.lean,
+                                             pose1.board.lean, t );
+
          struct skeleton *sk = &player->playeravatar->sk;
-         skeleton_lerp_pose( sk, frame->pose.keyframes, next->pose.keyframes, 
-                             t, pose->keyframes );
-         v3_lerp( frame->pose.root_co, next->pose.root_co, t, pose->root_co );
-         q_nlerp( frame->pose.root_q, next->pose.root_q, t, pose->root_q );
-         pose->type = k_player_pose_type_absolute;
-         pose->board.lean = vg_lerpf( frame->pose.board.lean,
-                                      next->pose.board.lean, t );
+         if( pose0.type != pose1.type ){
+            /* it would be nice to apply IK pass in-keyframes. TOO BAD! */
+            skeleton_copy_pose( sk, pose0.keyframes, player->pose.keyframes );
+         }
+         else {
+            skeleton_lerp_pose( sk, pose0.keyframes, pose1.keyframes, 
+                                t, player->pose.keyframes );
+         }
+      }
+      else{
+         player_copy_frame_animator( player, frame );
+         _player_pose[ frame->system ]( player, &player->pose );
       }
-      else 
-         memcpy( pose, &frame->pose, sizeof(frame->pose) );
    }
    else return;
 
-   struct skeleton *sk = &player->playeravatar->sk;
-   skeleton_apply_pose( sk, pose->keyframes, k_anim_apply_absolute );
+   player_apply_pose_to_skeleton( player );
 }
 
 VG_STATIC void player__pre_render( player_instance *player ){
index 319cf03a64943d53646c4c75fdff794dc33b9821..fc57680b7060349d8355ee6d58f630ab1cdaec04 100644 (file)
@@ -13,43 +13,23 @@ VG_STATIC void replay_clear( replay_buffer *replay ){
    replay->cursor = -99999.9;
 }
 
-replay_gamestate *replay_frame_gamestate( replay_frame *frame ){
+VG_STATIC void *
+replay_frame_data( replay_frame *frame, enum replay_framedata type ){
    void *baseptr = frame;
-   return baseptr + vg_align8(sizeof(replay_frame));
+   return baseptr + frame->data_table[type][0];
 }
 
-void *replay_gamestate_subsystem_data( replay_gamestate *gs ){
-   void *baseptr = gs;
-   return baseptr + vg_align8(sizeof(replay_gamestate));
-}
+VG_STATIC u16
+replay_frame_calculate_data_offsets( u16 data_table[4][2] ){
+   u32 total = vg_align8( sizeof(replay_frame) );
+   for( u32 i=0; i<4; i++ ){
+      data_table[i][0] = total;
+      total += vg_align8(data_table[i][1]);
 
-u32 replay_frame_gamestate_total_size( u32 subsystem_gamestate_size ){
-   if( subsystem_gamestate_size ){
-      return vg_align8( sizeof(replay_gamestate) ) + 
-             vg_align8( subsystem_gamestate_size );
+      if( total > 0xffff )
+         vg_fatal_error( "Exceeded frame storage capacity\n" );
    }
-   else
-      return 0;
-}
-
-replay_sfx *replay_frame_sfx( replay_frame *frame, u32 index ){
-   void *gs = replay_frame_gamestate( frame );
-   u32 total_size = 
-      replay_frame_gamestate_total_size( frame->subsystem_gamestate_size );
-
-   replay_sfx *array = (gs + total_size);
-   return &array[index];
-}
-
-u32 _replay_frame_size( u32 subsystem_gamestate_size, u32 sfx_count ){
-   return vg_align8( sizeof( replay_frame ) ) + 
-          replay_frame_gamestate_total_size( subsystem_gamestate_size ) +
-          vg_align8( sfx_count * sizeof(replay_sfx) );
-}
-
-u32 replay_frame_size( replay_frame *frame ){
-   return _replay_frame_size( frame->subsystem_gamestate_size, 
-                              frame->sfx_count );
+   return total;
 }
 
 VG_STATIC void replay_tailpop( replay_buffer *replay ){
@@ -67,15 +47,27 @@ VG_STATIC void replay_tailpop( replay_buffer *replay ){
 }
 
 VG_STATIC replay_frame *replay_newframe( replay_buffer *replay, 
-                                         u32 subsystem_gamestate_size, 
-                                         u32 sfx_count ){
+                                         u16 animator_size,
+                                         u16 gamestate_size,
+                                         u16 sfx_count ){
+   u16 data_table[4][2];
+   data_table[ k_replay_framedata_animator ][1]  = animator_size;
+   data_table[ k_replay_framedata_gamestate ][1] = gamestate_size;
+   data_table[ k_replay_framedata_sfx ][1]       = 0;
+   data_table[ k_replay_framedata_internal_gamestate ][1] = 0;
+   if( gamestate_size ){
+      data_table[ k_replay_framedata_internal_gamestate ][1] = 
+         sizeof( replay_gamestate );
+   }
+
+   u32 nextsize = replay_frame_calculate_data_offsets( data_table );
+
    replay_frame *frame = NULL;
    if( replay->head ){
       assert( replay->head );
 
-      u32 headsize = replay_frame_size( replay->head ),
-          nextpos  = ((void *)replay->head - replay->data) + headsize,
-          nextsize = _replay_frame_size( subsystem_gamestate_size, sfx_count );
+      u32 headsize = replay->head->total_size,
+          nextpos  = ((void *)replay->head - replay->data) + headsize;
 
       if( nextsize > replay->size ){
          vg_error( "Keyframe too big\n" );
@@ -94,7 +86,6 @@ VG_STATIC replay_frame *replay_newframe( replay_buffer *replay,
       }
 
 check_again:;
-
       u32 tailpos = (void *)replay->tail - replay->data;
 
       if( tailpos >= nextpos ){
@@ -114,13 +105,17 @@ check_again:;
    else
       frame = replay->data;
 
-   frame->subsystem_gamestate_size = subsystem_gamestate_size;
-   frame->sfx_count = sfx_count;
+   for( u32 i=0; i<4; i++ ){
+      frame->data_table[i][0] = data_table[i][0];
+      frame->data_table[i][1] = data_table[i][1];
+   }
+
+   frame->total_size = nextsize;
    frame->l = replay->head;
    frame->r = NULL;
    replay->head = frame;
    if( !replay->tail ) replay->tail = frame;
-   if( subsystem_gamestate_size ) replay->statehead = frame;
+   if( gamestate_size ) replay->statehead = frame;
 
    return frame;
 }
@@ -174,7 +169,7 @@ VG_STATIC replay_frame *replay_find_recent_stateframe( replay_buffer *replay ){
    u32 i=4096;
    while( i --> 0 ){
       if( !frame ) return frame;
-      if( frame->subsystem_gamestate_size ) return frame;
+      if( frame->data_table[ k_replay_framedata_gamestate ][1] ) return frame;
       frame = frame->l;
    }
 
@@ -253,8 +248,7 @@ void skaterift_record_frame( replay_buffer *replay, int force_gamestate ){
 
    if( !save_frame ) return;
 
-   u32 gamestate_size = 0;
-
+   u16 gamestate_size = 0;
    if( save_state ){
       gamestate_size = (u32 []){ 
          [k_player_subsystem_walk ] = sizeof(struct player_walk_state),
@@ -264,12 +258,21 @@ void skaterift_record_frame( replay_buffer *replay, int force_gamestate ){
                                        sizeof(struct replay_rb)
       }[ localplayer.subsystem ];
    }
+
+   u16 animator_size = (u16 []){
+      [k_player_subsystem_walk ] = sizeof(struct player_walk_animator),
+      [k_player_subsystem_drive] = 0,
+      [k_player_subsystem_skate] = sizeof(struct player_skate_animator),
+      [k_player_subsystem_dead ] = sizeof(struct player_dead_animator)
+   }[ localplayer.subsystem ];
    
-   replay_frame *frame = replay_newframe( replay, gamestate_size, 0 );
+   replay_frame *frame = replay_newframe( replay,
+                                          animator_size, gamestate_size, 0 );
+   frame->system = localplayer.subsystem;
 
    if( save_state ){
-      replay_gamestate *gs = replay_frame_gamestate( frame );
-      gs->system = localplayer.subsystem;
+      replay_gamestate *gs = 
+         replay_frame_data( frame, k_replay_framedata_internal_gamestate );
 
       /* permanent block */
       memcpy( &gs->rb, &localplayer.rb, sizeof(rigidbody) );
@@ -277,7 +280,7 @@ void skaterift_record_frame( replay_buffer *replay, int force_gamestate ){
                sizeof(struct player_cam_controller) );
       v3_copy( localplayer.angles, gs->angles );
 
-      void *dst = replay_gamestate_subsystem_data( gs );
+      void *dst = replay_frame_data( frame, k_replay_framedata_gamestate );
 
       /* subsytem/dynamic block */
       if( localplayer.subsystem == k_player_subsystem_walk )
@@ -298,53 +301,44 @@ void skaterift_record_frame( replay_buffer *replay, int force_gamestate ){
 
    replay->cursor = vg.time;
    replay->cursor_frame = frame;
-
-   player_pose *res = &frame->pose;
-   v3_zero( res->root_co );
-   q_identity( res->root_q );
-   res->type = k_player_pose_type_absolute;
-
-   struct skeleton *sk = &localplayer.playeravatar->sk;
-
-   memcpy( &frame->pose.board, &localplayer.pose.board, 
-            sizeof(localplayer.pose.board) );
    frame->time = vg.time;
-   v3_copy( localplayer.cam.pos, frame->cam_pos );
 
+   /* camera */
+   v3_copy( localplayer.cam.pos, frame->cam_pos );
    if( localplayer.gate_waiting ){
       m4x3_mulv( localplayer.gate_waiting->transport, 
                   frame->cam_pos, frame->cam_pos );
-
-      for( u32 i=1; i<sk->bone_count; i++ ){
-         struct skeleton_bone *sb = &sk->bones[i];
-         mdl_keyframe *kf = &res->keyframes[i-1];
-         m4x3f mtx;
-         m4x3_mul( localplayer.gate_waiting->transport, sk->final_mtx[i], mtx );
-         m4x3_decompose( mtx, kf->co, kf->q, kf->s );
-      }
    }
-   else
-      skeleton_decompose_mtx_absolute( sk, res->keyframes );
-
    v3_copy( localplayer.cam.angles, frame->cam_angles );
    frame->cam_fov = localplayer.cam.fov;
+
+   /* animator */
+   void *dst = replay_frame_data( frame, k_replay_framedata_animator );
+
+   if( localplayer.subsystem == k_player_subsystem_walk )
+      memcpy( dst, &localplayer._walk.animator, animator_size );
+   else if( localplayer.subsystem == k_player_subsystem_skate )
+      memcpy( dst, &localplayer._skate.animator, animator_size );
+   else if( localplayer.subsystem == k_player_subsystem_dead ){
+      memcpy( dst, &localplayer._dead.animator, animator_size );
+   }
 }
 
 VG_STATIC
 void skaterift_restore_frame( replay_frame *frame ){
-   replay_gamestate *gs = replay_frame_gamestate( frame );
-   void *src = replay_gamestate_subsystem_data( gs );
-
-   /* TODO: Move this to subsystem bindings now that its variable */
-   if( gs->system == k_player_subsystem_walk ){
-      memcpy( &localplayer._walk.state, src,
-              frame->subsystem_gamestate_size );
+   replay_gamestate *gs = 
+      replay_frame_data( frame, k_replay_framedata_internal_gamestate );
+   void *src = replay_frame_data( frame, k_replay_framedata_gamestate );
+   u16 src_size = frame->data_table[ k_replay_framedata_gamestate ][1];
+   assert( src_size );
+
+   if(frame->system == k_player_subsystem_walk ){
+      memcpy( &localplayer._walk.state, src, src_size );
    }
-   else if( gs->system == k_player_subsystem_skate ){
-      memcpy( &localplayer._skate.state, src,
-              frame->subsystem_gamestate_size );
+   else if( frame->system == k_player_subsystem_skate ){
+      memcpy( &localplayer._skate.state, src, src_size );
    }
-   else if( gs->system == k_player_subsystem_dead ){
+   else if( frame->system == k_player_subsystem_dead ){
       player__dead_transition( &localplayer );
       struct replay_rb *arr = src;
 
@@ -362,7 +356,7 @@ void skaterift_restore_frame( replay_frame *frame ){
       }
    }
 
-   localplayer.subsystem = gs->system;
+   localplayer.subsystem = frame->system;
 
    memcpy( &localplayer.rb, &gs->rb, sizeof(rigidbody) );
    v3_copy( gs->angles, localplayer.angles );
@@ -539,11 +533,17 @@ VG_STATIC void skaterift_replay_debug_info(void){
 
    player__debugtext( 1, "head @%u | tail @%u\n", head, tail );
 
+   for( u32 i=0; i<4; i++ ){
+      player__debugtext( 1, "[%u]: [%hu, %hu]\n", i,
+           replay->statehead->data_table[i][0],
+           replay->statehead->data_table[i][1] );
+   }
+
    if( replay->statehead ){
       u32 state = (void *)replay->statehead - replay->data;
       player__debugtext( 1, "gs @%u\n", state );
-      player__debugtext( 1, "gamestate_size: %u\n", 
-                         replay->statehead->subsystem_gamestate_size );
+      player__debugtext( 1, "gamestate_size: %hu\n", 
+           replay->statehead->data_table[k_replay_framedata_gamestate][1] );
    }
    else
       player__debugtext( 1, "gs @NULL\n" );
index 73bbb222585a30e97458ef566ca34964e755eff1..9890be0b80dfbe87403de6e73018a0f5a6ca4736 100644 (file)
@@ -19,33 +19,30 @@ struct replay_buffer {
    f64 cursor;
 };
 
-struct replay_frame {
-   player_pose pose;
+enum replay_framedata{
+   k_replay_framedata_animator,
+   k_replay_framedata_gamestate,
+   k_replay_framedata_internal_gamestate,
+   k_replay_framedata_sfx
+};
 
+struct replay_frame {
    v3f cam_pos, cam_angles;
    f32 cam_fov;
 
    f64 time;
    replay_frame *l, *r;
 
-   u32 subsystem_gamestate_size,
-       sfx_count;
+   enum player_subsystem system;
+   u16 total_size;
+   u16 data_table[4][2];
 };
 
 struct replay_gamestate {
-   enum player_subsystem system;
    rigidbody rb;
    v3f angles;
 
    struct player_cam_controller cam_control;
-
-#if 0
-   union {
-      struct player_skate_state skate;
-      struct player_walk_state  walk;
-      struct player_ragdoll     ragdoll;
-   };
-#endif
 };
 
 struct replay_sfx {
@@ -53,17 +50,18 @@ struct replay_sfx {
 };
 
 VG_STATIC replay_frame *replay_newframe( replay_buffer *replay, 
-                                         u32 gamestate_count, u32 sfx_count );
+                                         u16 animator_size,
+                                         u16 gamestate_size,
+                                         u16 sfx_count );
 VG_STATIC void replay_seek( replay_buffer *replay, f64 t );
 
-replay_gamestate *replay_frame_gamestate( replay_frame *frame );
-void *replay_gamestate_subsystem_data( replay_gamestate *gs );
-replay_sfx *replay_frame_sfx( replay_frame *frame, u32 index );
 VG_STATIC replay_frame *replay_find_recent_stateframe( replay_buffer *replay );
 VG_STATIC void replay_get_camera( replay_buffer *replay, camera *cam );
 VG_STATIC void replay_get_frame_camera( replay_frame *frame, camera *cam );
 VG_STATIC f32 replay_subframe_time( replay_buffer *replay );
 VG_STATIC void replay_clear( replay_buffer *replay );
+VG_STATIC void *
+replay_frame_data( replay_frame *frame, enum replay_framedata type );
 
 VG_STATIC void skaterift_replay_pre_update(void);
 VG_STATIC void skaterift_replay_imgui(void);
index fe34de2441ce6b3d40a5bbe5542b448fc5d2f4fa..d56fc982787b323111af1849b44ce185362ccb6a 100644 (file)
@@ -1110,12 +1110,12 @@ VG_STATIC void player__skate_pre_update( player_instance *player ){
       player->subsystem = k_player_subsystem_walk;
 
       v3f angles;
-      v3_copy( player->cam.angles, angles );
-      angles[2] = 0.0f;
+      v3_copy( player->cam.angles, player->angles );
+      player->angles[2] = 0.0f;
 
       player__begin_holdout( player );
       player__skate_kill_audio( player );
-      player__walk_transition( player, angles );
+      player__walk_transition( player );
       return;
    }
 
@@ -2773,6 +2773,19 @@ VG_STATIC void player__skate_animate( player_instance *player ){
    animator->board_euler[1] += extra;
    animator->trick_type = s->state.trick_type;
 
+   /* board lean */
+   f32 lean1, lean2 = animator->steer[0] * animator->reverse * -0.36f,
+       lean;
+
+   lean1 = animator->slide * animator->delayed_slip_dir;
+   if( fabsf(lean1)>fabsf(lean2) ) lean = lean1;
+   else                            lean = lean2;
+
+   if( ((int)roundf(animator->board_euler[0])) % 2 ) lean = -lean;
+   lean = vg_clampf( lean, -1.0f, 1.0f );
+   animator->board_lean = 
+      vg_lerpf(animator->board_lean, lean, vg.time_delta*18.0f);
+
    /* feet placement */
    struct player_board *board = 
       addon_cache_item_if_loaded( k_addon_type_board,
@@ -2886,13 +2899,12 @@ VG_STATIC void player__skate_animate( player_instance *player ){
    rb_extrapolate( &player->rb, animator->root_co, animator->root_q );
 }
                         
-VG_STATIC void player__skate_pose( player_instance *player ){
+VG_STATIC void player__skate_pose( player_instance *player, player_pose *pose ){
    struct player_avatar *av = player->playeravatar;
    struct skeleton *sk = &av->sk;
    struct player_skate *s = &player->_skate;
    struct player_skate_animator *animator = &s->animator;
-   player_pose *pose = &player->pose;
-   pose->type = k_player_pose_type_fk;
+   pose->type = k_player_pose_type_ik;
    v3_copy( animator->root_co, pose->root_co );
    v4_copy( animator->root_q, pose->root_q );
 
@@ -2923,17 +2935,7 @@ VG_STATIC void player__skate_pose( player_instance *player ){
       f32 dir_frame   = animator->z * (15.0f/30.0f),
           stand_blend = animator->offset[1]*-2.0f;
 
-      f32 lean1,
-          lean2 = animator->steer[0] * animator->reverse * -0.36f,
-          lean;
-
-      lean1 = animator->slide * animator->delayed_slip_dir;
-      if( fabsf(lean1)>fabsf(lean2) ) lean = lean1;
-      else                            lean = lean2;
-
-      if( ((int)roundf(animator->board_euler[0])) % 2 ) lean = -lean;
-      lean = vg_clampf( lean, -1.0f, 1.0f );
-      pose->board.lean = vg_lerpf(pose->board.lean, lean, vg.time_delta*18.0f);
+      pose->board.lean = animator->board_lean;
 
       stand_blend = vg_clampf( 1.0f-animator->local_cog[1], 0, 1 );
 
index e5dde1208fe1696b270748664932ea4bfded9abc..3d1a9806c93fb70d3dc01d74daa2832199e7ce8d 100644 (file)
@@ -112,6 +112,7 @@ struct player_skate{
       v4f qflip;
 
       v3f board_euler;
+      f32 board_lean;
       v2f steer, grab;
 
       f32 jump_charge;
@@ -325,7 +326,7 @@ VG_STATIC void player__skate_update       ( player_instance *player );
 VG_STATIC void player__skate_post_update  ( player_instance *player );
 VG_STATIC void player__skate_im_gui       ( player_instance *player );
 VG_STATIC void player__skate_animate      ( player_instance *player );
-VG_STATIC void player__skate_pose         ( player_instance *player );
+VG_STATIC void player__skate_pose( player_instance *player, player_pose *pose );
 VG_STATIC void player__skate_post_animate ( player_instance *player );
 VG_STATIC void player__skate_reset        ( player_instance *player,
                                             ent_spawn *rp );
index 2c038431e175825427749f2f37f56c5acf0f56c8..077dfd9a823d2cffa59acb10abd16323bc14cb7a 100644 (file)
@@ -787,15 +787,15 @@ VG_STATIC void player__walk_animate( player_instance *player ){
    q_normalize( animator->root_q );
 }
 
-VG_STATIC void player__walk_pose( player_instance *player ){
+VG_STATIC void player__walk_pose( player_instance *player, player_pose *pose ){
    struct player_walk *w = &player->_walk;
    struct player_walk_animator *animator = &w->animator;
    struct skeleton *sk = &player->playeravatar->sk;
    struct player_avatar *av = player->playeravatar;
 
-   player_pose *pose = &player->pose;
    v3_copy( animator->root_co, pose->root_co );
    v4_copy( animator->root_q, pose->root_q );
+   pose->board.lean = 0.0f;
 
    float walk_norm = (float)w->anim_walk->length/30.0f,
          run_norm  = (float)w->anim_run->length/30.0f,
@@ -914,7 +914,7 @@ VG_STATIC void player__walk_bind( player_instance *player ){
    w->anim_intro        = skeleton_get_anim( sk, "into_skate" );
 }
 
-VG_STATIC void player__walk_transition( player_instance *player, v3f angles ){
+VG_STATIC void player__walk_transition( player_instance *player ){
    struct player_walk *w = &player->_walk;
    w->state.activity = k_walk_activity_air;
 
index e1e075593e983fba0f4de82dea3e5fb3ece8526d..3dcdbd8001bbbe14a2fe634ac3431eba81ee6d54 100644 (file)
@@ -88,11 +88,11 @@ VG_STATIC void player__walk_pre_update  ( player_instance *player );
 VG_STATIC void player__walk_update      ( player_instance *player );
 VG_STATIC void player__walk_post_update ( player_instance *player );
 VG_STATIC void player__walk_animate     ( player_instance *player );
-VG_STATIC void player__walk_pose        ( player_instance *player );
+VG_STATIC void player__walk_pose( player_instance *player, player_pose *pose );
 VG_STATIC void player__walk_post_animate( player_instance *player );
 VG_STATIC void player__walk_im_gui      ( player_instance *player );
 VG_STATIC void player__walk_bind        ( player_instance *player );
-VG_STATIC void player__walk_transition  ( player_instance *player, v3f angles );
+VG_STATIC void player__walk_transition  ( player_instance *player );
 VG_STATIC void player__walk_reset       ( player_instance *player, 
                                           ent_spawn *rp );
 VG_STATIC void player__walk_restore( player_instance *player );
index b048af98d57dbe878f8e1c6b6c2a69f0cb54715d..b0c8da6e1e19de2b14808b57fc2ca5e1c5eabafe 100644 (file)
@@ -900,7 +900,7 @@ VG_STATIC void workshop_render_player_preview(void){
    struct skeleton *sk = &localplayer.playeravatar->sk;
 
    player_pose res;
-   res.type = k_player_pose_type_fk;
+   res.type = k_player_pose_type_ik;
 
    struct skeleton_anim *anim = skeleton_get_anim( sk, "idle_cycle+y" );
    skeleton_sample_anim( sk, anim, vg.time*0.1f, res.keyframes );