   Gimbal lock problem...
  Hi all,Recently, I have a discussion about gimbal lock with a guy.  He is convinced that all rotation representations have gimbal lock problem, including 4x4 rotation matrix, axis angles, quaternion etc... .  His argument is something like..."Since Euler angle suffer from gimbal lock, as we can convert it to others rotation representations, all rotation representations suffer from gimbal lock."I have tried very hard to told him gimbal lock is only an issue when you try to control rotation with Euler angles (or following the idea of Euler angles ).  I failed to convince him.Can anyone help me out?  ( Either correcting me or him is perfectly fine. )   
  Besides, I wrote a simple rotation interface which can avoid gimbal lock.  Please double check for me that whether the following program can or cannot provide a rotation interface with 3 degree of freedom without gimbal lock.Here is the source code of the program...#include <stdio.h>#include <stdlib.h>#include <string.h>#include <GL/glut.h>float mo[16];void init_mo();void update_mo( float angle, float x, float y, float z );void display();void keyboard( unsigned char key, int x, int y );void main( int argc, char **argv ){  glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );  glutInitWindowSize( 512, 512 );  glutCreateWindow( "gimbal_lock" );  glutDisplayFunc( display );  glutKeyboardFunc( keyboard );  init_mo();  glutMainLoop();}void display(){  GLint viewport[4];    glGetIntegerv( GL_VIEWPORT, viewport );  glEnable( GL_DEPTH_TEST );  glEnable( GL_LIGHTING );  glEnable( GL_LIGHT0 );  glClearColor( .1, .2, .3, 1 );  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );  glMatrixMode(GL_PROJECTION);    glLoadIdentity();    gluPerspective( 45, double(viewport[2])/viewport[3], 0.1, 10 );   glMatrixMode(GL_MODELVIEW);    glLoadIdentity();    gluLookAt( 0,0,3, 0,0,0, 0,1,0 );    glMultMatrixf(mo);    glutSolidTeapot(.7);  glutSwapBuffers();}void init_mo(){  memset( mo, 0, sizeof(mo) );  mo[0]=mo[5]=mo[10]=mo[15]=1;  glutPostRedisplay();}void update_mo( float angle, float x, float y, float z ){  glPushMatrix();    glLoadIdentity();    glRotatef( angle, x,y,z );    glMultMatrixf(mo);    glGetFloatv( GL_MODELVIEW_MATRIX, mo );  glPopMatrix();  glutPostRedisplay();}void keyboard( unsigned char key, int x, int y ){  switch( key )  {    case 27:init_mo();break;    case '1':update_mo( -5, 1,0,0 );    break;    case '2':update_mo( 5, 1,0,0 );    break;    case '3':update_mo( -5, 0,1,0 );    break;    case '4':update_mo( 5, 0,1,0 );    break;    case '5':update_mo( -5, 0,0,1 );    break;    case '6':update_mo( 5, 0,0,1 );    break;  }}PS: I knew how to use axis-angles and quaternion to build rotation interface without gimbal lock.  The above program is only an exploration of others possibility.  So, we may skip the discussion about axis-angles and quaternion for more efficient discussion.;  Short answer (have to leave here in a minute)...Rotations in matrix or quaternion form may appear to suffer from gimbal lock if they were constructed using Euler angles. However, gimbal lock is a behavior that is unique to Euler angles, and when properly handled, matrices and quaternions can and will be gimbal-lock-free.A quick glance at your code suggests that yes, you've implemented a gimbal-lock-free interface. Also, you may already know this, but if you change this:glRotatef( angle, x,y,z );glMultMatrixf(mo);To this:glMultMatrixf(mo);glRotatef( angle, x,y,z );You'll get local-axis rotations instead of world-axis rotations (that is, full 6DOF motion, as in a space simulator).Post back if you need more clarification.   ;  Hi,Nice program, I was looking for something like this.I've put it into source tags and re-indented it#include <stdio.h>#include <stdlib.h>#include <string.h>#include <GL/glut.h>float mo[16];void init_mo();void update_mo( float angle, float x, float y, float z );void display();void keyboard( unsigned char key, int x, int y );void main( int argc, char **argv ){glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );glutInitWindowSize( 512, 512 );glutCreateWindow( "gimbal_lock" );glutDisplayFunc( display );glutKeyboardFunc( keyboard );init_mo();glutMainLoop();}void display(){GLint viewport[4];glGetIntegerv( GL_VIEWPORT, viewport );glEnable( GL_DEPTH_TEST );glEnable( GL_LIGHTING );glEnable( GL_LIGHT0 );glClearColor( .1, .2, .3, 1 );glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective( 45, double(viewport[2])/viewport[3], 0.1, 10 );glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluLookAt( 0,0,3, 0,0,0, 0,1,0 );glMultMatrixf(mo);glutSolidTeapot(.7);glutSwapBuffers();}void init_mo(){memset( mo, 0, sizeof(mo) );mo[0]=mo[5]=mo[10]=mo[15]=1;glutPostRedisplay();}void update_mo( float angle, float x, float y, float z ){glPushMatrix();glLoadIdentity();glRotatef( angle, x,y,z );glMultMatrixf(mo);glGetFloatv( GL_MODELVIEW_MATRIX, mo );glPopMatrix();glutPostRedisplay();}void keyboard( unsigned char key, int x, int y ){switch( key ){case 27:init_mo();break;case '1':update_mo( -5, 1,0,0 );break;case '2':update_mo( 5, 1,0,0 );break;case '3':update_mo( -5, 0,1,0 );break;case '4':update_mo( 5, 0,1,0 );break;case '5':update_mo( -5, 0,0,1 );break;case '6':update_mo( 5, 0,0,1 );break;}}I didn't make any changes from your original.;Quote:Original post by jykA quick glance at your code suggests that yes, you've implemented a gimbal-lock-free interface. That guy (who having the discussion with me) said the program about cannot provide rotation with 3 degree of freedom.  His argment is something like..."At a particular time, the program above can only rotate around a particular axis which is 1 degree of freedom.  At most, it only provide a combined rotation of some distinct rotations with 1 degree of freedom.  Therefore, it is not 3 degree of freedom."His words really made me headache.  I have to admit that the statement is very creative.  Although I knew he is wrong, I couldn't come up with a strong proof to prove he is wrong.Can you help me out?  (Or, am I really making mistake about the functionality of my program?);Quote:"At a particular time, the program above can only rotate around a particular axis which is 1 degree of freedom.  At most, it only provide a combined rotation of some distinct rotations with 1 degree of freedom.  Therefore, it is not 3 degree of freedom."I'm not exactly sure what your friend is getting at.It's kind of too bad you posted this in the OpenGL forum - it's really a math question, and you'd probably stand a better chance of getting a good formal explanation in Math & Physics. (Maybe if you asked a mod, they'd move the thread for you...)Now, unless I'm misreading your code (and I don't think I am), you've created an application where you can rotate a teapot about each of the cardinal (world) axes independently; that is, the rotations do not affect each other, and there is no aliasing, gimbal lock, or other artifacts associated with the use of Euler angles. Correct?I would also suggest trying it with the order of multiplication reversed, as shown in my previous post (maybe you could even set up the program so you could toggle back and forth between one and the other). With the order of multiplication reversed, you should get similar behavior, except that the rotations will occur independently about the teapot's local axes.Maybe the guy is misreading your code - I don't know. Have you shown him the application in action? Not sure what else to say at this point, other than that I'm about as sure as I can be that you've got a 3DOF teapot going there that should be completely free from gimbal lock or any other Euler-angle-related artifacts.In short, I think your friend is either simply wrong, or is misunderstanding the point that you're trying to make.P.S. It might be worth pointing out that just because you can only rotate about one axis at a time doesn't mean you only have one degree of freedom. In fact, all you can really ever do is rotate about one axis at a time.   ;  Educate your friend with some appropiate mathematics: he cannot deny that if your program correctly implements rotation matrices and their multiplication it can represent any rotation.His sillogism is spectacularly wrong. By analogy: since the sofa he bought is too large for the doors and trunk of his car, and the car can be loaded on large trucks, no truck is large enough to bring home his sofa. I have a vague recollection of Homer Simpson having this sort of problem.