+ m3x3_transpose( inverse, inverse );
+}
+
+/*
+ * Creates inverse rotation matrices which the IK system uses.
+ */
+static void skeleton_create_inverses( struct skeleton *skele )
+{
+ /* IK: inverse 'plane-bone space' axis '(^axis,^bone,...)[base] */
+ for( int i=0; i<skele->ik_count; i++ )
+ {
+ struct skeleton_ik *ik = &skele->ik[i];
+
+ m4x3f inverse;
+ v3f iv0, iv1, ivaxis;
+ v3_sub( skele->bones[ik->target].co, skele->bones[ik->lower].co, iv0 );
+ v3_sub( skele->bones[ik->pole].co, skele->bones[ik->lower].co, iv1 );
+ v3_cross( iv0, iv1, ivaxis );
+ v3_normalize( ivaxis );
+
+ skeleton_inverse_for_ik( skele, ivaxis, ik->lower, ik->ia );
+ skeleton_inverse_for_ik( skele, ivaxis, ik->upper, ik->ib );
+ }
+}
+
+/*
+ * Apply a model matrix to all bones, should be done last
+ */
+static void skeleton_apply_transform( struct skeleton *skele, m4x3f transform )
+{
+ for( int i=0; i<skele->bone_count; i++ )
+ {
+ struct skeleton_bone *sb = &skele->bones[i];
+ m4x3_mul( transform, skele->final_mtx[i], skele->final_mtx[i] );
+ }
+}
+
+/*
+ * Apply an inverse matrix to all bones which maps vertices from bind space into
+ * bone relative positions
+ */
+static void skeleton_apply_inverses( struct skeleton *skele )
+{
+ for( int i=0; i<skele->bone_count; i++ )
+ {
+ struct skeleton_bone *sb = &skele->bones[i];
+ m4x3f inverse;
+ m3x3_identity( inverse );
+ v3_negate( sb->co, inverse[3] );
+
+ m4x3_mul( skele->final_mtx[i], inverse, skele->final_mtx[i] );
+ }