Why people are scared from quaternions ?
Hi All
I have spent allot of time trying to resolve my problem but I could not
find a solution. I posted my question on game programming forum but no body helped.
may be they are scared from quaternions. I am using directx so the coordinate
system is left handed where the positive z axis goes into the screen. I am trying to build a simple
camera. I am given the up vector, the position of the camera and the target to
look at. with this information in hand, it is very easy to build a left handed
look at matrix, I already did that but this is not what I want. my scene nodes
including cameras have their orientaions stored as quaternions. wheneve I need
to animate a node I manipulate the orientaion quaternion then finally it gets
converted into a world transform. this is working fine with me but I could not
make it work in case of camera. the same way I need to manipulate the camera
orientation quaternion and finally convert it to a view transform. sorry for
the long explanation but I think it might help. here is what I did :
the view transfom is the inverse of the transform needed to move the
camera position to the origin and realign the camera look, up and right with
the z, u and x axes
//Set camera position
m_relPos = camPos
//up vector
m_up.Normalize();
//Calculate look at vector
//m_relPos below should be the absolute pos but here
//I am assuming the camera has no parent
m_look = m_target - m_relPos
//Normalize the look vector
m_look.Normalize();
//Quaternion to rotate the look to z
core::Quaternion look2z;
//Quaternion to rotate the up to y
core::Quaternion up2y;
//calculate look2z
look2z = look2z.getRotationTo(m_look, core::Vector3::UNITZ);
//calculate up2y
up2y = up2y.getRotationTo(m_up, core::Vector3::UNITY);
//Update camera orientation
m_relOrient = look2z * up2y;
so far the camera m_relPos and m_relOrient are there
convert the m_relOrient to rotation matrix and set the translation
to m_relPos and store it in m_relTransform
//Calculate view transform as:
m_view = m_relTransform.getInverse();
what is really confusing me is that I guess there is something
tricky here. for example:
if we look at the origin from the positions:
camPos
====
(-10, 0, 0); ok
(-10, 10, 0); ok
(-10, 0, -10); ok
(-10, 10, -10); view is shifted or rotated
(0, 0, -10); ok
(0, 10, -10); view is shifted or rotated
(10, 0, -10); ok
(10, 10, -10); view is shifted or rotated
(10, 0, 0); ok
(10, 10, 0); ok
it does not work only in the cases where the y and z of the look vector
are both non zero. I can not find an explanation for this. I am suspicious
about the fact that direct x is a left handed system while the quaternion
math assumes right handed system.
sorry for the long message, I entended to do that to make things clear.
any help is appreciated
thanks again
I'd be interested if you got it to work because I only orientate my model's z along the look-at vector but after a while it goes upside-down because I don't know how to orientate it in 2 directions at once :(
Here's my quaternion code which works [smile]
You can ignore the #if DEBUG sections if you want - that's just to ensure that my code is passing in normalized vectors and that the result is a normalized quaternion.
EDIT: Also I should probably mention that I based that on the C++ code on geometrictools.com [smile]
Here's my quaternion code which works [smile]
You can ignore the #if DEBUG sections if you want - that's just to ensure that my code is passing in normalized vectors and that the result is a normalized quaternion.
/// <summary>/// Computes a quaternion that rotates unit-length vector v1 to unit-length vector v2. The rotation is about/// the axis perpendicular to both v1 and v2, with angle of that between v1 and v2. If v1 and v2 are parallel,/// any axis of rotation is used, such as the permutation (v2.Z,v2.X,v2.Y).</summary>/// <param name="v1">Normalized vector that the computed quaternion rotates from to v2.</param>/// <param name="v2">Normalized vector that the computed quaternion rotates to from v1.</param>/// <returns>A quaternion that rotates v1 to v2.</returns>public static Quaternion Align(Vector3 v1, Vector3 v2){#if DEBUG float sqrLen1 = v1.LengthSq(); float sqrLen2 = v2.LengthSq(); System.Diagnostics.Debug.Assert(sqrLen1 > 1 - ZeroTolerence && sqrLen1 < 1 + ZeroTolerence && sqrLen2 > 1 - ZeroTolerence && sqrLen2 < 1 + ZeroTolerence, MsgVecNonNormalized);#endif // If V1 and V2 are not parallel, the axis of rotation is the unit-length // vector U = Cross(V1,V2)/Length(Cross(V1,V2)). The angle of rotation, // A, is the angle between V1 and V2. The quaternion for the rotation is // q = cos(A/2) + sin(A/2)*(ux*i+uy*j+uz*k) where U = (ux,uy,uz). // // (1) Rather than extract A = acos(Dot(V1,V2)), multiply by 1/2, then // compute sin(A/2) and cos(A/2), we reduce the computational costs by // computing the bisector B = (V1+V2)/Length(V1+V2), so cos(A/2) = // Dot(V1,B). // // (2) The rotation axis is U = Cross(V1,B)/Length(Cross(V1,B)), but // Length(Cross(V1,B)) = Length(V1)*Length(B)*sin(A/2) = sin(A/2), in // which case sin(A/2)*(ux*i+uy*j+uz*k) = (cx*i+cy*j+cz*k) where // C = Cross(V1,B). Vector3 bisector = v1 + v2; bisector.Normalize(); float cosHalfAngle = Vector3.Dot(v1, bisector); Vector3 cross; if (cosHalfAngle > ZeroTolerence || cosHalfAngle < -ZeroTolerence) { cross = Vector3.Cross(v1, bisector); } else { cross = Vector3.Cross(v1, new Vector3(v2.Z, v2.X, v2.Y)); //cosHalfAngle = 0.0f; - already is very close //cross.Normalize(); }#if DEBUG float sqrLen = cross.X*cross.X+cross.Y*cross.Y+cross.Z*cross.Z+cosHalfAngle*cosHalfAngle; System.Diagnostics.Debug.Assert(sqrLen > 1 - ZeroTolerence && sqrLen < 1 + ZeroTolerence);#endif return new Quaternion(cross.X, cross.Y, cross.Z, cosHalfAngle);}
EDIT: Also I should probably mention that I based that on the C++ code on geometrictools.com [smile]
Hello silvia_steven_2000,
I see you are using...
core::Quaternion up2y;
... to define a quaternion. Are you not using the built in DirectX Quaternions?
If you are not using the DirectX quaternion, then your fear is quite possible. OpenGL does not have a built in quaternion structure so odds are probably fairly good that your custom quat was written to be right-handed.
If you are using the DirectX quaternion and just wrapped it up, then it will already have been adjusted for left-handed co-ords.
As per your specific problem I can not say what's wrong.
Good Luck,
I see you are using...
core::Quaternion up2y;
... to define a quaternion. Are you not using the built in DirectX Quaternions?
If you are not using the DirectX quaternion, then your fear is quite possible. OpenGL does not have a built in quaternion structure so odds are probably fairly good that your custom quat was written to be right-handed.
If you are using the DirectX quaternion and just wrapped it up, then it will already have been adjusted for left-handed co-ords.
As per your specific problem I can not say what's wrong.
Good Luck,
thanks DrGUI for the code, actually I have no problem with that since I already have the code the finds the quaternion to rotate a vector to a vector. but there is something wrong in the way I rotate the look and up vectors.
regarding the dx quaternion class. thanks for the hint but I doubt it is gonna change something, I have a good quaternion class. I think my problem is in the login I am using. look at this statement: the view transform is basically the inverse of the transform needed to translate the camera position to the origin and re-orient its local coordinates with the world x , y and z. I am trying to implement that. rotate the look to -z and up to y but it does work in some cases and does not wrok in the other cases. there should be something stupid that I am not paying attention to since in the cases where it does not work I can see the objects I am looking to but there are not in the middle of the screen. the camera is like shifted or missoriented.
regarding the dx quaternion class. thanks for the hint but I doubt it is gonna change something, I have a good quaternion class. I think my problem is in the login I am using. look at this statement: the view transform is basically the inverse of the transform needed to translate the camera position to the origin and re-orient its local coordinates with the world x , y and z. I am trying to implement that. rotate the look to -z and up to y but it does work in some cases and does not wrok in the other cases. there should be something stupid that I am not paying attention to since in the cases where it does not work I can see the objects I am looking to but there are not in the middle of the screen. the camera is like shifted or missoriented.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement