switch to dynamic sizes
authorhgn <hgodden00@gmail.com>
Sun, 9 Jul 2023 21:11:25 +0000 (22:11 +0100)
committerhgn <hgodden00@gmail.com>
Sun, 9 Jul 2023 21:11:25 +0000 (22:11 +0100)
player_dead.h
player_render.c
player_replay.c
player_replay.h
skaterift.c

index 4a10e986eba41a0f08728f157c7b2128af92b134..fbdb47f5a974665660fc9dc1213d39a0cd2fffb9 100644 (file)
@@ -3,8 +3,7 @@
 
 #include "player_api.h"
 
-struct player_dead
-{
+struct player_dead{
    v3f co_lpf, v_lpf, w_lpf;
 };
 
index b6cbf6311f387bae3f1aee10de0f9e8d92b4a28c..aaefb0742d806aa54fe09c34adbeb0bbca240d58 100644 (file)
@@ -183,12 +183,28 @@ VG_STATIC void player__animate_from_replay( player_instance *player,
    /* TODO: holdout blending (from when the game has to slow down) */
 
    player_animation res;
-   replay_frame *frame = replay->cursor_frame;
+   replay_frame *frame = replay->cursor_frame,
+                *next = NULL;
 
    if( frame ){
-      memcpy( &res, &frame->anim, sizeof(frame->anim) );
-      memcpy( &frame->board_pose, &player->board_pose, 
-              sizeof(player->board_pose) );
+      next = frame->r;
+
+      if( next ){
+         f32 t = replay_subframe_time( replay );
+
+         struct skeleton *sk = &player->playeravatar->sk;
+         skeleton_lerp_pose(sk, frame->anim.pose, next->anim.pose, t, res.pose);
+         v3_lerp( frame->anim.root_co, next->anim.root_co, t, res.root_co );
+         q_nlerp( frame->anim.root_q, next->anim.root_q, t, res.root_q );
+         res.type = k_player_animation_type_absolute;
+         player->board_pose.lean = vg_lerpf( frame->board_pose.lean,
+                                             next->board_pose.lean, t );
+      }
+      else {
+         memcpy( &res, &frame->anim, sizeof(frame->anim) );
+         memcpy( &frame->board_pose, &player->board_pose, 
+                 sizeof(player->board_pose) );
+      }
    }
    else return;
 
@@ -211,13 +227,26 @@ void player_record_replay_frame( player_instance *player,
    const f64 k_replay_rate = 1.0/30.0,
              k_gamestate_rate = 0.5;
 
-   u16 gamestates = 0;
-   if( statedelta > k_gamestate_rate || force_gamestate /* or switching */ ){
-      gamestates = 1;
+   u32 gamestate_size = 0;
+   void *gamestate_src = NULL;
+   if( (statedelta > k_gamestate_rate) || force_gamestate ){
+      if( player->subsystem == k_player_subsystem_walk ){
+         gamestate_size = sizeof(struct player_walk_state);
+         gamestate_src  = &player->_walk.state;
+      }
+      else if( player->subsystem == k_player_subsystem_skate ){
+         gamestate_size = sizeof(struct player_skate_state);
+         gamestate_src  = &player->_skate.state;
+      }
+      else if( player->subsystem == k_player_subsystem_dead ){
+         gamestate_size = sizeof(struct player_ragdoll);
+         gamestate_src  = &player->ragdoll;
+      }
    }
+   assert( gamestate_size < 0xffff );
    
-   if( (delta > k_replay_rate) || gamestates ){
-      replay_frame *frame = replay_newframe( replay, gamestates, 0 );
+   if( (delta > k_replay_rate) || gamestate_size ){
+      replay_frame *frame = replay_newframe( replay, gamestate_size, 0 );
       replay->cursor = vg.time;
       replay->cursor_frame = frame;
 
@@ -236,23 +265,19 @@ void player_record_replay_frame( player_instance *player,
       v3_copy( player->cam.angles, frame->cam_angles );
       frame->cam_fov = player->cam.fov;
 
-      if( gamestates ){
-         replay_gamestate *gs = replay_frame_gamestate( frame, 0 );
+      if( gamestate_size ){
+         replay_gamestate *gs = replay_frame_gamestate( frame );
          gs->system = player->subsystem;
 
-         if( player->subsystem == k_player_subsystem_walk ){
-            memcpy( &gs->walk, &player->_walk.state, 
-                     sizeof(struct player_walk_state) );
-         }
-         else if( player->subsystem == k_player_subsystem_skate ){
-            memcpy( &gs->skate, &player->_skate.state, 
-                     sizeof(struct player_skate_state) );
-         }
-
+         /* permanent block */
          memcpy( &gs->rb, &player->rb, sizeof(rigidbody) );
          memcpy( &gs->cam_control, &player->cam_control, 
                   sizeof(struct player_cam_controller) );
          v3_copy( player->angles, gs->angles );
+
+         /* subsytem/dynamic block */
+         void *dst = replay_gamestate_subsystem_data( gs );
+         memcpy( dst, gamestate_src, gamestate_size );
       }
    }
 }
index 09cc136cbd477d6395aaea837b2486f815ae1da9..1215f62d3f13d893114226b73fd422ebe842bcb7 100644 (file)
@@ -11,48 +11,85 @@ VG_STATIC void replay_clear( replay_buffer *replay ){
    replay->cursor = -99999.9;
 }
 
-replay_gamestate *replay_frame_gamestate( replay_frame *frame, u16 index ){
+replay_gamestate *replay_frame_gamestate( replay_frame *frame ){
    void *baseptr = frame;
-   
-   replay_gamestate *array = (baseptr + vg_align8( sizeof(replay_frame)));
-   return &array[ index ];
+   return baseptr + vg_align8(sizeof(replay_frame));
+}
+
+void *replay_gamestate_subsystem_data( replay_gamestate *gs ){
+   void *baseptr = gs;
+   return baseptr + vg_align8(sizeof(replay_gamestate));
+}
+
+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 );
+   }
+   else
+      return 0;
 }
 
-replay_sfx *replay_frame_sfx( replay_frame *frame, u16 index ){
-   void *gsarr = replay_frame_gamestate( frame, 0 );
-   u32 gssize = frame->gamestate_count * sizeof(replay_gamestate);
+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 = (gsarr + vg_align8(gssize));
+   replay_sfx *array = (gs + total_size);
    return &array[index];
 }
 
-u32 _replay_frame_size( u16 gamestate_count, u16 sfx_count ){
+u32 _replay_frame_size( u32 subsystem_gamestate_size, u32 sfx_count ){
    return vg_align8( sizeof( replay_frame ) ) + 
-          vg_align8( gamestate_count * sizeof(replay_gamestate) ) +
+          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->gamestate_count, frame->sfx_count );
+   return _replay_frame_size( frame->subsystem_gamestate_size, 
+                              frame->sfx_count );
+}
+
+VG_STATIC void replay_tailpop( replay_buffer *replay ){
+   if( replay->cursor_frame == replay->tail )
+      replay->cursor_frame = NULL;
+   if( replay->statehead == replay->tail )
+      replay->statehead = NULL;
+
+   replay->tail = replay->tail->r;
+
+   if( replay->tail )
+      replay->tail->l = NULL;
+   else
+      replay->head = NULL;
 }
 
 VG_STATIC replay_frame *replay_newframe( replay_buffer *replay, 
-                                         u16 gamestate_count, u16 sfx_count ){
+                                         u32 subsystem_gamestate_size, 
+                                         u32 sfx_count ){
    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( gamestate_count, sfx_count );
+          nextsize = _replay_frame_size( subsystem_gamestate_size, sfx_count );
 
       if( nextsize > replay->size ){
          vg_error( "Keyframe too big\n" );
          return NULL;
       }
 
-      if( nextpos + nextsize > replay->size )
+      if( nextpos + nextsize > replay->size ){
          nextpos = 0;
+         
+         /* maintain contiguity */
+         while( replay->tail ){
+            if( (void *)replay->tail - replay->data )
+               replay_tailpop( replay );
+            else break;
+         }
+      }
 
 check_again:;
 
@@ -60,21 +97,10 @@ check_again:;
 
       if( tailpos >= nextpos ){
          if( nextpos + nextsize > tailpos ){
-            /* remove links */
-            if( replay->cursor_frame == replay->tail )
-               replay->cursor_frame = NULL;
-            if( replay->statehead == replay->tail )
-               replay->statehead = NULL;
-
-            /* pop node */
-            replay->tail = replay->tail->r;
+            replay_tailpop( replay );
 
-            if( replay->tail ) {
-               replay->tail->l = NULL;
+            if( replay->tail )
                goto check_again;
-            }
-            else
-               replay->head = NULL;
          }
       }
 
@@ -86,13 +112,13 @@ check_again:;
    else
       frame = replay->data;
 
-   frame->gamestate_count = gamestate_count;
+   frame->subsystem_gamestate_size = subsystem_gamestate_size;
    frame->sfx_count = sfx_count;
    frame->l = replay->head;
    frame->r = NULL;
    replay->head = frame;
    if( !replay->tail ) replay->tail = frame;
-   if( gamestate_count ) replay->statehead = frame;
+   if( subsystem_gamestate_size ) replay->statehead = frame;
 
    return frame;
 }
@@ -143,25 +169,51 @@ VG_STATIC void replay_seek( replay_buffer *replay, f64 t ){
 
 VG_STATIC replay_frame *replay_find_recent_stateframe( replay_buffer *replay ){
    replay_frame *frame = replay->cursor_frame;
-
    u32 i=4096;
    while( i --> 0 ){
       if( !frame ) return frame;
-      if( frame->gamestate_count ) return frame;
+      if( frame->subsystem_gamestate_size ) return frame;
       frame = frame->l;
    }
 
    return NULL;
 }
 
+VG_STATIC f32 replay_subframe_time( replay_buffer *replay ){
+   replay_frame *frame = replay->cursor_frame;
+   if( !frame ) return 0.0f;
+   replay_frame *next = frame->r;
+   if( next ){
+      f64 l = next->time - frame->time,
+          t = (replay->cursor - frame->time) / l;
+      return vg_clampf( t, 0.0f, 1.0f );
+   }
+   else 
+      return 0.0f;
+}
+
+VG_STATIC void replay_get_frame_camera( replay_frame *frame, camera *cam ){
+   cam->fov = frame->cam_fov;
+   v3_copy( frame->cam_pos, cam->pos );
+   v3_copy( frame->cam_angles, cam->angles );
+}
+
 VG_STATIC void replay_get_camera( replay_buffer *replay, camera *cam ){
    cam->nearz = 0.1f;
    cam->farz = 100.0f;
    if( replay->cursor_frame ){
-      /* TODO: frame lerp */
-      cam->fov = replay->cursor_frame->cam_fov;
-      v3_copy( replay->cursor_frame->cam_pos, cam->pos );
-      v3_copy( replay->cursor_frame->cam_angles, cam->angles );
+      replay_frame *next = replay->cursor_frame->r;
+
+      if( next ){
+         camera temp;
+         
+         replay_get_frame_camera( replay->cursor_frame, cam );
+         replay_get_frame_camera( next, &temp );
+         camera_lerp( cam, &temp, replay_subframe_time( replay ), cam );
+      }
+      else {
+         replay_get_frame_camera( replay->cursor_frame, cam );
+      }
    }
    else {
       v3_zero( cam->pos );
@@ -200,16 +252,23 @@ VG_STATIC void skaterift_replay_pre_update(void){
 
       if( prev ){
          /* TODO: Make gamestate_apply function / swap ... */
-         replay_gamestate *gs = replay_frame_gamestate( prev, 0 );
+         replay_gamestate *gs = replay_frame_gamestate( prev );
+         void *src = replay_gamestate_subsystem_data( gs );
 
          if( gs->system == k_player_subsystem_walk ){
-            memcpy( &localplayer._walk.state, &gs->walk, 
-                     sizeof(struct player_walk_state) );
+            memcpy( &localplayer._walk.state, src,
+                    prev->subsystem_gamestate_size );
          }
          else if( gs->system == k_player_subsystem_skate ){
-            memcpy( &localplayer._skate.state, &gs->skate, 
-                     sizeof(struct player_skate_state) );
+            memcpy( &localplayer._skate.state, src,
+                    prev->subsystem_gamestate_size );
+         }
+         else if( gs->system == k_player_subsystem_dead ){
+            player__dead_transition( &localplayer );
+            memcpy( &localplayer.ragdoll, src, 
+                    prev->subsystem_gamestate_size );
          }
+
          localplayer.subsystem = gs->system;
 
          memcpy( &localplayer.rb, &gs->rb, sizeof(rigidbody) );
@@ -251,6 +310,8 @@ VG_STATIC void skaterift_replay_debug_info(void){
    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 );
    }
    else
       player__debugtext( 1, "gs @NULL\n" );
index 52a077291594ecd4fb1500c16b8fbcbe103af126..91b9f72ce2aabf02e4446bbedc2807f0d4168bee 100644 (file)
@@ -29,7 +29,8 @@ struct replay_frame {
    f64 time;
    replay_frame *l, *r;
 
-   u16 gamestate_count, sfx_count;
+   u32 subsystem_gamestate_size,
+       sfx_count;
 };
 
 struct replay_gamestate {
@@ -39,10 +40,13 @@ struct replay_gamestate {
 
    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 {
@@ -50,12 +54,16 @@ struct replay_sfx {
 };
 
 VG_STATIC replay_frame *replay_newframe( replay_buffer *replay, 
-                                         u16 gamestate_count, u16 sfx_count );
+                                         u32 gamestate_count, u32 sfx_count );
 VG_STATIC void replay_seek( replay_buffer *replay, f64 t );
 
-replay_gamestate *replay_frame_gamestate( replay_frame *frame, u16 index );
-replay_sfx *replay_frame_sfx( replay_frame *frame, u16 index );
+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 skaterift_replay_pre_update(void);
 VG_STATIC void skaterift_replay_imgui(void);
index 64fb65a2055522ca7f3d2d37b6944c14f10a5d45..b06db689de4648c2c0217f9b9d16d468ea00d1c5 100644 (file)
@@ -284,13 +284,6 @@ VG_STATIC void vg_pre_update(void){
 
    vg_slewf( &skaterift.time_rate, target, vg.time_frame_delta * 6.0f );
    vg.time_rate = vg_smoothstepf( skaterift.time_rate );
-
-   if( button_down( k_srbind_reset ) ){
-      if( skaterift.activity == k_skaterift_default ){
-         skaterift.activity = k_skaterift_replay;
-         player_record_replay_frame( &localplayer, &skaterift.replay, 1 );
-      }
-   }
    
    player__pre_update( &localplayer );
    global_skateshop_preupdate();
@@ -493,6 +486,14 @@ VG_STATIC void render_main_game(void){
    render_scene_gate_subview();
 
    present_view_with_post_processing();
+
+   /* capture the current resume frame at the very last point */
+   if( button_down( k_srbind_reset ) ){
+      if( skaterift.activity == k_skaterift_default ){
+         skaterift.activity = k_skaterift_replay;
+         player_record_replay_frame( &localplayer, &skaterift.replay, 1 );
+      }
+   }
 }
 
 VG_STATIC void vg_render(void){