#include #include #include Model::Model(const std::string &path, const glm::vec4 &static_color, std::shared_ptr shader) : OpenGlGraphics(shader) { this->model_path = path; this->static_color = static_color; } void Model::render() { for (unsigned int i = 0; i < meshes.size(); i++) { meshes[i].render(this->model_matrix, this->normal_matrix); } } void Model::realize() { Assimp::Importer importer; const aiScene *scene = importer.ReadFile(this->model_path, aiProcess_Triangulate | aiProcess_FlipUVs); if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { std::cout << "Error: Assimp: " << importer.GetErrorString() << std::endl; return; } this->directory = this->model_path.substr(0, this->model_path.find_last_of('/')); this->processNode(scene->mRootNode, scene); importer.FreeScene(); } void Model::processNode(aiNode *node, const aiScene *scene) { for(unsigned int i = 0; i < node->mNumMeshes; i++) { aiMesh *mesh = scene->mMeshes[node->mMeshes[i]]; this->meshes.push_back(this->processMesh(mesh, scene)); } for(unsigned int i = 0; i < node->mNumChildren; i++) { this->processNode(node->mChildren[i], scene); } } std::vector> Model::loadMaterialTextures(aiMaterial *mat, aiTextureType type) { std::vector> tex_vector; for (unsigned int i = 0; i < mat->GetTextureCount(type); i++) { aiString str; mat->GetTexture(type, i, &str); bool already_loaded = false; for (unsigned int j = 0; j < this->allocated_textures.size(); j++) { if (std::strcmp(this->allocated_textures[j]->getPath().c_str(), str.C_Str()) == 0) { /* texture already loaded */ tex_vector.push_back(this->allocated_textures[j]); already_loaded = true; break; } } if (!already_loaded) { auto new_texture = std::make_shared(str.C_Str()); new_texture->loadFromImagePath(this->directory); tex_vector.push_back(new_texture); this->allocated_textures.push_back(new_texture); } } return tex_vector; } Mesh Model::processMesh(aiMesh *mesh, const aiScene *scene) { std::vector vertices; std::vector indices; Material mesh_material; for(unsigned int i = 0; i < mesh->mNumVertices; i++) { Vertex vertex; glm::vec3 vector; vector.x = mesh->mVertices[i].x; vector.y = mesh->mVertices[i].y; vector.z = mesh->mVertices[i].z; vertex.Position = vector; vector.x = mesh->mNormals[i].x; vector.y = mesh->mNormals[i].y; vector.z = mesh->mNormals[i].z; vertex.Normal = vector; if(mesh->mTextureCoords[0]) { glm::vec2 vec; vec.x = mesh->mTextureCoords[0][i].x; vec.y = mesh->mTextureCoords[0][i].y; vertex.TextureCoords = vec; } else { vertex.TextureCoords = glm::vec2(0.0f, 0.0f); } vertices.push_back(vertex); } // process indices 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) { aiColor3D col; aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex]; auto diffuseTextures = loadMaterialTextures(material, aiTextureType_DIFFUSE); auto specularTextures = loadMaterialTextures(material, aiTextureType_SPECULAR); auto ambientTextures = loadMaterialTextures(material, aiTextureType_AMBIENT); mesh_material.pushDiffuseTexture(diffuseTextures); mesh_material.pushSpecularTexture(specularTextures); mesh_material.pushAmbientTexture(ambientTextures); if (!material->Get(AI_MATKEY_COLOR_AMBIENT, col)) mesh_material.setAmbientColor(glm::vec3(col.r, col.g, col.b)); if (!material->Get(AI_MATKEY_COLOR_SPECULAR, col)) mesh_material.setSpecularColor(glm::vec3(col.r, col.g, col.b)); if (!material->Get(AI_MATKEY_COLOR_DIFFUSE, col)) mesh_material.setDiffuseColor(glm::vec3(col.r, col.g, col.b)); material->Get(AI_MATKEY_SHININESS, mesh_material.shininess); material->Get(AI_MATKEY_SHININESS_STRENGTH, mesh_material.shininess_strength); std::cout << "Material: " << mesh_material << std::endl; } Mesh my_mesh = Mesh(vertices, indices, mesh_material, this->shaderprog); my_mesh.realize(); return my_mesh; }