Jump to content
  • Advertisement
Sign in to follow this  
LeGardien

Proper concatenation of matrix transforms for skeletal animation?

This topic is 4170 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have been working on a skeletal animation system for the past few weeks, initially using quaternions for both bone orientation and bone transforms. However, while this worked fine for cases where only one bone is allowed to rotate, as illustrated below, the transforms would be incorrect for cases where child bones are allowed to rotate as well. After much frustration, I tried to implement a matrix version of the transforms, since there seems to be much more literature on that subject, but unfortunately, I got similar results. Initial pose Pose with only upper legs allowed to rotate And here are the problem cases: Pose with upper and lower legs allowed to rotate Pose with upper, lower legs and feet allowed to rotate Since the problems only arise when there are hierarchical rotations, I'm guessing that there is something wrong with how I am concatenating the transforms. As you can see in the fourth image, the feet are totally disconnected from the rest of the body, as well as the lower legs. The way I am doing the transforms is by first calculating the default origin of every bone (in model space), and then storing in each bone a matrix of the form: T(-default model space bone origin) * R(rotation from keyframe data) * T(default model space bone origin) Then, right before the transforms for each vertex are calculated, each bone's matrix is multiplied by its parent's matrix. I know that if I apply the transforms separately on each vertex (that is, apply (-T)*R*T for each bone, in succession, from the most extreme child down to the root) it will probably work correctly. However, the textbooks seem to say that you can mix everything down to one transform. Given that I am working on a high-poly game, I would like to be able to avoid all those additional operations, if they are indeed unnecessary. So what am I doing wrong?

Share this post


Link to post
Share on other sites
Advertisement
You're missing the displacements from the parent bones. Storing the rotations as quaternions is fine, but I think that for computing the actual transforms matrices are easier since they contain both displacements and rotations (and scaling, but it's unusual to use that in skeletal animation). Right now I think your bone origins are being calculated relative to the position of the model, but really they need to be calculated relative to the position of the parent bones.

Share this post


Link to post
Share on other sites
Quote:
Original post by Vorpy
You're missing the displacements from the parent bones. Storing the rotations as quaternions is fine, but I think that for computing the actual transforms matrices are easier since they contain both displacements and rotations (and scaling, but it's unusual to use that in skeletal animation). Right now I think your bone origins are being calculated relative to the position of the model, but really they need to be calculated relative to the position of the parent bones.


Currently, my total matrix transform for a three-bone system would look like this:

(T(-global root bone origin) * R(root bone rotation) * T(global root bone origin)) * (T(-global bone #2 origin) * R(bone #2 rotation) * T(global bone #2 origin)) * (T(-global bone #3 origin) * R(bone #3 rotation) * T(global bone #3 origin))

So, then the total matrix transform should be something like the following?

T(-global root bone origin) * R(root bone rotation) * T(root bone to bone #2) * R(bone #2 rotation) * T(bone #2 to bone #3) * R(bone #3 rotation) * T(bone #3 global origin)

Share this post


Link to post
Share on other sites
Something like that, I think, yes. Except for that global bone #3 origin at the end, since bone 3 should only be positioned relative to bones 1 and 2. I think the origins of the bones should be at the joints.

Share this post


Link to post
Share on other sites
Still not working. :(

Here's a thought, though. Do the child bone displacements need to be prerotated before being multiplied into the total matrix transform?

Rotation about a single point is of the form T(-point) * R(root) * T(point), right? After rotating a point about the root bone, couldn't you perform the same rotation on the origin of bone #2 and then do a separate transformation of the form T(-rotated bone #2 origin)* R(root * bone #2 rotation) * T(rotated bone #2 origin)?

As you'll note, at present, the unrotated displacements are what I am using. Perhaps that is the problem?

It would make sense because the transform for bone N is dependent upon the transforms of all bones before N.

Share this post


Link to post
Share on other sites
Fixed it. Here's what I learned:

1) T(-global bone origin) * R(bone) * T(global bone origin) works perfectly (since -global of one bone plus global of the next will equal the displacement between them), but you have to prerotate the bone origins before you concatenate the matrices. A matrix with translation (x,y,z) concatenated to a string of matrices MEANS a translation of (x,y,z) NO MATTER WHAT.

2) When converting quaternion transforms to matrices, ALWAYS check your W components. Not doing this can cause your translations to have no effect, or a much greater effect than intended.

Thanks anyway for your help. You got me thinking, and thinking solves problems. :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!