How do I implement a quaternion based camera?
        Posted  
        
            by 
                kudor gyozo
            
        on Game Development
        
        See other posts from Game Development
        
            or by kudor gyozo
        
        
        
        Published on 2011-11-05T17:40:42Z
        Indexed on 
            2011/11/30
            18:17 UTC
        
        
        Read the original article
        Hit count: 616
        
I looked at several tutorials about this and when I thought I understood I tried to implement a quaternion based camera. The problem is it doesn't work correctly, after rotating for approx. 10 degrees it jumps back to -10 degrees. I have no idea what's wrong. I'm using openTK and it already has a quaternion class. I'm a noob at opengl, I'm doing this just for fun, and don't really understand quaternions, so probably I'm doing something stupid here. Here is some code: (Actually almost all the code except the methods that load and draw a vbo (it is taken from an OpenTK sample that demonstrates vbo-s))
I load a cube into a vbo and initialize the quaternion for the camera
protected override void OnLoad(EventArgs e) {
    base.OnLoad(e);
    cameraPos = new Vector3(0, 0, 7);
    cameraRot = Quaternion.FromAxisAngle(new Vector3(0,0,-1), 0);
    GL.ClearColor(System.Drawing.Color.MidnightBlue);
    GL.Enable(EnableCap.DepthTest);
    vbo = LoadVBO(CubeVertices, CubeElements);
}
I load a perspective projection here. This is loaded at the beginning and every time I resize the window.
protected override void OnResize(EventArgs e) {
    base.OnResize(e);
    GL.Viewport(0, 0, Width, Height);
    float aspect_ratio = Width / (float)Height;
    Matrix4 perpective = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspect_ratio, 1, 64);
    GL.MatrixMode(MatrixMode.Projection);
    GL.LoadMatrix(ref perpective);
}
Here I get the last rotation value and create a new quaternion that represents only the last rotation and multiply it with the camera quaternion. After this I transform this into axis-angle so that opengl can use it. (This is how I understood it from several online quaternion tutorials)
protected override void OnRenderFrame(FrameEventArgs e) {
    base.OnRenderFrame(e);
    GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
    double speed = 1;
    double rx = 0, ry = 0;
    if (Keyboard[Key.A]) {
        ry = -speed * e.Time;
    }
    if (Keyboard[Key.D]) {
        ry = +speed * e.Time;
    }
    if (Keyboard[Key.W]) {
        rx = +speed * e.Time;
    }
    if (Keyboard[Key.S]) {
        rx = -speed * e.Time;
    }
    Quaternion tmpQuat = Quaternion.FromAxisAngle(new Vector3(0,1,0), (float)ry);
    cameraRot = tmpQuat * cameraRot;
    cameraRot.Normalize();
    GL.MatrixMode(MatrixMode.Modelview);
    GL.LoadIdentity();
    Vector3 axis;
    float angle;
    cameraRot.ToAxisAngle(out axis, out angle);
    GL.Rotate(angle, axis);
    GL.Translate(-cameraPos);
    Draw(vbo);
    SwapBuffers();
}
Here are 2 images to explain better: I rotate a while and from this:

it jumps into this

Any help is appreciated.
Update1: I add these to a streamwriter that writes into a file:
    sw.WriteLine("camerarot: X:{0} Y:{1} Z:{2} W:{3} L:{4}", cameraRot.X, cameraRot.Y, cameraRot.Z, cameraRot.W, cameraRot.Length);
    sw.WriteLine("ry: {0}", ry);
The log is available here: http://www.pasteall.org/26133/text. At line 770 the cube jumps from right to left, when camerarot.Y changes signs. I don't know if this is normal.
Update2 Here is the complete project.
© Game Development or respective owner