X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=player_remote.c;h=dc133b25f0454e34deabf12fc019d8671c73eae6;hb=5ecddf16ae658b5f526d8d370a63223cf141a592;hp=71d12d1aa2e0f09967e96240089a08776e7726e8;hpb=d680579754c876a74bf77ac74a224900ce0b3ff9;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/player_remote.c b/player_remote.c index 71d12d1..dc133b2 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,93 @@ 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 ); + } + + v3_lerp( pose0.root_co, pose1.root_co, t, posed.root_co ); + q_nlerp( pose0.root_q, pose1.root_q, t, posed.root_q ); + posed.type = pose0.type; + posed.board.lean = vg_lerpf( pose0.board.lean, pose1.board.lean, t ); + + 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; + } +}