# LearnOpenGL-03模型加载
3D建模工具:Blender、3DS MAX、Maya。这些工具在导出模型文件时自动生成顶点坐标、顶点法线和纹理坐标。
3D数据格式:
- obj:只包含了模型数据以及材质信息,像是模型颜色和漫反射/镜面光贴图。
- collada:模型、光照、多种材质、动画数据、摄像机、完整的场景信息。
# 模型加载库Assimp
当使用Assimp导入一个模型的时候,它通常会将整个模型加载进一个场景(Scene)对象,它会包含导入的模型/场景中的所有数据。
- 和材质和网格(Mesh)一样,所有的场景/模型数据都包含在Scene对象中。Scene对象也包含了场景根节点的引用。
- 场景的Root node(根节点)可能包含子节点(和其它的节点一样),它会有一系列指向场景对象中mMeshes数组中储存的网格数据的索引。Scene下的mMeshes数组储存了真正的Mesh对象,节点中的mMeshes数组保存的只是场景中网格数组的索引。
- 一个Mesh对象本身包含了渲染所需要的所有相关数据,像是顶点位置、法向量、纹理坐标、面(Face)和物体的材质。
- 一个网格包含了多个面。Face代表的是物体的渲染图元(Primitive)(三角形、方形、点)。一个面包含了组成图元的顶点的索引。由于顶点和索引是分开的,使用一个索引缓冲来渲染是非常简单的(见[你好,三角形](https://learnopengl-cn.github.io/01 Getting started/04 Hello Triangle/))。
- 最后,一个网格也包含了一个Material对象,它包含了一些函数能让我们获取物体的材质属性,比如说颜色和纹理贴图(比如漫反射和镜面光贴图)。
# 网格
网格Mesh 是绘制三维图形的基本单元,一个模型会包含多个mesh。
比如一个人物的模型。可能包含胳膊、腿、脑袋,这些是单独建模的。所以有一个场景节点的概念,场景根节点指向了若干mesh的索引。
绘制函数:
- 遍历模型的所有纹理,为每个纹理分配对应的OpenGL 纹理单元,并将纹理的单元编号传递给着色器中的材质变量。
- 绑定纹理到对应的纹理单元,让着色器能够正确采样纹理。
- 绑定顶点数组对象(VAO)并绘制网格的三角形面,完成模型的渲染。
# 模型
class Model
{
public:
/* 函数 */
Model(char *path)
{
loadModel(path);
}
void Draw(Shader shader);
private:
/* 模型数据 */
vector<Mesh> meshes;
string directory;
/* 函数 */
void loadModel(string path);
void processNode(aiNode *node, const aiScene *scene);
Mesh processMesh(aiMesh *mesh, const aiScene *scene);
vector<Texture> loadMaterialTextures(aiMaterial *mat, aiTextureType type,
string typeName);
};