views:

331

answers:

4

Yesterday I asked: How could simply calling Pitch and Yaw cause the camera to roll?

Basically, I found out because of "Gimbal Lock" that if you pitch + yaw you will inevitably produce a rolling effect. For more information you can read that question.

I'm trying to stop this from happening. When you look around in a normal FPS shooter you don't have your camera rolling all over the place!

Here is my current passive mouse func:

int windowWidth = 640;
int windowHeight = 480;

int oldMouseX = -1;
int oldMouseY = -1;

void mousePassiveHandler(int x, int y)
{
    int snapThreshold = 50;

    if (oldMouseX != -1 && oldMouseY != -1)
    {
        cam.yaw((x - oldMouseX)/10.0);
        cam.pitch((y - oldMouseY)/10.0);


        oldMouseX = x;
        oldMouseY = y;

        if ((fabs(x - (windowWidth / 2)) > snapThreshold) || (fabs(y - (windowHeight / 2)) > snapThreshold))
        {
            oldMouseX = windowWidth / 2;
            oldMouseY = windowHeight / 2;
            glutWarpPointer(windowWidth / 2, windowHeight / 2);
        }
    }
    else
    {
        oldMouseX = windowWidth / 2;
        oldMouseY = windowHeight / 2;
        glutWarpPointer(windowWidth / 2, windowHeight / 2);
    }


    glutPostRedisplay();

}

Which causes the camera to pitch/yaw based on the mouse movement (while keeping the cursor in the center). I've also posted my original camera class here.

Someone in that thread suggested I use Quaternions to prevent this effect from happening but after reading the wikipedia page on them I simply don't grok them.

How could I create a Quaternions in my OpenGL/Glut app so I can properly make my "Camera" look around without unwanted roll?

+1  A: 

A Simple Quaternion-Based Camera, designed to be used with gluLookAt.

http://www.gamedev.net/reference/articles/article1997.asp

Don Neufeld
A: 

I would represent everything in polar coordinates. The wikipedia page should get you started.

Andy
A: 

You don't really need quaternions for that simple case, what you need is to input your heading and pitch into a 3-dimensional matrix calculation:

  1. Use your heading value with a rotation on Y axis to calculate MY

  2. Use your pitch value with a rotation on X axis to calculate MX

  3. For each point P, calculate R = MX * MY * P

The calculation can be done in 2 ways:

  1. T = MY * P, then R = MX * T

  2. T = MX * MY, then R = T * P

The first way is slower but easier to code at first, the second one is faster but you will need to code a matrix-matrix multiplication function.

ps. See http://en.wikipedia.org/wiki/Rotation_matrix#Dimension_three for the matrices

winden
+1  A: 

Keep your delta changes low to avoid that (i.e < 45 degrees)

Just calculate a small "delta" matrix with the rotations for each frame, fold this into the camera matrix each frame. (by fold I mean: cam = cam * delta)

If you're running for a long time, you might get some numerical errors, so you need to re-orthogonalize it. (look it up if that seems to happen)

That's the easiest way to avoid gimbal lock when just playing around with things. Once you get more proficient, you'll understand the rest.

As for quaternions, just find a good lib for them that can convert them to rotation matrices, then use the same technique (compute delta quat, multiply into main quat).

Marcus Lindblom