From 335c1bbd553b569df5465c9c56d7fe1287d8f182 Mon Sep 17 00:00:00 2001 From: Linloir <3145078758@qq.com> Date: Mon, 12 Dec 2022 16:43:50 +0800 Subject: [PATCH] Update and Implement Model class --- FinalProject/mesh.h | 2 +- FinalProject/model.cpp | 126 ++++++++++++++++++++++++++++++++++++++++- FinalProject/model.h | 17 ++++-- FinalProject/texture.h | 11 +++- 4 files changed, 146 insertions(+), 10 deletions(-) diff --git a/FinalProject/mesh.h b/FinalProject/mesh.h index 102324e..dd9628c 100644 --- a/FinalProject/mesh.h +++ b/FinalProject/mesh.h @@ -27,5 +27,5 @@ public: inline VertexArrayObject vao() const { return _vao; } public: - void render(ShaderProgram shader); + void render(const ShaderProgram& shader) const ; }; \ No newline at end of file diff --git a/FinalProject/model.cpp b/FinalProject/model.cpp index 43ab81d..e64d2e2 100644 --- a/FinalProject/model.cpp +++ b/FinalProject/model.cpp @@ -1,5 +1,6 @@ #pragma once +#include "logger.h" #include "model.h" Model::Model(std::string path) { @@ -8,13 +9,136 @@ Model::Model(std::string path) { loadModel(path); } +Model::~Model() { + // TODO: Maybe delete all meshes? +} + void Model::loadModel(std::string path) { Assimp::Importer importer; const aiScene* scene = importer.ReadFile( path, aiProcess_Triangulate | aiProcess_FlipUVs); if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { - std::cout << "ERROR::ASSIMP::" << importer.GetErrorString() << std::endl; + Logger::error("Failed to load model: " + std::string(importer.GetErrorString())); + _status = ERROR; return; } + _directory = path.substr(0, path.find_last_of('/')); + + processNode(scene->mRootNode, scene); +} + +void Model::processNode(aiNode* node, const aiScene* scene) { + // Process all meshes in node + for (unsigned int i = 0; i < node->mNumMeshes; i++) { + aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; + _meshes.push_back(processMesh(mesh, scene)); + } + + // Recursively process child nodes + for (unsigned int i = 0; i < node->mNumChildren; i++) { + processNode(node->mChildren[i], scene); + } +} + +Mesh Model::processMesh(aiMesh* mesh, const aiScene* scene) { + std::vector vertices; + std::vector indices; + std::vector textures; + + // Process vertices + for (unsigned int i = 0; i < mesh->mNumVertices; i++) { + // Create placeholder vectors + glm::vec3 vertexPosition = glm::vec3(0.0f); + glm::vec3 vertexNormal = glm::vec3(0.0f); + glm::vec2 vertexTextureCoordinate = glm::vec2(0.0f); + + // Process vertex positions + vertexPosition.x = mesh->mVertices[i].x; + vertexPosition.y = mesh->mVertices[i].y; + vertexPosition.z = mesh->mVertices[i].z; + + // Process vertex normals + if (mesh->mNormals) { + vertexNormal.x = mesh->mNormals[i].x; + vertexNormal.y = mesh->mNormals[i].y; + vertexNormal.z = mesh->mNormals[i].z; + } + + // Process vertex texture coordinates + if (mesh->mTextureCoords[0]) { + vertexTextureCoordinate.x = mesh->mTextureCoords[0][i].x; + vertexTextureCoordinate.y = mesh->mTextureCoords[0][i].y; + } + else { + vertexTextureCoordinate = glm::vec2(0.0f, 0.0f); + } + + // Create new vertex + Vertex newVertex = { + vertexPosition, + vertexNormal, + vertexTextureCoordinate + }; + + // Add vertex to vertices + vertices.push_back(newVertex); + } + + // 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]); + } + } + + // Process material + if (mesh->mMaterialIndex >= 0) { + aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; + + // Diffuse maps + std::vector diffuseMaps = loadMaterialTextures(material, aiTextureType_DIFFUSE, TextureType::DIFFUSE); + textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end()); + + // Specular maps + std::vector specularMaps = loadMaterialTextures(material, aiTextureType_SPECULAR, TextureType::SPECULAR); + textures.insert(textures.end(), specularMaps.begin(), specularMaps.end()); + } + + return Mesh(vertices, indices, textures); +} + +std::vector Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type, TextureType textureType) { + std::vector textures; + for (unsigned int i = 0; i < mat->GetTextureCount(type); i++) { + aiString str; + mat->GetTexture(type, i, &str); + bool skip = false; + for (unsigned int j = 0; j < _texturesLoaded.size(); j++) { + if (std::strcmp(_texturesLoaded[j].path().data(), str.C_Str()) == 0) { + textures.push_back(_texturesLoaded[j]); + skip = true; + break; + } + } + if (!skip) { + Texture newTexture(textureType, _directory + '/' + str.C_Str()); + textures.push_back(newTexture); + _texturesLoaded.push_back(newTexture); + } + } + return textures; +} + +void Model::render(const ShaderProgram& shader) const { + // Test for model status + if (_status != LOADED) { + Logger::error("Trying to render unloaded model"); + return; + } + // Render the model + for (unsigned int i = 0; i < _meshes.size(); i++) { + _meshes[i].render(shader); + } } diff --git a/FinalProject/model.h b/FinalProject/model.h index 09d20e7..fbc8ff4 100644 --- a/FinalProject/model.h +++ b/FinalProject/model.h @@ -10,23 +10,28 @@ #include "shader.h" class Model { +public: + enum MODELSTATUS { LOADING, LOADED, ERROR}; + private: - std::vector _meshes; + std::vector _meshes; + std::vector _texturesLoaded; std::string _directory; - bool _ready = false; + MODELSTATUS _status = LOADING; public: Model(std::string path); + ~Model(); public: - inline bool isReady() const { return _ready; } + inline MODELSTATUS isReady() const { return _status; } private: void loadModel(std::string path); void processNode(aiNode* node, const aiScene* scene); - Mesh* processMesh(aiMesh* mesh, const aiScene* scene); - std::vector loadMaterialTextures(aiMaterial* mat, aiTextureType type, std::string typeName); + Mesh processMesh(aiMesh* mesh, const aiScene* scene); + std::vector loadMaterialTextures(aiMaterial* mat, aiTextureType type, TextureType textureType); public: - void render(ShaderProgram shader); + void render(const ShaderProgram& shader) const; }; \ No newline at end of file diff --git a/FinalProject/texture.h b/FinalProject/texture.h index 0570a27..1da7b0f 100644 --- a/FinalProject/texture.h +++ b/FinalProject/texture.h @@ -1,15 +1,22 @@ #pragma once +#include + enum TextureType { DIFFUSE, SPECULAR }; class Texture { private: unsigned int _id; TextureType _type; + std::string _path; public: - unsigned int id() const; - TextureType type() const; + Texture(TextureType type, std::string path); + +public: + inline unsigned int id() const { return _id; } + inline TextureType type() const { return _type; } + inline std::string path() const { return _path; } inline void bind() const; inline void unbind() const;