3-3模型

39 阅读2分钟

Model类包含Mesh对象的vector,构造函数需要一个文件路径来加载模型

class Model 
{
public:
    Model(char *path)
    {
    loadModel(path); //加载模型路径
    } 
    void Draw(Shader shader);
private: 
    vector<Mesh> meshes; //meshVector
    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); 
    };
    

其中draw函数通过for循环所有mesh来画

void Draw(Shader &shader)
{ 
    for(unsigned int i = 0; i < meshes.size(); i++) 
    meshes[i].Draw(shader); 
}
  • aiProcess_GenNormals:如果模型不包含法向量的话,就为每个顶点创建法线。
  • aiProcess_SplitLargeMeshes:将比较大的网格分割成更小的子网格,如果你的渲染有最大顶点数限制,只能渲染较小的网格,那么它会非常有用。
  • aiProcess_OptimizeMeshes:和上个选项相反,它会将多个小网格拼接为一个大的网格,减少绘制调用从而进行优化。

加载模型函数

void loadModel(string path) 
{ 
    Assimp::Importer import; 
    const aiScene *scene = import.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);//读取文件路径
    //如果读取失败报错
    if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) 
    { 
        cout << "ERROR::ASSIMP::" << import.GetErrorString() << endl;
        return; 
    }
    directory = path.substr(0, path.find_last_of('/'));//找到最后一个下划线
    processNode(scene->mRootNode, scene); //进行递归
}

使用processNode函数处理所有网格,对所有子节点重复过程

void processNode(aiNode *node, const aiScene *scene)
{ 
    for(unsigned int i = 0; i < node->mNumMeshes; i++) //循环所有mesh
    { 
        aiMesh *mesh = scene->mMeshes[node->mMeshes[i]];
        meshes.push_back(processMesh(mesh, scene)); //加入vector
    } 
    for(unsigned int i = 0; i < node->mNumChildren; i++) 
    { 
        processNode(node->mChildren[i], scene); //递归所有子节点
    } 
}

然后将aiMesh对象转化为自己的mesh对象,访问所有属性后保存为自己的对象

分别处理顶点数据,法线和坐标纹理

然后循环所有mesh的face,遍历所有面,并储存face的索引

for(unsigned int i = 0; i < mesh->mNumFaces; i++) 
{ 
    aiFace face = mesh->mFaces[i];//遍历所有face
    for(unsigned int j = 0; j < face.mNumIndices; j++) 
        indices.push_back(face.mIndices[j]);
}

同理,再从mMaterialIndex属性中找出mesh的材质,并将信息储存在vector中