到目前为止的所有场景中,我们一直都在滥用我们的箱子朋友,但时间久了甚至是我们最好的朋友也会感到无聊。在日常的图形程序中,通常都会使用非常复杂且好玩的模型,它们比静态的箱子要好看多了。然而,和箱子对象不同,我们不太能够对像是房子、汽车或者人形角色这样的复杂形状手工定义所有的顶点、法线和纹理坐标。我们想要的是将这些模型(Model)导入(Import)到程序当中。模型通常都由3D艺术家在Blender、3DS Max或者Maya这样的工具中精心制作。

这些所谓的3D建模工具(3D Modeling Tool)可以让艺术家创建复杂的形状,并使用一种叫做UV映射(uv-mapping)的手段来应用贴图。这些工具将会在导出到模型文件的时候自动生成所有的顶点坐标、顶点法线以及纹理坐标。这样子艺术家们即使不了解图形技术细节的情况下,也能拥有一套强大的工具来构建高品质的模型了。所有的技术细节都隐藏在了导出的模型文件中。但是,作为图形开发者,我们就必须要了解这些技术细节了。

所以,我们的工作就是解析这些导出的模型文件以及提取所有有用的信息,将它们储存为OpenGL能够理解的格式。一个很常见的问题是,模型的文件格式有很多种,每一种都会以它们自己的方式来导出模型数据。像是Wavefront的.obj这样的模型格式,只包含了模型数据以及材质信息,像是模型颜色和漫反射/镜面光贴图。而以XML为基础的Collada文件格式则非常的丰富,包含模型、光照、多种材质、动画数据、摄像机、完整的场景信息等等。Wavefront的.obj格式通常被认为是一个易于解析的模型格式。建议至少去Wavefront的wiki页面上看看文件格式的信息是如何封装的。这应该能让你认识到模型文件的基本结构。

总而言之,不同种类的文件格式有很多,它们之间通常并没有一个通用的结构。所以如果我们想从这些文件格式中导入模型的话,我们必须要去自己对每一种需要导入的文件格式写一个导入器。很幸运的是,正好有一个库专门处理这个问题。

模型加载库

一个非常流行的模型导入库是Assimp,它是Open Asset Import Library(开放的资产导入库)的缩写。Assimp能够导入很多种不同的模型文件格式(并也能够导出部分的格式),它会将所有的模型数据加载至Assimp的通用数据结构中。当Assimp加载完模型之后,我们就能够从Assimp的数据结构中提取我们所需的所有数据了。由于Assimp的数据结构保持不变,不论导入的是什么种类的文件格式,它都能够将我们从这些不同的文件格式中抽象出来,用同一种方式访问我们需要的数据。

当使用Assimp导入一个模型的时候,它通常会将整个模型加载进一个场景(Scene)对象,它会包含导入的模型/场景中的所有数据。Assimp会将场景载入为一系列的节点(Node),每个节点包含了场景对象中所储存数据的索引,每个节点都可以有任意数量的子节点。Assimp数据结构的(简化)模型如下:

  • 和材质和网格(Mesh)一样,所有的场景/模型数据都包含在Scene对象中。Scene对象也包含了场景根节点的引用。
  • 场景的Root node(根节点)可能包含子节点(和其它的节点一样),它会有一系列指向场景对象中mMeshes数组中储存的网格数据的索引。Scene下的mMeshes数组储存了真正的Mesh对象,节点中的mMeshes数组保存的只是场景中网格数组的索引。
  • 一个Mesh对象本身包含了渲染所需要的所有相关数据,像是顶点位置、法向量、纹理坐标、面(Face)和物体的材质。
  • 一个网格包含了多个面。Face代表的是物体的渲染图元(Primitive)(三角形、方形、点)。一个面包含了组成图元的顶点的索引。由于顶点和索引是分开的,使用一个索引缓冲来渲染是非常简单的。
  • 最后,一个网格也包含了一个Material对象,它包含了一些函数能让我们获取物体的材质属性,比如说颜色和纹理贴图(比如漫反射和镜面光贴图)。

