Learn OpenGL with Qt——模型加载:Qt搭建Assimp环境

2023-10-27

如果你是中途开始学习本教程的,即使你对OpenGL已经非常熟悉,请至少了解以下几个章节,因为Qt中提供了OpenGL的很多便捷操作,熟悉这些操作可以让我们在Qt中高效的使用OpenGL进行绘图。

创建OpenGL窗口

着色器程序以及着色器的创建

纹理的创建与加载

使用Qt内置矩阵进行变换

针对Qt窗口的摄像机优化

Qt下OpenGL的必备知识及易错点

Assimp

到目前为止,我们已经在所有的场景中大面积滥用了我们的容器盒小盆友,但就是容器盒是我们的好朋友,时间久了我们也会喜新厌旧。一些图形应用里经常会使用很多复杂且好玩儿的模型,它们看起来比静态的容器盒可爱多了。但是,我们无法像定义容器盒一样手动地去指定房子、货车或人形角色这些复杂模型的顶点、法线和纹理坐标。我们需要做的也是应该要做的,是把这些模型导入到应用程序中,而设计制作这些3D模型的工作应该交给像Blender3DS Max或者Maya这样的工具软件。

那些3D建模工具,可以让美工们构建一些复杂的形状,并将贴图应用到形状上去,即纹理映射。然后,在导出模型文件时,建模工具会自己生成所有的顶点坐标、顶点法线和纹理坐标。这样,美工们可以不用了解大量的图像技术细节,就能有大量的工具集去随心地构建高品质的模型。所有的技术细节内容都隐藏在里导出的模型文件里。而我们,这些图形开发者,就必须得去关注这些技术细节了。

因此,我们的工作就是去解析这些导出的模型文件,并将其中的模型数据存储为OpenGL能够使用的数据。一个常见的问题是,导出的模型文件通常有几十种格式,不同的工具会根据不同的文件协议把模型数据导出到不同格式的模型文件中。有的模型文件格式只包含模型的静态形状数据和颜色、漫反射贴图、高光贴图这些基本的材质信息,比如Wavefront的.obj文件。而有的模型文件则采用XML来记录数据,且包含了丰富的模型、光照、各种材质、动画、摄像机信息和完整的场景信息等,比如Collada文件格式。Wavefront的obj格式是为了考虑到通用性而设计的一种便于解析的模型格式。建议去Wavefront的Wiki上看看obj文件格式是如何封装的。这会给你形成一个对模型文件格式的一个基本概念和印象。

模型加载库

现在市面上有一个很流行的模型加载库,叫做Assimp,全称为Open Asset Import Library。Assimp可以导入几十种不同格式的模型文件(同样也可以导出部分模型格式)。只要Assimp加载完了模型文件,我们就可以从Assimp上获取所有我们需要的模型数据。Assimp把不同的模型文件都转换为一个统一的数据结构,所有无论我们导入何种格式的模型文件,都可以用同一个方式去访问我们需要的模型数据。

