+typedef enum ik_dir ik_dir;
+enum ik_dir
+{
+ k_ikX,
+ k_iknX,
+ k_ikY,
+ k_iknY,
+ k_ikZ,
+ k_iknZ
+};
+
+static void ik_track_to( m4x3f m, v3f pos, v3f target, v3f axis,
+ ik_dir fwd, ik_dir up )
+{
+ v3f dir, other;
+ v3_sub( target, pos, dir );
+ v3_normalize( dir );
+ v3_cross( dir, axis, other );
+
+ if( fwd == k_ikX && up == k_ikY )
+ {
+ v3_copy( axis, m[0] );
+ v3_copy( dir, m[1] );
+ v3_copy( other, m[2] );
+ }
+
+ if( fwd == k_ikY && up == k_ikX )
+ {
+ v3_negate( axis, m[2] );
+ v3_copy( dir, m[1] );
+ v3_negate( other,m[0] );
+ }
+
+ if( fwd == k_ikY && up == k_iknX )
+ {
+ v3_negate( axis, m[2] );
+ v3_negate( dir, m[1] );
+ v3_copy( other,m[0] );
+ }
+
+ if( fwd == k_ikZ && up == k_ikY )
+ {
+ v3_copy( axis, m[1] );
+ v3_copy( dir, m[2] );
+ v3_negate( other, m[0] );
+ }
+
+ if( fwd == k_iknZ && up == k_ikY )
+ {
+ v3_negate( axis, m[1] );
+ v3_negate( dir, m[2] );
+ v3_negate( other, m[0] );
+ }
+
+ v3_copy( pos, m[3] );
+}
+
+static void ik_basic( struct ik_basic *ik, m4x3f m1, m4x3f m2,
+ enum ik_dir fwd, enum ik_dir up )