Hello everyone,
I am trying to make my java program display a 3D animation it reads from a Collada file.
I have read many tutorials, but yet something isn’t working right,
the way i do it is:
- I parse the collada file
- each frame i calculate the keyframe transform for each joint by multiplying the joint’s transform by it’s parent tranform
- I save as a SkinningMatrix the joint’s keyframe transform matrix multiplyed by the joint’s inverse bind matrix
- I load to the vertex shader the skinningMatrices for all joints and for each vertex it’s weights and joint’s indecies
- in the vertex shader i calculate the position by adding position * bindShapeMatrix * skinningMatrix[i] * weights[i] for all i that has weight > 0
but yet my animation looks really bad and wrong.
I’m adding my relevant source code and would thank you alot for any help.
vertex shader:
vec4 initPos = vec4(0, 0, 0, 0);
vec4 initNormal = vec4(0, 0, 0, 0);
int count = 0;
for(int i = 0; i < MAX_WEIGHTS; i++)
{
float weight = weights[i];
if(weight > 0) {
count++;
int jointIndex = joints[i];
vec4 tmpPos = vec4(position, 1.0) * bindShapeMatrix * jointsMatrix[jointIndex];
initPos += weight * tmpPos;
vec4 tmpNormal = vec4(normal, 0.0) * bindShapeMatrix * jointsMatrix[jointIndex];
initNormal += weight * tmpNormal;
}
}
if (count == 0)
{
initPos = bindShapeMatrix * vec4(position, 1.0);
initNormal = bindShapeMatrix * vec4(normal, 0.0);
}
vec4 worldPosition = transformationMatrix * initPos ;
vec4 positionRelativeToCam = viewMatrix * worldPosition;
gl_Position = projectionMatrix * positionRelativeToCam ;
in the render method:
private void setupSkeleton(AnimationData anim) {
Stack<Bone> boneStack = new Stack<Bone>();
boneStack.push(anim.getRootBone());
while(!boneStack.isEmpty()){
Bone bone = boneStack.pop();
Matrix4f worldMatrix = interpolate(bone, DisplayManager.getCurrentTime());
if(bone.getParent() != null){
worldMatrix = Matrix4f.mul(worldMatrix, bone.getParent().getWorldMatrix(), null);
}
bone.setWorldMatrix(worldMatrix);
Matrix4f invBindMatrix = bone.getInvBindMatrix();
//if the isnt an inv bind matrix
if(invBindMatrix == null){
invBindMatrix = new Matrix4f();
invBindMatrix.setIdentity();
}
bone.setSkinningMatrix(Matrix4f.mul(invBindMatrix, worldMatrix, null));
for(Bone child : bone.getChilds()){
boneStack.push(child);
}
}
shader.loadBindShapeMatrix(anim.getBindShapeMatrix());
//loads the skinning matrices of all the joints
shader.loadBones(anim.getBones());
}