• Create Account

#Actualbobhowdy

Posted 01 October 2012 - 01:03 PM

I'm using a .x (direct x) model file exported from Blender. It contains the mesh, armature and animation data for my model. I can get the model to render properly in its bind pose. I'm trying to animate it now. However, no matter what I try, I can't get the model to transform properly when rendering an animation pose. It's all deformed.

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?

#1bobhowdy

Posted 01 October 2012 - 10:33 AM

I'm using a .x (direct x) model file exported from Blender. It contains the mesh, armature and animation data for my model. I can get the model to render properly in its bind pose. I'm trying to animate it now. However, no matter what I try, I can't get the model to transform properly when rendering an animation pose. It's all deformed.

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?

PARTNERS