所以,我们需要做的第一件事是将一个物体加载到Scene对象中,遍历节点,获取对应的Mesh对象(我们需要递归搜索每个节点的子节点),并处理每个Mesh对象来获取顶点数据、索引以及它的材质属性。最终的结果是一系列的网格数据,我们会将它们包含在一个Model对象中。

网格

当使用建模工具对物体建模的时候,艺术家通常不会用单个形状创建出整个模型。通常每个模型都由几个子模型/形状组合而成。组合模型的每个单独的形状就叫做一个网格(Mesh)。比如说有一个人形的角色:艺术家通常会将头部、四肢、衣服、武器建模为分开的组件,并将这些网格组合而成的结果表现为最终的模型。一个网格是我们在OpenGL中绘制物体所需的最小单位(顶点数据、索引和材质属性)。一个模型(通常)会包括多个网格。

在下一节中,我们将创建我们自己的Model和Mesh类来加载并使用刚刚介绍的结构储存导入后的模型。如果我们想要绘制一个模型,我们不需要将整个模型渲染为一个整体,只需要渲染组成模型的每个独立的网格就可以了。然而,在我们开始导入模型之前,我们首先需要将Assimp包含到我们的工程当中。

构建Assimp

你可以在Assimp的下载页面中选择相应的版本。在写作时使用的Assimp最高版本为3.1.1。我们建议你自己编译Assimp库,因为它们的预编译库在大部分系统上都是不能运行的。如果你忘记如何使用CMake自己编译一个库的话,可以复习创建窗口小节。

构建Assimp时可能会出现一些问题,所以我会将它们的解决方案列在这里,便于大家排除错误:

  • CMake在读取配置列表时,不断报出DirectX库丢失的错误。报错如下:
Could not locate DirectX
CMake Error at cmake-modules/FindPkgMacros.cmake:110 (message):
Required library DirectX not found! Install the library (including dev packages)
and try again. If the library is already installed, set the missing variables
manually in cmake.

这个问题的解决方案是安装DirectX SDK,如果你之前没安装过的话。你可以从这里下载SDK。

  • 安装DirectX SDK时,可能遇到一个错误码为s1023的错误。这种情况下,请在安装SDK之前根据这个先卸载C++ Redistributable package(s)。
  • 一旦配置完成,你就可以生成解决方案文件了,打开解决方案文件并编译Assimp库(可以编译为Debug版本也可以编译为Release版本,只要能工作就行)。
  • 使用默认配置构建的Assimp是一个动态库(Dynamic Library),所以我们需要包含所生成的assimp.dll文件以及程序的二进制文件。你可以简单地将DLL复制到我们程序可执行文件的同一目录中。
  • Assimp编译之后,生成的库和DLL文件位于code/Debug或者code/Release文件夹中。
  • 接着把编译好的LIB文件和DLL文件拷贝到工程的相应目录下,并在解决方案中链接它们。并且记得把Assimp的头文件也复制到你的include目录中(头文件可以在从Assimp中下载的include目录里找到)。

如果你仍遇到了未报告的错误,欢迎在评论区中寻求帮助。

如果你想让Assimp使用多线程来获得更高的性能,你可以使用Boost库来编译Assimp。你可以在它们的安装页面找到完整的安装介绍。

现在,你应该已经编译完Assimp库并将它链接到你的程序中了。下一步:导入漂亮的3D物体!

