模型model
模型model, 封装一个包含渲染的基础数据
模型
拥有的功能: 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); };从文件导入
借助
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); 。。。解析数据
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()); }绘制功能
cpp void Draw(Shader shader) { for(unsigned int i = 0; i < meshes.size(); i++) meshes[i].Draw(shader); }
纹理结构
cpp struct Texture { unsigned int id; //纹理id string type; //纹理类型 };网格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); }