--- /dev/null
+#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 */
#include "skaterift.h"
#include "player_common.h"
+#include "network_compression.h"
enum player_subsystem{
k_player_subsystem_walk = 0,
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;
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;
}
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;
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 */
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);
.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),