views:

1397

answers:

6

I'm coding a basic OpenGL game and I've got some code that handles the mouse in terms of moving the camera.

I'm using the following method:

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();

}

However, after looking around in circles you'll find the camera starts to "roll" (rotate). Since I'm only calling Pitch and Yaw, I don't see how this is possible.

Here is the code I'm using for my Camera class: http://pastebin.com/m20d2b01e

As far as I know, my camera "rolling" shouldn't happen. It should simply pitch up and down or yaw left and right. NOT roll.

What could be causing this?

+5  A: 

Well, if you start off looking forward horizontal to the horizon, pitch up 90 degrees, then yaw left 90 degrees, then pitch down 90 degrees, you'd be looking in the same direction as you started, but the horizon would be vertical (as if you'd rolled 90 degrees left).

Edit: I think the problem is that yaw/pitch/roll would be appropriate if the camera is being treated like an airplane. What you probably want to do is treat it like a point in a sphere, keeping track of where on the sphere you are pointing the camera. Instead of yaw/pitch, use spherical coordinates keeping track of theta (latitude) and phi (longitude). They may sound similar, but consider the extreme case where the camera is pointing directly up. With yaw/pitch, you can still freely adjust the yaw and pitch from that straight-up direction. With theta/phi, you could only adjust theta downward, and no matter how much you adjusted phi, decreasing theta would still give you a camera that is parallel to the horizon. This is how FPS camera's work (you can't look so far down that you're looking behind you).

Edit 2: Looking at the camera code you linked to, you want to be using the rotLati(float angle) and rotLongi(float angle) functions.

Kip
If I start moving my mouse in tight circles on the screen you'll see a distinct and slow roll. It completely rolls all 360 degrees. It isn't inverting the view.
KingNestor
+1 Beat me to it.If you're moving your mouse in tight circles, you'll get small amounts of roll. That's just how the combination of movements work.
Eclipse
well if you replace the 90's in my answer with 20's, the answer would still be the same. moving in circles would do basically what i am describing.
Kip
Nestor, Kip just explained how pitching and yawing can be combined to get the net effect of a roll. His numbers are exaggerated to make the effect easier to see -- hold your hand in front of you and make those motions with it. You're getting smaller motions from your mouse, which is why you have to move it around a lot more before you go 360 degrees, but it's still the same issue.
Rob Kennedy
+3  A: 

Pitch/yaw/roll are all relative to your vehicle's orientation. When you pitch up/down, you change your axis of yaw. Likewise, when you yaw, you change your pitch axis. So it's possible to change your orientation in a way similar to a roll maneuver just by a combination and pitch & yaw maneuvers.

Calvin
+2  A: 

I believe this circumstance is called Gimbal Lock - there's an example of it with illustrations on the wikipedia page.

Ray Hidayat
+8  A: 

Congratulations -- you have discovered Lie group theory!

Yes, it's possible. The outcome of a series of transformations depends on the order in which they're executed. Doing a pitch followed by a yaw is not the same as a doing a yaw, followed by a pitch. In fact, in the limit of infinitesimally small yaws and pitches, the difference amounts to a pure roll; the general case is a little more complicated.

(Physicists call this the "commutation relationships of the rotational group".)

If you're familiar with rotation matrices, you can work it out quite easily.

heh, looks like we were thinking exactly the same thing ;-)
David Zaslavsky
+6  A: 

You will probably need to use quaternions for composing rotations, if you are not doing so already. This avoids the problem of gimbal lock which you can get when orienting a camera by rotation around the 3 axes.

Here is how to convert between them.

geofftnz
Use quaternions is the answer.
Steven
+4  A: 

Mathematically the reason for this is that rotations in 3D space do not commute. What that means is that pitch() followed by yaw() is not the same as yaw() followed by pitch(), but a consequence of that fact is that the three kinds of rotations are inextricably linked and you can't perform any two of them without getting some of the third. In other words, any sequence of pitch()es and yaw()s will produce a noticeable roll() effect over time, unless the second half of the sequence is the exact reverse of the first half. (There's a lot of fairly intricate math involved in this, but the details aren't particularly relevant)

David Zaslavsky