Animation implementation headache

Started by
12 comments, last by JarkkoL 12 years, 9 months ago
Hey all,

I've spent the last few weeks trying to implement skin and bone animation in my engine with no success =(
I have a quick question for experienced animators out there.

I have my joints, inverse bind matrices, weights, and which joints effect each vertex all setup. I intended to ignore the animation data for now (input, output and interpolations) as I wanted to see my model transformed from model pose to the default pose before I added more complexity with animating it.

After hitting my head against the wall for days debugging, trying to figure out why I can render the skeleton properly but when I try to transform the model it explodes, I have to wonder if I am flawed in assuming that I can get a proper result while ignoring the animation data.

Is it necessary to pick a certain keyFrame from the animation data in order to render the model in a single default pose?

Thanks in advance.
Advertisement



Is it necessary to pick a certain keyFrame from the animation data in order to render the model in a single default pose?

Thanks in advance.



If you can provide a pose for the model otherwise then the answer is no. Otherwise, maybe it is a good start to use data which should work correctly.


There are lots of things that can go wrong with skin & bones. First of all, can you verify that your animation hierarchy is correct? I mean, if you render your bones are you getting the shape you are expecting?

Cheers!
When I render my bones alone (no inverseBind calculations yet) I do get a correct skeleton.

When I try to render just my inverse bind matrices I get a crazy skeleton (i thought that the inverse bind matrices would be a skeleton of the character in bind pose, i.e. arms held outward with palms down)

Also once I multiply my bones with my inverse bind and try to render that skeleton it is also a crazy exploded mess.

I thought that maybe my problem was from multiplying in the wrong order, but I have tried every possible order and nothing looks right.

Any help is appreciated!

When I render my bones alone (no inverseBind calculations yet) I do get a correct skeleton.

When I try to render just my inverse bind matrices I get a crazy skeleton (i thought that the inverse bind matrices would be a skeleton of the character in bind pose, i.e. arms held outward with palms down)

Also once I multiply my bones with my inverse bind and try to render that skeleton it is also a crazy exploded mess.

I thought that maybe my problem was from multiplying in the wrong order, but I have tried every possible order and nothing looks right.

Any help is appreciated!


Hi,

Correct skeleton sounds good. You cannot render the inverse bone matrices and get something understandable out.

The inverse matrix is actually a matrix that transforms a vertex from the bind-pose to the bone space. This is needed in order to animate the skin correctly.

The point of bind-pose is to provide a common space for all the vertices. You can think that a vertex in the bind pose has already the bone matrix (bone matrices) applied once which you'll need to cancel with the inverse-bone matrix before animating it with a new bone matrix.

If the skeleton renders correctly, your animation data seems ok. The problem may be with the inverse transforms, skinning shader. Can you provide some code?
Sure thing, here is my shader code

<script id="shaderFour-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;

uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
uniform mat3 uNMatrix;

attribute vec4 index;
attribute vec4 weight;
uniform mat4 Joints[44];

void main(void) {
vec4 newVertex;
vec4 newNormal;
int Index;
float totalWeight;
float normalizedWeight;


Index = int(index.x); //Cast to int
newVertex = (Joints[Index] * vec4(aVertexPosition, 1.0)) * weight.x;
totalWeight += weight.x;

Index = int(index.y); //Cast to int
newVertex = ((Joints[Index] * vec4(aVertexPosition, 1.0)) * weight.y) + newVertex;
totalWeight += weight.y;

Index = int(index.z); //Cast to int
newVertex = ((Joints[Index] * vec4(aVertexPosition, 1.0)) * weight.z) + newVertex;
totalWeight += weight.z;

Index = int(index.w); //Cast to int
newVertex = ((Joints[Index] * vec4(aVertexPosition, 1.0)) * weight.w) + newVertex;
totalWeight += weight.w;

if(totalWeight != 1.0)
{
normalizedWeight = 1.0 / totalWeight;
newVertex *= normalizedWeight;
}

gl_Position = uPMatrix * uMVMatrix * vec4(newVertex.xyz, 1.0);



For vertices with less than 4 joints effecting them, I use a weight of 0.

With a quick look to your shader code I noticed following:

[color=#1C2837][size=2]- [color=#1C2837][size=2]Index = [color=#1C2837][size=2]int(index.x);[color=#1C2837][size=2] <- are you sure that you get correct values from index? Are you able to pass the value to the shader as integer?
[color=#1C2837][size=2]

[color=#1C2837][size=2]- you could normalize your weights while loading (just to simplify your shader)
[color="#1c2837"]

[color="#1c2837"]- you could possible write the code as a loop which would make it a bit easier to understand and less prone to errors.
[color="#1c2837"]

[color="#1c2837"]- it is hard to determine the order of the matrix calculations, perhaps you should have a another rigid mesh shader where you can verify that your view and projection matrix are applied in correct order.
[color="#1c2837"]

[color="#1c2837"]The output of this shader is garbage more or less?
[color="#1c2837"]

[color="#1c2837"]Cheers!
Yeah I think the only way for me to debug it at this point is to write the code for it outside of the shader and debug each value. It's a lot of work but I've already spent about 30hours trying to figure out whats wrong. At least this will get be on the right path.

I suspect that my problem will be incorrect ordering of matrices.
Hi again,
I had a second thought. If you remove the skinning part of your shader (the lines where you use the Joints matrices)


newVertex = aVertexPosition;



//Index = int(index.x); //Cast to int
//newVertex = (Joints[Index] * vec4(aVertexPosition, 1.0)) * weight.x;
//totalWeight += weight.x;
...





[color="#1c2837"]You should end up with shader which shows your skin in the bind-pose if your projection and view matrices work correctly.

[color="#1c2837"]Cheers!
I was able to render the model in bind pose (arms outward and palms down).

If I only render the joints I can also see the skeleton in a walking position.

It seems that those are about the only ways for me to debug things without pulling everything out of the shader =(


I was able to render the model in bind pose (arms outward and palms down).

If I only render the joints I can also see the skeleton in a walking position.

It seems that those are about the only ways for me to debug things without pulling everything out of the shader =(





Well I guess that we have narrowed down the problem to the skinning part of the shader (the code or the matrices have something wrong). Everything else seems to work as it should.

The index part is one question. You could try to multiply your [color="#880000"][font="CourierNew, monospace"]index.xyzw by 255.0f before casting to int.[/font]
[font="CourierNew, monospace"] [/font]
[font="CourierNew, monospace"][color="#880000"]Cheers!
[/font]

This topic is closed to new replies.

Advertisement