I created a simple object that is simply two bones and a cuboid. It looks like an elbow joint of an arm sticking straight up in the air. I have the following matrices:

Root (Contains everything) = rootMatrix

Cube (Contains the entire model) = modelMatrix

Armature (Contains the two bones) = armatureMatrix

Armature_RootBase (Root "upper arm" bone)

SkinMatrix_RootBase (The skin matrix for the root bone)

Armature_TipTop (is the "forearm" bone)

SkinMatrix_TipTop (The skin matrix for the second bone)

When loading the model in, I transform all the vertices by the bind matrix to have the bind pose as the default. I get the bind matrix with:

Matrix4f bindMatrix = new Matrix4f(); Matrix4f.mul(bindMatrix, rootMatrix, bindMatrix); Matrix4f.mul(bindMatrix, modelMatrix, bindMatrix);

That works great. The bind pose is exactly as it should be, how it's shown in Blender.

Now when I try to animate is where the problems come in. I'm using GLSL to apply the bone matrices to the vertices. When I send identity matrices for all the bones it works fine. I've done tests and I know the GLSL is working and sending the matrices and applying the bones to the correct vertices. The main problem is I don't know how to properly get the matrices.

**I have a bind pose model and I need to take a rotation, translation and scale and create the proper matrix to transform the model.**

I'll explain my current non-working process, because it might just need a little tweak to make it work.

I have structures to mimic the structure of the armature. At the moment I'm exporting full animations from Blender (I'll work out interpolation later), so I have a key frame for every frame. I can apply an animation to a model and I'm able to lookup the animation rotation, translation and scale for any bone.

Basically I go through and calculate the new bone matrices, then send them to my shader to be applied to the bones. So the update process goes like this:

Starting with the root bone

UpdateFinalTransform(Bone)

calculateAnimationTransform()

foreach child bone

UpdateFinalTransform(child)

Where calculateAnimationTransform() looks like this:

transformMatrix.setIdentity(); combinedMatrix.setIdentity(); //clear the transform and animation matrices Matrix4f bindMatrix = new Matrix4f(getBindMatrix()); //get the bind matrix for this model Matrix4f.mul(transformMatrix, (Matrix4f)bindMatrix.invert(), transformMatrix); //multiply by the inverted bind matrix Matrix4f skinMatrix = getSkinWeightMatrix(); //get the skin matrix for this bone Matrix4f animationTransform = new Matrix4f(); //rotate, scale, translate animationTransform.applyQuaternion(new Quaternion(rotation)); tmpMatrix.setIdentity(); tmpMatrix.m00 = scale.x; tmpMatrix.m11 = scale.y; tmpMatrix.m22 = scale.z; Matrix4f.mul(animationTransform, tmpMatrix, animationTransform); tmpMatrix.setIdentity(); tmpMatrix.m30 = position.x; tmpMatrix.m31 = position.y; tmpMatrix.m32 = position.z; Matrix4f.mul(animationTransform, tmpMatrix, animationTransform); setCombinedMatrix(animationTransform); //set the animation transform for this bone, so that children bones can access it combinedMatrix = getTransformMatrix(); //get the combined transform of this animation transform * parent animation transform Matrix4f finalMatrix = Matrix4f.mul(skinMatrix, combinedMatrix, null); //skin the combined matrix Matrix4f.mul(finalMatrix, transformMatrix, transformMatrix); //apply the inverted bind pose Matrix4f.mul((Matrix4f)bindMatrix.invert(), transformMatrix, transformMatrix); //undo the inverted bind pose

each bone has that getTransformMatrix() method that looks like this:

if (parent == null) { return Matrix4f.mul(combinedMatrix, parentArmature.getArmatureRootMatrix(), null); } else { return Matrix4f.mul(combinedMatrix, parent.getCombinedMatrix(), null); }

combinedMatrix is set to its default armature matrix if an animation matrix is not defined.

So my questions.

1. Am I creating the animationTransform properly?

2. Is this the correct order of transforms?

3. What am I missing?

4. How do I do it properly?

**Edited by bobhowdy, 01 October 2012 - 01:03 PM.**