Program Listing for File ModelLoader.cpp
↰ Return to documentation for file (src/Assets/Loaders/ModelLoader.cpp)
#include "Ramus/Assets/Loaders/ModelLoader.hpp"
#include "Ramus/Core/Services/Logger.hpp"
#include "Ramus/Graphics/Geometry/Mesh.hpp"
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include <string>
#include <vector>
namespace ramus
{
std::shared_ptr<Model> ModelLoader::Load(const std::string& path)
{
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(path
, aiProcess_Triangulate
| aiProcess_JoinIdenticalVertices
| aiProcess_FlipUVs
| aiProcess_GenNormals
| aiProcess_CalcTangentSpace);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
{
Logger::GetRendererLogger()->debug("Assimp Error: Failed to import model @ {}", path);
return nullptr;
}
else if (!scene->HasMeshes())
{
Logger::GetRendererLogger()->debug("Assimp Error: Model @ contains no meshes {}", path);
return nullptr;
}
auto model = std::make_shared<Model>();
ProcessNode(scene->mRootNode, scene, *model);
return model;
}
void ModelLoader::ProcessNode(aiNode* node, const aiScene* scene, Model& model)
{
for (unsigned int i = 0; i < node->mNumMeshes; i++)
{
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
model.AddMesh(ProcessMesh(mesh, scene));
}
for (unsigned int i = 0; i < node->mNumChildren; i++)
{
ProcessNode(node->mChildren[i], scene, model);
}
}
std::unique_ptr<Mesh> ModelLoader::ProcessMesh(aiMesh* mesh, const aiScene* scene)
{
std::vector<Vertex> vertices = ExtractVertices(mesh);
std::vector<uint32_t> indices = ExtractIndices(mesh);
return std::make_unique<Mesh>(std::move(vertices), std::move(indices));
}
std::vector<Vertex> ModelLoader::ExtractVertices(aiMesh* mesh)
{
std::vector<Vertex> vertices;
vertices.reserve(mesh->mNumVertices);
for (uint32_t i = 0; i < mesh->mNumVertices; i++)
{
Vertex vertex;
vertex.position = { mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z };
if (mesh->HasNormals())
vertex.normal = { mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z };
vertex.texCoords = mesh->mTextureCoords[0]
? glm::vec2(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y)
: glm::vec2(0.0f);
vertices.push_back(vertex);
}
return vertices;
}
std::vector<uint32_t> ModelLoader::ExtractIndices(aiMesh* mesh)
{
std::vector<uint32_t> indices;
indices.reserve(mesh->mNumFaces * 3);
for (uint32_t f = 0; f < mesh->mNumFaces; f++)
{
const aiFace& face = mesh->mFaces[f];
indices.push_back(face.mIndices[0]);
indices.push_back(face.mIndices[1]);
indices.push_back(face.mIndices[2]);
}
return indices;
}
}