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

Quaternion angles incorrect?

Started by BloodLust666 Feb 26, 2009 at 8:44 AM 7 replies 8.2k views
Original Post
BloodLust666
BloodLust666
I've been delving into quaternions for a while with animation and I found a tutorial to help me out, everything works fine with bone animation and whatnot but I still didn't understand them fully. Now I want to use quaternions for all my orientation for all entities which means I need to understand them more. I tried to put in a certain value into my quaternion and render it at that orientation but it's not coming out right. I'm trying to render a simple quad with orientation Quat(0.0, 0.0, 1.0f, PI/4) and it's definitely not looking correctly, should look like a diamond and barely turned maybe PI/12 or something much smaller


// in Main
// ....
camera.SetOrientation(sWQuaternion(0.0f, 0.0f, 1.0f, W_PI_4));
// ...
window.RunMainLoop();

// in main render loop
// ...
// update camera in camera::update()
{
m_matView.SetRotationQuaternion(m_orientation);
m_matView.SetTranslation(-m_position);
}
// ...
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(cam->GetViewMatrix().mat);
// render objects

// in Matrix4x4::SetRotationQuaternion(Quaternion quat)
{
	float x2, y2, z2, w2, xy, xz, yz, wx, wy, wz;

	LoadIdentity();

	x2 = quat.X * quat.X;
	y2 = quat.Y * quat.Y;
	z2 = quat.Z * quat.Z;
	w2 = quat.W * quat.W;

	xy = quat.X * quat.Y;
	xz = quat.X * quat.Z;
	yz = quat.Y * quat.Z;

	wx = quat.X * quat.W;
	wy = quat.Y * quat.W;
	wz = quat.Z * quat.W;


	mat[0] = 1.0f - 2.0f * ( y2 + z2 );
	mat[1] = 2.0f * ( xy + wz );
	mat[2] = 2.0f * ( xz - wy );
	mat[3] = 0.0f;

	mat[4] = 2.0f * ( xy - wz );
	mat[5] = 1.0f - 2.0f * ( x2 + z2 );
	mat[6] = 2.0f * ( yz + wx );
	mat[7] = 0.0f;

	mat[8] = 2.0f * ( xz + wy );
	mat[9] = 2.0f * ( yz - wx );
	mat[10] = 1.0f - 2.0f * ( x2 + y2 );
	mat[11] = 0.0f;
}
// in Matrix4x4::SetTranslation(Vector3 vec)
{
	mat[12] = vec.X;
	mat[13] = vec.Y;
	mat[14] = vec.Z;
	mat[15] = 1.0f;
}
-------------------------Unless specified otherwise, my questions pertain:Windows Platform (with the mindset to keep things multi-platform as possible)C++Visual Studio 2008OpenGL with SFML
Dirk Gregorius
Dirk Gregorius
If you have a unit axis and some angle in radians the corresponding quaternion that describes this orientation is:

q.x = sin( angle / 2 ) * axis.x;
q.y = sin( angle / 2 ) * axis.y;
q.z = sin( angle / 2 ) * axis.z;
q.w = cos( angle / 2 );


So for your particular example the quaternion should be constructed like this:
Quat( 0, 0, sin( PI / 8 ), cos( PI / 8 ) );
Endemoniada
Endemoniada
If the axis used to create the quaternion is normalized will the quaternion also be normalized or should I normalized the quaternion afterwards ?
Zakwayda
Zakwayda
Quote:
Original post by Endemoniada
If the axis used to create the quaternion is normalized will the quaternion also be normalized or should I normalized the quaternion afterwards ?
Using the formula DonDickieD posted, if the rotation axis is unit length the resulting quaternion will be unit length, so there's no need to normalize it.
BloodLust666
BloodLust666
ah, interesting. Thanks! actually that worked :)

going further, I guess I misunderstood how quats work. I thought the x,y,z of the quat was the actual axis to rotate about and the w was the amount so that a quat of (0,0,1,PI) would be a quat with an axis going in the positive Z and rotated PI radians. Obviously that's wrong by the correction that was made, but what's the actual relationship between a quat and the axis and angle?
-------------------------Unless specified otherwise, my questions pertain:Windows Platform (with the mindset to keep things multi-platform as possible)C++Visual Studio 2008OpenGL with SFML
BloodLust666
BloodLust666
also, another question: how do I add the rotation of one quaternion to another. For all objects in my engine, I have an orientation, and a rotational velocity which are both quaternions. I'll set my orientation to (0,0,1,PI/4) but I want to rotate about the Z PI/2 radians per second, so my rotational velocity will be (0,0,1,PI/2). Do I merely just do a multiplication of (0,0,1,PI/4) * [ (0,0,1,PI/2) * dt]?

