OpenGL (dans Qt) – problème en rotation

J’ai fait un code simple en openGL. Vous devez sélectionner une image, c’est ça. Maintenant, vous pouvez faire la rotation en utilisant ces touches

  • a, s -> pivoter autour de l’axe des x
  • d, f -> tourner autour de l’axe des y
  • b, n -> tourner autour de l’axe z.

Le problème est que la rotation de l’axe z fonctionne toujours bien. Mais les rotations x, y ne sont pas toujours correctes.

Test: appuyez sur n’importe quel bouton, vous pouvez voir qu’un axe n’est pas du tout en mouvement, l’autre axe se déplace. Vous pouvez le vérifier pour les trois axes. Mais après un certain temps, même si vous avez essayé de faire pivoter l’object autour de l’axe des x, vous pouvez voir que les trois axes se déplacent. La chose étrange est que la rotation autour de l’axe z fonctionne toujours correctement. seuls les deux autres font la migraine.

Voici le “main.cpp”

#include  #include  #include  #include  #include  #include  #include  #include  #include  #include  class MyMessageBox:public QMessageBox { public: MyMessageBox(std::ssortingng message,QWidget *parent=0):QMessageBox(QMessageBox::NoIcon,QSsortingng("ErrorMessage"),QSsortingng(message.c_str()),QMessageBox::Ok,parent,Qt::Widget) { } }; class MyOpenGL:public QGLWidget { double x_Rot; double y_Rot; double z_Rot; QVector textures; // it does nothing. It got added just for the sake of the program run QVector openGL_Images; public: MyOpenGL(QWidget * parent); ~MyOpenGL(); void initializeGL(); void resizeGL(int w, int h); void paintGL(); void drawCube(QPoint upper_Left_Point,int length,int width,int height,QVector textures); void drawAxis(); QVector3D get_In_OpenGL_Coordinates(QPoint qwidget_Point); void keyPressEvent(QKeyEvent * event); void mousePressEvent(QMouseEvent * event); }; MyOpenGL::MyOpenGL(QWidget *parent):QGLWidget(QGLFormat(QGL::SampleBuffers),parent) { setAutoFillBackground(false); } MyOpenGL::~MyOpenGL() { } void MyOpenGL::initializeGL() { //textures.push_back(new GLuint); //textures.push_back(new GLuint); QSsortingng fileName=QFileDialog::getOpenFileName(); openGL_Images.push_back(convertToGLFormat(QImage(fileName).scaled(QSize(256,256)))); openGL_Images.push_back(convertToGLFormat(QImage(fileName).scaled(QSize(256,256)))); openGL_Images.push_back(convertToGLFormat(QImage(fileName).scaled(QSize(256,256)))); openGL_Images.push_back(convertToGLFormat(QImage(fileName).scaled(QSize(256,256)))); openGL_Images.push_back(convertToGLFormat(QImage(fileName).scaled(QSize(256,256)))); openGL_Images.push_back(convertToGLFormat(QImage(fileName).scaled(QSize(256,256)))); //glGenTextures(1,textures[0]); //glBindTexture(GL_TEXTURE_2D,*textures[0]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glEnable(GL_TEXTURE_2D); glShadeModel(GL_SMOOTH); glClearColor(0.0f,0.0f,0.0f,0.0f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST); } void MyOpenGL::resizeGL(int w, int h) { glMasortingxMode(GL_PROJECTION); glLoadIdentity(); glViewport(45,0,w,h); gluPerspective(45.0f,((double)width())/height(),1.0f,100.0f); //gluOrtho2D(-10.0f,10.0f,-10.0f,10.0f); glMasortingxMode(GL_MODELVIEW); glLoadIdentity(); paintGL(); } void MyOpenGL::paintGL() { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(0.0,0.0,-10.0); glRotatef(x_Rot,1.0f,0.0f,0.0f); glRotatef(y_Rot,0.0f,1.0f,0.0f); glRotatef(z_Rot,0.0f,0.0f,1.0f); drawAxis(); //drawCube(QPoint(0,0),1,1,1,textures); } void MyOpenGL::drawCube(QPoint upper_Left_Back_Point, int length, int width, int height,QVector textures1) { //glGenTextures(1,textures[0]); //glBindTexture(GL_TEXTURE_2D,*textures[0]); QVector3D starting_Point = get_In_OpenGL_Coordinates(upper_Left_Back_Point); double x=starting_Point.x(); double y=starting_Point.y(); double z=starting_Point.z(); //glGenTextures(1,textures[0]); //glBindTexture(GL_TEXTURE_2D,*textures[0]); glTexImage2D(GL_TEXTURE_2D,0,3,openGL_Images[0].width(),openGL_Images[0].height(),0,GL_RGBA,GL_UNSIGNED_BYTE,openGL_Images[0].bits()); glBegin(GL_QUADS); // glColor3f(1.0f,0.0f,0.0f); glTexCoord2f(0,1);glVertex3f(x-width,y+height,z-length); glTexCoord2f(1,1);glVertex3f(x+width,y+height,z-length); glTexCoord2f(1,0);glVertex3f(x+width,y+height,z+length); glTexCoord2f(0,0);glVertex3f(x-width,y+height,z+length); glEnd(); //glGenTextures(1,textures[1]); //glBindTexture(GL_TEXTURE_2D,*textures[1]); glTexImage2D(GL_TEXTURE_2D,0,3,openGL_Images[1].width(),openGL_Images[1].height(),0,GL_RGBA,GL_UNSIGNED_BYTE,openGL_Images[1].bits()); glBegin(GL_QUADS); //glColor3f(0.0f,1.0f,0.0f); glTexCoord2f(0,1);glVertex3f(x+width,y+height,z-length); glTexCoord2f(1,1);glVertex3f(x+width,y-height,z-length); glTexCoord2f(1,0);glVertex3f(x+width,y-height,z+length); glTexCoord2f(0,0);glVertex3f(x+width,y+height,z+length); glEnd(); glTexImage2D(GL_TEXTURE_2D,0,3,openGL_Images[2].width(),openGL_Images[2].height(),0,GL_RGBA,GL_UNSIGNED_BYTE,openGL_Images[2].bits()); glBegin(GL_QUADS); //glColor3f(0.0f,0.0f,1.0f); glTexCoord2f(0,1);glVertex3f(x+width,y-height,z-length); glTexCoord2f(1,1);glVertex3f(x-width,y-height,z-length); glTexCoord2f(1,0);glVertex3f(x-width,y-height,z+length); glTexCoord2f(0,0);glVertex3f(x+width,y-height,z+length); glEnd(); glTexImage2D(GL_TEXTURE_2D,0,3,openGL_Images[3].width(),openGL_Images[3].height(),0,GL_RGBA,GL_UNSIGNED_BYTE,openGL_Images[3].bits()); glBegin(GL_QUADS); //glColor3f(1.0f,1.0f,0.0f); glTexCoord2f(0,1);glVertex3f(x-width,y+height,z+length); glTexCoord2f(1,1);glVertex3f(x-width,y+height,z-length); glTexCoord2f(1,0);glVertex3f(x-width,y-height,z-length); glTexCoord2f(0,0);glVertex3f(x-width,y-height,z+length); glEnd(); glTexImage2D(GL_TEXTURE_2D,0,3,openGL_Images[4].width(),openGL_Images[4].height(),0,GL_RGBA,GL_UNSIGNED_BYTE,openGL_Images[4].bits()); glBegin(GL_QUADS); //glColor3f(1.0f,0.0f,1.0f); glTexCoord2f(0,1);glVertex3f(x-width,y+height,z-length); glTexCoord2f(1,1);glVertex3f(x+width,y+height,z-length); glTexCoord2f(1,0);glVertex3f(x+width,y-height,z-length); glTexCoord2f(0,0);glVertex3f(x-width,y-height,z-length); glEnd(); glTexImage2D(GL_TEXTURE_2D,0,3,openGL_Images[5].width(),openGL_Images[5].height(),0,GL_RGBA,GL_UNSIGNED_BYTE,openGL_Images[5].bits()); glBegin(GL_QUADS); //glColor3f(0,1,1); glTexCoord2f(0,1);glVertex3f(x-width,y+height,z+length); glTexCoord2f(1,1);glVertex3f(x+width,y+height,z+length); glTexCoord2f(1,0);glVertex3f(x+width,y-height,z+length); glTexCoord2f(0,0);glVertex3f(x-width,y-height,z+length); glEnd(); } void MyOpenGL::drawAxis() { //int length = 1; //int height = 1; //int width = 1; //int x = 0; //int y=0; //int z = 0; glBegin(GL_LINES); glColor3f(1,0,0); glVertex3f(0,0,0); glVertex3f(3,0,0); glColor3f(0,1,0); glVertex3f(0,0,0); glVertex3f(0,3,0); glColor3f(0,0,1); glVertex3f(0,0,0); glVertex3f(0,0,3); //glVertex3f(x-width,y+height,z+length); //glVertex3f(x+width,y+height,z+length); //glVertex3f(x+width,y-height,z+length); //glVertex3f(x-width,y-height,z+length); glEnd(); } QVector3D MyOpenGL::get_In_OpenGL_Coordinates(QPoint qwidget_Point) { return QVector3D(0,0,0); } void MyOpenGL::keyPressEvent(QKeyEvent * event) { switch(event->key()) { case Qt::Key_A: x_Rot-=5; break; case Qt::Key_S: x_Rot+=5; break; case Qt::Key_D: y_Rot+=5; break; case Qt::Key_F: y_Rot-=5; break; case Qt::Key_B: z_Rot+=5; break; case Qt::Key_N: z_Rot-=5; break; default: break; } updateGL(); } void MyOpenGL::mousePressEvent(QMouseEvent *event) { double x = event->pos().x(); double y = event->pos().y(); double z=-1; glReadPixels(x,y,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,&z); double projection[16]; glGetDoublev(GL_PROJECTION_MATRIX,projection); double modelView[16]; glGetDoublev(GL_MODELVIEW_MATRIX,modelView); int viewPort[4]; glGetIntegerv(GL_VIEWPORT,viewPort); double x_Gl; double y_Gl; double z_Gl; gluUnProject(x,y,z,modelView,projection,viewPort,&x_Gl,&y_Gl,&z_Gl); QSsortingng ss; QTextStream ss_Text(&ss); ss_Text << x_Gl << " " << y_Gl << " " <show(); return app.exec(); } 

