mirror of
https://github.com/Linloir/SceneEditor.git
synced 2025-12-17 15:38:11 +08:00
187 lines
6.7 KiB
C++
187 lines
6.7 KiB
C++
#pragma once
|
||
|
||
#include "logger.h"
|
||
#include "model.h"
|
||
|
||
Model::Model(std::string path) {
|
||
// Load model meta info from path
|
||
// TODO: Implement as async task
|
||
loadModel(path);
|
||
}
|
||
|
||
Model::~Model() {
|
||
// TODO: Maybe delete all meshes?
|
||
}
|
||
|
||
// file path is ...\\...\\.obj, and processnode & processmesh have been called here
|
||
void Model::loadModel(std::string path) {
|
||
Logger::info("Loading model from path: " + path);
|
||
Assimp::Importer importer;
|
||
const aiScene* scene = importer.ReadFile(
|
||
path, aiProcess_Triangulate | aiProcess_FlipUVs);
|
||
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
|
||
Logger::error("Failed to load model: " + std::string(importer.GetErrorString()));
|
||
_status = ERR;
|
||
return;
|
||
}
|
||
|
||
// Convert all '\' to '/'
|
||
std::replace(path.begin(), path.end(), '\\', '/');
|
||
_directory = path.substr(0, path.find_last_of('/'));
|
||
|
||
Logger::info("Model read successfully");
|
||
Logger::info("Processing model nodes");
|
||
processNode(scene->mRootNode, scene);
|
||
_status = LOADED;
|
||
Logger::info("Model loaded");
|
||
}
|
||
|
||
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;
|
||
|
||
Logger::debug("Processing mesh with " + std::to_string(mesh->mNumVertices) + " vertices");
|
||
// 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);
|
||
glm::vec3 vertexTangent = glm::vec3(0.0f);
|
||
glm::vec3 vertexBitangent = glm::vec3(0.0f);
|
||
|
||
// Process vertex positions
|
||
// ʹ<><CAB9>ѭ<EFBFBD><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>еĻ<D0B5><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ѭ<EFBFBD><D1AD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
|
||
for (int j = 0; j < 3; j++) {
|
||
vertexPosition[j] = mesh->mVertices[i][j];
|
||
left_down_back[j] = left_down_back[j] < vertexPosition[j] ? left_down_back[j] : vertexPosition[j];
|
||
right_up_front[j] = right_up_front[j] > vertexPosition[j] ? right_up_front[j] : vertexPosition[j];
|
||
}
|
||
|
||
//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]) {
|
||
// Process texture coordinates
|
||
vertexTextureCoordinate.x = mesh->mTextureCoords[0][i].x;
|
||
vertexTextureCoordinate.y = mesh->mTextureCoords[0][i].y;
|
||
|
||
//// Process vertex tangents
|
||
//if (mesh->mTangents) {
|
||
// vertexTangent.x = mesh->mTangents[i].x;
|
||
// vertexTangent.y = mesh->mTangents[i].y;
|
||
// vertexTangent.z = mesh->mTangents[i].z;
|
||
//}
|
||
//
|
||
//// Process vertex bitangents
|
||
//if (mesh->mBitangents) {
|
||
// vertexBitangent.x = mesh->mBitangents[i].x;
|
||
// vertexBitangent.y = mesh->mBitangents[i].y;
|
||
// vertexBitangent.z = mesh->mBitangents[i].z;
|
||
//}
|
||
}
|
||
else {
|
||
vertexTextureCoordinate = glm::vec2(0.0f, 0.0f);
|
||
}
|
||
|
||
// Create new vertex
|
||
Vertex newVertex = {
|
||
vertexPosition,
|
||
vertexNormal,
|
||
vertexTextureCoordinate,
|
||
//vertexTangent,
|
||
//vertexBitangent
|
||
};
|
||
|
||
// Add vertex to vertices
|
||
vertices.push_back(newVertex);
|
||
}
|
||
Logger::debug("Vertices vector memory usage: " + std::to_string(vertices.size() * sizeof(Vertex) / 1024) + " KB");
|
||
|
||
Logger::debug("Processing mesh with " + std::to_string(mesh->mNumFaces) + " faces");
|
||
// 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]);
|
||
}
|
||
}
|
||
Logger::debug("Indices vector memory usage: " + std::to_string(indices.size() * sizeof(unsigned int) / 1024) + " KB");
|
||
|
||
Logger::debug("Processing mesh materials");
|
||
// 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());
|
||
}
|
||
Logger::debug("Textures vector memory usage: " + std::to_string(textures.size() * sizeof(Texture) / 1024) + " KB");
|
||
|
||
Logger::debug("Mesh processed");
|
||
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;
|
||
Logger::debug("Texture already loaded, skipped");
|
||
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);
|
||
}
|
||
}
|