2011-06-19 51 views
3

我在openGL中做了一個簡單的代碼。你必須選擇一張圖片,就是這樣。現在,可以通過使用這些鍵OpenGL(在Qt中) - 旋轉問題

  • A,S使旋轉 - >繞x軸
  • d,F - >繞Y軸
  • B,N - >繞Z軸。

問題是z軸旋轉一直很好。但是,x,y旋轉並不總是正確的。

測試: 按任意(一個)按鈕,然後您可以看到一個軸沒有任何移動,另一個軸正在移動。你可以檢查這三個軸。但過了一段時間後,即使您試圖繞x軸旋轉物體,您也會看到所有三個軸都在移動。奇怪的是,圍繞z軸旋轉始終正常工作。只有另外兩個人頭痛。

這裏是 「的main.cpp」

#include <QApplication> 
#include <QFileDialog> 
#include <QHBoxLayout> 
#include <QKeyEvent> 
#include <QMessageBox> 
#include <QPainter> 
#include <QTextStream> 
#include <QtOpenGL/QGLWidget> 
#include <QVector3D> 
#include <QWidget> 

class MyMessageBox:public QMessageBox 
{ 
public: 
    MyMessageBox(std::string message,QWidget *parent=0):QMessageBox(QMessageBox::NoIcon,QString("ErrorMessage"),QString(message.c_str()),QMessageBox::Ok,parent,Qt::Widget) 
    { 
    } 
}; 

class MyOpenGL:public QGLWidget 
{ 
    double x_Rot; 
    double y_Rot; 
    double z_Rot; 
    QVector<GLuint *> textures; // it does nothing. It got added just for the sake of the program run 
    QVector<QImage> 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<GLuint *> 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); 

    QString 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) 
{ 
    glMatrixMode(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); 
    glMatrixMode(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<GLuint *> 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); 

    QString ss; 
    QTextStream ss_Text(&ss); 
    ss_Text << x_Gl << " " << y_Gl << " " << z_Gl ; 
    MyMessageBox mm(ss.toStdString()); 
    mm.exec(); 
} 

int main(int argc,char * argv[]) 
{ 
    QApplication app(argc,argv); 

    MyOpenGL * f = new MyOpenGL(NULL); 
    f->show(); 

    return app.exec(); 
} 

這裏,.pro文件

SOURCES += \ 
    main.cpp 

QT += opengl 

有人請幫我出這一點。

+0

你預計會發生什麼? – Mikola

+0

@Mikola我期待着Z軸在其他兩個軸上的行爲。 – prabhakaran

+0

我很抱歉,那不是很具體。 「z軸行爲」是什麼意思? – Mikola

回答

4

首先在你的代碼的一些意見:

  1. 你在哪裏初始化x_Rot,y_Rot和z_Rot?我不明白這發生了什麼。

下,多了一些一般性評論:

從技術上講,你現在正在做的是繞X,Y和Z。如果你想做其他事情,比如每次按下按鈕時都要遞增地旋轉,那麼你需要仔細考慮你正在嘗試做什麼。一種方法是逐步在OpenGL中應用旋轉矩陣。另一種可能性是在客戶端存儲一個quaterion /矩陣,然後每個幀重置視圖轉換。還有一種可能性是在每次旋轉中敲出一堆trig並計算x/y/z角度的正確偏差(不推薦)。一旦你明白了你實際上想要做的是什麼,你可以做任何這些和更多的事情。爲了達到這一點,你將不得不讀一些(對不起,這是數學的工作原理)。作爲一個起點,這裏有一些基本的wiki頁面,以幫助你去:

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

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

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

1

這似乎是你的問題是Gimbal Lock

使用四元數的處理這個問題最簡單的方法之一。

+0

用於Gimbal Lock的+1。請注意,只是將旋轉存儲在每個幀的矩陣中,並且連續更新可能會解決問題。四元數對插入旋轉是很好的,但當你只是想遞增地旋轉某些東西時並不總是必要的。 – Macke