views:

1596

answers:

4

I'm not sure exactly how to explain this but hopefully you'll understand what I mean.

Basically I've drawn a cube and want to drag the mouse around to view all the sides. Rotating only horizontally or vertically is fine, but if I try to combine these then things go a little weird.

e.g. if I rotate 180 degrees vertically (to get 'upside down') and then drag the mouse horizontally then the cube spins in the opposite direction to the mouse motion.

This is the relevant code:

double camera_angle_h = 0;
double camera_angle_v = 0;

int drag_x_origin;
int drag_y_origin;
int dragging = 0;

void display() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    gluLookAt(0.0, 0.0, 25.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    glRotated(camera_angle_v, 1.0, 0.0, 0.0);
    glRotated(camera_angle_h, 0.0, 1.0, 0.0);

    draw_cube();

    glFlush();
    glutSwapBuffers();
}

void mouse_click(int button, int state, int x, int y) {
    if(button == GLUT_LEFT_BUTTON) {
        if(state == GLUT_DOWN) {
            dragging = 1;
            drag_x_origin = x;
            drag_y_origin = y;
        }
        else
            dragging = 0;
    }
}

void mouse_move(int x, int y) {
    if(dragging) {
        camera_angle_v += (y - drag_y_origin)*0.3;
        camera_angle_h += (x - drag_x_origin)*0.3;
        drag_x_origin = x;
        drag_y_origin = y;
    }
}
+1  A: 

It sounds as if your application is suffering from gimbal lock. There are a few ways to remedy it, the easiest is to clamp the allowed rotations.

unwind
+2  A: 

You are using euler angles and so have the problem of gimbal lock.

A simple solution is to store rotation inside your model-matrix and rotate this matrix instead of storing only 2 angles (by using matrix multiplication).

Look into this answer for more information: http://stackoverflow.com/questions/1225377/will-this-cause-gimbal-lock

a more complex solution is to store quaternions

Peter Parker
A: 

Most applications only allow up to 90 degrees up/down rotation; otherwise, the view is upside down and yes left-to-right is reversed. For most applications, it doesn't make sense to rotate so far that you're looking at the world upside-down.

Also, this isn't gimbal lock like the other two answerers said; gimbal lock requires three (or more?) axes of rotation. Put simply, gimbal lock is when one axis has been rotated 90 degrees either direction, so that the other two axes line up; and then a rotation around either of the other two axes causes the same effect. The airplane image halfway down the wikipedia page shows it well.

Anyway, your best bet is to clamp camera_angle_v to the range (-90,90); in other words, whenever you add or subtract to it, then check if it's greater than 90 and set it to 90, or if it's less than -90 then set it to -90.

Also just to note, I have actually had problems in the past when a v angle is exactly 90 or -90, so I would clamp it to +/- 89.9 instead.

Ricket
A: 

Since you are using GLUT, you probably have the code to deal with this on your system. Take a look for the trackball.c and trackball.h source files. Googling for them will also find the source. This is a simple library to help you with this exact issue. Some GLUT examples that use them are dinospin, bounce, etc.

goger