Jump to content
  • Advertisement
Sign in to follow this  
browerjs

Quaternion's and gimbal lock

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

I was experiencing gimbal lock with using RotateX*RotateY*RotateZ, so i switched to quaternion's and i'm still having the same problem when i'm trying to rotate my mesh. here is my code:
Quaternion rotquaternion = EulerToQuaternion(Geometry.DegreeToRadian(m_YAngle),
				Geometry.DegreeToRadian(m_XAngle),Geometry.DegreeToRadian(m_ZAngle));

device.Transform.World = Matrix.RotationQuaternion(rotquaternion);


m_XAngle, m_YAngle, m_ZAngle are incremented by the delta of the mouse movement. I only increment one of the angles at a time, i choose that angle by having a radio button to select whether to rotate around the X,Y, or Z axis. Here is my code for the EulerToQuaternion method.
private Quaternion EulerToQuaternion(float yaw, float pitch, float roll)
{
	float cr, cp, cy, sr, sp, sy, cpcy, spsy;

	cy = (float)Math.Cos(yaw/2);
	cp = (float)Math.Cos(pitch/2);
	cr = (float)Math.Cos(roll/2);

	sy = (float)Math.Sin(yaw/2);
	sp = (float)Math.Sin(pitch/2);
	sr = (float)Math.Sin(roll/2);

	cpcy = cp * cy;
	spsy = sp * sy;

	float w = cr * cpcy + sr * spsy;
	float x = cr * sp * cy - sr * cp * sy;
	float y = cr * cp * sy + sr * sp * cy;
	float z = sr * cpcy - cr * spsy;

	Quaternion retval = new Quaternion(x,y,z,w);
	return retval;
}


When my mesh is initially displayed i can rotate around any of the axis properly, but if i move around the X axis 270 deg. and the Y axis 270 deg. my X and Z movement until i move my Y axis again are around the same axis. What am I don't wrong? I've been struggling with this for days with a variety of Quaternion and Matrix calculations, and can't seem to get past this gimbal lock.

Share this post


Link to post
Share on other sites
Advertisement
Even though you're using quaternions as an intermediate representation here, you're still using Euler angles to generate the quaternions. The use of Euler angles is where the gimbal lock is coming from. Quaternions aren't magical; they can't add back the degree of freedom that you removed earlier. Switch from an Euler angle representation to an axis-angle representation.

BTW, this is really more appropriate to the Math & Physics forum. Tell me if you want me to move it there.

Share this post


Link to post
Share on other sites
As for representing the angles as an axis-angle representation, how do i go about doing that, I've been searching up and down the web, and have yet to find a good example.

here is my code for changing the angles:

private void Viewer_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
{
if(!m_fLeftMouseButtonDown)
{
m_fLeftMouseButtonDown = true;
m_iRelativeXPos = e.X;
m_iRelativeYPos = e.Y;
}
else
{
int xmovement = Math.Abs(e.X-m_iRelativeXPos);
int ymovement = Math.Abs(e.Y-m_iRelativeYPos);
if(m_rbXRotation.Checked)
{
if(e.X < m_iRelativeXPos)
{
m_XAngle += xmovement;
}
else if(e.X > m_iRelativeXPos)
{
m_XAngle -= xmovement;
}
}

if(m_rbYRotation.Checked)
{
if(e.Y < m_iRelativeYPos)
{
m_YAngle -= ymovement;
}
else if(e.Y > m_iRelativeYPos)
{
m_YAngle += ymovement;
}
}

if(m_rbZRotation.Checked)
{
if(e.Y < m_iRelativeYPos)
{
m_ZAngle -= ymovement;
}
else if(e.Y > m_iRelativeYPos)
{
m_ZAngle += ymovement;
}
}
if(m_XAngle>359)
{
m_XAngle = m_XAngle-360;
}
else if(m_XAngle<0)
{
m_XAngle = m_XAngle+360;
}
else if(m_YAngle>359)
{
m_YAngle = m_YAngle-360;
}
else if(m_YAngle<0)
{
m_YAngle = m_YAngle+360;
}
else if(m_ZAngle>359)
{
m_ZAngle = m_ZAngle-360;
}
else if(m_ZAngle<0)
{
m_ZAngle = m_ZAngle+360;
}

m_iRelativeXPos = e.X;
m_iRelativeYPos = e.Y;
}
}




m_rb* are the Radio Buttons.

PS: If you want to move it, that's fine.

Share this post


Link to post
Share on other sites
Quote:
Original post by browerjs
m_XAngle, m_YAngle, m_ZAngle are incremented by the delta of the mouse movement. I only increment one of the angles at a time, i choose that angle by having a radio button to select whether to rotate around the X,Y, or Z axis.

Like already pointed out, the problem is essentially you're still storing cumulative result of 'delta' rotations in Euler angles.

A possible way to fix it would be to discard your m_Angle variables altogether, and to store object orientation in single quaternion instead. Then, to alter this orientation build a temporary quaternion in accordance with delta of mouse movement, and multiply (or post-multiply depending on what type of rotation you want) the orientation quaternion of your object by it. You can then use this orientation quaternion to build the final matrix for your object.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!