Skip to main content
GameDev.net gamedev.net
🔒 Locked 🎮 Unity

Using Quaternions

Started by GaryNas Oct 26, 2005 at 10:57 AM 4 replies 850+ views
Original Post
GaryNas
GaryNas
What is a suitable way to use quaternions in my application? Say I want the initial orientation of my teapot to be <90, 35, 80> (all degrees)... do I convert this Euler angle to a quaternion? Furthermore, what about if I want to rotate the teapot by degrees later on. Do I convert the Euler angle again to a quaternion or is there a way to create a quaternion directly (without Euler angles) just by knowing x,y,z? Thanks!
Kwizatz
Kwizatz
I am not an expert on quaternions, but the way I use them is to create one for (x,0,0), one for (0,y,0) and one for (0,0,z) and multiply them IE: Final rotation= qX*qY*qZ.
then extract the matrix and apply that to the geometry I want to rotate.

Any other rotations you apply after that would be relative to the current position, IE:
if you rotate 90,0,0 and then 90,0,0, you will end up with the object rotated 180 degrees around X from the original position.
Richy2k
Richy2k
The way i've tried using quaternions is multiplying the geometry directly by the quaternion:

qN = qR * V * qR*

the vector component of qV being the new vertex, V being the vertex to rotate, and qR being the rotation quaternion. qR* is the conjugation of it.

To convert a eular angle to a quaternion i manuelly multiplied out each of the x,y & z rotation quaternions manuelly, optimised it, and put it into code to do it in one go.
JohnBolton
JohnBolton
For general use, it is probably better to use matrices rather than quaternions. Matrices are easier to understand and to use, and are used by the hardware.

Once you have figured all that out, you might look at specific areas of your code to see where quaternions might be more appropriate.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
tthibault
tthibault
Here is some code I use for doing various things.

Quote:

s there a way to create a quaternion directly (without Euler angles) just by knowing x,y,z?


This is what I use
void	Quaternion::InitFromRadians(float	Xrad,float	Yrad,float	Zrad){	float	cosX	=	cosf(Xrad*.5);	float	sinX	=	sinf(Xrad*.5);	float	cosY	=	cosf(Yrad*.5);	float	sinY	=	sinf(Yrad*.5);		float	cosZ	=	cosf(Zrad*.5);	float	sinZ	=	sinf(Zrad*.5);	Quaternion	X,Y,Z;		X.w	=	cosX;		X.x	=	sinX;		X.y = 0;		X.z = 0;	Y.w	=	cosY;	Y.x	=	0;	Y.y = sinY;	Y.z = 0;	Z.w =	cosZ;	Z.x	=	0;	Z.y = 0;	Z.z = sinZ;	*this	=	X*Y*Z;	}..and to multiply quaternions:Quaternion &	Quaternion::operator *(Quaternion & B){  Quaternion C;  C.x = w*B.x + x*B.w + y*B.z - z*B.y;  C.y = w*B.y - x*B.z + y*B.w + z*B.x;  C.z = w*B.z + x*B.y - y*B.x + z*B.w;   C.w = w*B.w - x*B.x - y*B.y - z*B.z;  return C;}


This function converts a quaternion to a matrix, i.e, if your orientation is stored as a quaternion, it will translate it to a 3x3 matrix, aka a 3 vector basis that represents an orthogonal coordinate system
Matrix3x3 &	Quaternion::ToMatrix(){	Matrix3x3	Output;	float	wx, wy, wz;	float	xx, yy, yz;	float	xy, xz, zz;	float	x2, y2, z2;	x2 = x + x;	y2 = y + y;	z2 = z + z;	xx = x * x2;	xy = x * y2;	xz = x * z2;	yy = y * y2;	yz = y * z2;	zz = z * z2;	wx = w * x2;	wy = w * y2;	wz = w * z2;	Output.mat[0][0] = 1.0f-(yy+zz);	Output.mat[0][1] = xy-wz;	Output.mat[0][2] = xz+wy;	Output.mat[1][0] = xy+wz;	Output.mat[1][1] = 1.0f-(xx+zz);	Output.mat[1][2] = yz-wx;	Output.mat[2][0] = xz-wy;	Output.mat[2][1] = yz+wx;	Output.mat[2][2] = 1.0f-(xx+yy);	return	Output;}


This function rotates the vector handed in the specified number of radians about each axis
void		Quaternion32RotateVector3Radians(Vector3	*ToRotate,float	xradians,float yradians,float zradians){	float	CosX = cosf((xradians)*.5);	float	SinX = sinf((xradians)*.5);	float	CosY = cosf((yradians)*.5);	float	SinY = sinf((yradians)*.5);	float	CosZ = cosf((zradians)*.5);	float	SinZ = sinf((zradians)*.5);	Quaternion	XAxisRot(CosX,SinX,0,0);	Quaternion YAxisRot(CosY,0,SinY,0);	Quaternion ZAxisRot(CosZ,0,0,SinZ);	//Am I doing anything incorrect about the order of multiplications here?	//EDIT:	yes, I had to reverse the order here! Now it works (Update this in FPS_CheckMouse as well)	Quaternion temp = ZAxisRot * YAxisRot * XAxisRot;	Quaternion temp_view(0,ToRotate->x,ToRotate->y,ToRotate->z);	Quaternion NewView = FastHomoMorphism(&temp,&temp_view);	ToRotate->x = NewView.x;	ToRotate->y = NewView.y;	ToRotate->z = NewView.z;}Quaternion	FastHomoMorphism(Quaternion *A, Quaternion *B){	//Multiply A by B in the fastest method possible	//12 mults (13 if you count negating a multiplication by negative 1)	//8 adds	//You can do this because B represents view and has a w component of 0, so you can skip those operations	float NewX = A->w*B->x + A->y*B->z - A->z*B->y;	float NewY = A->w*B->y - A->x*B->z + A->z*B->x;	float NewZ = A->w*B->z + A->x*B->y - A->y*B->x;	float NewW = - A->x*B->x - A->y*B->y - A->z*B->z; //notice that you need this in the calculations below, so don't ignore		Quaternion	rslt(NewW, NewX, NewY, NewZ);	Quaternion	conj(A->w, -A->x, -A->y, -A->z);	//Now we need to multiply rsl by conj in the fastest way possible	  Quaternion	Final;  //12 mults  //9 adds  Final.x = rslt.w*conj.x + rslt.x*conj.w + rslt.y*conj.z - rslt.z*conj.y;  Final.y = rslt.w*conj.y - rslt.x*conj.z + rslt.y*conj.w + rslt.z*conj.x;  Final.z = rslt.w*conj.z + rslt.x*conj.y - rslt.y*conj.x + rslt.z*conj.w;   Final.w = 0;//w*conj.w - x*conj.x - y*conj.y - z*conj.z;  return Final;}



That's the code I've written for my own math library. Note most of it is taken from other sources, math books, stuff online (some is from the doom3 SDK)...it's not like I truly understood this stuff to implement it entirely on my own (sadly, I'm a math major and I should).
...and do not wildly extrapolate. Just because Saddam Hussein gassed Kurds in 1990 doesn't mean he eats babies' brains.
Richy2k
Richy2k
Yeah what I'm doing is purely testing purposes - matrices are gonna be used on the geometry in the engine im working on. Quaternions will just be used to represent orientation and aid in animation.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.