OpenGL - 旋转问题 - Qt

5

我正在尝试学习在Qt中编写OpenGL代码。我创建了一个应用程序,显示两个图形。其中一个是三角形"A",另一个三角形"B"与"A"完全相同,只是绕z轴(z轴垂直于计算机屏幕)旋转了-90度。现在的问题是旋转会改变尺寸。我在下面发布了"main.cpp"的内容。

#include <QApplication>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QtOpenGL/QGLWidget>
#include <QWidget>

class MyOpenGL:public QGLWidget
{
public:
    MyOpenGL(QWidget * parent);
    ~MyOpenGL();
    void initializeGL();
    void resizeGL(int w, int h);
    void paintGL();
};

MyOpenGL::MyOpenGL(QWidget *parent):QGLWidget(QGLFormat(QGL::SampleBuffers),parent)
{
    setAutoFillBackground(false);
}

MyOpenGL::~MyOpenGL()
{

}

void MyOpenGL::initializeGL()
{
    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();
    gluPerspective(45.0f,width()/height(),10.0f,100.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void MyOpenGL::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    //glTranslatef(0.0,0.0,-10.0);

    glBegin(GL_TRIANGLES);
    glColor3f(1.0f,0.0f,0.0f);
    glVertex3f(-1.0f,0.0f,-10.0f);
    glColor3f(0.0f,1.0f,0.0f);
    glVertex3f(1.0f,0.0f,-10.0f);
    glColor3f(0.0f,0.0f,1.0f);
    glVertex3f(0.0f,4.0f,-10.0f);
    glEnd();

    glRotatef(90.0,0.0f,0.0f,-1.0f);

    glBegin(GL_TRIANGLES);
    glColor3f(1.0f,0.0f,0.0f);
    glVertex3f(-1.0f,0.0f,-10.0f);
    glColor3f(0.0f,1.0f,0.0f);
    glVertex3f(1.0f,0.0f,-10.0f);
    glColor3f(0.0f,0.0f,1.0f);
    glVertex3f(0.0f,4.0f,-10.0f);
    glEnd();

    glLoadIdentity();
}

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

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

    return app.exec();
}

这是个配置文件。
SOURCES += \
    main.cpp

QT += opengl

这是生成应用程序的截图

在此输入图片描述

据我所知,旋转不会改变尺寸。但是这里尺寸正在改变。如果有人能解决我的疑惑,我将非常感激他/她。


@VJo 我编辑了问题,请阅读最后几行。 - prabhakaran
4个回答

4
我不能确定发生了什么,但我看到可能存在一些问题。
gluPerspective(45.0f,width()/height(),10.0f,100.0f);

如果widthheight都返回整数(很可能会这样),那么它们相除的结果也将是一个整数。这不会给你一个正确的纵横比。将它们中的一个转换为float以获得实际的纵横比。
接下来,尝试在paintGL函数的顶部放置一个glLoadIdentity()调用。

我从来没有想过这个问题。就像你所说的,宽度/高度搞砸了一切。现在它正常工作了。 - prabhakaran

0
你需要设置视图:
void MyOpenGL::resizeGL(int w, int h)
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glViewport(0,0,w,h);
    gluPerspective(45.0f,(double)w/(double)h,10.0f,100.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    updateGL();
}

此外,在渲染图像时无需重置投影矩阵:
void MyOpenGL::paintGL()
{
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();


    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    //glTranslatef(0.0,0.0,-10.0);

    glBegin(GL_TRIANGLES);
    glColor3f(1.0f,0.0f,0.0f);
    glVertex3f(-1.0f,0.0f,-10.0f);
    glColor3f(0.0f,1.0f,0.0f);
    glVertex3f(1.0f,0.0f,-10.0f);
    glColor3f(0.0f,0.0f,1.0f);
    glVertex3f(0.0f,4.0f,-10.0f);
    glEnd();

    glRotatef(90.0,0.0f,0.0f,-1.0f);

    glBegin(GL_TRIANGLES);
    glColor3f(1.0f,0.0f,0.0f);
    glVertex3f(-1.0f,0.0f,-10.0f);
    glColor3f(0.0f,1.0f,0.0f);
    glVertex3f(1.0f,0.0f,-10.0f);
    glColor3f(0.0f,0.0f,1.0f);
    glVertex3f(0.0f,4.0f,-10.0f);
    glEnd();
}

但正如有人所说,尝试使用glOrtho而不是gluPerspective。


你仍然需要在顶部(或底部,但顶部更明确)使用glLoadIdentity来防止累积连续旋转。resizeGL只会在窗口大小改变时被调用。 - Nicol Bolas
@Nicol 对的,但是视图最初必须在初始化函数中设置。 - BЈовић
@Nicol 对,完全忘记了。现在已经修复了。 - BЈовић

0
如果您需要进行2D渲染,请使用gluOrtho2D而不是gluPerspective(3D渲染)。
实际上,这并不是问题,这只是将3D对象投影到2D平面的正常过程。

在你的建议之后,我使用了gluOrtho2D(-10.0f,10.0f,-10.0f,10.0f)。但是屏幕上什么也看不到,变成了空白。 - prabhakaran
当然,您必须编辑您的代码。1)尝试使用glVertex2d,2)一些提示 - Optillect Team
@Optillect团队:他的顶点怎么样?它们的Z值为-10,因此它们将在相机视野内,并且不会被近裁剪剪切。绕Z轴旋转不会改变它们的Z值,因此它们不会离相机越来越远或更近。问题出在哪里? - Nicol Bolas
@Nicol,三角形的底边长度为2个单位,高度为4个单位。我的意思是,由于3D投影的原因,这两个三角形旋转后看起来不一样。 - Optillect Team
无论如何,你关于两个整数的除法是正确的。我刚刚注意到结果取决于透视投影矩阵。 - Optillect Team
显示剩余3条评论

-1
为了进行旋转,您必须先将物体移至原点,然后旋转并将其移回所需位置。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接