模型model

模型model, 封装一个包含渲染的基础数据

  1. 模型

    拥有的功能: 1.从模型文件加载、2.解析模型文件(顶点数据,贴图数据等)3.绘制功能的封装。

        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);
        };
    1. 从文件导入

      借助assimp插件

      #include <assimp/Importer.hpp>
      #include <assimp/scene.h>
      #include <assimp/postprocess.h>
      Assimp::Importer importer;
      const aiScene *scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);
      。。。
    2. 解析数据

      glm::vec3 vector; 
      //position
      vector.x = mesh->mVertices[i].x;
      vector.y = mesh->mVertices[i].y;
      vector.z = mesh->mVertices[i].z; 
      vertex.Position = vector;
      //normal
      vector.x = mesh->mNormals[i].x;
      vector.y = mesh->mNormals[i].y;
      vector.z = mesh->mNormals[i].z;
      vertex.Normal = vector;
      //TextureCoord
      if(mesh->mTextureCoords[0]) // 网格是否有纹理坐标?
      {
          glm::vec2 vec;
          vec.x = mesh->mTextureCoords[0][i].x; 
          vec.y = mesh->mTextureCoords[0][i].y;
          vertex.TexCoords = vec;
      }
      else
          vertex.TexCoords = glm::vec2(0.0f, 0.0f);
      // 。。。。
      //三角形
      for(unsigned int i = 0; i < mesh->mNumFaces; i++)
      {
          aiFace face = mesh->mFaces[i];
          for(unsigned int j = 0; j < face.mNumIndices; j++)
              indices.push_back(face.mIndices[j]);
      }
      //纹理
      if(mesh->mMaterialIndex >= 0)
      {
          aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex];
          vector<Texture> diffuseMaps = loadMaterialTextures(material, 
                                              aiTextureType_DIFFUSE, "texture_diffuse");
          textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
          vector<Texture> specularMaps = loadMaterialTextures(material, 
                                              aiTextureType_SPECULAR, "texture_specular");
          textures.insert(textures.end(), specularMaps.begin(), specularMaps.end());
      }
    3. 绘制功能 cpp void Draw(Shader shader) { for(unsigned int i = 0; i < meshes.size(); i++) meshes[i].Draw(shader); }

  2. 纹理结构 cpp struct Texture { unsigned int id; //纹理id string type; //纹理类型 };

  3. 网格Mesh > 准备好顶点和纹理结构,则可以准备mesh结构了

        class Mesh {
            public:
                /*  网格数据  */
                vector<Vertex> vertices;
                vector<unsigned int> indices;
                vector<Texture> textures;
                /*  函数  */
                Mesh(vector<Vertex> vertices, vector<unsigned int> indices, vector<Texture> textures);
                void Draw(Shader shader);
            private:
                /*  渲染数据  */
                unsigned int VAO, VBO, EBO;
                /*  函数  */
                void setupMesh();
        };  
        Mesh(vector<Vertex> vertices, vector<unsigned int> indices, vector<Texture> textures)
        {
            this->vertices = vertices;
            this->indices = indices;
            this->textures = textures;
            //创建绑定设置渲染数据。
            setupMesh();
        }
        void setupMesh()
        {
            glGenVertexArrays(1, &VAO);
            glGenBuffers(1, &VBO);
            glGenBuffers(1, &EBO);
            //bind
            glBindVertexArray(VAO);
            glBindBuffer(GL_ARRAY_BUFFER, VBO);
            //set vertex datas
            glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);  
            //set includies datas
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), 
                         &indices[0], GL_STATIC_DRAW);
            // 顶点位置
            glEnableVertexAttribArray(0);   
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
            // 顶点法线
            glEnableVertexAttribArray(1);   
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));
            // 顶点纹理坐标
            glEnableVertexAttribArray(2);   
            glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords));
            //结束绑定
            glBindVertexArray(0);
        }  
        void Draw(Shader shader) 
        {
            unsigned int diffuseNr = 1;
            unsigned int specularNr = 1;
            for(unsigned int i = 0; i < textures.size(); i++)
            {
                glActiveTexture(GL_TEXTURE0 + i); // 在绑定之前激活相应的纹理单元
                // 获取纹理序号(diffuse_textureN 中的 N)
                string number;
                string name = textures[i].type;
                if(name == "texture_diffuse")
                    number = std::to_string(diffuseNr++);
                else if(name == "texture_specular")
                    number = std::to_string(specularNr++);
                shader.setFloat(("material." + name + number).c_str(), i);
                glBindTexture(GL_TEXTURE_2D, textures[i].id);
            }
            glActiveTexture(GL_TEXTURE0);
            // 绘制网格
            glBindVertexArray(VAO);
            glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
            glBindVertexArray(0);
        }

文章作者: Yonggang Long
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Yonggang Long !
 上一篇
2022-08-10 Yonggang Long
下一篇 
2022-08-10 Yonggang Long
  目录