Like everyone else in the world, judging from the number of quaternion threads in this section, ive been *trying* to implement a quaternion camera. And i have been largely successful, except for one annoying effect i cannot seem to get rid of.
Here is my Camera class (the relevant parts anyway)
// Translate position //
glTranslatef(-Position.x, -Position.y, Position.z);
}
Pitch refers to the rotation about the x axis, while heading refers to the y rotation. This code works when im simply looking around (not changing my position), so i believe my GetMatrix and Rotation quaternion setup is correct. However, problems start occuring when i do move. If i rotate around the x-axis (pitch), the movement distorts considerably. If i am turned 90 degrees on the y axis and 45 on the x axis, strafing actually causes my Position.y to change! Also, if i simply call Move, the camera moves towards the wrong center.
But if my Rotation matrix is right, then that means that the problem lies here:
Vector3 direction = Rotation * Vector3(0.0f, 0.0f, speed);
Position += direction;
(and same for the strafing function)
So here is the code for vector rotation using a quaternion:
I suppose you use Camera::Look() to setup your view matrix? My guess would be that this part is where your problem is. Also, if you want a 6-DoF camera, you shouldn't be keeping pitch and heading separately - accumulate all orientation changes in your Rotation quaternion instead.
Of course, it depends on how you setup the rest of your transforms, but I would do something like this:
Why do you need to get the inverse (conjugate in this case) of the Rotation quaternion before getting its matrix? I have never seen this before.
Why did you put glTranslatef before the view transform?
Well, the order of transformations is pretty much arbitrary. However, the results differ depending on the order you apply rotation, scale and translation. You have to be aware of that and pick the order that yields your desired result. I usually use scale, rotate, translate (SRT).
In any case, the reason why you have to use the inverse of the rotation is the following. In order to transform your view, what you want to be doing is translate all objects by the inverse of the view transformation. The inverse of a product of matricies is the reversed product of their inverses, so (SRT)^-1 = T^1R^1S^1. The inverse of a translation is simply its negation. The inverse of a rotation represented by a quaternion is its inverse (or if the quaternion is normalized, the conjugate).
Well, the order of transformations is pretty much arbitrary. However, the results differ depending on the order you apply rotation, scale and translation. You have to be aware of that and pick the order that yields your desired result. I usually use scale, rotate, translate (SRT).
In any case, the reason why you have to use the inverse of the rotation is the following. In order to transform your view, what you want to be doing is translate all objects by the inverse of the view transformation. The inverse of a product of matricies is the reversed product of their inverses, so (SRT)^-1 = T^1R^1S^1. The inverse of a translation is simply its negation. The inverse of a rotation represented by a quaternion is its inverse (or if the quaternion is normalized, the conjugate).
Oh wow, did not think of it that way.
That makes sense. I guess before when i was applying the incorrect quaternion i was unknowingly compensating for it by changing random things in my other functions. All is back to normal though.
The quaternion is conjugated because Camera::Look() is (presumably) intended to set up a view matrix, which is typically the inverse of the model/object/world matrix for the same object. The inverting of the rotation and translation and the changing of the transform order (translate first, then rotate) has the desired effect of creating the inverse transform. [Edit: As kloffy said.]
Also, I think it's worth noting that the use of quaternions in this context is more or less pointless. (Maybe there's more to it than what you posted, but as far as the code excerpts shown are concerned at least, the use of quaternions doesn't gain you anything.)