当导入一个模型文件时,即Assimp加载一整个包含所有模型和场景数据的模型文件到一个scene对象时,Assimp会为这个模型文件中的所有场景节点、模型节点都生成一个具有对应关系的数据结构,且将这些场景中的各种元素与模型数据对应起来。下图展示了一个简化的Assimp生成的模型文件数据结构:

 

  • 所有的模型、场景数据都包含在scene对象中,如所有的材质和Mesh。同样,场景的根节点引用也包含在这个scene对象中
  • 场景的根节点可能也会包含很多子节点和一个指向保存模型点云数据mMeshes[]的索引集合。根节点上的mMeshes[]里保存了实际了Mesh对象,而每个子节点上的mMesshes[]都只是指向根节点中的mMeshes[]的一个引用(译者注:C/C++称为指针,Java/C#称为引用)
  • 一个Mesh对象本身包含渲染所需的所有相关数据,比如顶点位置、法线向量、纹理坐标、面片及物体的材质
  • 一个Mesh会包含多个面片。一个Face(面片)表示渲染中的一个最基本的形状单位,即图元(基本图元有点、线、三角面片、矩形面片)。一个面片记录了一个图元的顶点索引,通过这个索引,可以在mMeshes[]中寻找到对应的顶点位置数据。顶点数据和索引分开存放,可以便于我们使用缓存(VBO、NBO、TBO、IBO)来高速渲染物体。(详见Hello Triangle
  • 一个Mesh还会包含一个Material(材质)对象用于指定物体的一些材质属性。如颜色、纹理贴图(漫反射贴图、高光贴图等)

所以我们要做的第一件事,就是加载一个模型文件为scene对象,然后获取每个节点对应的Mesh对象(我们需要递归搜索每个节点的子节点来获取所有的节点),并处理每个Mesh对象对应的顶点数据、索引以及它的材质属性。最终我们得到一个只包含我们需要的数据的Mesh集合。

用建模工具构建物体时,美工通常不会直接使用单个形状来构建一个完整的模型。一般来说,一个模型会由几个子模型/形状组合拼接而成。而模型中的那些子模型/形状就是我们所说的一个网格。例如一个人形模型,美工通常会把头、四肢、衣服、武器这些组件都分别构建出来,然后在把所有的组件拼合在一起,形成最终的完整模型。一个网格(包含顶点、索引和材质属性)是我们在OpenGL中绘制物体的最小单位。一个模型通常有多个网格组成。

获取Assimp

方式一:官网:http://assimp.sourceforge.net/main_downloads.html

方式二(推荐):博主的蓝奏云网盘资源:https://italink.lanzous.com/icylqcf

因为Assimp官方的已编译库不能很好地覆盖在所有平台上运行,我们需要借助CMake来重新编译一个当前环境能够使用的库。

因此,你还需要一个CMake(同样你可以点击这里,下载博主的Cmake资源)

构建Assimp

博主的Qt使用的是32位MinGw编译,因此需要构建一个专门的assimp库。

步骤:

1、添加Cmake/bin环境变量:把刚刚下载的Cmake安装好,把安装目录下的/bin目录添加到系统环境变量,配置成功后,使用cmd输入cmake可以看到一系列指令,说明配置成功。

2、添加MinGW环境变量:Qt的根目录下./Tool/mingw530_32/bin目录也添加到环境变量中,添加成功能在cmd中使mingw32-make指令

3、使用cmake构建Assimp库:

编辑指令:将下方指令中的路径修改为你本地Qt的MinGW路径:

cmake -G "MinGW Makefiles" -DENABLE_BOOST_WORKAROUND=ON -DBUILD_STATIC_LIB=ON -DCMAKE_RC_COMPILER=E:/Qt5.10.0/Tools/mingw530_32/bin/windres.exe -DCMAKE_MAKE_PROGRAM=E:/Qt5.10.0/Tools/mingw530_32/bin/mingw32-make.exe -DCMAKE_LFLAGS=-static -DCMAKE_LFLAGS_DLL=-static -DDX9_INCLUDE_PATH=E:/Qt5.10.0/Tools/mingw530_32/i686-w64-mingw32/include -DD3D9_LIBRARY=E:/Qt5.10.0/Tools/mingw530_32/i686-w64-mingw32/lib/libd3d9.a -DD3DX9_LIBRARY=E:/Qt5.10.0/Tools/mingw530_32/i686-w64-mingw32/lib/libd3dx9.a .

cd到Assimp的根目录,粘贴上方修改后的指令,回车运行。

构建完成后,不要关闭控制台窗口,进行下一步。

4、使用MinGW编译上面的Assimp库:

输入如下指令

mingw32-make -j 4

然后开始编译,如果你编译中途出错 ,可能是你对Assimp库进行了不正当的操作,可以把assimp删了,重新解压一个出来。

中途停住了,可以敲几下回车。

出现上图的情况,说明我们的Assimp已经可以使用了!

在项目中使用Assimp库

这里我重新创建一个QWidget项目用于测试

右键项目名——添加库——外部库

库文件为:...\assimp-4.1.0\lib\libassimp.dll.a

包含路径为:...\assimp-4.1.0\include

 然后我们就成功导入Assimp库了,导入之后pro项目文件增加了

 然后在main.cpp中使用一个Assimp对象看看

#include "widget.h"
#include <QApplication>

#include <assimp/Importer.hpp>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    Assimp::Importer importer;
    return a.exec();
}

运行没出错就说明成功导入

如果崩溃了,说明你可能需要手动导入一下dll

将assimp4.1.0/bin/目录下的两个dll

复制到你的项目生成目录 比如你是debug模式运行,把dll复制到如下目录中

注意初次导入库可能会导致代码提示功能没有更新,需要重新打开一下QtCreator

好了,现在我们已经能够使用Assimp库了,下一节我们将开始使用Assimp来导入3D模型。

 

结语

笔者在完成这一节的教程真可谓是一波未平一波又起,learnopengl的网站不知怎么的,这几天进不去,而且原learnOpenGL所封装的模型加载库并不适用于Qt,因此需要做很多调整,耽搁了几天。废话不多说,下节我们来玩个好玩的东西!

Assimp环境的配置十分感谢下面两位博主的博文!

https://blog.csdn.net/qq_31615919/article/details/80480497

https://blog.csdn.net/gamesdev/article/details/26969559

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Learn OpenGL with Qt——模型加载:Qt搭建Assimp环境 的相关文章

  • SQLServer JDBC 驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接

    网上有不少人遇到过使用jdbc连接sqlserver出错的情况 错误信息为 Caused by com microsoft sqlserver jdbc SQLServerException 驱动程序无法通过使用安全套接字层 SSL 加密与
  • 大数据开发教程——MapReduce原理及编程

    什么是MapReduce MapReduce是一种编程模型 用于大规模数据集 大于1TB 的并行运算 概念 Map 映射 和 Reduce 归约 是它们的主要思想 都是从函数式编程语言里借来的 还有从矢量编程语言里借来的特性 MapRedu
  • protobuf版本冲突问题解决

    1 proto caffe pb h 17 2 error error This file was generated by an older version of protoc 如果你装有anaconda 以及tensorflow 或者在
  • 【软件测试】—— 基础知识总结

    目录 基础篇 1 什么是软件测试 2 软件测试的目的 3 软件测试与软件开发的区别 概念篇 1 什么是需求 2 需求是软件测试的依据 3 测试用例 4 什么是BUG 5 开发模型 5个模型 1 瀑布模型 2 螺旋模型 3 4 增量模型 迭代
  • 继续谈下调用约定

    继续谈下调用约定 今天写了个DLL是用extern C 导出的 以前一直用 def文件 结果出现了以下错误 无法解析的外部符号 declspec dllimport int cdecl SetStatus int imp SetStatus
  • 原生js jquery设置输入框不可编辑,attr、prop对比

    1 设置输入框不可编辑 点击switch按钮 输入框可编辑和不可编辑切换 p E mail p
  • 期权是什么?一分钟带你玩转期权策略!

    很多人问我期权是什么 这个问题怎么回答呢 首先期权是一种交易模式 如同股票期货一样 但它又不同于股票和期货 因为它有自己的交易规则和特性 期权更多是一种工具 可以做空大盘对冲下跌风险 下文解答期权是什么 一分钟带你玩转期权策略 本文来自 期
  • 使用Python的requests库与chatGPT进行通信

    前言 在人工智能领域 自然语言处理模型如OpenAI GPT 3 5 Turbo具有广泛的应用 虽然官方提供了Python库来与这些模型进行交互 但也有一些人更喜欢使用requests库来自定义请求和处理响应 比如现在很多第三方LLM都提供
  • epoll 相对于select的优势

    epoll 相对于select的优势 分类 LinuxKnowHow 819 0 举报 收藏 这个问题至今才去查 是因为我需要用的地方真的不是很多 学习了那么多年 不知道自己究竟学了什么 觉得自己的优势就是针对特定知识点都熟悉点 一整套的软
  • 微信小程序支付踩坑notify_url(支付回调)

    最近做了微信小程序支付 支付成功之后发现notify url回调地址竟然没有访问 检查了无数次代码 下单结果里面的回调地址看了又看 都没有错啊 把回调地址复制出来到浏览器上面 外网也是可以访问的啊 然后我再分析 为什么以前公众号支付都没有出
  • Rust - 简单使用 reqwest 发起 HTTP 请求

    Rust 简单使用 reqwest 发起 HTTP 请求 一 reqwest 是什么 二 使用 reqwest 发起请求 1 在 Cargo tom 添加依赖 2 main rs 三 文章参考 一 reqwest 是什么 reqwest 是
  • Lua调用Unity完成登入注册

    今天的内容是用Lua调用Unity完成登入注册 这里只是完成了一个很简单的功能哦 注意哦 这里间的Lua文件放在同一个过程的同一个文件夹下 这里用到了一个Lua模块 a CS UnityEngine Lua调用C 需要这个前缀 One fu
  • 项目管理软件dhtmlxGantt配置教程(十):如何设置时间和范围

    1 时间单位 要设置比例的单位 请使用相应比例对象中的unit属性 可能的值是 分钟 小时 天 周 季度 月 年 gantt config scales unit month step 1 format F Y unit day step
  • vue路由history模式刷新页面出现404问题

    vue hash模式下 URL中存在 用 history 模式就能解决这个问题 但是history模式会出现刷新页面后 页面出现404 解决的办法是用nginx配置一下 在nginx的配置文件中修改 方法一 server listen 90
  • oracle中nextday,Oracle日期函数 next_day

    Oracle日期函数 next day 在Oracle是提供了next day求指定日期的下一个日期 语法 next day date weekday date is used to find the next weekday weekda
  • TCP/IP的层次结构以及各层数据封装的过程 (一)

    参考文献 TCP IP详解 卷1 协议 Tcp ip协议的四个层次 在以上的图中 FTP属于应用层的协议 TCP UDP属于运输层的协议 在TCP IP协议族中 网络层IP提供的是一种不可靠的服务 它尽可能的把分组从源节点送到目的节点 但是
  • libevent源码学习(9):事件event

    目录 在event之前需要知道的event base event结构体 创建 注册一个event 向event base中添加一个event 设置event的优先级 激活一个event 删除一个event 获取指定event的状态 纯超时e
  • AD覆铜技巧、连接类型问题。

    首先先说说连接的问题 如过孔的连接主要分两种 一直是直接连接的过孔 另一种就是梅花孔 或十字孔 那么这两种连接有什么特别的地方呢 直接连接 使过孔或者焊盘与覆铜层接触面积更大 可以将整块铜层作为器件的散热板 易于散热 适合连接一些大功率 发
  • js实现todolist总结

    首先在网页布局设置好的情况下 进行js文件的编写 要求实现增加 删除 和实时变化 其实这都可以在存在浏览器的本地存储中 下面先列出我的html页面及css文件内容

随机推荐

  • 众享比特中标中电投电力工程有限公司区块链项目

    近日 众享比特中标中电投电力工程有限公司的区块链系统在建设项目档案中跨企业认证应用项目 众享比特将与中电投电力工程有限公司展开密切合作 应用区块链技术助力其实现工程建设档案在项目公司 监理单位 总承包单位 施工单位等跨企业认证 破解数字化档
  • 中尺度混凝土二维有限元求解——运行弯曲、运行光盘、运行比较、运行半圆形(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现 1 概述 中尺度混凝土二维有限元求解是一种常见的工程
  • 天平数学,12个球称3次

    天平数学 12个球称3次 问题 天平数学问题 有12个外观完全一样的球 其中有一个球和其他球的重量不一致 如何使用一个天平称3次得出不一致的球是哪个 解答 方法一 12个球 1 2 3 4 5 6 7 8 9 10 11 12 第一次 1
  • Android studio4.0 内嵌 UnityActivity

    Android studio4 0 内嵌 UnityActivity 用最简单方法嵌入UnityActivity 首先 得导出Unity Android工程 其次 新建android studio工程 排错 感言 问题 用最简单方法嵌入Un
  • 03系统多界面_秒懂:海湾JB-QB-GST200报警控制器系统调试步骤

    海湾JB QB GST200报警控制器系统调试步骤 此调试步骤可用于海湾消防JB QB GST200壁挂式火灾报警控制器 联动型 JB QB GST200立柜式火灾报警控制器 联动型 JB QB GST200琴台式火灾报警控制器 联动型 一
  • 报错处理(收集)

    1 vue axios 报错 Uncaught in promise TypeError Cannot convert undefined or null to object at Function keys
  • c++11 多线程支持 (std::shared_future)

    定义于头文件
  • 基于MYCAT的MYSQL主从与读写分离配置详解与示例

    原文地址 http blog csdn net dreamcode article details 49511833 第三版 基于Mycat的MySQL主从读写分离配置详解与示例 完整文章下载地址 http download csdn ne
  • R语言回归模型中的训练集和测试集划分

    训练集和测试集划分 set seed 1234 nn 0 8 data iris length iris 1 sub lt sample 1 nrow data round nrow data nn length sub data trai
  • Word‘由于宏安全设置 无法找到宏’问题解决

    针对这个问题 尝试试很多网上的做法无果后 意外发现是自己电脑的杀毒软件把该文件误认为是病毒隔离起来 只需将其恢复到信任区即可 若仍无法解决 检查word是否启用宏
  • 我靠TikTok抖音赚到了人生第一桶金:这个风口行业,真的很赚钱

    现代人的 懒 简直超乎你想象 吃饭靠外卖 买东西靠快递 凡是一切你能想到的 麻烦 现代科技都能替你搞定 而这 恰恰是一种新型的赚钱方式 十年前的淘宝被人嘲笑 说这是马云的异想天开 十年后的淘宝 拼多多 京东告诉你 这一切都已成真 而且带着一
  • 虚拟机迁移原理

    我们常常遇到需要迁移虚拟机的问题 比如需要维护某台设备 会将设备上的一切应用迁移到另一台设备 但是如何将虚拟机进行迁移呢 好比说 虚拟机中正在运行一个程序 这个程序有源源不断的数据访问 怎么使得在不影响这些访问的情况下把虚拟机迁移到领一台服
  • C语言图形库——EasyX常用函数

    上节讲到贴出一张图片的过程 本节接着介绍一些基本的图形库函数 头文件 include
  • 深入浅出SSD--5.1PCIE基础知识

    深入浅出SSD 5 1PCIE基础知识 1 关于PCIE的速度 SSD使用PCIe接口比SATA快 下面是PCIE1 0 2 0 3 0速度 表中的带宽 比如PCIe3 0 1 带宽为2GB s 是指双向带宽 即读写带宽 如果单指读或者写
  • 本周最新文献速递20220522

    本周最新文献速递20220522 一 精细解读文献 一 文献题目 Single nucleus chromatin accessibility profiling highlights regulatory mechanisms of co
  • xml转换word文档

    点击下载 download value flag let this this this axios method get url url lengthMeasurementTwice params machineId this machin
  • http请求头origin、referer和host区别

    1 Host 描述请求将被发送的目的地 包括且仅仅包括域名和端口号 HTTP 1 1 的所有请求报文中必须包含一个Host头字段 且只能设置一个 2 Origin 请求头origin表明了请求来自于哪个站点 包括且仅仅包括协议 域名和端口
  • 创维机顶盒E900刷LinuxNas系统

    家里有一个一直没用的创维E900的机顶盒 芯片是海思 hi3798v100 的 本着废物利用的原则 我想将他刷成linux 没想到网上真的有教程 https histb com 我看了一下 以我现在的技术 问题不大 大不了变砖罢了 反正都是
  • js 中数字小数点末尾的0显示与否

    js 中数字小数点末尾的0显示与否 不显示0 显示0 数字格式化 不显示0 我们先来看一道例题 然后围绕其展开 零 的讨论 问题 得到一个随机数组成的数组 数组长度为10 结果类似于 0 243 0 162 0 701 0 501 此处封装
  • Learn OpenGL with Qt——模型加载:Qt搭建Assimp环境

    如果你是中途开始学习本教程的 即使你对OpenGL已经非常熟悉 请至少了解以下几个章节 因为Qt中提供了OpenGL的很多便捷操作 熟悉这些操作可以让我们在Qt中高效的使用OpenGL进行绘图 创建OpenGL窗口 着色器程序以及着色器的创