Quaternion cameras

Currently using Ogre for one of my final projects at university, it forces you to use quaternions for scene nodes orientations (I don't have a problem with that, in fact my Spear Framework uses Quaternions for orientation almost exclusively).A decent camera class needs to do a couple of things:

Use whatever Mouse/Keyboard event API that is available, be it Win32's RawInput events or GLFW's listener callbacks, and cache input for every mouse move event it gets sent. For keyboard events, store the key state, but you shouldn't need to be told that, right? Set all movement to a vector in the camera class, add or subtract, don't set, otherwise you get errors like pressing both 'strafe left' and 'strafe right' moves you in whatever is lower in the if statement chain, but releasing one direction cancels movement for both! Let's call this movement vector acceleration and the mouse movement vector, at this point in time, Vector2's work well; mouseMoveThisFrame During the camera's update frame, do this, presuming that all angles are in radians (Ogre, HLSL, DirectXMath, XNAMath all use radians, why don't you?):

if (mouseMoveThisFrame.y != 0.0f){
rotAroundX += mouseMoveThisFrame.y * deltaTime * 3.f;
if (mouseMoveThisFrame.x != 0.0f) {
rotAroundY += mouseMoveThisFrame.x* deltaTime * 3.f;
while (rotAroundX >Math::HALF_PI) { rotAroundX = Math::HALF_PI; }
while (rotAroundX < -Math::HALF_PI) { rotAroundX = -Math::HALF_PI; }
while (rotAroundY >= Math::TWO_PI){ rotAroundY -= Math::TWO_PI; }
while (rotAroundY <= 0) { rotAroundY += Math::TWO_PI; }

if ((mouseMoveThisFrame.x) != 0.f || mouseMoveThisFrame.y != 0.f){
Quaternion rotQuat = Quaternion::IDENTITY;
Quaternion xQuat = Quaternion(Vector3(-rotAroundX,0.f,0.f));
Quaternion yQuat = Quaternion(Vector3(0.f,-rotAroundY,0.f));

or rotation, and for movement each frame, if you store your rotation angles (in whatever form) as separate, you can do the following to make the player move along the view direction you so choose:

Quaternion rotateAroundY(Vector3(0.f,-rotAroundY,0.f)); m_velocity += rotateAroundY*(m_acceleration* deltaTime);

NOTE: This code presumes that Quaternion's '*' operator performs

((quaternion) * (vector) * (quaternion's conjugate))

instead of just the first half of that. At the end of the frame that the input is used, SET IT TO ZERO. This may seem silly, but a long standing, currently on hiatus, project of mine has a currently unusable camera because of a bug relating to this. This camera is rock solid, the only problems you may have with it are fat frames causing a large amount of mouse movement, but that can be solved with a speed limit.

Until next time!