Ici, le fichier .pro

 SOURCES += \ main.cpp QT += opengl 

Quelqu’un, s’il vous plaît, aidez-moi à en sortir.

D’abord quelques observations sur votre code:

  1. Où initialisez-vous x_Rot, y_Rot et z_Rot? Je ne vois pas où cela se passe.

Ensuite, quelques commentaires plus généraux:

Techniquement, ce que vous faites maintenant tourne autour de x, y et z. Si vous voulez faire autre chose, comme par exemple faire une rotation incrémentielle à chaque pression sur un bouton, vous devez bien réfléchir à ce que vous essayez de faire. Une façon de faire consiste à appliquer les masortingces de rotation dans OpenGL de manière incrémentielle. Une autre possibilité est de stocker une quantité / masortingce sur le client, puis chaque image réinitialise la transformation de vue. Encore une autre possibilité est de bash un tas de sortingg et de calculer la déviation correcte dans les angles x / y / z par rotation (non recommandé). Vous pouvez faire n’importe laquelle de ces choses et plus encore, une fois que vous avez compris ce que vous essayez réellement de faire. Pour arriver à ce point, vous devrez lire un peu (désolé, c’est comme ça que fonctionnent les mathématiques). Comme sharepoint départ, voici quelques pages wiki de base pour vous aider à démarrer:

http://en.wikipedia.org/wiki/Rotation_representation_%28mathematics%29

http://en.wikipedia.org/wiki/Rotation_masortingx

http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation

Il semble que votre problème est Gimbal Lock

L’utilisation des quaternions est l’un des moyens les plus simples de résoudre ce problème.