Update and Implement Model class

This commit is contained in:
Linloir 2022-12-12 16:43:50 +08:00
parent 647edbbc7a
commit 335c1bbd55
No known key found for this signature in database
GPG Key ID: 58EEB209A0F2C366
4 changed files with 146 additions and 10 deletions

View File

@ -27,5 +27,5 @@ public:
inline VertexArrayObject vao() const { return _vao; } inline VertexArrayObject vao() const { return _vao; }
public: public:
void render(ShaderProgram shader); void render(const ShaderProgram& shader) const ;
}; };

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "logger.h"
#include "model.h" #include "model.h"
Model::Model(std::string path) { Model::Model(std::string path) {
@ -8,13 +9,136 @@ Model::Model(std::string path) {
loadModel(path); loadModel(path);
} }
Model::~Model() {
// TODO: Maybe delete all meshes?
}
void Model::loadModel(std::string path) { void Model::loadModel(std::string path) {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene* scene = importer.ReadFile( const aiScene* scene = importer.ReadFile(
path, aiProcess_Triangulate | aiProcess_FlipUVs); path, aiProcess_Triangulate | aiProcess_FlipUVs);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { 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; 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<Vertex> vertices;
std::vector<unsigned int> indices;
std::vector<Texture> 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<Texture> diffuseMaps = loadMaterialTextures(material, aiTextureType_DIFFUSE, TextureType::DIFFUSE);
textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
// Specular maps
std::vector<Texture> specularMaps = loadMaterialTextures(material, aiTextureType_SPECULAR, TextureType::SPECULAR);
textures.insert(textures.end(), specularMaps.begin(), specularMaps.end());
}
return Mesh(vertices, indices, textures);
}
std::vector<Texture> Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type, TextureType textureType) {
std::vector<Texture> 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);
}
} }

View File

@ -10,23 +10,28 @@
#include "shader.h" #include "shader.h"
class Model { class Model {
public:
enum MODELSTATUS { LOADING, LOADED, ERROR};
private: private:
std::vector<Mesh*> _meshes; std::vector<Mesh> _meshes;
std::vector<Texture> _texturesLoaded;
std::string _directory; std::string _directory;
bool _ready = false; MODELSTATUS _status = LOADING;
public: public:
Model(std::string path); Model(std::string path);
~Model();
public: public:
inline bool isReady() const { return _ready; } inline MODELSTATUS isReady() const { return _status; }
private: private:
void loadModel(std::string path); void loadModel(std::string path);
void processNode(aiNode* node, const aiScene* scene); void processNode(aiNode* node, const aiScene* scene);
Mesh* processMesh(aiMesh* mesh, const aiScene* scene); Mesh processMesh(aiMesh* mesh, const aiScene* scene);
std::vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, std::string typeName); std::vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, TextureType textureType);
public: public:
void render(ShaderProgram shader); void render(const ShaderProgram& shader) const;
}; };

View File

@ -1,15 +1,22 @@
#pragma once #pragma once
#include <string>
enum TextureType { DIFFUSE, SPECULAR }; enum TextureType { DIFFUSE, SPECULAR };
class Texture { class Texture {
private: private:
unsigned int _id; unsigned int _id;
TextureType _type; TextureType _type;
std::string _path;
public: public:
unsigned int id() const; Texture(TextureType type, std::string path);
TextureType type() const;
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 bind() const;
inline void unbind() const; inline void unbind() const;