PDA

View Full Version : Direction vector from quaternion? (sorry)



McNugget
05-10-2003, 11:52 AM
Hi all,

I tried to learn everything about quaternions and matrices the past weeks and solved the loved gible lock now.

When I try to move in 3D space I have now a new problem.
My quaternion code is based on nehe's gametutorial 7 and some articles from gameasutra and gamedev, because the gametut. 7 is not very intuitive...

So what I'm going to do is to get the direction vector from the quaternion.
I modyfied the gametut. function so looks a bit different but that shouldn't matter:




MFVector3D MFQuaternion::GetDirectionVector()
{
MFVector3D v3dTmp;
Normalize();

v3dTmp.x = 2.0f*(x*z-w*y);
v3dTmp.y = 2.0f*(y*z+w*x);
v3dTmp.z = 1.0f-2.0f*(x*x+y*y);

return v3dTmp;
}

I dont really know what the hack is wrong with this. Maybe its not a mistake made here, so lets see another snip of code:


MFQuaternion &MFQuaternion::Set(float xT, float yT, float zT)
{
MFQuaternion xQ(xT, 1.0f, 0.0f, 0.0f);
MFQuaternion yQ(yT, 0.0f, 1.0f, 0.0f);
MFQuaternion zQ(zT, 0.0f, 0.0f, 1.0f);

*this = xQ;

*this *= yQ;

*this *= zQ;

return *this;
}

MFQuaternion &MFQuaternion::Set(float angle, float xT, float yT, float zT)
{
float factor = xT*xT+yT*yT+zT*zT;
if(!factor)
factor = (float) EPSILON;

float scaleBy = (float) (1.0/sqrt(factor));

w = (float) cos(angle/2.0f);

float sinHalfAngle = (float) sin(angle/2.0f);
x = xT*scaleBy*sinHalfAngle;
y = yT*scaleBy*sinHalfAngle;
z = zT*scaleBy*sinHalfAngle;

return *this;
}

MFQuaternion MFQuaternion: :operator* (const MFQuaternion Q)
{
MFQuaternion Qtmp;
Qtmp.x = w*Q.x + x*Q.w + y*Q.z - z*Q.y;
Qtmp.y = w*Q.y + y*Q.w + z*Q.x - x*Q.z;
Qtmp.z = w*Q.z + z*Q.w + x*Q.y - y*Q.x;
Qtmp.w = w*Q.w - x*Q.x - y*Q.y - z*Q.z;
return Qtmp;
}

void MFQuaternion: :operator*=(const MFQuaternion Q)
{
MFQuaternion Qtmp;
Qtmp.x = w*Q.x + x*Q.w + y*Q.z - z*Q.y;
Qtmp.y = w*Q.y + y*Q.w + z*Q.x - x*Q.z;
Qtmp.z = w*Q.z + z*Q.w + x*Q.y - y*Q.x;
Qtmp.w = w*Q.w - x*Q.x - y*Q.y - z*Q.z;
x = Qtmp.x;
y = Qtmp.y;
z = Qtmp.z;
w = Qtmp.w;
}


My rotation is applied as follows:


rotX = -mouse.y / 500; // Mouse Look
rotY = -mouse.x / 500; // Mouse Look
// rotZ += 0.001*Engine.Tools->procPower;

qRotation *= MFQuaternion(rotX, rotY, rotZ);
// qRotation.QuatToAxisAngle(axisX, axisY, axisZ, rotAngle);
mRotation = qRotation.QuatToM4();
glMultMatrixf(mRotation.v);
// glRotatef((float) (rotAngle*PIUNDER180), axisX, axisY, axisZ);

v3dDirection = qRotation.GetDirectionVector();
qRotationT = qRotation;

qRotation = MFQuaternion(0.0f, 90.0f, 0.0f) * qRotation;
v3dRight = qRotation.GetDirectionVector();
qRotation = qRotationT;

qRotation = MFQuaternion(90.0f, 0.0f, 0.0f) * qRotation;
v3dUp = qRotation.GetDirectionVector();
qRotation = qRotationT;


The direction vectors I get are not orthogonal. They seem to be messed up when I rotate the camera (I have a little coordinate System on my screen [thanks to vincoof] so I can see what happend to them).

Maybe someone can find the mistake or you can help with ideas...

Regards,
McNugget

[This message has been edited by McNugget (edited 05-10-2003).]

Ozzy
05-10-2003, 09:38 PM
Depending on the manipulations u've got/need to do with your rotations stored as quats (which is a good idea), conversions into others formats are also really usefull for human beings ;) For instance, you can extract many usefull and comprehensive infos by translating your quats back to eulers,matrices,axis angle and so on..
check out http://skal.planet-d.net/demo/matrixfaq.htm

conclusion: quats are usefull to avoid gimbal lock then it's obvious to handle all your rotations with them internally but don't forget to get back to understandable values for others manipulations it is *not* wasted rastertime :)

hth

McNugget
05-11-2003, 12:05 AM
Thankx a lot!

I've worked on this problem sor a long time now and last night I found a solution!!

What I do is converting the quat back to a matrix. Thats what I do since one week.
I tried to get the direction vectors from the quat which doesn't work anyway. Dont ask my why. (I think I posted the function)

Then, after some testing, I tried to get the vectors from the matrix I just generated from my quat. That doesn't work, too!!
Uhg, what the hack....

But yesterday evening I found the solution:
glGetFloatv(...) gets just the same matrix as I put in a second before.
So I tried to use the transpose of the MODEL_VIEW_MATRIX for getting the vectors which works perfectly! Buh, what a feeling! http://www.opengl.org/discussion_boards/ubb/wink.gif

Ok, thankx anyways! I just needed some time http://www.opengl.org/discussion_boards/ubb/smile.gif

oliii
05-11-2003, 02:22 PM
you could just rotate a vector by a quaternion to get it's orientation.

Say you want the orientation of the Up vector of a camera, you multiply (0, 1, 0) by the quat.

McNugget
05-11-2003, 10:36 PM
You're talking about something like this:

[CODE]
v3dDirection = qRotation.GetDirectionVector();

qRotation *= MFQuaternion(0.0f , 90.0f, 0.0f);

v3dRight = qRotation.GetDirectionVector();

qRotation *= MFQuaternion(90.0f , 0.0f, 0.0f);

v3dUp = qRotation.GetDirectionVector();

??? right?

this does not work! Look at the code I've posted some days ago. You can find: GetDirectionVector(). If you can find a problem or a mistake please tell me!
I tried this version first before I checked the matrix version out.
When I rotate using the quat-rotation-version I get everything but orthogonal vectors. They move somewhere (with the length 1.0f). Triy to download this file and take a look at the pictures to understand what I meen:
little coordinate system (http://www.ewetel.net/~dieter.birnschein/mf-studios/coord.zip)

Thankx
McNugget