Qt OpenGL初探 - 画坐标轴
- 引言
- 一、过程详解
- 1.1 项目创建
- 1.2 实现细节
- 二、核心代码
- 三、官方文档
- 3.1 官网地址
- 3.2 官方手册的使用
引言
Qt OpenGL
模块可以很方便地将OpenGL应用在Qt程序中,本文使用其画了一个3D坐标轴(见上图),并详细讲解了具体的编码过程与官方手册的使用。
OpenGL
是业界采用最广泛的二维和三维图形API。它独立于窗口系统和操作系统,并且网络透明。OpenGL使软件开发人员能够在CAD、内容创建、能源、娱乐、游戏开发、制造、医疗和虚拟现实等市场中创建高性能、视觉吸引力强的图形软件应用程序。但是OpenGL
只处理3D渲染,对于GUI编程并不友好。OpenGL应用程序的用户界面必须使用另一个工具包创建,比如MFC或Qt
。
一、过程详解
1.1 项目创建
-
- 创建一个MainWindow项目,便于后续显示,在pro文件需添加以下内容:
QT += opengl
win32:LIBS += -lOpengl32 -lglu32
unix:LIBS += -lglut -lGLU
- 创建一个MainWindow项目,便于后续显示,在pro文件需添加以下内容:
-
- 创建QopenGLDemo 类,继承QOpenGLWidget
class QopenGLDemo : public QOpenGLWidget
- 创建QopenGLDemo 类,继承QOpenGLWidget
-
- 在MainWindow构造函数中添加如下代码,将创建的3D窗口添加到主窗口中,用于显示
QopenGLDemo *m_gl = new QopenGLDemo(this);
this->setCentralWidget(m_gl);
- 在MainWindow构造函数中添加如下代码,将创建的3D窗口添加到主窗口中,用于显示
-
- 在QopenGLDemo.cpp中实现三个虚函数即可显示,
initializeGL
、resizeGL
、paintGL
,后续有三个函数的完整代码
- 在QopenGLDemo.cpp中实现三个虚函数即可显示,
1.2 实现细节
核心为paintGL
函数的实现
-
- 先画三条直线
- 先画三条直线
// 初始化
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轴…
-
- 调整角度,让其显示z轴
- 调整角度,让其显示z轴
glTranslatef(0, 0, -30); // 调整绘图坐标
glRotatef(45.0, 0, -1, 0); // 绕y轴旋转45度
glRotatef(45.0, 1, 0, -1); // 绕向量(1,0,-1) 旋转45度
增加两行旋转代码,感觉有那么点立体的意思了
-
- 画坐标轴的箭头
- 画坐标轴的箭头
// 坐标轴箭头 参考官方文档: 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
就会使得原点回到旋转和平移之前的位置。
-
- 最后增加一个原点
// 画原点 - 白色
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/
-
- 进入
OpenGL 4 Reference Pages
手册地址,glu
开头的函数点击下图箭头处链接:
- 进入
-
- 继续点击下图箭头处链接,跳转到glu开头的函数:
- 继续点击下图箭头处链接,跳转到glu开头的函数:
-
- 下滑找到
gluCylinder函数
点击即可看到其具体的参数:
- 下滑找到