How to write Euler to Quaternion conversion, aka quaternion hell!!!

This topic is 4014 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Share on other sites
In such cases, it's often useful to go back to basics and work through the low-level maths. For example, create 3 unit vectors that point along the axes in the positive direction, create a quaternion that will have a simple effect (e.g. rotate 90" cw on the y-axis), then apply this quaternion to your unit vectors (by converting the quaternion to a matrix then multiplying the vectors by the matrix, or multiplying the vectors by the quaternion directly). Check where the unit vectors end up pointing - if the results don't make sense you need to go back and understand why not, check your assumptions, conventions etc.. When you get rotation about a single axis working on all axes, move on to 2 axis then 3 axis rotation, at each step making sure you get the results you expect. Once you are happy the low-level maths is working as you need it, then move further up your pipeline and do similar tests.

It's hard to spot your exact problem just from looking at the code you posted, but if you can't get it fixed, there are also lots of quaternion camera articles around that can be easily searched for which may offer extra insight - there's even one on gamedev.net.

Share on other sites
Thanks very much for taking the time to post. Writing the post forced me to rethink it all through again, after which I prayed, went back to work and God quickly led me to a piece of info that was missing in my thinking here:

http://www.gamedev.net/community/forums/topic.asp?topic_id=72342

For some reason the part about how quaternions were "nothing magic" sparked new thinking and I rewrote the code once through and it worked! I'll repost the working code so others might benefit from my suffering. Thanks again!

public Camera(float initialLat, float initialLon)
{

CreateProjectionMatrix((float)Math.PI / 3.0f, 1.3f, 1.0f, 8000.0f);

//this gets the xyz point corresponding to lat/lon == (0,0)
m_position = WorldLatLonConverter.GetXYZFromLatLon(0f, 0f);

m_initialLook = Vector3.Normalize(-m_position);
m_initialUp = new Vector3(0f, 1f, 0f);

//this should be the orientation of being over lat/lon == (0,0) and
//looking straight towards the center of the earth. alternative way to
//look at this is yaw == pitch == roll == 0
m_orientation = EulerToQuaternion(0, 0, 0);

Update();

SetCameraLocation(initialLat, initialLon, 0f);

}

public void SetCameraLocation(float lat, float lon, float heading)
{

m_orientation = Quaternion.Identity;

Quaternion rotation = EulerToQuaternion(lon, lat, heading);

//the rotation that's about to be applied will only work
//for setting the position if the m_position is along the
//x-axis like it was when it was initialized.
Vector3 newPosition = new Vector3(m_position.Length(), 0f, 0f);
m_position = newPosition;

Rotate(rotation);

}

private Quaternion EulerToQuaternion(float yaw, float pitch, float roll)
{

Vector3 Vpitch = new Vector3(0f, 0f, 1f) * (float)Math.Sin(pitch / 2);
Quaternion Qpitch = new Quaternion(Vpitch.X, Vpitch.Y, Vpitch.Z, (float)Math.Cos(pitch / 2));

//the '-' is because the way direction of positive longitude changes
//is right-handed but our system is left-handed
Vector3 Vyaw = new Vector3(0f, 1f, 0f) * (float)Math.Sin(-yaw / 2);
Quaternion Qyaw = new Quaternion(Vyaw.X, Vyaw.Y, Vyaw.Z, (float)Math.Cos(-yaw / 2));

Vector3 Vroll = new Vector3(1f, 0f, 0f) * (float)Math.Sin(roll / 2);
Quaternion Qroll = new Quaternion(Vroll.X, Vroll.Y, Vroll.Z, (float)Math.Cos(roll / 2));

Quaternion Qrotation = Qroll * Qpitch * Qyaw;

return Qrotation;

}

public void Rotate(Quaternion rotationQuaternion)
{

rotationQuaternion.Normalize();

m_orientation = m_orientation * rotationQuaternion;
m_orientation.Normalize();

Matrix rotation = Matrix.RotationQuaternion(m_orientation);

//we set the look and up vectors off of the orientation quaternion to ensure there's
//never any error due to floating point rouding etc.
m_up = Vector3.TransformNormal(m_initialUp, rotation);
m_look = Vector3.TransformNormal(m_initialLook, rotation);

//as we rotate we need to move the position as well, spun about the axis by angle radians
rotation = Matrix.RotationQuaternion(rotationQuaternion);
m_position = Vector3.TransformNormal(m_position, rotation);

m_lookAt = m_position + m_look;

m_view = Matrix.LookAtLH(Position, m_lookAt, m_up);

UpdateCameraValues();

}

1. 1
Rutin
44
2. 2
3. 3
4. 4
5. 5

• 11
• 9
• 12
• 10
• 13
• Forum Statistics

• Total Topics
632983
• Total Posts
3009714
• Who's Online (See full list)

There are no registered users currently online

×