Rotations using quaternions

Started by
6 comments, last by Vast 17 years, 11 months ago
Hello everyone. Basically, right now I am writing a camera, but I will need the code later to rotate all of my objects. So, my problem is that I wish to rotate my objects arbitrarily, without any constraints (such as if I drag the mouse up, I wish to have my camera rotate more and more until I can make a 360). Right now, it doesn't seem to work. Ok, what I am doing now is this: - Rotation around the Y axis (left and right) I rotate a quaternion qA around the (0,1,0) axis, by given degree, and store it. - Rotation around the X axis (up and down) (quaternion qB) I calculate the view vector (camView - camPos), normalize that, then I take a cross product of the view vector with my up vector, and use that as my axis to rotate around the X axis. That works, but when I look all the way down my view flips to go to the reverse, instead of continuing to rotate (I hope you know what i mean). Yes and I want to keep rotation so that if I keep dragging my mouse down eventually the world would be upside down. - Rotation around the Z axis (tilting) (quaternion qC) I didn't even get that to work :( Stupid stupid stupid. At the end, I multiply qA * qB (i ignore qC because it just doesn't work as i want) and then i do something that looks like this

CVector3 CQuaternion::Rotate (const CVector3& v) const
{
	CQuaternion vec2 = (*this) * CQuaternion(0, v.x, v.y, v.z) * CQuaternion (r, -x, -y, -z);

	return CVector3 (vec2.x, vec2.y, vec2.z);
}
(I forgot where I ripped that from. Code's not mine). the passed parameter is actually the viewVector calculated earlier. So, I get the result from that function taking the view vector, I set the camView to camPos + result, and voila! It works like a normal camera, but not what I want. If anyone could please give me a heads up on what I should do to make my unconstrained camera, I'd be highly grateful. Btw, I really don't want to use Matricies, or anything else (like OpenGL axis rotations). Thanks. - Tima
Advertisement
Looks like you have got your order of multiplication incorrect. To rotate a vector by a quaternion, do the following multiplication (after embedding the vector in quat space, i.e. create quat from vector with w = 0 and x,y,z the vector)

q * v * q'

where v = vector embedded in quat space
q = quat representing the rotation
q' = quat conjugate (multiply x, y, z components by -1)

... the result is the x,y,z part of the quaternion multiplication.

EDIT: Looking at it again, that fuction you posted is correct since *this is a quaternion, the middle bit of the multiplication is the embedding of the vector in quat space, and the 3rd multiplicand is the quat conjugate of *this.
"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley
A few comments:
  • Even though you say you don't want to use a matrix, I recommend that you do. Matrices are easier to learn and understand, and a matrix is better suited for a camera than a quaternion (for various practical reasons). Once you have implemented your camera using a matrix and you have figured out how cameras work, then you might look at using a quaternion.
  • Your camera flips around when looking up or looking down because it is pointing in a direction parallel to your up vector. You need to use you camera's local up vector rather than the world up vector if you want the camera to point up or down.
  • Look up Euler-angle-to-matrix (or Euler-angle-to-quaternion, if you insist) conversion. Compare to yours.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
Hmm. I see, I already have an implementation of Euler to Quat, and it works the same way. Still not going the way I want it to though.

Could you please elaborate on the concept of a "local" vector? would that be the vector perpendicular to my current view vector? I think I see where you are going with this... at least it is sort of making sense in my head.

What about rotation around the Z axis? Any ideas how I would go about doing that?

Thanks guys, you're being very helpful.

- Tima
Something like this:
    camera.direction = normalize( target - camera.position );    camera.right = normalize( cross( camera.direction, camera.up ) ); // camera.up instead of world.up    camera.up = cross( camera.right, camera.direction ) 
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
hmm, I see.

I have a couple of questions though.

First, would the initial value of camera.up be 0,1,0 (considering I use Y axis as up)?

Second, what is the difference between the target and camera.direction? Sorry, this should be obvious but I just don't see it, and then as addition how should target be updated in relation to the general camera set up?

I think thats all for now.
Thanks!


Regards,
- Tima
Quote:Original post by Vast
hmm, I see.

I have a couple of questions though.

First, would the initial value of camera.up be 0,1,0 (considering I use Y axis as up)?


Yes

Quote:
Second, what is the difference between the target and camera.direction? Sorry, this should be obvious but I just don't see it, and then as addition how should target be updated in relation to the general camera set up?


Direction = (normalised) vector from position to target = (normalised)
posTarget - posCam

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley
EDIT: nevermind, it all works fine!

Thank you very much for all of your help, it was a pleasure having to recieve help from you guys.

Here's the working code:
		//==========================		// Get all the prerequisites		//==========================		vector3 direction = new vector3(view.x - position.x,										view.y - position.y,										view.z - position.z);		direction.Normalize();		right = direction.CrossProduct(up).GetNormalized();		up = right.CrossProduct(direction);		//=====================		// Do all the rotations		//=====================		rotation.SetRotation(-x, right);		rotation = rotation.Mul(new quaternion(y, up));		direction = rotation.Rotate(direction);		view.x = position.x + direction.x;		view.y = position.y + direction.y;		view.z = position.z + direction.z;



Thank you very very much :)
- Tima

This topic is closed to new replies.

Advertisement