Some quaternion questions [resolved]

Started by
1 comment, last by iNsAn1tY 19 years, 6 months ago
Hello. I've been working on using quaternions to represent rotations in my scene graph, and I'm a little confused. I started out with the Quaternions tutorial on GameTutorials.com, and I've also read quite a bit of this: Euclidean Space - Maths - Quaternions. However, I still have a couple of questions about using quaternions, and I'm hoping someone can answer them. Here they are: 1. A quaternion represents one rotation about one axis, right? If this holds true, then if I wanted a 45 degree rotation about the x axis, then a 30 degree rotation about the y axis, then a 90 degree rotation about the z axis, would qFinal below contain the correct rotation?
qRotX.Set(45.0f, 1.0, 0.0f, 0.0f);
qRotY.Set(30.0f, 0.0, 1.0f, 0.0f);
qRotZ.Set(90.0f, 1.0, 0.0f, 0.0f);
qFinal = qRotX * qRotY * qRotZ;
Can I concatenate rotations like that? It seems at the moment that I can't. I have a simple model of a box in my scene graph, and when I multiply together a quaternion for rotation about the X axis, and a quaternion for rotation about the Y axis, the model skews and distorts. It's fine if I have one rotation or the other, but not both together. Plus, if I use the Rotate member of my scene graph, which multiplies a quaternion with a small step in rotation by the scene graph's main quaternion, the skews and distortions become worse as time progresses. I've gone through the quaternion code a couple of times, looking for incorrect statements, but I haven't found any. Basically, I'd just like a way of scaling, rotating and translating a given object, without distorting it. Am I going about this the right way? 2. I thought a decent way of using quaternions would be for controlling the camera. The Player object holds it's own position and orientation (in the form of a CVector3 class and a CQuaternion class respectively) because the global camera can be comandeered by other objects. The code below is highly unoptimized (uses a rotation matrix, etc.), but it shows what I'm trying to do:
...
    
CQuaternion qRotX, qRotY, qFinal;
    
qRotX.Set(-m_vOrientation.m_fX, CVector3(1.0f, 0.0f, 0.0f));
qRotY.Set(-m_vOrientation.m_fY, CVector3(1.0f, 0.0f, 0.0f));
qFinal = qRotX * qRotY;

// Reset the view vector...
CVector3 m_vView;
m_vView.m_fZ = -1.0f;

// Apply the rotation created above to the view
// vector, then add the translation vector to it...
m_vView = m_vView * qFinal.GetRotationMatrix();
m_vView += m_vTranslation;

g_pApp->GetGlobalCamera()->SetTranslation(m_vTranslation);
g_pApp->GetGlobalCamera()->SetView(m_vView);
    
...

Basically, I create a new view vector every frame by rotating the vector (0, 0, -1) by two quaternions. This unit vector is then added to the player's position to give a proper view vector. However, this is causing some problems. It has reversed my movement with the arrow keys (ie. up moves you backward, down moves you forward), and when I move the mouse left and right, the rotation suddenly increases exponetially. Is there a better way to represent the player's movement and looking than this? If there is, can someone point me to a page that would explain it? Thanks in advance for any replies... EDIT: Did some digging around, and it seems that the quaternion multiplication code on Euclidean Space is incorrect. I found this tutorial at CProgramming.com, implemented the method outlined there, and bingo, no distortion on quaternions that are multiplied together. The camera problem seems to be sorted too, but that will require some more testing to be sure. Anyway, consider both issues above resolved... [Edited by - iNsAn1tY on October 2, 2004 12:26:42 PM]
My opinion is a recombination and regurgitation of the opinions of those around me. I bring nothing new to the table, and as such, can be safely ignored.[ Useful things - Firefox | GLee | Boost | DevIL ]
Advertisement
In the APIs I've seen Set is used to explicitly set the four elements of the quaternion. As a rotation quaternion is a unit quaternion its elements must all be between -1 and 1, so calling it with (45, 1, 0, 0) will create a non-unit quaternion. Such will tend to scale as well as rotate.

What you need is a 'create a quaternion from an angle and axis' function or method. If you don't have one it's simple enough to create. Something like

qRot.Set(cos(angle), x * sin(angle), y * sin(angle), z * sin(angle));

where 'angle' is the angle, 'sin' and 'cos' trig functions and (x, y, z) a unit vector along the axis. This assumes the first element of the quaternion is the real element - so for example to generate an identity quaternion you use:

qIdentity.Set(1, 0, 0, 0);
John BlackburneProgrammer, The Pitbull Syndicate
My apologies, I forgot to point out that the Set method used there accepts (angle, x, y, z), not (w, x, y, z). It creates a unit length quaternion from an axis-angle rotation. Thanks for pointing that out, I've just changed that function to something less confusing...
My opinion is a recombination and regurgitation of the opinions of those around me. I bring nothing new to the table, and as such, can be safely ignored.[ Useful things - Firefox | GLee | Boost | DevIL ]

This topic is closed to new replies.

Advertisement