I'm attempting the implement a quaternion based camera but I am having issues with the rotation.
My camera has an origin and an orientation (quaternion). The origin and quaternion are lerped and slerped between logical updates. The camera vector components (direction, origin, up, left) are computed every frame for the renderer (in my case it goes directly into a gluLookAt()):
void Camera::update() {
direction = (orientation * Vector<3>(0, 0, 1)).normalize();
up = (Vector<3>(0, 1, 0)).normalize();
(self.rotateVelocity is the change in mouse coordinates)
At first the rotation appears to be correct, but as I turn the camera around the y-axis rotation inverts (moving mouse up makes camera rotate down) and if I face left the camera does not rotate at all vertically. It seems as though my camera's left vector is incorrect, but I know that it is correct (camera strafing works).
I am also sure that my quaternion rotation is correct, I believe I am just using them incorrectly. Is there anything obviously wrong with my approach?
You code to perform a rotation using a quaternion is not correct. If q is a unit quaternion and v is a vector you want to rotate, then the correct rotated vector is
u = q v q-1 = q v q*,
where q* is the quaternion conjugate of q. The correct code should be something like:
You code to perform a rotation using a quaternion is not correct. If q is a unit quaternion and v is a vector you want to rotate, then the correct rotated vector is
u = q v q-1 = q v q*,
where q* is the quaternion conjugate of q. The correct code should be something like:
I don't know if this affects your answer or not... but when I multiply a quaternion by a vector I believe it is calculating the rotation. I honestly didn't attempt to understand the math behind this when I implemented it, I was just looking for a quick solution:
Your inverse isn't correct. Conjugation and inversion are equal only when working on unit quaternions (i.e. quaternions such that the norm is 1). More generally, the inverse quaternion is given by
q-1 = q*/(qq*).
The correct implementation of inverse and conjugate are therefore something like
template <class T>
Quaternion<T> Quaternion<T>::inverse() const {
T n = this->norm();
return Quaternion(w / n, - v / n);
}
I find quite confusing to use the product to do rotation when working with quaternions. In mathematics the product between a quaternion and a 3D vector is usually interpreted as a quaternion product.
Just to reinforce what apatriarca said, you definitely don't want to implement the * operator as rotation of a vector by a quaternion (IMO), as it's counterintuitive, potentially confusing, and mathematically incorrect.
(Some math libraries do use the * operator for this, so obviously not everyone agrees with the above, but nevertheless I strongly recommend avoiding ambiguous overloading of this sort.)