network compression test
authorhgn <hgodden00@gmail.com>
Tue, 3 Oct 2023 18:17:15 +0000 (19:17 +0100)
committerhgn <hgodden00@gmail.com>
Tue, 3 Oct 2023 18:17:15 +0000 (19:17 +0100)
network_compression.h [new file with mode: 0644]
player.h
player_remote.c
player_skate.c
player_skate.h

diff --git a/network_compression.h b/network_compression.h
new file mode 100644 (file)
index 0000000..6ef08f9
--- /dev/null
@@ -0,0 +1,115 @@
+#ifndef NETWORK_COMPRESSION_H
+#define NETWORK_COMPRESSION_H
+
+#include "vg/vg_stdint.h"
+#include "vg/vg_m.h"
+
+typedef struct bitpack_ctx bitpack_ctx;
+struct bitpack_ctx {
+   enum bitpack_mode {
+      k_bitpack_compress,
+      k_bitpack_decompress
+   }
+   mode;
+
+   u8 *buffer;
+   u32 bytes, buffer_len;
+};
+
+static void bitpack_bytes( bitpack_ctx *ctx, u32 bytes, void *data ){
+   u8 *ext = data;
+   for( u32 i=0; i<bytes; i++ ){
+      u32 index = ctx->bytes+i;
+      if( ctx->mode == k_bitpack_compress ){
+         if( index < ctx->buffer_len )
+            ctx->buffer[index] = ext[i];
+      }
+      else{
+         if( index < ctx->buffer_len )
+            ext[i] = ctx->buffer[index];
+         else
+            ext[i] = 0x00;
+      }
+   }
+   ctx->bytes += bytes;
+}
+
+static void bitpack_qf32( bitpack_ctx *ctx, u32 bits, 
+                          f32 min, f32 max, f32 *v ){
+   u32 mask = (0x1 << bits) - 1;
+
+   if( ctx->mode == k_bitpack_compress ){
+      u32 a = vg_quantf( *v, bits, min, max );
+      bitpack_bytes( ctx, bits/8, &a );
+   }
+   else {
+      u32 a = 0;
+      bitpack_bytes( ctx, bits/8, &a );
+      *v = vg_dequantf( a, bits, min, max );
+   }
+}
+
+static void bitpack_qv2f( bitpack_ctx *ctx, u32 bits,
+                          f32 min, f32 max, v2f v ){
+   for( u32 i=0; i<2; i ++ )
+      bitpack_qf32( ctx, bits, min, max, v+i );
+}
+
+static void bitpack_qv3f( bitpack_ctx *ctx, u32 bits,
+                          f32 min, f32 max, v3f v ){
+   for( u32 i=0; i<3; i ++ )
+      bitpack_qf32( ctx, bits, min, max, v+i );
+}
+
+static void bitpack_qv4f( bitpack_ctx *ctx, u32 bits,
+                          f32 min, f32 max, v4f v ){
+   for( u32 i=0; i<4; i ++ )
+      bitpack_qf32( ctx, bits, min, max, v+i );
+}
+
+static void bitpack_qquat( bitpack_ctx *ctx, v4f quat ){
+   const f32 k_domain = 0.70710678118f;
+
+   if( ctx->mode == k_bitpack_compress ){
+      v4f qabs;
+      for( u32 i=0; i<4; i++ )
+         qabs[i] = fabsf(quat[i]);
+
+      u32 lxy =  qabs[1]>qabs[0],
+          lzw = (qabs[3]>qabs[2])+2,
+          l   = qabs[lzw]>qabs[lxy]? lzw: lxy;
+
+      f32 sign = vg_signf(quat[l]);
+
+      u32 smallest[3];
+      for( u32 i=0, j=0; i<4; i ++ )
+         if( i != l )
+            smallest[j ++] = vg_quantf( quat[i]*sign, 10, -k_domain, k_domain );
+      
+      u32 comp = (smallest[0]<<2) | (smallest[1]<<12) | (smallest[2]<<22) | l;
+      bitpack_bytes( ctx, 4, &comp );
+   }
+   else {
+      u32 comp;
+      bitpack_bytes( ctx, 4, &comp );
+
+      u32 smallest[3] = {(comp>>2 )&0x3ff,
+                         (comp>>12)&0x3ff,
+                         (comp>>22)&0x3ff},
+          l = comp & 0x3;
+
+      f32 m = 1.0f;
+
+      for( u32 i=0, j=0; i<4; i ++ ){
+         if( i != l ){
+            quat[i] = vg_dequantf( smallest[j ++], 10, -k_domain, k_domain );
+            m -= quat[i]*quat[i];
+         }
+      }
+
+      quat[l] = sqrtf(m);
+      q_normalize( quat );
+   }
+}
+
+#endif /* NETWORK_COMPRESSION_H */
index 63e30287bef6cf4e8b15917088070e21c725ad91..bb870288f9ce1971ce181c42dd431d206bfcc974 100644 (file)
--- a/player.h
+++ b/player.h
@@ -3,6 +3,7 @@
 
 #include "skaterift.h"
 #include "player_common.h"
