OpenGL (в Qt) - проблема в ротации - PullRequest
3 голосов
/ 19 июня 2011

Я сделал простой код в openGL.Вы должны выбрать изображение, вот и все.Теперь вы можете сделать поворот с помощью этих клавиш

  • 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

Кто-нибудь, пожалуйста, помогите мне в этом.

Ответы [ 2 ]

4 голосов
/ 19 июня 2011

Сначала несколько замечаний по вашему коду:

  1. Где вы инициализируете x_Rot, y_Rot и z_Rot?Я не вижу, где это происходит.

Далее, еще несколько общих комментариев:

Технически, то, что вы сейчас делаете, вращается вокруг x, y и z.Если вы хотите сделать что-то еще, например, вращаться постепенно с каждым нажатием кнопки, то вам нужно тщательно подумать о том, что вы пытаетесь сделать.Одним из способов сделать это является постепенное применение матриц вращения в OpenGL.Другая возможность - сохранить кватерион / матрицу на клиенте, а затем каждый кадр сбрасывает преобразование представления.Еще одна возможность состоит в том, чтобы объединить триггеры и вычислить правильное отклонение углов 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

1 голос
/ 21 июня 2011

Похоже, ваша проблема Блокировка подвеса

Использование кватернионов - один из самых простых способов решения этой проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...