在上一篇文章中我们了解了 Assimp 这个库,但是只知道这个库只是作为一个加载的作用,并不清楚如何使用,这这一篇便是介绍 Assimp 的数据结构以及我们自己创建的两个为方便使用它而创建的类。
首先看一下 Assimp 的结构图:
Assimp 读取模型文件后,会将其加载到一套通用的数据结构中,如上图所示,首先是一个 Scene 对象,对象中包括了多个场景对象,各个对象以树状结构展开,而 Scene 中储存了根节点 mRootNode。mMeshes 和 mMatertials 则是存储了模型的 Mesh(网格:代表一个可绘制的实体)与 Material(材质)数据,每一个 Children(子节点) 包括了它的孩子节点集合和网格(Mesh)索引集合,注意 Child Node 中的 Mesh 集合中存储的是 Scene 对象里的 Mesh 数组的索引,也就是说具体数据是在 Scene 中存储的,这里只有索引。
除了 Scene 对象之外,便是代表具体网格数据的 Mesh 对象了,Mesh 对象存储了网格的顶点位置(mVertices)、法向量(mNormals)、纹理坐标(mTetureCoords)、面(mFaces)和物体的材质索引(mMaterialIndex),材质数据则是在在 Scene 对象的 mMaterials[] 中存储。
在了解了 Assimp 的通用数据结构后,我们就可以从 Scene 对象中接收数据了。首先构造一个我们自己的 Mesh 类,用来直接进行 Mesh 的绘制工作。在此之前仍需要定义好两个东西,Vertex 与 Texture 。
1 | struct Vertex { |
我们定义了公开的包括顶点 Vertex(顶点中定义了位置,法线等等),索引以及纹理,同时留下了构造方法以及 Draw 绘制接口 。而 Private 则是定义了我们在构造或者绘制过程中需要做的一些事。以下来看具体实现:
1 | Mesh::Mesh(std::vector<Vertex> vertices, std::vector<unsigned int> indices, std::vector<Texture> textures) { |
实现的内容没有多少难度,Mesh 的构造中就是复制以及我们之前学过的绑定顶点对象以及填充数据等, Draw 方法传入一个 Shader(着色器对象),并读取纹理贴图后为 Shader 对象的属性赋值以及绘制等。
暂时明白了 Mesh 的实现,接下来看看将 Scene 解析并将所有 Mesh 绘制的 Model 类:
1 | class Model { |
Mesh 中已经完成了对网格的操作,而在 Model 中我们的重点仅仅是将 Scene 的属性按照数据结构解析并赋给 Mesh 而已,我们留下了构造方法已经绘制函数,绘制函数很简单,就是遍历 meshes 数组,挨个调用 mesh 对象的 draw 方法就可以了。
1 | void Model::Darw(Shader shader) { |
而构造方法则是层层调用解析函数,最外层是 loadModel 方法,在 loadModel 里使用 Assimp 读取 obj 文件以及贴图文件的文件夹地址,然后调用解析节点方法(processNode):
1 | Model::Model(char *path, bool gamma) : gammaCorrection(gamma) { |
我们之前说了,每个节点中存放的是 Mesh 在 Scene 对象里的数组的索引和子节点,所以 processNode 的实现则是依据索引解析 Mesh 对象并将其保存到 Model 的 meshes 数组里,同时递归子节点。
1 | void Model::processNode(aiNode *node, const aiScene *scene) { |
解析 Mesh 对象则是使用了 processMesh 方法,里边的内容也不难考虑,即将 assimp 的 Mesh 里存放的数据挨个转移到我们自定义的 Mesh 类对象里,包括顶点数据 Vertex 对象以及材质 Texture 对象,而 assimp 的Mesh 类只有材质的索引属性,所以需要我们调用读取材质的方法(loadMaterialTextures):
1 | Mesh Model::processMesh(aiMesh *mesh, const aiScene *scene) { |
除此之外还有从 scene 对象里读取材质以及从文件里读取贴图的两个方法:
1 | std::vector<Texture> Model::loadMaterialTextures(aiMaterial *mat, aiTextureType type, std::string typeName) { |