[SOLVED] How are BoneTracks interpreted?

I am writing a custom model loader (to load IQE files). So far, things have been working well, but I’ve run into a snag when playing animations. When I load a skeleton, but don’t animate it at all, the skeleton takes the pose I expect it to, but as soon as I start running an animation, the orientation of the bones all change, so that the skeleton itself becomes rotated and then individual bones are rotated improperly relative to their parent bone. Other than that, the animation seems to be playing correctly. I am wondering how the rotation and translation values in a BoneTrack are interpreted (eg. are they relative to something?) by the engine, so that I can more easily debug this.

Can anyone provide me with any info, hints, or suggestions?

EDIT: The solution was that BoneTrack transforms are supposed to be relative to the binding pose, whereas the transforms I was adding were absolute. This was not that difficult to figure out. The hard part (for me) was calculating the correct rotation based on the absolute rotation and the binding pose rotation. The correct calculation turned out to be:

boneTrackRotation = bindingPoseRotation.inverse().mult(absoluteRotation);

There’s this thing called a “binding pose” that makes animation a bit complicated. Every bone has a binding transform (usually just a rotation) relative to its parent. At every joint, the animation transforms from the bone track are applied on top of the binding pose.

1 Like

So suppose I have a binding pose, and then an absolute rotation I want the bone to have at a key frame, how would I calculate the rotation that should be in the bone track?

I would have thought it was:

boneTrackRotation = absoluteRotation.mult(bindingPoseRotation.inverse());

But that doesn’t seem to produce the right results. The results seem close, but the animation is slightly off. Do I need to also take the rotation of the parent bone into consideration?

EDIT: I am pretty weak on my Quaternion math.

EDIT: Figured it out. The correct line was:

boneTrackRotation = bindingPoseRotation.inverse().mult(absoluteRotation);

I assume by “absolute rotation” you mean the bone’s orientation in the coordinate system of the skeletonized object. Correct?

The transforms in the bone track are relative to both the parent and the bind pose, so you’d have to undo both of those to get the correct answer. And of course the parent’s orientation is affected by its bind pose and local rotation, and so on back to the root bone. And of course the skeleton as a whole might be rotated.

And as you’ve discovered, with quaternions, A x B does not necessarily equal B x A.

1 Like

Of course, but the harder question is does A x B = A.mult(B) or B.mult(A)?

In jme it’s technically:
A x B = a.mult(b)

…but the whole question gets deeper because different environments may treat A x B differently. (pre mult versus post mult)

In the JME scene graph, it’s parent.mult(child) to get world rotation… which is probably a clearer way of stating it.

2 Likes

Just some precision about this. This also guaranty correct rotation. if the rotation was accumulated from frame to frame we’ll end up with too much error in the end and the last frames would look wrong.

I don’t know the math logic behind this though, probably because we use quaternions and they don’t represent exactly the same rotation as a corresponding matrix…or… I’m full of shit… anyway just know that this is the reason behind this design

That makes a certain amount of sense to me.

If there were an accumulation of errors, that would be caused by
floating-point arithmetic. It’s of particular concern since jME3
implements quaternions using single-precision. Avoiding
error accumulation is an important aspect of Numerical Methods.