# 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的索引。

绘制函数:

  1. 遍历模型的所有纹理,为每个纹理分配对应的OpenGL 纹理单元,并将纹理的单元编号传递给着色器中的材质变量。
  2. 绑定纹理到对应的纹理单元,让着色器能够正确采样纹理。
  3. 绑定顶点数组对象(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);
};
Last Updated: 1/30/2026, 8:32:15 AM