that's not coming out right either though... but here's my code to do that

Quaternion Quaternion::operator*(const Quaternion &q) const{	Quaternion quat;	quat.W = W*q.W - X*q.X - Y*q.Y - Z*q.Z;	quat.X	= q.W*X + q.X*W + q.Y*Z - q.Z*Y;	quat.Y	= q.W*Y + q.Y*W + q.Z*X - q.X*Z;	quat.Z	= q.W*Z + q.Z*W + q.X*Y - q.Y*X;	quat.Normalize();	return quat;}// I use this for multiplying against a delta time, do I have the correct thinking for this?  Is it really just a multiplication against the W?  or should ALL components be multiplied by my dt?Quaternion operator*(float dt) const {return Quaternion(X,Y,Z,W*dt);}

-------------------------Unless specified otherwise, my questions pertain:Windows Platform (with the mindset to keep things multi-platform as possible)C++Visual Studio 2008OpenGL with SFML
nilkn
nilkn
Quote:
Original post by BloodLust666
ah, interesting. Thanks! actually that worked :)

going further, I guess I misunderstood how quats work. I thought the x,y,z of the quat was the actual axis to rotate about and the w was the amount so that a quat of (0,0,1,PI) would be a quat with an axis going in the positive Z and rotated PI radians. Obviously that's wrong by the correction that was made, but what's the actual relationship between a quat and the axis and angle?


It would be nice if that were so, but unfortunately, as DonDickieD showed, it's not quite this simple.

If u is a unit vector representing the rotation axis and θ is the angle through which you wish to rotate the object, the desired quaternion is q = cos(θ / 2) + sin(θ / 2) u. To apply q to a vector v as a rotation operator, the formula

v' = qvq-1

is used. Of course, in order for this to make sense, v must be represented as a quaternion, typically in the form 0 + v.

That this formula does indeed perform rotations can be proved in a variety of ways. In particular, by writing q = cos(θ / 2) + sin(θ / 2) u and q-1 = cos(θ / 2) - sin(θ / 2) u in the above formula, expanding, and applying the rules for quaternion multiplication and several identities, the equation can be reduced to a form that shows that it's a rotation somewhat clearly.

Quote:
Original post by BloodLust666
also, another question: how do I add the rotation of one quaternion to another.


Look at what happens when using the previous formula. Let the quaternions p and q represent rotations through the angles θ1 and θ2 about axes u1 and u2, respectively. If we start with the vector v, rotating it by p yields

v' = pvp-1.

Now, if we rotate v' by q, we get

vf = qv'q-1 = q(pvp-1)q-1.

However, since p-1q-1 = (qp)-1, the RHS becomes

(qp)v(qp)-1.

Hence, rotations represented by quaternions may be concatenated by multiplying the quaternions.

Edit: I had a p where I meant q.

[Edited by - nilkn on February 26, 2009 2:35:48 PM]
BloodLust666
BloodLust666
hmm... I'm not sure if I understand what the p^-1 would look like in code? What's the reciprocal of a quaternion? just 1 over all the components?

can you show me a snippet of the concatenation function for 2 quaternions?
-------------------------Unless specified otherwise, my questions pertain:Windows Platform (with the mindset to keep things multi-platform as possible)C++Visual Studio 2008OpenGL with SFML
Zakwayda
Zakwayda
Quote:
hmm... I'm not sure if I understand what the p^-1 would look like in code? What's the reciprocal of a quaternion? just 1 over all the components?

can you show me a snippet of the concatenation function for 2 quaternions?
In this context, '^-1' refers to the quaternion inverse. As for concatenating two rotation quaternions, this is done via quaternion multiplication. Both the inverse and multiplication operations will be described in any decent article or reference on quaternions, so if I were you I'd just look around online and find some examples.

Topic Locked

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

Sign in to reply to this topic.