# How can I integrate IK into a hierarchical editing environment?

I have a situation where I'm trying to push the output of an IK solver back into a user editable joint hierarchy (which stores components as it's primary source), and I'm not sure how to go about it.

My IK solver returns three world space transforms representing the position and orientation of a chain of joints (0,1,2).

A: I need to turn this into a hierarchy so that transform 2 is local to transform 1, and transform 1 is local to transform 0. Now I have local transforms for each joint.

B: Further: I need to decompose each joint's new local matrix into source Translation, Rotation and Scale.

Can anyone give me some tips for each step? I have some ideas, but I'm worried that to do B I need to particularly careful with A.

Edit:

For example if I get my world matrices like this:

M4 world_mats[3] = IK_solve( ikparams );


And then convert them to local like this:

M4 local_mats[3] = GenerateLocalChain( world_mats );


And then extract components:

Scale     s[];
Rotation  r[];
Translate t[];

foreach ( matrix in local_mats )
Decompose( matrix, s, r, t );


How can I implement the Decompose() function to match matrices created inGenerateLocalChain()?

If your matrices are invertible, which they should be, then to get the local B just do (A^-1) B or B (A^-1) depending on the order they were multiplied to get to their current state. You can repeat this process to get back the other matrices.

For part B lets say your matrix was made by S*R*T. I'm pretty sure you should be able to read of the translation as the first three elements of the last row. The determinate of the upper 3x3 matrix is the uniform scale (I am assuming the last column is 0,0,0,1). You can remove the scale from the 3x3 rotation matrix by dividing by the determinate of the upper 3x3 matrix.

If you are introducing non-uniform scale I'm not sure how to get your matrices back, I'll think about it. IK is not going to need to scale things, so if your bones have non-uniform scale I bet you can bake it into the geometry before you start.

• Good point about the scale, I'm sure the output matrices have uniform scale. However given that the local matrices are generated in step A, not by a composition of matrices, what can I assume about extracting components from them? – Justicle Aug 18 '10 at 22:21
• Yeah, its tough to say for sure, but if you perform the decomposition after you have created the local matrices I think it should work, regardless of how the matrices were created. I am 90% sure, if have any trouble performing, let me know and I'll see if I can help you. – Jonathan Fischoff Aug 18 '10 at 22:27
• As jpaver mentioned, the scale can be deduced from the length of the three axes in your rotation matrix, which are, depending on your setup, either the rows or columns of the matrix. – Kaj Aug 19 '10 at 7:39

For step A,

LocalTransform for your joint = Inverse(WorldTransform for parent joint) * WorldTransform for your joint. (If you're dealing with orthonormal matrices, Transpose can replace Inverse)

For step B, Assuming your matrix is in column major form:

• For extracting translation, just grab the first 3 components of the last column.

• For extracting non-uniform scale, assuming your matrix is in column major form, you should be able to extract the scale components by determining the length of the vector in the first 3 components of the first column, 2nd column, 3rd column eg.

Vec3 getMatrixScale(Matrix* matrix)
{
Vec3 scaleVec;
scaleVec.x = Vec3Length((Vec3*)&matrix->data[0]);
scaleVec.y = Vec3Length((Vec3*)&matrix->data[4]);
scaleVec.z = Vec3Length((Vec3*)&matrix->data[8]);
return scaleVec;
}


• For extracting rotation, normalize the vectors from which your scale extraction took place and the resulting 3x3 will be your rotation matrix. Convert this to a quaternion or euler angles. Many sites out there discuss this already:

EDIT: How you decompose your matrix will depend upon how apply (Rotate, Scale, Translate) to reconstruct your local transform during animation. If it is indeed S*R*T as Jonathan mentioned, then what I've already described should do the trick.

If you want to know specifically about transforming rotation representation to/from matrix form then you'll have to clarify exactly how you represent "Rotation". The links I posted deal with common variants of this.

• Thanks for your reply. I edited the question with some example code for more clarity. – Justicle Aug 18 '10 at 22:39