FBX and Skinned Animation

Started by
22 comments, last by Buckeye 9 years, 8 months ago

Your problem is in specifying the translation for joint_c. You have it translated along the Z axis of joint_b, which is apparently where you want it in WORLD (not local) coordinates. If you want joint_c to be "inline" with joint_b in the bind pose without regard to joint_b's rotation, you want to translate joint_c along joint_b's primary axis, which appears to be the X axis, not the Z. Joint_b's rotation will then rotate joint_c into the position shown on the left.

As questioned before, it's not clear what data you're using to render the images. You should show what you're actually getting, in addition to what you want. If joint_c is translated locally +2 along the Z-axis, then (by it's parent's orientation) rotated -pi/2 about the Y-axis to (-2, 0, 0), then translated +2 along the X-axis, it would appear at the origin, not (2,0,2) as you've shown. If joint_c is, instead, translated locally +2 along the X-axis, then it would be rotated to (0, 0, 2) and translated to (2, 0, 2).

Some tough love: In general, it's a lot easier to debug using actual data than "Here's what I want. My code doesn't work. What's wrong?"

By the way, in the code you've posted, you've still got re-used variables that makes it difficult to review, I'm afraid. To repeat, I would suggest you not re-use variables until (or even after) you've got the process well established. In this case, you're using bind-pose transforms to create animation transforms. Yeah, it appears to be "efficient" but, for review purposes, it requires going back and forth to check values and checking whether you've got trans*rot rather than rot*trans, etc.

The animation matrix (before combining) for each joint should be a local animation transform with respect to the joint's parent. It should reflect the animated orientation of the joint. However, you set the anim transform for joint_b to identity. Yeah, you're using the local transform to create an animation transform. But (I repeat) I'm suggesting you NOT REUSE variables until you get the process well understood. Later, when you create other animation sequences, you don't want to use bind-pose transforms mixed in with animation transforms.

For testing, it appears you want joint_b to be in the same orientation as it has in the bind pose. So code it again! Don't use the bind-pose transforms. For joint_b, in this particular situation, it may work, but setup the routine for the more general case.

Similarly, the local animation transform for joint_c should be the local rotation matrix times the local translation matrix. Don't use the bind-pose transforms. And, in this case, it appears you've coded joint_c translated along the WORLD Z-axis, instead of joint_b's local axis.

And.. in your D3DXVec3TransformCoord you re-use variables. I know that's for testing, but, eventually, in the shader, the input vertex will be transformed to an output vertex, not overwritten.

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.

Advertisement

c) bone hierarchy
d) transform of each bone in it's bind pose

pose data:
a) for each pose, the local rotation of each bone (relative to it's parent).

That is why FBX - keeping transformations derived relativly across binding rooting of a multi tree (like if it wanted to rule inverse procedural kinematics...lol) - is a one big mess stuff, creating a data hard to derive the final absolute matrix from. One needs to create absolute object space bone transformations per frame. FBX experimenatal unofficial uncompromised format with pile of SDKs end exporters, is too wrong for it.

Wite your own 3ds max script to output transformations of boning objects. Only viable solution for explicit animations and for rulling your production out. Trust me, I know what I am talking about.

Hi Buckeye,

You pretty much solved my problem with your first paragraph. I was using the wrong axis for the local translation value. I also feel like I finally have a pretty good understanding of what it means to go from one bone space to another.

My goal was to setup a simple bone chain by hand so I could learn the mechanics of creating the offset (inverse bind) matrix as well as interpolating bones between poses to move the model vertices; and also to know exactly what data I should be getting from my FXB converter which brings me to this...

I know you don't use FBX but please bear with me. I can't figure out how to get the local transforms for each bone in the bind pose, or if they are even accessable. I can get the inverse world transforms of each bone and I already know the hiearchy. Can I do my own math to get the local bone transforms so I can compute the offset matrices myself ? If I can do that then I think I am all set.

I'm sorry if I got you a little annoyed with reusing variables and stuff, I will now be much more explicit in my code. It's like you said, it's better if I help others help me.

Thanks a lot man.


I can get the inverse world transforms of each bone and I already know the hie[r]archy. Can I do my own math to get the local bone transforms so I can compute the offset matrices myself ? If I can do that then I think I am all set.

Maybe we have semantics problems. The inverse world transform of a bone is the offset matrix.

If you have the offset matrix (inverse world transform) and you can import animation matrices, you should be able to animate the mesh.

However, to answer your question, you should be able to extract local transforms if you have the hierarchy.

To keep things clear, hopefully, I'll define what I'm assuming.

The inverse world transform transforms from world space to bone space. The inverse of the inverse, therefore, is the bone's world transform, and transforms from bone space to world space.

That is, bone-world-xform = inverse( inverse-bone-world-transform ).

That bone-world-transform can be defined as:

A. bone-world-xform = bone-to-parent-matrix * parent-to-world-matrix.

To calculate just the bone-to-parent-matrix, you can transform the parent-to-world-matrix to an identity matrix by multiplying the parent-to-world by its inverse. That is, for any matrix, M * M-1 = Identity. Conveniently, you state you have the inverse world transforms. So, multiplying equation A by the inverse-parent-world-transform (the emphasized matrix multiplication below results in an identity matrix):

bone-world-xform * inverse-parent-to-world-transform = bone-to-parent-matrix * parent-to-world-matrix * inverse-parent-to-world-matrix.

bone-to-parent-matrix * identity = bone-to-parent-matrix, which I assume is what you mean by the bone's local transform.

In words, multiply a bone's to-world matrix by the inverse of the parent's to-world matrix to get the bone's to-parent matrix.

Is that what you'd like to do?

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.

This topic is closed to new replies.

Advertisement