Qt OpenGL初探 - 画坐标轴

发布时间:2024年01月13日

引言

在这里插入图片描述
Qt OpenGL模块可以很方便地将OpenGL应用在Qt程序中,本文使用其画了一个3D坐标轴(见上图),并详细讲解了具体的编码过程与官方手册的使用。

OpenGL是业界采用最广泛的二维和三维图形API。它独立于窗口系统和操作系统,并且网络透明。OpenGL使软件开发人员能够在CAD、内容创建、能源、娱乐、游戏开发、制造、医疗和虚拟现实等市场中创建高性能、视觉吸引力强的图形软件应用程序。但是OpenGL只处理3D渲染,对于GUI编程并不友好。OpenGL应用程序的用户界面必须使用另一个工具包创建,比如MFC或Qt

一、过程详解

1.1 项目创建

    1. 创建一个MainWindow项目,便于后续显示,在pro文件需添加以下内容:
      QT += opengl
      win32:LIBS += -lOpengl32 -lglu32
      unix:LIBS += -lglut -lGLU
    1. 创建QopenGLDemo 类,继承QOpenGLWidget
      class QopenGLDemo : public QOpenGLWidget
    1. 在MainWindow构造函数中添加如下代码,将创建的3D窗口添加到主窗口中,用于显示
      QopenGLDemo *m_gl = new QopenGLDemo(this);
      this->setCentralWidget(m_gl);
    1. 在QopenGLDemo.cpp中实现三个虚函数即可显示,initializeGLresizeGLpaintGL,后续有三个函数的完整代码

1.2 实现细节

核心为paintGL函数的实现

    1. 先画三条直线
      在这里插入图片描述
    // 初始化
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除屏幕和深度缓存
    glLoadIdentity();  // 重置
    glTranslatef(0, 0, -30);    // 调整绘图坐标
    // 坐标轴
    float axis_length = 10;
    glLineWidth(5);
    glBegin(GL_LINE_STRIP);
    glColor3f(1, 0, 0);
    glVertex3f(0, 0, 0);
    glVertex3f(axis_length, 0, 0);
    glEnd();
    glFlush();

    glBegin(GL_LINE_STRIP);
    glColor3f(0, 1, 0);
    glVertex3f(0, 0, 0);
    glVertex3f(0, axis_length, 0);
    glEnd();
    glFlush();

    glBegin(GL_LINE_STRIP);
    glColor3f(0, 0, 1);
    glVertex3f(0, 0, 0);
    glVertex3f(0, 0, axis_length);
    glEnd();
    glFlush();

glTranslatef(0, 0, -30);一定要有,根据投影矩阵:绘制的图形的Z轴坐标 >=0的话屏幕就不会显示。上图由于角度问题,并没有显示z轴…

    1. 调整角度,让其显示z轴
      在这里插入图片描述
	glTranslatef(0, 0, -30);    // 调整绘图坐标
    glRotatef(45.0, 0, -1, 0);  // 绕y轴旋转45度
    glRotatef(45.0, 1, 0, -1);  // 绕向量(1,0,-1) 旋转45度

增加两行旋转代码,感觉有那么点立体的意思了

    1. 画坐标轴的箭头
      在这里插入图片描述
    // 坐标轴箭头  参考官方文档: https://registry.khronos.org/OpenGL-Refpages/gl4/
    GLUquadricObj *objCylinder = gluNewQuadric();
    glPushMatrix();
    glColor3f(0, 0, 1);
    glTranslatef(0, 0, axis_length);
    gluCylinder(objCylinder, 0.3, 0.0, 0.3, 100, 1);  // gluCylinder绘制一个沿z轴定向的圆柱体
    glPopMatrix();

    glPushMatrix();
    glColor3f(1, 0, 0);
    glRotatef(90, 0, 1, 0);      // 沿着y轴转90度 使得x轴对着原z轴方向
    glTranslatef(0, 0, axis_length);
    gluCylinder(objCylinder, 0.3, 0.0, 0.3, 100, 1);  // gluCylinder绘制一个沿z轴定向的圆柱体
    glPopMatrix();

    glPushMatrix();
    glColor3f(0, 1, 0);
    glRotatef(-90, 1, 0, 0.0);   // 沿着x轴转90度 使得y轴对着原z轴方向
    glTranslatef(0, 0, axis_length);
    gluCylinder(objCylinder, 0.3, 0.0, 0.3, 100, 1);  // gluCylinder绘制一个沿z轴定向的圆柱体
    glPopMatrix();