OPenGL 学习笔记之 Assimp 知识相关推荐

  1. OpenGL学习笔记:矩阵变换

    文章目录 缩放 glm矩阵表示 glm缩放矩阵实现 位移 齐次坐标 glm位移矩阵实现 旋转 沿x轴旋转 沿y轴旋转 沿z轴旋转 沿任意轴旋转 glm旋转矩阵实现 矩阵的组合 glm矩阵组合使用 接上 ...

  2. 【OpenGL学习笔记⑧】——键盘控制正方体+光源【冯氏光照模型 光照原理 环境光照+漫反射光照+镜面光照】

    ✅ 重点参考了 LearnOpenGL CN 的内容,但大部分知识内容,小编已作改写,以方便读者理解. 文章目录 零. 成果预览图 一. 光照原理与投光物的配置 1.1 光照原理 1.2 投光物 二. ...

  3. php基础教学笔记,php学习笔记:基础知识

    php学习笔记:基础知识 2.每行结尾不允许有多余的空格 3.确保文件的命名和调用大小写一致,是由于类Unix系统上面,对大小写是敏感的 4.方法名只允许由字母组成,下划线是不允许的,首字母要小写,其 ...

  4. 数据挖掘学习笔记 5 线性回归知识及预测糖尿病实例

    #2018-03-21 16:45:01 March Wednesday the 12 week, the 080 day SZ SSMR http://blog.csdn.net/eastmount ...

  5. OpenGL学习笔记(一)绘制点线面及多面体

    OpenGL学习笔记(一)绘制点线面及多面体 绘制点线面 #include <iostream> #include <GL/GLUT.h> #define PI 3.14159 ...

  6. 【学习笔记--FMCW基础知识】

    学习笔记--FMCW基础知识 前言 mmWave测距原理 mmWave区分多个物体 mmWave的距离分辨率(Range Solution) mmWave的最大测量距离 前言 由于工作原因需要了解TI ...

  7. 好记性不如烂笔头-linux学习笔记4apache相关知识

    好记性不如烂笔头-linux学习笔记4apache相关知识 apache 启动有2种模式 1是prefork模式,每个进程对应一个线程,如果是比较稳定的平台,那么prefork模式是worker模式 ...

  8. OpenGL学习笔记(一):环境搭建、三维空间坐标系理解以及OpenGL的基本使用

    原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7866 ...

  9. OPENGL学习笔记之八

    OPENGL学习笔记之八 2017/11/15 阅读材料来自learnopengl.com以及learnopengl-cn.github.io 我们通常会自己设定一个坐标的范围,之后再在顶点着色器中将 ...

  10. 【OpenGL学习笔记】地月系

    OpenGL学习笔记2-地月系 文章目录 OpenGL学习笔记2-地月系 前言 运行结果 纹理图片 一.TexturePool 1.**TexturePool.h** 2.**TexturePool. ...

最新文章

  1. 字符串全排列的问题 python和c语言实现
  2. 怎么快速搜索服务器里的文件,Windows中快速搜索指定文件夹
  3. android socket ppt,socket網路設計.ppt
  4. Leetcode题库 94.二叉树的中序遍历(递归 C实现)
  5. 应用程序无法启动_Windows 10触发启动应用程序警报,以避免系统变慢
  6. php算法台阶,php如何解决青蛙跳台阶的问题(代码)
  7. 怎么格式化电脑_U盘格式化后数据能恢复吗?人人都能学会的恢复方法!
  8. Java中ArrayList类的用法
  9. XML文件解析--Python
  10. dbeaver 设置编码_DBeaver 一个神奇的数据库操作软件
  11. SourceAnalysis/Binder源码分析.md
  12. 流式上传文件到服务器磁盘,通过HTTP将数据从浏览器流式传输到服务器的方法...
  13. 维盟路由器pppoe服务配置(价值80元的帖子)
  14. 01 初识微信小程序
  15. python爬虫-京东全网搜索
  16. 开源一款苹果 macOS 工具 - AppleParty(苹果派)
  17. 阿里云实人认证生成签名SignNature工具类
  18. 关于九宫格的一个算法,求大神助攻
  19. P3386二分图最大匹配模版
  20. c语言指针一步错步步错,一步错步步错经典句子

热门文章

  1. 3d打印英语文献_万华推出可3D打印PP粉末材料
  2. php 图片底色替换,手把手教你替换相片中的颜色(给相片换底色)
  3. C语言数字图像处理---1.3 图像直方图
  4. 计算机网络专业以后装网线,安装了1000M宽带后,您就不必再上网了吗?千兆宽带有多快?...
  5. 率先驶入广州,百度Apollo“整车无人”车队街头开跑
  6. 油管上最火的java面试题集合
  7. jQuery表格新增行
  8. 制作macOS苹果电脑U盘启动盘
  9. 最新 Hostinger域名转出教程 (2019年6月版本)
  10. HTML基础(一)HTML标签