Skip to main content
GameDev.net gamedev.net
🔒 Locked 🎮 Unity

.X animation

Started by Sagito Jul 20, 2010 at 5:54 PM 1 replies 700+ views
Original Post
Sagito
Sagito
Hello,

I'm trying to build a manual parser for .X files, without using the DirectX specific functions for loading, just to learn by practicing how skinning and animation works. I am already able to present the mesh on the screen, and I'm pretty sure that all of the data in the file is being loaded correctly (including animation data).

I'm now trying to reproduce the animation set contained in a sample .x file, but I can't seem to get it right. Each bone saves its matrix, children bones, the vertices it affects and their weight. Then, before drawing a mesh I update it and try to perform the transformations given by the bones. To do so, for each bone, I get the bone matrix, multiply it by the keyframe matrix (a matrix that is interpolated from two consecutive keyframes) and transform each vertex affected by the bone by the resulting matrix * the weight for that vertex.

Something like:

foreach (Bone bone in bones)   matrix boneMatrix = bone->matrix;   matrix animMatrix = animation->getCurrentMatrix();   //I'm hoping that this gives me the bone position in a given moment   matrix result = boneMatrix * animMatrix;   foreach (Vertex v in vertices)       matrix weightedMatrix = result * bone->getWeight(v);       v = weightedMatrix * v;   endend


However, doing something like this simply destroys the mesh and the animation is nothing like what it should be. I'm probably missing something very evident here, but I can't seem to find what...

Thanks in advance...
http://sagito.wordpress.com
Buckeye
Buckeye
I'm not sure that applying the weights to the matrices is correct. In a shader, the weights are applied to the positions, not the matrices.

From an animation shader:
    float3 p = float3(0.0f, 0.0f, 0.0f);    float lastWeight = 0.0f;    int n = NumVertInfluences-1;    for(int i = 0; i < n; ++i)    {        lastWeight += weights;	p += weights * mul(pos, (float4x3)FinalTransforms[boneIndices]);    }    lastWeight = 1.0f - lastWeight;        p += lastWeight * mul(pos, (float4x3)FinalTransforms[boneIndices[n]]);

You need to duplicate that algorithm. "weights" is the array of vertex weights. "FinalTransforms" is an array of final matrices, one for each bone. "boneIndices" is an array of the influence vertex indices.

That is, weights is the weight for vertex boneIndices.

The FinalTransforms are calculated first. Then, for each vertex, starting with a temporary position = (0,0,0) - apply the first influence matrix to the bone position. Then apply the weighting factor for that influence vertex. Add that weighted position to the temporary position. Continue with the rest of the influences, ensuring the total weight = 1.0

EDIT:
final bone position = weight[0]*( unweighted position * influenceMatrix[0] ) + weight[1]*( unweighted position * influenceMatrix[1] + ...
Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly. You don't forget how to play when you grow old; you grow old when you forget how to play.
samster581
samster581
I don't know what "boneMatrix" is or where it comes from, but there are at least two important matrices you need to use
for transforming skinned meshes, with or without animation:

template FrameTransformMatrix {

Matrix4x4 frameMatrix;
}
"Defines a local transform for a frame (and all its child objects)."


template SkinWeights {
<6F0D123B-BAD2-4167-A0D0-80224F25FABB>
STRING transformNodeName;
DWORD nWeights;
array DWORD vertexIndices[nWeights];
array FLOAT weights[nWeights];
Matrix4x4 matrixOffset;
);
"The matrix matrixOffset transforms the mesh vertices to the space of the bone. When concatenated to the
bone's transform, this provides the world space coordinates of the mesh as affected by the bone."


If you want my advice, first get the skinned mesh transformation down correctly. This does not require animation.
When that's working, try adding animation. Because, you obviously can't animate a skinned mesh if it's not tranformed correctly
in the first place.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.