在OpenGL中三维实体会被拆分成一个个小的平面图形来进行绘制。比如我们绘制的立方体,可以拆分成六个平面来进行绘制。这里我们以一个带纹理的正方体来说明一下三维实体的绘制方法。

绘制立方体

由于正方体的点比较多,为了提升数据的封装性我们定义一个结构体来表示每个点对应的空间坐标和纹理坐标。

struct CubePoint {QVector3D posCoord;        //空间坐标QVector2D textureCoord;    //纹理坐标CubePoint(const QVector3D& position = QVector3D(),const QVector2D& texture = QVector2D()):posCoord(position), textureCoord(texture) {}};

添加了立方体每个点的数据结构之后,我们就可以添加对应的坐标信息了。立方体的坐标示意图如下所示:

在程序中初始化各个顶点的位置信息和纹理信息:

//QVector<CubePoint> m_data;
//m_data是顶点信息的数据容器
void SimpleGLWindow::initializeCubeData()
{//正方体六个面对应的数据m_data = {// FRONT FACE{{-0.5, -0.5,  0.5}, {0, 0}},        {{ 0.5, -0.5,  0.5}, {1, 0}},{{ 0.5,  0.5,  0.5}, {1, 1}},        {{-0.5,  0.5,  0.5}, {0, 1}},// TOP FACE{{-0.5,  0.5,  0.5}, {0, 0}},        {{ 0.5,  0.5,  0.5}, {1, 0}},{{ 0.5,  0.5, -0.5}, {1, 1}},        {{-0.5,  0.5, -0.5}, {0, 1}},// BACK FACE{{-0.5,  0.5, -0.5}, {0, 0}},        {{ 0.5,  0.5, -0.5}, {1, 0}},{{ 0.5, -0.5, -0.5}, {1, 1}},        {{-0.5, -0.5, -0.5}, {0, 1}},// BOTTOM FACE{{-0.5, -0.5, -0.5}, {0, 0}},        {{ 0.5, -0.5, -0.5}, {1, 0}},{{ 0.5, -0.5,  0.5}, {1, 1}},        {{-0.5, -0.5,  0.5}, {0, 1}},// LEFT FACE{{-0.5, -0.5, -0.5}, {0, 0}},        {{-0.5, -0.5,  0.5}, {1, 0}},{{-0.5,  0.5,  0.5}, {1, 1}},        {{-0.5,  0.5, -0.5}, {0, 1}},// RIGHT FACE{{ 0.5, -0.5,  0.5}, {0, 0}},        {{ 0.5, -0.5, -0.5}, {1, 0}},{{ 0.5,  0.5, -0.5}, {1, 1}},        {{ 0.5,  0.5,  0.5}, {0, 1}},};
}

在initializeGL()中调用数据初始化方法:

void SimpleGLWindow::initializeGL()
{...//开启深度测试glEnable(GL_DEPTH_TEST);//开启剔除操作效果glEnable(GL_CULL_FACE);//禁用背面的的光照和阴影效果,避免不必要的计算glCullFace(GL_BACK);//初始化数据initializeCubeData();//设置刷新显示的时候的默认颜色为RGB(255,255,255)glClearColor(1, 1, 1, 0);
}

数据初始化完成之后,我们就可以在绘制方法中绘制立方体了,对应的绘制操作如下所示:

void SimpleGLWindow::paintGL()
{//清空颜色缓存和深度缓存glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//将OpenGL视口和窗口保持相同glViewport(0, 0, width(), height());//重置变换矩阵glLoadIdentity();//为了查看方便对视图进行旋转//m_angle是旋转的角度glRotatef(m_angle, 1.0, 0.0, 0.0);glRotatef(m_angle, 0.0, 1.0, 0.0);//绑定纹理if(m_texture){m_texture->bind();}//启动纹理glEnable(GL_TEXTURE_2D);//绘制立方体glBegin(GL_QUADS);for(const CubePoint &point: m_data) {glTexCoord2d(point.textureCoord.x(), point.textureCoord.y());glVertex3f(point.posCoord.x(), point.posCoord.y(), point.posCoord.z());}glEnd();//关闭纹理glDisable(GL_TEXTURE_2D);
}

绘制出来的效果如下所示:

立方体动画

上面方法绘制出来的立方体是静态的。为了让图形不那么单调,我们加一个定时器让立方体旋转起来,对应的实现如下所示:

SimpleGLWindow::SimpleGLWindow(QWindow *parent) :QOpenGLWindow(NoPartialUpdate, parent)
{//设置多采样的值QSurfaceFormat fmt = format();fmt.setSamples(25);setFormat(fmt);//设置定时器修改旋转的值QTimer* timer = new QTimer(this);timer->setInterval(30);connect(timer,&QTimer::timeout,this,[&](){m_angle+=1;this->update();});timer->start();
}

显示效果如下所示:

除了定时器外,我们还可以使用灵活度更高的动画框架来让立方体动起来,对应的设置如下:

//simpleglwindow.h
class SimpleGLWindow : public QOpenGLWindow, protected QOpenGLFunctions_1_1
{Q_OBJECTQ_PROPERTY(float angle READ angle WRITE setAngle)
public:qreal angle() const;void setAngle(const qreal &angle);
private:qreal m_angle = 60;...
};
//simpleglwindow.cpp
SimpleGLWindow::SimpleGLWindow(QWindow *parent) :QOpenGLWindow(NoPartialUpdate, parent)
{//设置多采样的值QSurfaceFormat fmt = format();fmt.setSamples(25);setFormat(fmt);QPropertyAnimation *animation = new QPropertyAnimation(this);animation->setTargetObject(this);animation->setPropertyName("angle");animation->setStartValue(0);animation->setEndValue(359);animation->setDuration(5000);animation->setLoopCount(-1);animation->setEasingCurve(QEasingCurve::InCubic);animation->start();
}
qreal SimpleGLWindow::angle() const
{return m_angle;
}void SimpleGLWindow::setAngle(const qreal &angle)
{m_angle = angle;this->update();
}

显示效果如下:

完整的工程代码,欢迎参考:

//simpleglwindow.h
#pragma execution_character_set("utf-8")#ifndef SIMPLEGLWINDOW_H
#define SIMPLEGLWINDOW_H#include <QOpenGLWindow>
#include <QOpenGLFunctions_1_1>
#include <QOpenGLTexture>
#include <QVector3D>
#include <QVector2D>
#include <QTimer>
#include <QObject>//使用的OpenGLFunction的版本是1.1
class SimpleGLWindow : public QOpenGLWindow, protected QOpenGLFunctions_1_1
{Q_OBJECTQ_PROPERTY(float angle READ angle WRITE setAngle)
public:SimpleGLWindow(QWindow *parent = 0);qreal angle() const;void setAngle(const qreal &angle);protected://初始化操作void initializeGL();//绘制函数void paintGL();protected://窗口尺寸变化的事件void resizeGL(int w, int h);private:void initialTexture();//初始化正方体的数据void initializeCubeData();//OpenGL纹理QOpenGLTexture* m_texture = nullptr;//纹理图片QImage* m_texture_image = nullptr;struct CubePoint {QVector3D posCoord;        //空间坐标QVector2D textureCoord;    //纹理坐标CubePoint(const QVector3D& position = QVector3D(),const QVector2D& texture = QVector2D()):posCoord(position), textureCoord(texture) {}};qreal m_angle = 60;QVector<CubePoint> m_data;
};#endif // SIMPLEGLWINDOW_H
//simpleglwindow.cpp
#include "simpleglwindow.h"
#include <QDebug>
#include <QPropertyAnimation>SimpleGLWindow::SimpleGLWindow(QWindow *parent) :QOpenGLWindow(NoPartialUpdate, parent)
{//设置多采样的值QSurfaceFormat fmt = format();fmt.setSamples(25);setFormat(fmt);QPropertyAnimation *animation = new QPropertyAnimation(this);animation->setTargetObject(this);animation->setPropertyName("angle");animation->setStartValue(0);animation->setEndValue(359);animation->setDuration(5000);animation->setLoopCount(-1);animation->setEasingCurve(QEasingCurve::InCubic);animation->start();//    QTimer* timer = new QTimer(this);
//    timer->setInterval(30);
//    connect(timer,&QTimer::timeout,this,[&](){m_angle+=1;this->update();});
//    timer->start();
}void SimpleGLWindow::initializeGL()
{//初始化OpenGL函数if (!initializeOpenGLFunctions()){qDebug() << "init opengl functions failed";}initialTexture();//开启深度测试glEnable(GL_DEPTH_TEST);//开启剔除操作效果glEnable(GL_CULL_FACE);//禁用背面的的光照和阴影效果,避免不必要的计算glCullFace(GL_BACK);initializeCubeData();//设置刷新显示的时候的默认颜色为RGB(255,255,255)glClearColor(1, 1, 1, 0);
}void SimpleGLWindow::paintGL()
{//清空颜色缓存和深度缓存glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//将OpenGL视口和窗口保持相同glViewport(0, 0, width(), height());//重置变换矩阵glLoadIdentity();//为了查看方便对视图进行旋转glRotatef(m_angle, 1.0, 0.0, 0.0);glRotatef(m_angle, 0.0, 1.0, 0.0);//绑定纹理if(m_texture){m_texture->bind();}//启动纹理glEnable(GL_TEXTURE_2D);glBegin(GL_QUADS);for(const CubePoint &point: m_data) {glTexCoord2d(point.textureCoord.x(), point.textureCoord.y());glVertex3f(point.posCoord.x(), point.posCoord.y(), point.posCoord.z());}glEnd();//关闭纹理glDisable(GL_TEXTURE_2D);
}void SimpleGLWindow::resizeGL(int w, int h)
{qDebug() << w << h;
}void SimpleGLWindow::initialTexture()
{//初始化图片和纹理m_texture_image = new QImage(":/background.jpg");m_texture = new QOpenGLTexture(m_texture_image->mirrored());//添加放大和缩小的时候的滤波器m_texture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);m_texture->setMagnificationFilter(QOpenGLTexture::Linear);
}void SimpleGLWindow::initializeCubeData()
{m_data = {// FRONT FACE{{-0.5, -0.5,  0.5}, {0, 0}},        {{ 0.5, -0.5,  0.5}, {1, 0}},{{ 0.5,  0.5,  0.5}, {1, 1}},        {{-0.5,  0.5,  0.5}, {0, 1}},// TOP FACE{{-0.5,  0.5,  0.5}, {0, 0}},        {{ 0.5,  0.5,  0.5}, {1, 0}},{{ 0.5,  0.5, -0.5}, {1, 1}},        {{-0.5,  0.5, -0.5}, {0, 1}},// BACK FACE{{-0.5,  0.5, -0.5}, {0, 0}},        {{ 0.5,  0.5, -0.5}, {1, 0}},{{ 0.5, -0.5, -0.5}, {1, 1}},        {{-0.5, -0.5, -0.5}, {0, 1}},// BOTTOM FACE{{-0.5, -0.5, -0.5}, {0, 0}},        {{ 0.5, -0.5, -0.5}, {1, 0}},{{ 0.5, -0.5,  0.5}, {1, 1}},        {{-0.5, -0.5,  0.5}, {0, 1}},// LEFT FACE{{-0.5, -0.5, -0.5}, {0, 0}},        {{-0.5, -0.5,  0.5}, {1, 0}},{{-0.5,  0.5,  0.5}, {1, 1}},        {{-0.5,  0.5, -0.5}, {0, 1}},// RIGHT FACE{{ 0.5, -0.5,  0.5}, {0, 0}},        {{ 0.5, -0.5, -0.5}, {1, 0}},{{ 0.5,  0.5, -0.5}, {1, 1}},        {{ 0.5,  0.5,  0.5}, {0, 1}},};
}qreal SimpleGLWindow::angle() const
{return m_angle;
}void SimpleGLWindow::setAngle(const qreal &angle)
{m_angle = angle;this->update();
}

采用QT进行OpenGL开发(二)绘制立方体相关推荐

  1. 基于Qt ffmpeg opengl开发跨平台安卓实时投屏软件

    [开源]基于Qt ffmpeg opengl开发跨平台安卓实时投屏软件 码云地址 https://gitee.com/Barryda/QtScrcpy github地址 https://github. ...

  2. 【OpenGL ES】绘制立方体

    1 前言 本文主要介绍使用 OpenGL ES 绘制立方体,读者如果对 OpenGL ES 不太熟悉,请回顾以下内容: 绘制三角形 绘制彩色三角形 绘制正方形 绘制圆形 在绘制立方体的过程中,主要用到 ...

  3. QT中OpenGL开发起步

    OpenGL中环境搭建 近期由于需要做一个GUI展示的OpenGL程序,因此想到用QT来做界面,需要在QT中写OpenGL,配完环境后,在这里总计一下. QT基础 总体看来,QT的版本较为混乱,有时候 ...

  4. QT+OpenGL实现Coordinate Systems,绘制立方体

    将learningopengl入门篇的Coordinate Systems代码在QT框架下实现,绘制一些带纹理贴图的动态立方体 目录 一.环境 二.代码实现 glm 着色器类 shader.h 着色器 ...

  5. Qt OpenGL(二十八)——Qt OpenGL 核心模式-绘制一个正方体(正六面体)

    Qt OpenGL(二十七)--Qt OpenGL 核心模式-绘制一个正方体(正六面体) 截止到上一篇文章,一川想使用Qt封装的类绘制一个旋转的彩色三角形的目标就实现了. 上一篇在介绍了使用变换矩阵的 ...

  6. Qt OpenGL(二十)——Qt OpenGL 核心模式版本

    Qt OpenGL(二十)--Qt OpenGL 核心模式版本 一.写在前面 在之前的OpenGL教程(1~19)中,采用的方式都是固定渲染管线,也就是OpenGL3.2版本之前的写法,但是OpenG ...

  7. android平台下OpenGL ES 3.0绘制立方体的几种方式

    OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...

  8. 《视觉开发专题》之 OpenGL 3D动画绘制图形学概念的理解

    知识前导 计算机图形学的终极目标--讨好人类视觉系统   最近在啃的书中有一本叫<计算机图形学 原理及实践>,这本书让我深有感触的是其绪论中对计算机构建真实感图像的理解:我们所致力的最终目 ...

  9. 【Qt】2D绘图之绘制图像(二)

    00. 目录 文章目录 00. 目录 01. 概述 02. 开发环境 03. 绘制QImage图像 04. 绘制QPixmap图像 05. 绘制QPicture图像 06. 综合对比 07. 附录 0 ...

最新文章

  1. 第一个小项目 - 去掉指定文件中的注释
  2. 单例带来的线程安全问题
  3. 公积金10万元,为何却不能贷款买房?
  4. 使用Oracle做定时任务
  5. C++学习之路 | PTA(天梯赛)—— L2-007 家庭房产 (25分)(带注释)(并查集)(精简)
  6. 我们很需要“企业即时通讯”
  7. 单列布局、两列布局、三列布局
  8. MFC中如何在CMainFrame类中访问CxxxView视图类中的成员
  9. Vijos P1199核弹危机
  10. 2013总结之“酒肉穿肠过,佛在心中坐”
  11. MSP430加密代码保护
  12. Apollo选型及优势介绍
  13. flash 磨损均衡处理
  14. SpringBoot部署
  15. 【全】各种颜色对应的 Hex code 和对应的 RGB 值
  16. POI之Word转化为Markdown-yellowcong
  17. springboot+shiro+redis+jwt实现多端登录:PC端和移动端同时在线(不同终端可同时在线)
  18. 推荐给互联网人的5个赛道
  19. Software Engineering at Google翻译-III-8-Style Guides and Rules(风格指南和规则 )
  20. P1_M4_L4 Longitudinal Vehicle Model(车辆纵向动力学建模)

热门文章

  1. easyui中linkbutton连续点击事件
  2. 使用了一段时间Linux虚拟机,突然ping www.baidu.com不通(NAT模式),ping 网关也ping不通
  3. 在线使用Python通过染色体id+位置查询基因名列表
  4. Awstats安装配置
  5. Prometheus+Node_exporter+Grafana监控(附送保姆级别linux安装攻略)
  6. 嵌入式计算机答辩标准,秦云川答辩公告
  7. DAO,Service,Controler的简介
  8. dumpsys使用详解
  9. 解决:Could not build wheels for pycocotools, which is required to install pyproject.toml-based
  10. 5g上行速率怎么提升_5G网络室内覆盖系统的解决方案解析