Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

UPDATE The error here was a pretty simple one. I have missed a radian to degrees conversion. No need to read the whole thing if you have some other problem.

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);
    //////////////////////////////////////////////////////////////////////
    // THIS IS WHAT I DID WRONG: I NEED TO CONVERT FROM RADIANS TO DEGREES
    //////////////////////////////////////////////////////////////////////
    //BEFORE
    //GL.Rotate(angle, axis);
    //AFTER
    GL.Rotate(angle * (float)180.0/(float)Math.PI, axis);
    GL.Translate(-cameraPos);

    Draw(vbo);
    SwapBuffers();
}

Here are 2 images to explain better: I rotate a while and from this:

this

it jumps into this

enter image description here

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.

share|improve this question
2  
I don't understand the problem. Have you tried printing out the quaternions that you're using to render with? –  Nicol Bolas Nov 5 '11 at 18:24
1  
Agreed, debug your rx, ry and Quaternion values. –  Daniel Nov 5 '11 at 23:09
    
Why don't you upload your entire project somewhere to rapidshare? Would be easier. –  bobobobo Nov 27 '11 at 0:50
    
OK I will upload it when I get home. –  gyozo kudor Nov 28 '11 at 8:02

3 Answers 3

up vote 7 down vote accepted

While you haven't shown the necessary code to verify my assumption here, I can almost guarantee that your problem is actually that this line:

cameraRot.ToAxisAngle(out axis, out angle);

is returning an angle value expressed in radians, while

GL.Rotate(angle, axis);

wants angle to be provided in degrees.

To fix it, you need to convert the angle value when passing it to GL.Rotate(), like this:

GL.Rotate(angle * 180.0/3.141593, axis);
share|improve this answer
    
Yes, that was the problem. :) Thanks a lot. I knew opengl expects degrees, I assumed that ToAxisAngle returns degrees. I just looked at the opentk code and it is radians. BTW I have provided full source code at the end. –  gyozo kudor Dec 1 '11 at 19:14
    
@NickCaplinger correctly points out that in C#, there is a Math.Pi constant available, which should be used in preference to the literal 3.141593 value I used in that final calculation. –  Trevor Powell Jun 1 '13 at 0:04

Don't. It may seem that it would be less work to have a camera that can be manipulated like other scene objects, but in the long run it is better to have a camera where you can define a position, eye direction and up vector. Especially when you start programming motion models it is really a pain to work with quaternions.

share|improve this answer
1  
Agreed. I'm not a fan of the "if it's hard to pronounce it must be better" method of designing my applications, too =) –  Patrick Hughes Nov 30 '11 at 19:35
    
Quaternion is hard to pronounce? –  stephelton Nov 30 '11 at 20:55
1  
A little humor goes a long way =D By inference I imply that the question comes from someone who has no idea WHY he wants a quaternion camera, just that it's a neat buzzword and OMG I want it sooo bad now! It's certainly not a subject to tackle when something like handling radians and degree parameters properly in the broken code above isn't dealt with properly. –  Patrick Hughes Nov 30 '11 at 21:34
2  
This question isn't really about cameras; it's about how to represent rotations in game code, and how to convert those game representations into a form such that OpenGL can use them. It's a perfectly legitimate question, and I don't think mocking the OP's lack of domain experience is helpful in any way. It's not like the OP made a stupid mistake; OpenGL's insistence on using degrees when expressing angles is downright bizarre. Everyone makes this mistake their first time using OpenGL. So get off your high horses, people. Geez. –  Trevor Powell Nov 30 '11 at 22:27
    
I just wanted to understand how a quaternion based camera works and I made this project in a day when I had nothing else to do. I have no real plans with this. –  gyozo kudor Dec 1 '11 at 18:57

Don't know much about OpenTK internals. In my experience I did not see math library with proper implementation of quat that keeps needed precision (machine), because all of them affects e^2-e^3 errors. So the effect you see: the precision (and epsilon value) is about 10^-5, and it 'jumps' near zero. This is my guess :)

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.