From eb28dee29482c7ffe8bc0203d302e3ee6dbfd943 Mon Sep 17 00:00:00 2001 From: hgn Date: Sun, 1 Oct 2023 00:58:01 +0100 Subject: [PATCH] interp test 1 --- network_msg.h | 1 + player_remote.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++-- player_remote.h | 31 +++++++++--- player_render.h | 2 + skaterift.c | 4 ++ 5 files changed, 154 insertions(+), 12 deletions(-) diff --git a/network_msg.h b/network_msg.h index b76e695..286bfb0 100644 --- a/network_msg.h +++ b/network_msg.h @@ -92,6 +92,7 @@ typedef struct netmsg_playerframe netmsg_playerframe; enum{ k_inetmsg_playerframe = 200 }; struct netmsg_playerframe{ u32 inetmsg_id; + f64 timestamp; u8 client, subsystem; u8 animdata[]; }; diff --git a/player_remote.c b/player_remote.c index 71d12d1..4989b07 100644 --- a/player_remote.c +++ b/player_remote.c @@ -1,4 +1,6 @@ #include "player_remote.h" +#include "skeleton.h" +#include "player_render.h" static void player_remote_unwatch( struct network_player *player ){ addon_cache_unwatch( k_addon_type_player, player->playermodel_view_slot ); @@ -12,6 +14,14 @@ static void player_remote_clear( struct network_player *player ){ player->subsystem = k_player_subsystem_invalid; } +static void player_remote_clear_interp( u32 index ){ + struct interp_buffer *buf = &netplayers.interp_data[ index ]; + buf->t = -99999999.9; + for( u32 i=0; iframes); i ++ ){ + buf->frames[i].active = 0; + } +} + static void player_remote_rx_200_300( SteamNetworkingMessage_t *msg ){ netmsg_blank *tmp = msg->m_pData; @@ -27,6 +37,7 @@ static void player_remote_rx_200_300( SteamNetworkingMessage_t *msg ){ /* TODO: interpret the uids */ player->board_view_slot = 0; player->playermodel_view_slot = 0; + player_remote_clear_interp( playerjoin->index ); vg_strncpy( playerjoin->username, player->username, sizeof(player->username), k_strncpy_always_add_null ); @@ -70,7 +81,7 @@ static void player_remote_rx_200_300( SteamNetworkingMessage_t *msg ){ else if( tmp->inetmsg_id == k_inetmsg_playerframe ){ u32 datasize = msg->m_cbSize - sizeof(netmsg_playerframe); - if( datasize > sizeof(netplayers.list[0].animdata) ){ + if( datasize > sizeof(union interp_animdata) ){ vg_error( "Player frame data exceeds animdata size\n" ); return; } @@ -86,8 +97,30 @@ static void player_remote_rx_200_300( SteamNetworkingMessage_t *msg ){ return; } + struct interp_buffer *ib = &netplayers.interp_data[ frame->client ]; + struct interp_frame *dest = NULL; + + f64 min_time = INFINITY; + for( u32 i=0; iframes); i++ ){ + struct interp_frame *ifr = &ib->frames[i]; + + if( !ifr->active ){ + dest = ifr; + break; + } + + if( ifr->timestamp < min_time ){ + min_time = ifr->timestamp; + dest = ifr; + } + } + + dest->active = 1; + dest->timestamp = frame->timestamp; + dest->subsystem = frame->subsystem; + struct network_player *player = &netplayers.list[ frame->client ]; - memcpy( &player->animdata, frame->animdata, datasize ); + memcpy( &dest->data, frame->animdata, datasize ); player->subsystem = frame->subsystem; player->down_bytes += msg->m_cbSize; } @@ -105,6 +138,7 @@ static void remote_player_send_playerframe(void){ frame->inetmsg_id = k_inetmsg_playerframe; frame->client = 0; frame->subsystem = localplayer.subsystem; + frame->timestamp = vg.time_real; memcpy( frame->animdata, sys->animator_data, sys->animator_size ); netplayers.up_bytes += size; @@ -194,7 +228,8 @@ static void remote_player_network_imgui( m4x4f pv ){ ui_info( panel, buf ); v4f wpos = { 0.0f, 2.0f, 0.0f, 1.0f }; - m4x3_mulv( netplayers.final_mtx[0], wpos, wpos ); + struct player_avatar *av = localplayer.playeravatar; + m4x3_mulv( netplayers.final_mtx[av->sk.bone_count*i], wpos, wpos ); m4x4_mulv( pv, wpos, wpos ); if( wpos[3] > 0.0f ){ @@ -202,7 +237,7 @@ static void remote_player_network_imgui( m4x4f pv ){ v2_add( wpos, (v2f){ 0.5f, 0.5f }, wpos ); ui_rect wr; - wr[0] = vg_clampf(wpos[0] * vg.window_x, -32000.0f,32000.0f); + wr[0] = vg_clampf(wpos[0] * vg.window_x, -32000.0f,32000.0f)-150; wr[1] = vg_clampf((1.0f-wpos[1]) * vg.window_y, -32000.0f,32000.0f); wr[2] = 300; @@ -217,3 +252,88 @@ static void remote_player_network_imgui( m4x4f pv ){ ui_info( panel, "offline" ); } } + +static void pose_remote_player( u32 index, + struct interp_frame *f0, + struct interp_frame *f1 ){ + + struct interp_buffer *buf = &netplayers.interp_data[ index ]; + struct player_avatar *av = localplayer.playeravatar; + struct skeleton *sk = &localplayer.playeravatar->sk; + m4x3f *final_mtx = &netplayers.final_mtx[ av->sk.bone_count*index ]; + + struct player_subsystem_interface *sys0 = player_subsystems[f0->subsystem], + *sys1 = NULL; + + player_pose pose0, pose1, posed; + + sys0->pose( &f0->data, &pose0 ); + + if( f1 ){ + f32 t = (buf->t - f0->timestamp) / (f1->timestamp - f0->timestamp); + t = vg_clampf( t, 0.0f, 1.0f ); + + sys1 = player_subsystems[f1->subsystem]; + sys1->pose( &f1->data, &pose1 ); + + if( pose0.type != pose1.type ){ + /* it would be nice to apply IK pass in-keyframes. TOO BAD! */ + skeleton_copy_pose( sk, pose0.keyframes, posed.keyframes ); + } + else { + skeleton_lerp_pose( sk, pose0.keyframes, pose1.keyframes, t, + posed.keyframes ); + } + + apply_full_skeleton_pose( &av->sk, &posed, final_mtx ); + } + else { + apply_full_skeleton_pose( &av->sk, &pose0, final_mtx ); + } +} + +static void animate_remote_player( u32 index ){ + + f64 min_time = 999999999.9, + max_time = -999999999.9, + abs_max_time = -999999999.9; + + struct interp_frame *minframe = NULL, + *maxframe = NULL, + *abs_max_frame = NULL; + + struct interp_buffer *buf = &netplayers.interp_data[index]; + for( u32 i=0; iframes); i ++ ){ + struct interp_frame *ifr = &buf->frames[i]; + + if( ifr->active ){ + if( (ifr->timestamp < min_time) && (ifr->timestamp > buf->t) ){ + min_time = ifr->timestamp; + minframe = ifr; + } + + if( (ifr->timestamp > max_time) && (ifr->timestamp < buf->t) ){ + max_time = ifr->timestamp; + maxframe = ifr; + } + + if( ifr->timestamp > abs_max_time ){ + abs_max_time = ifr->timestamp; + abs_max_frame = ifr; + } + } + } + + if( minframe && maxframe ){ + pose_remote_player( index, minframe, maxframe ); + buf->t += vg.time_frame_delta; + } + else { + buf->t = abs_max_time - 0.25; + + if( abs_max_frame ) + pose_remote_player( index, abs_max_frame, NULL ); + else + return; + } +} diff --git a/player_remote.h b/player_remote.h index 1360e54..ca96290 100644 --- a/player_remote.h +++ b/player_remote.h @@ -8,19 +8,33 @@ struct { struct network_player { int active; u16 board_view_slot, playermodel_view_slot; + enum player_subsystem subsystem; char username[32]; u32 down_bytes; f32 down_kbs; - - enum player_subsystem subsystem; - union { - struct player_skate_animator _skate; - struct player_walk_animator _walk; - struct player_dead_animator _dead; - } animdata; } - list[ 32 ]; + list[32]; + + struct interp_buffer { + /* collect the most recent 6 frames of animation data */ + struct interp_frame { + int active; + f64 timestamp; + enum player_subsystem subsystem; + + union interp_animdata { + struct player_skate_animator _skate; + struct player_walk_animator _walk; + struct player_dead_animator _dead; + } + data; + } + frames[6]; + + f64 t; + } + interp_data[32]; m4x3f *final_mtx; @@ -33,5 +47,6 @@ static netplayers; static void player_remote_rx_200_300( SteamNetworkingMessage_t *msg ); static void remote_player_debug_update(void); static void remote_player_send_playerframe(void); +static void animate_remote_player( u32 index ); #endif /* PLAYER_REMOTE_H */ diff --git a/player_render.h b/player_render.h index 44f26e1..f25f68b 100644 --- a/player_render.h +++ b/player_render.h @@ -87,5 +87,7 @@ static void render_playermodel( camera *cam, world_instance *world, struct player_model *model, struct skeleton *skeleton, m4x3f *final_mtx ); +static void apply_full_skeleton_pose( struct skeleton *sk, player_pose *pose, + m4x3f *final_mtx ); #endif /* PLAYER_RENDER_H */ diff --git a/skaterift.c b/skaterift.c index 7041f94..81b8091 100644 --- a/skaterift.c +++ b/skaterift.c @@ -459,6 +459,9 @@ static void animate_remote_players(void){ for( u32 i=0; iactive ) continue; + + animate_remote_player( i ); +#if 0 if( player->subsystem > k_player_subsystem_max ) continue; struct player_subsystem_interface *sys = @@ -470,6 +473,7 @@ static void animate_remote_players(void){ sys->pose( &player->animdata, &pose ); apply_full_skeleton_pose( &av->sk, &pose, &netplayers.final_mtx[ av->sk.bone_count*i ] ); +#endif } } -- 2.25.1