+static void character_ragdoll_copypose( struct character *ch, v3f v )
+{
+ for( int i=0; i<ch->ragdoll_count; i++ )
+ {
+ struct ragdoll_part *part = &ch->ragdoll[i];
+
+ v3f pos, offset;
+ u32 bone = part->bone_id;
+
+ m4x3_mulv( ch->sk.final_mtx[bone], ch->sk.bones[bone].co, pos );
+ m3x3_mulv( ch->sk.final_mtx[bone], part->offset, offset );
+ v3_add( pos, offset, part->rb.co );
+ m3x3_q( ch->sk.final_mtx[bone], part->rb.q );
+ v3_copy( v, part->rb.v );
+ v3_zero( part->rb.w );
+
+ rb_update_transform( &part->rb );
+ }
+}
+
+static void character_debug_ragdoll( struct character *ch )
+{
+ for( u32 i=0; i<ch->ragdoll_count; i ++ )
+ rb_debug( &ch->ragdoll[i].rb, 0xff00ff00 );
+}
+
+static void character_ragdoll_iter( struct character *ch )
+{
+ rb_solver_reset();
+
+ for( int i=0; i<ch->ragdoll_count; i ++ )
+ rb_collide( &ch->ragdoll[i].rb, &world.rb_geo );
+
+ rb_presolve_contacts( rb_contact_buffer, rb_contact_count );
+
+ v3f rv;
+
+ float shoe_vel[2] = {0.0f,0.0f};
+ for( int i=0; i<2; i++ )
+ if( ch->shoes[i] )
+ shoe_vel[i] = v3_length( ch->ragdoll[i].rb.v );
+
+ for( int j=0; j<ch->ragdoll_count; j++ )
+ {
+ struct ragdoll_part *pj = &ch->ragdoll[j];
+ struct skeleton_bone *bj = &ch->sk.bones[pj->bone_id];
+
+ if( pj->parent != 0xffffffff )
+ {
+ struct ragdoll_part *pp = &ch->ragdoll[pj->parent];
+ struct skeleton_bone *bp = &ch->sk.bones[pp->bone_id];
+
+ v3f lca, lcb;
+ v3_negate( pj->offset, lca );
+ v3_add( bp->co, pp->offset, lcb );
+ v3_sub( bj->co, lcb, lcb );
+
+ rb_debug_constraint_position( &pj->rb, lca, &pp->rb, lcb );
+
+ if( pj->use_limits )
+ {
+ rb_debug_constraint_limits( &pj->rb, &pp->rb, lca, pj->limits );
+ }
+ }
+ }
+
+ /* CONSTRAINTS */
+ for( int i=0; i<10; i++ )
+ {
+ rb_solve_contacts( rb_contact_buffer, rb_contact_count );
+
+ for( int j=0; j<ch->ragdoll_count; j++ )
+ {
+ struct ragdoll_part *pj = &ch->ragdoll[j];
+ struct skeleton_bone *bj = &ch->sk.bones[pj->bone_id];
+
+ if( pj->parent != 0xffffffff )
+ {
+ struct ragdoll_part *pp = &ch->ragdoll[pj->parent];
+ struct skeleton_bone *bp = &ch->sk.bones[pp->bone_id];
+
+ v3f lca, lcb;
+ v3_negate( pj->offset, lca );
+ v3_add( bp->co, pp->offset, lcb );
+ v3_sub( bj->co, lcb, lcb );
+
+ rb_constraint_position( &pj->rb, lca, &pp->rb, lcb );
+
+ if( pj->use_limits )
+ {
+ rb_constraint_limits( &pj->rb, lca, &pp->rb, lcb, pj->limits );
+ }
+ }
+ }
+ }
+
+ /* INTEGRATION */
+ for( int i=0; i<ch->ragdoll_count; i++ )
+ rb_iter( &ch->ragdoll[i].rb );
+
+ /* SHOES */
+
+ for( int i=0; i<ch->ragdoll_count; i++ )
+ rb_update_transform( &ch->ragdoll[i].rb );
+}