0
101 Nov 27, 2005 at 20:20

Ok, i admit, i just don’t get it.

Here is what i’d like to achieve:
I have a skeleton for skeletal animation. Every Bone stores a local rotation-quaternion and a local translation-vector.

Now, every frame i set those local transformations depending on an interpolated animation.

The next step is, to calculate the ABSOLUTE rotations (quaternion) and translations (vector) for every bone, so that i can send them to the GPU.
Note: I don’t want to use matrices! With matrices everything works fine, but i want to do this using quaternions.

Now, i know how to rotate around a given point, using quaternions. That means, i have no problem rotating ONE object around it’s center, or so. The problem arises, when using a hierachy of objects.

That means, if Object O2 is the child of O1, i want to include all rotations/translations of O1 into those of O2 and additionally rotate/translate O2 by its own local transformations.
And this is, where i am pulling my hair out the last 3 days.

Could someone maybe post some code or stuff to show me how this is done correctly? Please? Google seems to know no articles which explain this particular problem with quaternions.

My problem is not the rotation itself. That’s easy, simply multiply the quaternion of O1 with that of O2 and it’s rotated correctly. The problem is the pivot-point of O2. I want it to rotate around O1s pivot-point for O1s rotation and around O2s pivot-point for O2s rotation. You certainly know, what i mean. The problem is, i need to include this in O2s final translation-vector and there seems to be an infinite amount of wrong combinations possible, and i might be the first man on earth trying all of them :wallbash:

Thanks,
Jan.

#### 5 Replies

0
101 Nov 27, 2005 at 20:55

I explained calculating the final translation vector, you can accumulate all the transformations in a single quaternion+translation pair using the same method.

If you have a translation, what would this translation be after a rotation? Simply the translation rotated. So (Q1 + T1) * Q2 + T2 becomes Q1 * Q2 + (T1 * Q2) + T2, which is another quaterion, translation pair: Q1 * Q2 for the quaternion, and (T1 * Q2) + T2 for the translation. To apply another transformation, use the same trick

0
101 Nov 27, 2005 at 23:15

I’m sorry, but it doesn’t work. At least not, as i understand you.

I have the following information about my bones:

For some child-bone i want to calculate the final quaternion+translation. For that bone i know
- its local rotation
- its local translation
- its relative position to the unrotated/untranslated parent-bone, which is supposed to be the pivot-point

I don’t know exactly what i should fill into Q1,Q2,T1,T2 from your given formula.

If Q1/T1 is the parent, Q2/T2 is the child, i set

Q1 = final rotation of the parent
T1 = final translation of the parent
Q2 = local rotation of the child
T2 = ? relative position to the parent (rotated/not rotated?)

I tried some other stuff, i am out of ideas for now.

Anyway, thanks for the help.

Jan.

0
101 Nov 28, 2005 at 11:07

Wooha! It works! :w00t:

Man, thanks for your help! After rethinking all night about it, i finally realized what translations you meant. After all, it’s really not that difficult, but it is a bit different than with matrices. With matrices you always use the relative position of a bone to its parent bone as the pivot-point. With quaternions i need to use the absolute position of the bone in the unrotated/untranslated skeleton, rotate around that and then modify it with the parent-bones transformation.

That was my first experience with quaternions, i admit it took me a while to get it.

Again, thanks for your help. :worthy:
Jan.

0
101 Nov 28, 2005 at 13:13

Woohoo ;)

0
101 Sep 23, 2008 at 09:11

Hello, this thread is years old but I’m having the same problem.

Any chance someone could elaborate here? My goal is to maintain the bone hierarchy in quaternion/translation all the way through the pipeline into the shader rather than sending a matrix palette. I’m sure other people do this but I couldn’t find any other info about it other than this thread.

I have it almost working in that the skeleton appears to animate properly when I debug it with line drawing code but it seems like the palette creation part is getting screwed up. I say this because my animated character is stretching all over the place and this normally happens with a screwed up palette.

I’m guessing that this is due to a bug in the creation of the inverse bind pose transforms, the composition of the absolute transforms or maybe in the shader.

The Q1/T1 terminology is a bit vague though. I tried guessing but it didn’t work.

In my set up I have a hierarchy of bones {B0…Bn}

Each bone looks something like this:

struct Bone
{
Quaternion LocalRotation;
Vector3 LocalTranslation;
Quaternion AbsoluteRotation;
Vector3 AbsoluteTranslation
Bone& ParentBone;
};


When I first load a model I create a skeleton from the bind pose information and keep that stashed in my model prototype class.

I also calculate the inverse bind pose skeleton and store this in the model as well. To do this I clone the bind pose skeleton and then rip through the bones and set LocalRotation to its inverse and LocalTranslation to -LocalTranslation. Finally I call a function that calculates (AbsoluteRotation, AbsoluteTranslation) which I will use later when creating palette entries (More on this function later)

When I want to animate a model instance I create a skeleton instance and initialize it to the model bind pose. The animation mixer then adjusts the LocalRotation and LocalTranslation on each bone as necessary from the animation data. Off Topic Question: What is the preferred way to keep the animation data … in bone space or model space?

After the animation mixer has done its thing I then call the function I mentioned above that calculates the AbsoluteRotation, AbsoluteTranslation for each bone on the animated skeleton.

The way this function works is:

this.AbsoluteRotation = ParentBone.AbsoluteRotation * this.LocalRotation;
this.AbsoluteTranslation = ParentBone.AbsoluteTranslation + Transform(this.LocalTranslation, ParentBone.AbsoluteRotation);


Note: It is the case that the bone array is sorted so that dependent bones are always further along than their parents.

To calculate the palette entries I iterate the bones again and calculate P0..Pn

PaletteRotation[i] = Bones[i].AbsoluteRotation * InverseBoneOffsets[i].AbsoluteRotation;
PaletteTranslation[i] = Bones[i].AbsoluteTranslation * InverseBoneOffsets[i].AbsoluteTranslation;