   Quaternion Camera Class
  I'm working on a quaternion camera class, so I can look around with the mouse.  I'm having trouble getting the code to work right.  Please help!Alot of the code below comes from the quaternion camera class tutorial found here: http://www.gamedev.net/reference/articles/article1997.asp/* Camera.cpp */#include "camera.h"#include <iostream>using namespace std;   camera::camera() {    init();}  void camera::init() {    fovy = 20;    far = 20;    Position.Set(0,0,-20);    View.Set(0,0,0);    Up.Set(0,1,0);    screenwidth = 800;    screenheight = 600;    MouseSensitivity = 50;}void camera::SetViewByMouse(void){    int MouseX, MouseY;    int MiddleX = screenwidth/2;    int MiddleY = screenheight/2;    CVec3 MouseDirection (0, 0, 0); static double CurrentRotationAboutX = 0.0;    double maxAngle = 1;    SDL_GetMouseState(&MouseX, &MouseY);    if((MouseX == MiddleX) && (MouseY == MiddleY))   return;    SDL_WarpMouse(MiddleX, MiddleY);   MouseDirection.x = (MiddleX - MouseX)/MouseSensitivity;MouseDirection.y = (MiddleY - MouseY)/MouseSensitivity;    CurrentRotationAboutX += MouseDirection.y;    if(CurrentRotationAboutX > 1)    {   CurrentRotationAboutX = 1;   return;    }    if(CurrentRotationAboutX < -1)    {   CurrentRotationAboutX = -1;   return;    }    else    {   CVec3 tmp = View - Position; CVec3 Axis = tmp.CrossProduct(Up);   Axis.Normalize();   RotateCamera(MouseDirection.y, Axis.x, Axis.y, Axis.z);   RotateCamera(MouseDirection.x, 0, 1, 0);    }}void camera::RotateCamera(double Angle, double x, double y, double z){CVec3 tmp = View - Position;    Quaternion temp, quat_view, result;    temp.x = x * sin(Angle/2);    temp.y = y * sin(Angle/2);    temp.z = z * sin(Angle/2);    temp.w = cos(Angle/2);    quat_view.x = tmp.x;    quat_view.y = tmp.y;    quat_view.z = tmp.z;    quat_view.w = 0;    result =  temp * quat_view * temp.inverse();View.x = result.x;    View.y = result.y;    View.z = result.z;    }void camera::setCamera() { //sets camera in position    glMatrixMode(GL_PROJECTION);    glLoadIdentity();    gluPerspective(fovy, 1, 0, far);    glMatrixMode(GL_MODELVIEW);    glLoadIdentity();    gluLookAt(Position.x, Position.y, Position.z,View.x, View.y, View.z, Up.x, Up.y, Up.z);}If I remove the * temp.inverse() from the above code in the rotate camera function, I am able to look around but the verticle limits are incorrect, and have a tendancy to change...Here is the quaternion class I wrote, I guess there could be an error here.../*Quaternion.cpp*/#include "Quaternion.h"Quaternion::Quaternion(){    x = 0.0f;    y = 0.0f;    z = 0.0f;    w = 0.0f;}Quaternion::Quaternion(float x_val, float y_val, float z_val, float w_val) {    x = x_val;    y = y_val;    z = z_val;    w = w_val;}Quaternion Quaternion::operator *(const Quaternion &q) {Quaternion r;r.w = w*q.w - x*q.x - y*q.y - z*q.z;r.x = w*q.x + x*q.w + y*q.z - z*q.y;r.y = w*q.y + y*q.w + z*q.x - x*q.z;r.z = w*q.z + z*q.w + x*q.y - y*q.x;return r;}double Quaternion::length(void) {    double length = sqrt(x*x+y*y+z*z+w*w);    return length;}Quaternion Quaternion::normalize(void){    double L = length();    Quaternion r; r.x = x / L;    r.y = y / L;    r.z = z / L;    r.w = w / L;    return r;}Quaternion Quaternion::conjugate() {    Quaternion r; r.x = -x;    r.y = -y;    r.z = -z; return r;}Quaternion Quaternion::inverse(void) {    Quaternion r;    r = conjugate();return r.normalize(); }And finally the Vector class I am using.../* CVec3.h */#ifndef CVec3_h#define CVec3_h#include <math.h>class CVec3{public:// Datafloat x, y, z;// CtorsCVec3( float InX, float InY, float InZ ){x = InX;y = InY;z = InZ;}CVec3( ){x = 0.0f;y = 0.0f;z = 0.0f;}    inline void Set(float InX, float InY, float InZ ) {   x = InX;y = InY;z = InZ;  }// Operator Overloadsinline bool operator== (const CVec3& V2) const {if (x == V2.x && y == V2.y && z == V2.z) return true;else return false;}inline CVec3 operator+ (const CVec3& V2) const {return CVec3( x + V2.x,  y + V2.y,  z + V2.z);}inline CVec3 operator- (const CVec3& V2) const{return CVec3( x - V2.x,  y - V2.y,  z - V2.z);}inline CVec3 operator- ( ) const{return CVec3(-x, -y, -z);}inline CVec3 operator/ (float S ) const{float fInv = 1.0f / S;return CVec3 (x * fInv , y * fInv, z * fInv);}inline CVec3 operator/ (const CVec3& V2) const{return CVec3 (x / V2.x,  y / V2.y,  z / V2.z);}inline CVec3 operator* (const CVec3& V2) const{return CVec3 (x * V2.x,  y * V2.y,  z * V2.z);}inline CVec3 operator* (float S) const{return CVec3 (x * S,  y * S,  z * S);}// Functionsinline float Dot( const CVec3 &V1 ){return V1.x*x + V1.y*y + V1.z*z;}inline CVec3 CrossProduct( const CVec3 &V2 ){return CVec3(y * V2.z  -  z * V2.y,z * V2.x  -  x * V2.z,x * V2.y  -  y * V2.x );}// These require math.h for the sqrtf functionfloat Magnitude( ){return sqrtf( x*x + y*y + z*z );}float Distance( const CVec3 &V1 ){return ( *this - V1 ).Magnitude();}inline void Normalize(){float fMag = ( x*x + y*y + z*z );if (fMag == 0) {return;}float fMult = 1.0f/sqrtf(fMag);  x *= fMult;y *= fMult;z *= fMult;return;   }};#endif
  A quick look at the tutorial and your code indicates that this may be a classic case of 'quaternion abuse'. Not only are quaternions completely unnecessary for a typical FPS-style camera, they offer no benefits to speak of in this context whatsoever. In fact, they just complicate what is by itself a fairly straightforward problem.I suppose that isn't a particularly helpful answer, but IMO you'd be better off re-writing your camera class from scratch, using basic principals of trigonometry and linear algebra, then you would trying to track down the bug in your quaternion implementation. As for the latter though, it could be any number of things, such as missing a radians/degrees conversion or a typo in the quat code.Quote:I'm working on a quaternion camera class, so I can look around with the mouse.Just to dispell some possible misunderstanding, using a quaternion and being able to 'look around with the mouse' have nothing to do with each other. Also, in a properly implemented camera it is not necessary to restrict the pitch value; you should be able to use the full [-90,90] range with no problem.If you have any questions about other camera techniques or would like links to some references, feel free to ask.   ;  I totally agree with JYK.  I've never worked on a game that used a quaternion to describe the orintentaion of a camera.  Normally they're used to describe the orientation of joints in a bone system.I once wrote a small 3D engine that used a quaternion to describe all scene graph object rotations and as it turned out it wasn't going anywhere.  The quaternion class ended up having to actually cache a matrix representation of itself because you don't want to use a quaternion to describe the orientation of an oriented bounding volume since it depends on the columns of a matrix... converting from a quaternion to a matrix isn't free.;  I started off using trig, but I had some issues making the function to pitch the camera vector up and down work correctly. What math is involved in that operation?   ;Quote:Original post by int3grateI started off using trig, but I had some issues making the function to pitch the camera vector up and down work correctly. What math is involved in that operation?In this thread, a few posts up from the bottom, is an explanation of how to compute the basis vectors for an FPS camera that might be helpful.   