Bug in my quaternions project

Hello,

I want to draw a cube on (0,0,0) coordinates and to rotate on (0,0,0)-(1,1,-1) axis. When i use this code it works fine:

see the video: http://www.dailymotion.com/video/xihlz8_1

void C_Shape::v_Spin()
{
glRotatef(m_xSpinAngle, 1, 1, -1); //m_xSpinAngle is incremedted with 0.05f on other thread
glRotatef(m_ySpinAngle, 1, 1, -1); //m_ySpinAngle is incremedted with 0.05f on other thread
glRotatef(m_zSpinAngle, 1, 1, -1); //m_ZSpinAngle is incremedted with 0.05f on other thread
}

Now i want to use quaternions rotation, but the rotation is very strange. Can someone give me a hint ?

http://www.dailymotion.com/video/xihlzi_2

void C_Shape::v_Spin()
{

glQuaternion q;
float Matrix[16];
m_qX.CreateFromAxisAngle(m_xSpinAngle, 1.0f, 0.0f, 0.0f);
m_qY.CreateFromAxisAngle(m_ySpinAngle, 0.0f, 1.0f, 0.0f);
m_qZ.CreateFromAxisAngle(m_zSpinAngle, 0.0f, 0.0f, 1.0f);

q = m_qX * m_qY * m_qZ;
q.CreateMatrix(Matrix);

glMultMatrixf(Matrix);

}

void glQuaternion::CreateFromAxisAngle(float degrees, float x, float y, float z) {

float angle = float((degrees / 180.0f) * PI);


float result = (float)sin( angle / 2.0f );
	

m_w = (float)cos( angle / 2.0f );


m_x = float(x * result);
m_y = float(y * result);
m_z = float(z * result);  

//#]

}

void glQuaternion::CreateMatrix(float * pMatrix) {

if(!pMatrix) return;

// First row
pMatrix[ 0] = 1.0f - 2.0f * ( m_y * m_y + m_z * m_z ); 
pMatrix[ 1] = 2.0f * (m_x * m_y + m_z * m_w);
pMatrix[ 2] = 2.0f * (m_x * m_z - m_y * m_w);
pMatrix[ 3] = 0.0f;  

// Second row
pMatrix[ 4] = 2.0f * ( m_x * m_y - m_z * m_w );  
pMatrix[ 5] = 1.0f - 2.0f * ( m_x * m_x + m_z * m_z ); 
pMatrix[ 6] = 2.0f * (m_z * m_y + m_x * m_w );  
pMatrix[ 7] = 0.0f;  

// Third row
pMatrix[ 8] = 2.0f * ( m_x * m_z + m_y * m_w );
pMatrix[ 9] = 2.0f * ( m_y * m_z - m_x * m_w );
pMatrix[10] = 1.0f - 2.0f * ( m_x * m_x + m_y * m_y );  
pMatrix[11] = 0.0f;  

// Fourth row
pMatrix[12] = 0;  
pMatrix[13] = 0;  
pMatrix[14] = 0;  
pMatrix[15] = 1.0f;

}

glQuaternion glQuaternion::operator*(glQuaternion q) {

glQuaternion r;

r.m_w = m_w*q.m_w - m_x*q.m_x - m_y*q.m_y - m_z*q.m_z;
r.m_x = m_w*q.m_x + m_x*q.m_w + m_y*q.m_z - m_z*q.m_y;
r.m_y = m_w*q.m_y + m_y*q.m_w + m_z*q.m_x - m_x*q.m_z;
r.m_z = m_w*q.m_z + m_z*q.m_w + m_x*q.m_y - m_y*q.m_x; 

return(r);
//#]

}

glQuaternion::glQuaternion() : m_w(1.0f), m_x(0.0f), m_y(0.0f), m_z(0.0f) {
//#[ operation glQuaternion()
//#]
}

When i use this code it works fine

So your problem is that it works fine?


void C_Shape::v_Spin()
{
  glRotatef(m_xSpinAngle, 1, 1, -1);
  glRotatef(m_ySpinAngle, 1, 1, -1);
  glRotatef(m_zSpinAngle, 1, 1, -1);
}

This is no different from this:


void C_Shape::v_Spin()
{
  glRotatef(m_xSpinAngle + m_ySpinAngle + m_zSpinAngle, 1, 1, -1);
}

Just because you called the value “m_xSpinAngle” doesn’t mean that it will rotate along the X axis. It rotates about the axis you specify.

And this doesn’t have anything to do with quaternions.

Sorry, Alfonse Reinheart, i push “Post” by mistake when i didn’t finish it all. But thank you for the quick response :smiley:

Why in the first case you always rotate around (1, 1, -1) vector.
And in the second you rotate around the x, y, z axis. This will be two different rotations.
If you think that in the second case you first rotate around x, then around y, etc, you are not right. For this effect you must correct your multiplication.

    RQuat[0] = quat1[0] * quat2[0] - quat1[1] * quat2[1] - quat1[2] * quat2[2] - quat1[3] * quat2[3];
    RQuat[1] = quat1[0] * quat2[1] + quat1[1] * quat2[0] - quat1[2] * quat2[3] + quat1[3] * quat2[2];
    RQuat[2] = quat1[0] * quat2[2] + quat1[2] * quat2[0] - quat1[3] * quat2[1] + quat1[1] * quat2[3];
    RQuat[3] = quat1[0] * quat2[3] + quat1[3] * quat2[0] - quat1[1] * quat2[2] + quat1[2] * quat2[1];

Sorry, Itun.itu, but i don’t understand what do you want to say with RQuat[0], RQuat[1] etc. vectors :frowning: I’m still a beginner with OpenGL. Can you give an example ?

It seems the problem lies in the multiplication of the quarternions. A quaternion, simplistically, is a vector with an angle telling it how much it turn. If you stick your fingers in the right hand rule position so three fingers represent the three axis. Now rotate the x axis (middle finger) so the z axis (forefinger) points down, that is the application of the quaternion created with the x axis to the base frame. Now without resetting the x axis, rotate the z axis so the x axis points up, that is the multiplication of the z axis quarternion to the x axis quarternion and then applying this new quarternion to the base frame. Now for something completely different, to quote Monty Python, apply the rotation to the z axis prior to the x axis, you get a different result.

I haven’t looked closely at the code but it seems like that presented by Vic Hollis in his Nehe tutorial:
http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=Quaternion_Camera_Class. Diney Bomfim also has an excellent explanation of quarternions http://db-in.com/blog/2011/04/cameras-on-opengl-es-2-x. I have been writing a quaternion camera based upon their inputs at www.sjonesart.com/gl.php under the C# section.