+ k_ragdoll_floatydrag = 1.0f,
+ k_ragdoll_limit_scale = 1.0f;
+
+VG_STATIC int k_ragdoll_div = 1,
+ ragdoll_frame = 0,
+ k_ragdoll_debug_collider = 1,
+ k_ragdoll_debug_constraints = 0;
+
+VG_STATIC void player_ragdoll_init(void)
+{
+ VG_VAR_F32( k_ragdoll_limit_scale );
+ VG_VAR_I32( k_ragdoll_div );
+ VG_VAR_I32( k_ragdoll_debug_collider );
+ VG_VAR_I32( k_ragdoll_debug_constraints );
+}
+
+VG_STATIC void player_init_ragdoll_bone_collider( struct skeleton_bone *bone,
+ struct ragdoll_part *rp )
+{
+ m4x3_identity( rp->collider_mtx );
+
+ if( bone->collider == k_bone_collider_box ){
+ v3f delta;
+ v3_sub( bone->hitbox[1], bone->hitbox[0], delta );
+ v3_muls( delta, 0.5f, delta );
+ v3_add( bone->hitbox[0], delta, rp->collider_mtx[3] );
+
+ v3_copy( delta, rp->obj.rb.bbx[1] );
+ v3_muls( delta, -1.0f, rp->obj.rb.bbx[0] );
+
+ q_identity( rp->obj.rb.q );
+ rp->obj.type = k_rb_shape_box;
+ rp->colour = 0xffcccccc;
+ }
+ else if( bone->collider == k_bone_collider_capsule ){
+ v3f v0, v1, tx, ty;
+ v3_sub( bone->hitbox[1], bone->hitbox[0], v0 );
+
+ int major_axis = 0;
+ float largest = -1.0f;
+
+ for( int i=0; i<3; i ++ ){
+ if( fabsf( v0[i] ) > largest ){
+ largest = fabsf( v0[i] );
+ major_axis = i;
+ }
+ }
+
+ v3_zero( v1 );
+ v1[ major_axis ] = 1.0f;
+ rb_tangent_basis( v1, tx, ty );
+
+ float r = (fabsf(v3_dot(tx,v0)) + fabsf(v3_dot(ty,v0))) * 0.25f,
+ l = fabsf(v0[ major_axis ]);
+
+ /* orientation */
+ v3_muls( tx, -1.0f, rp->collider_mtx[0] );
+ v3_muls( v1, -1.0f, rp->collider_mtx[1] );
+ v3_muls( ty, -1.0f, rp->collider_mtx[2] );
+ v3_add( bone->hitbox[0], bone->hitbox[1], rp->collider_mtx[3] );
+ v3_muls( rp->collider_mtx[3], 0.5f, rp->collider_mtx[3] );
+
+ rp->obj.type = k_rb_shape_capsule;
+ rp->obj.inf.capsule.height = l;
+ rp->obj.inf.capsule.radius = r;
+
+ rp->colour = 0xff000000 | (0xff << (major_axis*8));
+ }
+ else{
+ vg_warn( "type: %u\n", bone->collider );
+ vg_fatal_exit_loop( "Invalid bone collider type" );
+ }
+
+ m4x3_invert_affine( rp->collider_mtx, rp->inv_collider_mtx );
+
+ /* Position collider into rest */
+ m3x3_q( rp->collider_mtx, rp->obj.rb.q );
+ v3_add( rp->collider_mtx[3], bone->co, rp->obj.rb.co );
+ v3_zero( rp->obj.rb.v );
+ v3_zero( rp->obj.rb.w );
+ rb_init_object( &rp->obj );
+}
+
+/*
+ * Get parent index in the ragdoll
+ */
+VG_STATIC u32 ragdoll_bone_parent( struct player_ragdoll *rd,
+ struct player_avatar *av, u32 bone_id )
+{
+ for( u32 j=0; j<rd->part_count; j++ )
+ if( rd->parts[ j ].bone_id == bone_id )
+ return j;
+
+ vg_fatal_exit_loop( "Referenced parent bone does not have a rigidbody" );
+ return 0;
+}