由于gluCylinder这个函数只能在原点处冲着z轴正向画圆柱(锥),想要在x轴和y轴上画,需要先将这两个轴旋转到z轴位置,并且进行平移。其中glPushMatrix即保存现场,直接glPopMatrix就会使得原点回到旋转和平移之前的位置。

    1. 最后增加一个原点
    // 画原点 - 白色
    glPointSize(10.0f);
    glBegin(GL_POINTS);
    glColor3f(1, 1, 1);
    glVertex3f(0, 0, 0);
    glEnd();
    glFlush();

二、核心代码

void QopenGLDemo::initializeGL(){
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);  // rgba
    glShadeModel(GL_SMOOTH);               // 平滑着色  GL_FLAT 单调着色
}
void QopenGLDemo::resizeGL(int w, int h){
    glViewport(0, 0, w, h);           //重置当前的视口
    // glMatrixMode() 用以指定当前要操作的矩阵  GL_MODELVIEW(模型视图,默认值),GL_PROJECTION(投影),GL_TEXTURE(纹理),GL_COLOR(颜色)
    glMatrixMode(GL_PROJECTION);      //选择投影矩阵
    glLoadIdentity();                 //重置投影矩阵 为 单位矩阵

    gluPerspective(60.0, double(w) / h, 0.1, 1000.0);  //建立透视投影

    glMatrixMode(GL_MODELVIEW);       //选择模型矩阵
    glLoadIdentity();                 //重置模型矩阵 为 单位矩阵

}
void QopenGLDemo::paintGL(){
    // 初始化
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除屏幕和深度缓存
    glLoadIdentity();  // 重置

    glTranslatef(0, 0, -30);    // 调整绘图坐标
    glRotatef(45.0, 0, -1, 0);  // 绕y轴旋转45度
    glRotatef(45.0, 1, 0, -1);  // 绕向量(1,0,-1) 旋转45度

    // 坐标轴
    float axis_length = 10;
    glLineWidth(5);
    glBegin(GL_LINE_STRIP);
    glColor3f(1, 0, 0);
    glVertex3f(0, 0, 0);
    glVertex3f(axis_length, 0, 0);
    glEnd();
    glFlush();

    glBegin(GL_LINE_STRIP);
    glColor3f(0, 1, 0);
    glVertex3f(0, 0, 0);
    glVertex3f(0, axis_length, 0);
    glEnd();
    glFlush();

    glBegin(GL_LINE_STRIP);
    glColor3f(0, 0, 1);
    glVertex3f(0, 0, 0);
    glVertex3f(0, 0, axis_length);
    glEnd();
    glFlush();

    // 坐标轴箭头  参考官方文档: https://registry.khronos.org/OpenGL-Refpages/gl4/
    GLUquadricObj *objCylinder = gluNewQuadric();
    glPushMatrix();
    glColor3f(0, 0, 1);
    glTranslatef(0, 0, axis_length);
    gluCylinder(objCylinder, 0.3, 0.0, 0.3, 100, 1);  // gluCylinder绘制一个沿z轴定向的圆柱体
    glPopMatrix();

    glPushMatrix();
    glColor3f(1, 0, 0);
    glRotatef(90, 0, 1, 0);      // 沿着y轴转90度 使得x轴对着原z轴方向
    glTranslatef(0, 0, axis_length);
    gluCylinder(objCylinder, 0.3, 0.0, 0.3, 100, 1);  // gluCylinder绘制一个沿z轴定向的圆柱体
    glPopMatrix();

    glPushMatrix();
    glColor3f(0, 1, 0);
    glRotatef(-90, 1, 0, 0.0);   // 沿着x轴转90度 使得y轴对着原z轴方向
    glTranslatef(0, 0, axis_length);
    gluCylinder(objCylinder, 0.3, 0.0, 0.3, 100, 1);  // gluCylinder绘制一个沿z轴定向的圆柱体
    glPopMatrix();

    // 画原点 - 白色
    glPointSize(10.0f);
    glBegin(GL_POINTS);
    glColor3f(1, 1, 1);
    glVertex3f(0, 0, 0);
    glEnd();
    glFlush();
}

三、官方文档

3.1 官网地址

官网:https://www.opengl.org/
官方手册(进官网点 Documentation),如下图:

在这里插入图片描述

3.2 官方手册的使用

官方手册好像是没有搜索功能的…
OpenGL 4 Reference Pages中的gluCylinder函数为例:https://registry.khronos.org/OpenGL-Refpages/gl4/

    1. 进入OpenGL 4 Reference Pages手册地址,glu开头的函数点击下图箭头处链接:
      在这里插入图片描述
    1. 继续点击下图箭头处链接,跳转到glu开头的函数:
      在这里插入图片描述
    1. 下滑找到gluCylinder函数点击即可看到其具体的参数:
      在这里插入图片描述
文章来源:https://blog.csdn.net/qq_38204686/article/details/135352555
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。