rotating stuff in OpenGL using quaternions

Started by
12 comments, last by HermanssoN 15 years, 1 month ago
Hello. I'm trying to rotate stuff in OpenGL using quaternions. I made a camera that works nice, but when I'm trying to rotate using glRotatef I'm getting wrong results. I was not sure if I should put this in the GL forum or the math forum. anyways, what I do is: on every frame. Quaternion Q; Q = Quaternion.FromAxisAngle(Vector3.UnitY, 0.005f); m_Rotation = Quaternion.Mult(Q, m_Rotation ); Normaly I use my own quaternion class but now I use OpenTKs quaternions to be sure that the math is correct when it is time to render. float Angle; Vector3 Axis; m_Rotation .ToAxisAngle(out Axis, out Angle); Gl.glRotatef(Angle, Axis.X, Axis.Y, Axis.Z); The result is not correct, the cube in this case, starts to rotate correctly but after a litle while, the Axis vector flipps from Y= 1 to Y = -1. And i don't know why :/ The most anoying thing is that my camera use tha same code for rotation. and it works like a charm. the difference is that i use gluLookAt so i don't have to use glRotatef. I have functions for extracting Right,At and Up from a quatenrion. I't would be nice if there where an example somewhere, like the spinning trinagle, that used quaternions.
Advertisement
Here are a few things you might double-check:

1. Make sure you're not missing a radians<->degrees conversion.

2. If you're not doing this already, you should normalize m_Rotation after it's updated to compensate for numerical drift.

3. If the *observed* behavior is correct, but if you're just concerned because you're getting an axis with y = -1 rather than y = 1, it's probably just an aliasing issue (remember that [angle, 0, 1, 0] and [-angle, 0, -1, 0] represent the same rotation).

Not all of these would explain the behavior you're seeing, but it's probably worth double-checking these things anyway.

Also, although the axis-angle method should work, you could instead use glMultMatrixf() and see if that makes any difference (that is, build a matrix using the object position and the direction vectors as extracted from the quaternion, and submit it to OpenGL directly).
Thnx for reply.
I just can't find the problem!

So i'm going to post the whole code snippet, I removed all but the vital code:

public class ECRenderer	{		        private Quaternion m_Rot;		public ECRenderer()		{			            m_Rot = Quaternion.Identity;		}					public void Render()		{            RotateY();            Vector3 Axis;            float Angle;                        m_Rot.ToAxisAngle( out Axis, out Angle );            Gl.glRotatef(Angle, Axis.X, Axis.Y, Axis.Z);                        Gl.glBegin(Gl.GL_TRIANGLES);                        Gl.glColor3f(1, 0, 0);            Gl.glVertex3f(0, 20, 20);            Gl.glColor3f(0, 1, 0);            Gl.glVertex3f(8, 0, 20);            Gl.glColor3f(0, 0, 1);            Gl.glVertex3f(-8, 0, 20);                        Gl.glEnd();     			                                               	        }        public void RotateY()        {            //Will be unit length, OpenTK return normalized            Quaternion Q2 = Quaternion.FromAxisAngle(Vector3.UnitY, 0.005f);            //Don't realy need to make a copy when pasing by ref, but just to rule it out            Quaternion Q1 = m_Rot;            Quaternion.Mult(ref Q1, ref Q2, out m_Rot);            m_Rot = Quaternion.Normalize(m_Rot);        }       	}


This should, In my opinion, rotate the Triangle. The result is like before, it rotates like it should for a short while until that Axis flip. Worth mentioning is that Angle goes up to around 5 and than down again.

It feels like there is something I'm missing, or rather there must be :/
Did you check all of the things I mentioned in my previous post? Have you confirmed that none of them is the problem?
What you see there is all that happens.

there are no conversion from degrees to radians.

Quaternion.FromAxisAngle(Vector3.UnitY, 0.005f) return a normalized Quaternion

all that happens is

ECRenderer R = new ECRenderer();
while( !quit )
{
Update();//Check is 'Q' is pressed, if so quit
R.Render();
}


Does the function ToAxisAngle() return the angle in degrees, or in radians?
radians

source from OpenTK:

public void ToAxisAngle(out Vector3 axis, out float angle)
{
Vector4 result = ToAxisAngle();
axis = result.Xyz;
angle = result.W;
}

/// <summary>
/// Convert this instance to an axis-angle representation.
/// </summary>
/// <returns>A Vector4 that is the axis-angle representation of this quaternion.</returns>
public Vector4 ToAxisAngle()
{
Quaternion q = this;
if (q.W > 1.0f)
q.Normalize();

Vector4 result = new Vector4();

result.W = 2.0f * (float)System.Math.Acos(q.W); // angle
float den = (float)System.Math.Sqrt(1.0 - q.W * q.W);
if (den > 0.0001f)
{
result.Xyz = q.Xyz / den;
}
else
{
// This occurs when the angle is zero.
// Not a problem: just set an arbitrary normalized axis.
result.Xyz = Vector3.UnitX;
}

return result;
}



And does glRotatef() take an angle in degrees, or in radians?
Holy hell, this is awkward.

just checked up glRotatef, and yes..it's in degrees..

Nice to know i got my math right, to bad I'm stupid :)

Thnx for your help!!

[Edited by - HermanssoN on March 15, 2009 4:16:32 PM]
Quote:It's the normal glRotatef, so i gues radians.
All OpenGL implementations that I'm aware of use degrees.
Quote:But eaven if it was degrees, the only thing that would happe is that the rotation would be very slow, right?
Not necessarily - depending on how periodicity and so on is handled by OpenGL and by your application, leaving the conversion out could lead to fairly unpredictable results.

Anyway, I'd try adding the conversion - it probably needs to be in there anyway, and who knows, it might fix the problem :)

This topic is closed to new replies.

Advertisement