3

i have a Quaternion, based on a coordinate system where the Y axis is up, the X axis is to the right and the Z axis looks towards me.

Now i want to move a character in another application(C++) based on this quaternion. This would be no problem if the coordinate systems where identical, but this application uses a different coordinate system. Z is up, X is to the right and Y is trough the monitor(inwards).

I tried to simply rotate the quaternion to adjust the coordinate system, but every rotation i tried, it didnt look even close to be correct.

My Thought is that i need some kind of base transformation, but i have no idea how to do this with a quaternion, does any one know how to perform a base transformation on a quaternion?

EDIT

I use the Eigen C++ lib for Quaternions. Here are the Quaternions i used:

Quaternion<float> QX90( Eigen::AngleAxisf( M_PI /2.0, Eigen::Vector3f::UnitX() ) );
Quaternion<float> nQX90( Eigen::AngleAxisf( -M_PI /2.0, Eigen::Vector3f::UnitX() ) );

Quaternion<float> Qrshoulder = .... //the Quaternion in the Y up coordinate system

i tried with rotating the X axis :

Qrshoulder=Qrshoulder*QX90; 
Qrshoulder=QX90*Qrshoulder;
Qrshoulder=Qrshoulder*nQX90;
Qrshoulder=nQX90*Qrshoulder;

This didnt work. I also tried several other multiplications, i nearly tried every rotation that seems logical. I am confused..it seems this cannot be done with Quaternion multiplication

EDIT 2

I have absolute and hierarchical quaternions. Hierarchical Quaternions provides the amount of rotation in 3D space from the parent bone to the child..the absolute quaternions are the multiplied hierarchical bone orientations.

On the other hand, the character i want to animate has an engine behind, which already multiplies the bones, so i definitely need to use the hierarchical rotations. But the problem is, when i use hierarchical rotations, the Y axis always lies on the direction of the bone.

What i tried from Nolnoch's answer :

Quaternion<float> QNX( Eigen::AngleAxisf( 0, Eigen::Vector3f(1,0,0) ) );

rot=(QNX*QX90*Qrshoulder).toRotationMatrix();
targetNode->setRotation( Eigen::Transform3f( rot ) );

This didnt work either with hierarchcal nor with absolute orientations. Here is the article that describes what quaternions i get : http://msdn.microsoft.com/en-us/library/hh973073.aspx

What i think i miss, is when using the hierarchical orientations, i get the correct amount of rotation i need, but then the coordinate system is completly messed up because the Y axis is along the bone, and in my collada the coordinate system is always Z up. I have no clue how i can change this, i am not even sure if that is my problem.

1
  • If you are willing to use some other library, boost::math has quaternion support. Commented Apr 24, 2013 at 0:05

2 Answers 2

2

Can you show what rotations you've tried? It sounds like your secondary basis is the original basis after a 90 degree rotation about the negative X axis.

You can represent this with a quaternion [w, x, y, z] = [cos(PI / 4), sin(PI / 4), 0, 0] based on an angle-axis vector [(PI / 2), 1, 0, 0]. You can also convert your original quaternion to matrix form and concatenate an affine rotational matrix. I forget the order of the sin/cos terms at the moment.

Also be careful in what order you are multiplying your vectors and matrices. (v' = Rv) != (v' = vR).

[EDIT 1]
The thing is, quaternions have no inherent handedness or attachment to a particular basis. They are simply a quantity of motion about directional components defined in reference to the origin. Additionally, they store no explicit information about previous rotations.

So a final quaternion that is the representation of rotating 35 degrees about the Z axis in one context will still be rotating 35 degree about the Z axis in the other. Since your second basis is a rotation about X away from your original basis, this should work.

Other things to consider:

You mention a shoulder -- is this a hierarchical structure? If so, is this particular quaternion the true final/global quaternion for that limb, or is it in reference to another local context (and being concatenated)?

Under what context are you implementing this quaternion in your other application? If it's the same hierarchical structure, try transforming your ModelView by this correctional quaternion before you start the recursive rendering, then transform back when you're done (or use a matrix stack).

[EDIT 2]
What is QNX? You define an axis with no associated movement. If you are trying to use a zero or "empty" quaternion, it's [w, x, y, z] = [1, 0, 0, 0].

Quaternion multiplication, unless modified in a library's implementation, is from right (base rotation) to left (new rotation). I checked on Eigen, and it doesn't mention switching things around in the docs.

Also, every rotation transforms the global axes along with the object, so as I mentioned above, this correctional quaternion (QX90) should be added to the global, absolute rotation before the hierarchical model is ever rendered. See below.

Identity Matrix (clean slate)             Rotations in effect: [ ]
  Rotation 1                                                   [1]
    Draw some object                                           [1]

Identity Matrix                                                [ ]
  Rotation Q (QX90)                                            [Q]
    Rotation A (hip)                                           [A*Q]
      Draw hip                                                 [A*Q]
      Rotation B (spine)                                       [B*A*Q]
        Draw spine                                             [B*A*Q]
        Rotation C (shoulder)                                  [C*B*A*Q]
          Draw shoulder                                        [C*B*A*Q]

I've only rendered hierarchical models recursively as opposed to the iterative structure of the MSDN guide you posted. Still, this is the idea behind the state of the global transformation matrix with respect to its rotational components.

Sign up to request clarification or add additional context in comments.

5 Comments

thank you again for your effort, i updated the question. i couldnt solve this yet..but you are right with the hierarchical structure!
I'm more than happy to help -- I love this stuff. I've added to the answer again.
thank you again sir..i understand what you are telling here, but the problem is: the engine behind already multiplies every bone, i cannot touch the engine. In theory i only need to add the hierarchical rotation on top of this stack, to move correctly. But then again the coordinate system isnt right..and a simply rotation about X +- 90 does not work.
However the expression QNX*QX90*Qrshoulder doesn't put the hierarchy on top of the stack -- it puts it at the bottom. Good luck on this one!
i think i will try to calculate the rotations/quaternions myself..this seems to be easier than to use the ones i get provided
1

There is no rotation of Q that will give what you want, since the orthonormal basis in the new space Q' has different handedness.

One way to get what you want is to extract the X,Y,Z vectors of the input quaternion Q as follows:

X = <1-2*qY*qY-2*qZ*qZ, 2*qX*qY+2*qZ*qW, 2*qX*qZ-2*qY*qW>
Y = <2*qX*qY-2*qZ*qW, 1-2*qX*qX-2*qZ*qZ, 2*qZ*qY+2*qX*qW>
Z = <2*qX*qZ+2*qY*qW, 2*qZ*qY-2*qX*qW, 1-2*qX*qX-2*qY*qY>

where qX,qY,qZ,qW are the elements of Q, and X,Y,Z are the basis vectors. This is extracted from the function for quaternion-to-matrix (Quaternion::getMatrix)

Now interchange the axes as desired.

X' = X
Y' = -Z
Z' = Y

Finally, construct a new quaternion using the new basis vectors X',Y',Z'. I recently addressed how to construct a quaternion-from-orthonormal-basis in an answer to this question here: Quaternion from Orthogonal Basis

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.