+#include "network_compression.h"
 
 enum player_subsystem{
    k_player_subsystem_walk = 0,
@@ -43,6 +44,7 @@ struct player_subsystem_interface{
    void(*animate)(void);
    void(*pose)( void *animator, player_pose *pose );
    void(*post_animate)(void);
+   void(*network_animator_exchange)( bitpack_ctx *ctx, void *data );
 
    void *animator_data;
    u32 animator_size;
index 73ed42ce3a7f4e9f0a2c4544671aaaff61e914a5..cfad5e9018d236280207831ffc020eeeaa03095f 100644 (file)
@@ -157,7 +157,25 @@ static void player_remote_rx_200_300( SteamNetworkingMessage_t *msg ){
       dest->boundary_hash = frame->boundary_hash;
 
       struct network_player *player = &netplayers.list[ frame->client ];
-      memcpy( &dest->data, frame->animdata, datasize );
+
+      struct player_subsystem_interface *sys = 
+         player_subsystems[ frame->subsystem ];
+
+      if( sys->network_animator_exchange ){
+         bitpack_ctx ctx = {
+            .mode = k_bitpack_decompress,
+            .buffer = frame->animdata,
+            .buffer_len = datasize,
+            .bytes = 0,
+         };
+         
+         memset( &dest->data, 0, sys->animator_size );
+         sys->network_animator_exchange( &ctx, &dest->data );
+      }
+      else {
+         memcpy( &dest->data, frame->animdata, datasize );
+      }
+
       player->subsystem = frame->subsystem;
       player->down_bytes += msg->m_cbSize;
    }
@@ -227,7 +245,20 @@ static void remote_player_send_playerframe(void){
       frame->boundary_hash = localplayer.boundary_hash;
       frame->instance_id = world_static.active_instance;
 
-      memcpy( frame->animdata, sys->animator_data, sys->animator_size );
+      if( sys->network_animator_exchange ){
+         bitpack_ctx ctx = {
+            .mode = k_bitpack_compress,
+            .buffer = frame->animdata,
+            .buffer_len = size,
+            .bytes = 0,
+         };
+         
+         sys->network_animator_exchange( &ctx, sys->animator_data );
+         size = ctx.bytes;
+      }
+      else{
+         memcpy( frame->animdata, sys->animator_data, sys->animator_size );
+      }
 
       netplayers.up_bytes += size;
 
index f8b41660955128441b76d9badc5284f7a6cb6d6c..7acc9f5ff0292652a4caa0ce6e7afbbc5b5b89db 100644 (file)
@@ -3185,4 +3185,53 @@ static void player__skate_reset( ent_spawn *rp ){
    state->head_position[1] = 1.8f;
 }
 
+#include "network_compression.h"
+
+static void player__skate_animator_exchange( bitpack_ctx *ctx, void *data ){
+   struct player_skate_animator *animator = data;
+   
+   bitpack_bytes( ctx, sizeof(animator->root_co), animator->root_co );
+   bitpack_qquat( ctx, animator->root_q );
+   bitpack_qv3f( ctx, 8, -1.0f, 1.0f, animator->offset );
+   bitpack_qv3f( ctx, 8, -1.0f, 1.0f, animator->local_cog );
+   bitpack_qf32( ctx, 8,  0.0f, 1.0f, &animator->slide );
+   bitpack_qf32( ctx, 8, -1.0f, 1.0f, &animator->z );
+   bitpack_qf32( ctx, 8, -1.0f, 1.0f, &animator->x );
+
+   /* these could likely be pressed down into single bits if needed */
+   bitpack_qf32( ctx, 8,  0.0f, 1.0f, &animator->fly );
+   bitpack_qf32( ctx, 8,  0.0f, 1.0f, &animator->grind );
+   bitpack_qf32( ctx, 8,  0.0f, 1.0f, &animator->stand );
+   bitpack_qf32( ctx, 8,  0.0f, 1.0f, &animator->push );
+   bitpack_qf32( ctx, 8,  0.0f, 1.0f, &animator->jump );        /*??*/
+   bitpack_qf32( ctx, 8,  0.0f, 1.0f, &animator->jump_charge ); /*??*/
+
+   /* just the sign bit? */
+   bitpack_qf32( ctx, 8, -1.0f, 1.0f, &animator->reverse );
+   bitpack_qf32( ctx, 8, -1.0f, 1.0f, &animator->delayed_slip_dir );
+   bitpack_bytes( ctx, 1, &animator->jump_dir );
+   bitpack_bytes( ctx, 1, &animator->trick_type );
+
+   bitpack_qf32( ctx, 8,  0.0f, 1.0f, &animator->grind_balance );
+   bitpack_qf32( ctx, 8, -1.0f, 1.0f, &animator->airdir );
+   bitpack_qf32( ctx, 8, -1.0f, 1.0f, &animator->weight );
+   bitpack_qf32( ctx, 8,  0.0f, 1.0f, &animator->trick_foot );
+   bitpack_qf32( ctx, 8,  0.0f, 1.0f, &animator->slap );
+   bitpack_qf32( ctx, 8,  0.0f, 1.0f, &animator->subslap );
+   bitpack_qf32( ctx, 8,  0.0f, 1.0f, &animator->grabbing );
+
+   /* animator->wobble is ommited */
+
+   bitpack_qv2f( ctx, 8, -1.0f, 1.0f, animator->foot_offset );
+   bitpack_qquat( ctx, animator->qfixuptotal );
+   bitpack_qquat( ctx, animator->qflip );
+
+   bitpack_qv3f( ctx, 16, -100.0f, 100.0f, animator->board_euler );
+   bitpack_qf32( ctx, 8, -1.0f, 1.0f, &animator->board_lean );
+   bitpack_qv2f( ctx, 8, -1.0f, 1.0f, animator->steer );
+   bitpack_qv2f( ctx, 8, -1.0f, 1.0f, animator->grab );
+
+   bitpack_qf32( ctx, 16,  0.0f, 120.0f, &animator->push_time );
+}
+
 #endif /* PLAYER_SKATE_C */
index 68f2dcb9980c06f7c0c2a3ba78c84051a5a73225..e5cc42f3500988a00d78fe353f04b2e756649b7c 100644 (file)
@@ -287,6 +287,7 @@ static void player__skate_animate      (void);
 static void player__skate_pose         (void *animator, player_pose *pose);
 static void player__skate_post_animate (void);
 static void player__skate_reset        (ent_spawn *rp);
+static void player__skate_animator_exchange( bitpack_ctx *ctx, void *data );
 
 static void player__skate_clear_mechanics(void);
 static void player__skate_reset_animator(void);
@@ -303,6 +304,7 @@ struct player_subsystem_interface static player_subsystem_skate = {
    .animate = player__skate_animate,
    .pose = player__skate_pose,
    .post_animate = player__skate_post_animate,
+   .network_animator_exchange = player__skate_animator_exchange,
 
    .animator_data = &player_skate.animator,
    .animator_size = sizeof(player_skate.animator),