silvia_steven_2000 122 Report post Posted July 17, 2005 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 0 Share this post Link to post Share on other sites
DrGUI 402 Report post Posted July 17, 2005 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./// <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] 0 Share this post Link to post Share on other sites
Kahsm 302 Report post Posted July 17, 2005 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, 0 Share this post Link to post Share on other sites
silvia_steven_2000 122 Report post Posted July 17, 2005 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. 0 Share this post Link to post Share on other sites