Advertisement

Quaternions problem

Started by June 11, 2003 02:09 PM
5 comments, last by ftsf 21 years, 8 months ago
i''ve implemented a quaternions class, even though i dont really understand the maths behind it. when i run the program and rotate the object it wont rotate fully, it gets stuck about halfway through its rotation and when i let go it slowly rotates back to its original orientation. this is really confusing me as i didnt intentionally program any of that. this is the code i''m using in the render function RotAngle is filled by the keyboard input.

keyQuat.identity();
keyQuat.euler(RotAngle.x, RotAngle.y, RotAngle.z);
RotAngle.x = 0;
RotAngle.y = 0;
RotAngle.z = 0;
float res[4];
keyQuat*=rotQuat;
keyQuat.axisangles(res);
rotQuat=keyQuat;

glTranslatef(cCam.x, cCam.y, cCam.z);
glRotatef(res[0], res[1], res[2], res[3]);
 
This is the quaternion class i''m using

quat::quat()
{
	x = 0;
	y = 0;
	z = 0;
	w = 1;
}

void quat::norm()
{
	float scale = 1.0f / sqrtf(x*x + y*y + z*z + w*w);
	x *= scale;
	y *= scale;
	z *= scale;
	w *= scale;
}

void quat::euler(float Ax, float Ay, float Az)
{
	Ax = deg2rad(Ax);
	Ay = deg2rad(Ay);
	Az = deg2rad(Az);
	identity();
	quat qY, qZ;
	x = sin(Ax/2);
	w = cos(Ax/2);

	qY.y = sin(Ay/2);
	qY.w = cos(Ay/2);

	qZ.z = sin(Az/2);
	qZ.w = cos(Az/2);

	*this*=qY;
	*this*=qZ;
	norm();
}

bool quat::operator*=(quat q)
{
	x = (w * q.x) + (x * q.w) + (y * q.z) + (z * q.y);
	y = (w * q.y) + (y * q.w) + (z * q.x) + (x * q.z);
	z = (w * q.z) + (z * q.w) + (x * q.y) + (y * q.x);
	w = (w * q.w) - (x * q.x) - (y * q.y) - (z * q.z);
	norm();
	return true;
}

bool quat::operator=(quat q)
{
	x = q.x;
	y = q.y;
	z = q.z;
	w = q.w;
	return true;
}

void quat::identity()
{
	x = 0;
	y = 0;
	z = 0;
	w = 1;
}

void quat::axisangles(float result[4])
{
	float scale	= (x*x)+(y*y)+(z*z);
	result[0] = rad2deg(2*acosf(w)); // angle to rotate
	result[1] = rad2deg(x / scale);
	result[2] = rad2deg(y / scale);
	result[3] = rad2deg(z / scale);
}

void quat::matrix(float m[16])
{
	m[0] = w*w + x*x - y*y - z*z;
	m[1] = 2*x*y + 2*w*z;
	m[2] = 2*x*z + 2*w*y;
	m[3] = 0;
	m[4] = 2*x*y - 2*w*z;
	m[5] = w*w - x*x + y*y - z*z;
	m[6] = 2*y*z + 2*w*x;
	m[7] = 0;
	m[8] = 2*x*z + 2*w*y;
	m[9] = 2*y*z - 2*w*x;
	m[10] = w*w - x*x - y*y + z*z;
	m[11] = 0;
	m[12] = 0;
	m[13] = 0;
	m[14] = 0;
	m[15] = 0;
}
 
if anyone can help me out here i''d be very thankful
You can find this over here.

The code has comments explaining the math and is an example for you. Hope it helps.


-solo (my site)
-solo (my site)
Advertisement
Considering you''re using quaternion to avoid gimbal lock, it''s a very bad idea to create the quaternion using euler angles.

What you should do is :
- save the orientation of your object/camera/whatever in a quaternion.
- when rotating the object using the keys/mouse, multiply the quaternion that holds the object''s orientation with the quaternion that represents the rotation.

This way, you''ll get rid of gimbal lock.

BTW, I really don''t know why your object rotates back. Do you use the quaternion to save the orientation, or do you use the modelview matrix to save the orientation, i.e. do you glLoadIdentity each frame or not ? If you don''t I suspect some kind or math error when calculating axis+angle from quaternion.
SaM3d!, a cross-platform API for 3d based on SDL and OpenGL.The trouble is that things never get better, they just stay the same, only more so. -- (Terry Pratchett, Eric)
ok i think i''ve got it working now... except i have another odd problems where the object shears when it rotates in more than one angle at once. anyone else experienced this or know how to fix it?
ok i think i fixed it, i wasnt normalising the quat
Just out of curiosity... are you using the mouse or the keyboard for input?
Advertisement
Hey, I noticed that in your last command, the glRotatef one, you called it something like this, ''cause I can''t remember exactly, " glRotatef(variable[0], variable[1], variable[2], variable[3]);" I''m not sure how the array is set up, but some of the probelems you might be having is that to use glRotatef, the first argument is the angle, and the next three arguments should be floats between 0 and 1 specifying the percent of rotation to apply to each axis. So, glRotatef(90.0, 0.0, 1.0, 0.0); would rotate 90 degrees on the y axis. glRotatef(90.0, 0.5, 0.5, 0.5); would rotatef 45 degrees on each set of axes. I hope you understand this and I hope I''m not wrong. I just stick with vectors. I wrote my own code to avoid lock.

"Donkey, if it were me, you''d be dead."
I cna ytpe 300 wrods pre mniute.
"Donkey, if it were me, you'd be dead."I cna ytpe 300 wrods pre mniute.

This topic is closed to new replies.

Advertisement