My camera rotates around a point when I try to change the orientation. If I rotate my camera, say, 30 degrees in the Y axis, instead of the camera looking 30 degrees to the right, the camera rotates around the point it was looking at.
o is the camera, A and B are 3D models. The lines show line-of-sight.
This is what I expect:
A B
| > /
| /
| /
|/
o
This is what actually happens:
A B
|\
| \
| \
| > \
o
Now, from my understanding, in order to move the camera I have to move the world by the inverse of that amount. So if I want to move +1 in the Z axis I translate the world -1 in the Z axis. Since I am using quaternions to represent orientations, I use the camera quaternion's inverse (since the orientations are always unit quaternions, I optimize by using the conjugate instead of calculating the inverse) to rotate the world by the right amount.
Here is how I convert a quaternion to a matrix, where q is the inverted quaternion:
[1 - 2 * (q.y * q.y + q.z * q.z) 2 * (q.x * q.y - q.w * q.z) 2 * (q.x * q.z + q.w * q.y) 0]
|2 * (q.x * q.y + q.w * q.z) 1 - 2 * (q.x * q.x + q.z * q.z) 2 * (q.y * q.z - q.w * q.x) 0|
|2 * (q.x * q.z - q.w * q.y) 2 * (q.y * q.z + q.w * q.z) 1 - 2 * (q.x * q.x + q.y * q.y) 0|
[0 0 0 1]
After that, I set the translation component of the matrix:
[... ... ... -x]
|... ... ... -y|
|... ... ... -z|
[0 0 0 1]
And finally I multiply that onto the model-view matrix stack, then render all my objects. I am pretty sure this math is correct, but it doesn't produce the results that I was expecting. Clearly the forward and right vectors are the problem, so my only question is why are they wrong and how should they be set if I want to get the results I am expecting. Thanks.
EDIT: I have found the solution from this guy's quaternion camera class. First i construct a rotation matrix like i was doing before, but then I take the column vectors of the matrix from the first, second and third columns (xa, ya, and za respectively). Then I set the translational component of the matrix like this:
[... ... ... -xa.dotProduct(cameraPos)]
|... ... ... -ya.dotProduct(cameraPos)|
|... ... ... -za.dotProduct(cameraPos)|
[... ... ... ... ]
Then the resulting matrix can be multiplied onto the modelview matrix stack, and it works perfectly.
EDIT: I have found the solution from this guy's quaternion camera class. First i construct a rotation matrix like i was doing before, but then I take the column vectors of the matrix from the first, second and third columns (xa, ya, and za respectively). Then I set the translational component of the matrix like this:
[... ... ... -xa.dotProduct(cameraPos)] |... ... ... -ya.dotProduct(cameraPos)| |... ... ... -za.dotProduct(cameraPos)| [... ... ... ... ]
Then the resulting matrix can be multiplied onto the modelview matrix stack, and it works perfectly.
Yes, this is exactly what I would have suggested, only a bit different. You must understand, that OpenGL does not have a camera, but instead you just move the world in the opposite direction, so you need to find the inverse transformation matrix.
A camera just rotates about and moves. This makes things very simple. The tnverse of translation is just the same vector with opposite sign, and the inverse of a rotation matrix is it's transpose (column and rows exchanged). Now look at a homogenous transformation matrix like OpenGL uses them:
R t
0 1
The upper left 3×3 is the rotational part, the rightmost column is the translation vector. I think the rest you already figured yourself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With