我在openGL中做了一个简单的代码。 你必须select一个图片,就是这样。 现在,您可以使用这些键进行旋转
问题是Z轴旋转始终正常工作。 但是,x,y旋转并不总是正确的。
testing:按下任意(一个)button,就可以看到一个轴没有移动,另一个轴正在移动。 你可以检查这三个轴。 但是过了一段时间,即使您试图绕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
有人请帮我解决这个问题。
首先对你的代码进行一些观察:
接下来,一些更一般的评论:
从技术上讲,你现在正在做的是围绕x,y和z旋转。 如果你想做其他的事情,比如每次按下按钮递增旋转,那么你需要仔细考虑你正在做什么。 一种方法是在OpenGL中逐渐应用旋转矩阵。 另一种可能是在客户端存储一个四元数/矩阵,然后每一帧重置视图转换。 还有一种可能性,就是敲出一堆trig,然后计算每次旋转的x / y / z角度的正确偏差(不推荐)。 一旦你明白了你实际上想要做的是什么,你可以做任何其他的事情。 为了达到这一点,你将不得不读一些(对不起,这是数学如何工作)。 作为一个起点,以下是一些基本的维基页面,可以帮助您:
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
看来你的问题是Gimbal Lock
使用四元数是解决这个问题最简单的方法之一。