OpenGL - a moving camera with a mouse

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

Basically, I drew a cube and want to drag the mouse to view all sides. Rotating only horizontally or vertically is fine, but if I try to combine them, everything will be a little strange.

eg. if I rotate 180 degrees vertically (to β€œflip up”) and then drag the mouse horizontally, then the cube rotates in the opposite direction to the mouse movement.

This is the corresponding 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; } } 
+4
source share
5 answers

You use Euler angles, and therefore the problem is with the cardan lock.

A simple solution is to save rotation within your matrix model and rotate this matrix instead of saving only 2 angles (using matrix multiplication).

Look at this answer for more information: Will this be the reason for the cardan lock?

a more difficult solution is to preserve the quaternions

+4
source

As others have said, using quaternions is a solution. Ken Shoemake offers a great code for converting quaternions and Euler angles to IV graphic gems (see code examples here , see "Converting Euler Angle"). It also has transformations with and from rotation matrices.

If you want to rotate with your mouse, perhaps the gold standard is the Arcball interface described by Shoemake in Graphics Gems IV (avalable here , for now). An improved version of Arcball is distributed with the Glut library as a β€œtrackball”, which offers a more intuitive interface when clicks occur outside the scope of rotation. It was written by Gavin Bell and is available here and here . Bell trackball is the approach used by the Blender project, and I believe commercial packages use something like that.

+4
source

It sounds like your application is suffering from gimbal lock . There are several ways to fix this; the easiest way is to clamp the allowed spins.

+2
source

Most applications only allow 90 degrees up / down rotation; otherwise, the view is upside down, and from left to right - vice versa. For most applications, it makes no sense to rotate so that you look at the world in reverse order.

Moreover, it is not a cardan lock, as the other two defendants said; A cardan lock requires three (or more?) rotation axes. Simply put, a cardan lock is when one axis is rotated 90 degrees in any direction, so that the other two axes line up; and then rotation around either of the other two axes produces the same effect. The image of the plane halfway down the Wikipedia page shows this well.

In any case, it is best to hold camera_angle_v to a range (-90.90); in other words, whenever you add or subtract it, check if it exceeds 90 and sets it to 90, or if it is less than -90, then set it to -90.

It is also easy to note that I actually had problems in the past when the angle v is 90 or -90, so I would pin it to +/- 89.9.

+2
source

Since you are using GLUT, you probably have code to solve this problem on your system. See the source files for trackball.c and trackball.h. For them, there is also a source on Google. This is a simple library that will help you with this particular problem. Some examples of GLUT that use them are dinospin, rebound, etc.

0
source

All Articles