写在前面
上一节Obj模型加载作为模型加载的基础篇,介绍了模型中Mesh的概念,以及从Obj模型文件转换为OpenGL数据格式的方法。上一节绘制的结果还是很简陋,本节将给出上节承诺的酷炫的3D模型的加载方法:)。本节示例程序均可以在我的github下载。
本节内容参考自
1.www.learnopengl.com Model loading
2.Loading models using the Open Asset Import Library
下载和安装AssImp
AssImp是一个模型加载库,它将不同格式的模型数据转换为统一的抽象的数据类型,因而支持较多的模型文件格式。下载和编译这个库的过程,你可以参考官方文档。这里也为Windows用户提供了编译好的lib和dll文件,可以从我的github下载。
AssImp的数据结构
AssImp的主要的类如下图所示:
这里对上述图作简要说明:
aiScene 作为AssImp加载模型的根数据结构,保存了从模型加载的顶点位置、法向量、纹理、光照等数据,例如它通过数组mMeshes保存Mesh数据,通过mMaterials保存材质数据。总之aiScene保存了加载的模型数据,其余类通过索引aiScene中存储的对象来获取对应的数据。
aiNode 模型通过层次结构存储,根节点mRootNode保存在aiScene中,根节点下面有0至多个子节点,每个节点通过aiNode类表达,aiNode中包含一个或者多个Mesh,注意这里的Mesh是对aiScene中Mesh数据的一个索引。
aiMesh是上一节中所讲的Mesh对象,Mesh中包含顶点位置数据、法向量、纹理数据,每个Mesh可以包含一个或者多个Face。
aiFace是一个面,一般来讲在读取模型时通过后处理选项(post-process flag)将模型转换为三角形网格,那么这里的面主要是三角形面。后处理选项稍后介绍。通过三角形面,我们可以获取渲染模型需要的索引数据。
OpenGL需要的数据结构
加载模型的任务就是将抽象的模型数据转换为OpenGL可以处理的VBO,EBO,纹理数据。在程序内部我们定义了Mesh,Model结构来作为内部格式。Mesh表达是绘制的最小实体,它包含顶点属性数据、材质数据;Model则是包含1个或者多个Mesh的模型。定义Mesh结构如下:
// 表示一个顶点属性
struct Vertex
{
glm::vec3 position;
glm::vec2 texCoords;
glm::vec3 normal;
};
// 表示一个Texture
struct Texture
{
GLuint id;
aiTextureType type;
std::string path;
};
// 表示一个用于渲染的最小实体
class Mesh
{
public:
void draw(const Shader& shader) const;// 绘制Mesh
Mesh():VAOId(0), VBOId(0), EBOId(0){}
Mesh(const std</