1

I am frustratingly close to working skeletal animation in WebGL.

Background

I have a model with a zombie walk animation that I got for free. I downloaded the entire thing in a single Collada file. I wrote a parser to get all the vertices, normals, joints influence indices/weights, and joint matrices. I am able to render the character in its bind pose by doing

joints[i].skinning_matrix = MatrixMultiply(joints[i].inverse_bind_pose_matrix, joints[i].world_matrix);

where a joint's world matrix is the joint's bind_pose_matrix multiplied by its parent's world matrix. I got the inverse_bind_pose_matrix by doing:

joints[i].inverse_bind_pose_matrix = MatrixInvert(joints[i].world_matrix);

So really, rendering the character in its bind pose is just passing Identity matrices to the shader, so maybe I'm not even doing that part right at all. However, the inverse bind pose matrices that I calculate are nearly identical to the ones supplied by the Collada file, so I'm pretty sure those are good.

Here's my model in its bind pose:

bind pose

Problem

Once I go ahead and try to calculate the skinning matrix using a single frame of the animation (I chose frame 10 at random), it still resembles a man but something is definitely wrong.

I'm using the same inverse_bind_pose_matrix that I calculated in the first place. I'm using a new world matrix, calculated instead by multiplying each joint's keyframe/animation matrix by its parent's new world matrix.

I'm not doing any transposing anywhere in my entire codebase, though I think I've tried transposing pretty much any combination of matrices to no avail.

Here is my model in his animation frame 10 pose:

anim pose

Some Relevant Code

vertex shader:

attribute float aBoneIndex1;
// up to aBoneIndex5

attribute float aBoneWeight1;
// up to aBoneWeight5

uniform mat4 uBoneMatrices[52];

void main(void) {
  vec4 vertex = vec4(0.0, 0.0, 0.0, 0.0);
  vertex += aBoneWeight1 * vec4(uBoneMatrices[int(aBoneIndex1)] * aPosition);
  vertex += aBoneWeight2 * vec4(uBoneMatrices[int(aBoneIndex2)] * aPosition);
  vertex += aBoneWeight3 * vec4(uBoneMatrices[int(aBoneIndex3)] * aPosition);
  vertex += aBoneWeight4 * vec4(uBoneMatrices[int(aBoneIndex4)] * aPosition);
  vertex += aBoneWeight5 * vec4(uBoneMatrices[int(aBoneIndex5)] * aPosition);

  // normal/lighting part

  // the "/ 90.0" simply scales the model down, problem persists without it.
  gl_Position = uPMatrix * uMVMatrix * vec4(vertex.xyz / 90.0, 1.0);
}

You can see my parser in its entirety (if you really really want to...) on GitHub and you can see the model live here.

Andrew Rasmussen
  • 14,912
  • 10
  • 45
  • 81
  • Github says 404. Have you ever solved the problem? – TN. Feb 26 '14 at 21:04
  • @TN.: yep, you can see the live animation at http://venz.io/demo and the github repo at https://github.com/arasmussen/Venzio – Andrew Rasmussen Feb 27 '14 at 02:37
  • 2
    If you solved the problem, you should post and accept the answer for the benefit of other readers with the same question. – ArtOfWarfare Aug 06 '15 at 10:40
  • 1
    @ArtOfWarfare: So sorry, I don't remember what the problem was. I just remember toying with it very carefully for days and changing which order I was multiplying things and etc... Again, the source code is on github - see comment above. – Andrew Rasmussen Aug 06 '15 at 16:55
  • 1
    To anyone looking into how to do skeletal animations in WebGL there's [this](https://webglfundamentals.org/webgl/lessons/webgl-skinning.html) – gman May 15 '19 at 08:13

0 Answers0