+ v3_copy( d->co_lpf, localplayer.rb.co );
+ v3_zero( localplayer.rb.v );
+ v3_zero( localplayer.rb.w );
+
+ if( (skaterift.activity == k_skaterift_default) &&
+ button_down(k_srbind_dead_respawn) ){
+ ent_spawn *spawn = world_find_closest_spawn(
+ world_current_instance(), localplayer.rb.co );
+
+ if( spawn ){
+ v3_copy( spawn->transform.co, localplayer.rb.co );
+ player__reset();
+ srinput.state = k_input_state_resume;
+ }
+ else {
+ vg_error( "No spawns!\n" );
+ }
+ }
+}
+
+static void player__dead_animate(void){
+ struct player_dead *d = &player_dead;
+ struct player_dead_animator *animator = &d->animator;
+ struct player_ragdoll *rd = &localplayer.ragdoll;
+ struct skeleton *sk = &localplayer.skeleton;
+
+ m4x3f transforms[ 32 ];
+
+ /* root transform */
+ q_m3x3( localplayer.rb.q, transforms[0] );
+ v3_copy( localplayer.rb.co, transforms[0][3] );
+
+ v4_copy( localplayer.rb.q, animator->transforms[0].q );
+ v3_copy( localplayer.rb.co, animator->transforms[0].co );
+
+ /* colliders with bones transforms */
+ for( int i=0; i<rd->part_count; i++ ){
+ struct ragdoll_part *part = &rd->parts[i];
+
+ m4x3f mtx;
+
+ v4f q_int;
+ v3f co_int;
+
+ float substep = vg.time_fixed_extrapolate;
+ v3_lerp( part->prev_co, part->obj.rb.co, substep, co_int );
+ q_nlerp( part->prev_q, part->obj.rb.q, substep, q_int );
+ v4_copy( part->obj.rb.q, q_int );
+
+ q_m3x3( q_int, mtx );
+ v3_copy( co_int, mtx[3] );
+
+ m4x3_mul( mtx, part->inv_collider_mtx, transforms[part->bone_id] );
+ }
+
+ /* bones without colliders transforms */
+ for( u32 i=1; i<sk->bone_count; i++ ){
+ struct skeleton_bone *sb = &sk->bones[i];
+
+ if( sb->parent && !sb->collider ){
+ v3f delta;
+ v3_sub( sk->bones[i].co, sk->bones[sb->parent].co, delta );
+
+ m4x3f posemtx;
+ m3x3_identity( posemtx );
+ v3_copy( delta, posemtx[3] );
+
+ /* final matrix */
+ m4x3_mul( transforms[sb->parent], posemtx, transforms[i] );
+ }
+ }
+
+ /* measurements */
+ for( u32 i=1; i<sk->bone_count; i++ ){
+ struct skeleton_bone *sb = &sk->bones[i];
+
+ v3_zero( animator->transforms[i].co );
+ q_identity( animator->transforms[i].q );
+
+ m4x3f parent, inverse, local;
+ m3x3_identity( parent );
+ v3_sub( sk->bones[i].co, sk->bones[sb->parent].co, parent[3] );
+ m4x3_mul( transforms[ sb->parent ], parent, parent );
+ m4x3_invert_affine( parent, inverse );
+
+ v3f _s;
+ m4x3_mul( inverse, transforms[i], local );
+ m4x3_decompose( local, animator->transforms[i].co,
+ animator->transforms[i].q, _s );
+ }