118 lines
3.3 KiB
C++
118 lines
3.3 KiB
C++
#include "ResourceManager.h"
|
|
|
|
#include <iostream>
|
|
#include <stdexcept>
|
|
|
|
#include <assimp/Importer.hpp>
|
|
#include <assimp/postprocess.h>
|
|
#include <assimp/scene.h>
|
|
|
|
#include "texture.h"
|
|
#include "font.h"
|
|
#include "MeshData.h"
|
|
|
|
ResourceManager::~ResourceManager()
|
|
{
|
|
for (auto& [path, texture] : textures) {
|
|
if (!texture) continue;
|
|
texture->Delete();
|
|
delete texture;
|
|
}
|
|
for (Texture* texture : createdTextures) {
|
|
texture->Delete();
|
|
delete texture;
|
|
}
|
|
for (auto& [path, font] : fonts)
|
|
delete font;
|
|
for (auto& [path, mesh] : meshes)
|
|
delete mesh;
|
|
}
|
|
|
|
const MeshData* ResourceManager::GetMeshData(const std::string& path)
|
|
{
|
|
auto existing = meshes.find(path);
|
|
if (existing != meshes.end())
|
|
return existing->second;
|
|
|
|
// Pre-transforming bakes each node's placement in, so the merged meshes keep their layout
|
|
Assimp::Importer importer;
|
|
const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_GenSmoothNormals |
|
|
aiProcess_JoinIdenticalVertices | aiProcess_PreTransformVertices);
|
|
|
|
MeshData* data = nullptr;
|
|
if (!scene || (scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) || scene->mNumMeshes == 0) {
|
|
std::cout << "RESOURCE MANAGER: couldn't load mesh " << path << ": " << importer.GetErrorString() << "\n";
|
|
}
|
|
else {
|
|
data = new MeshData();
|
|
for (unsigned int m = 0; m < scene->mNumMeshes; m++) {
|
|
const aiMesh* mesh = scene->mMeshes[m];
|
|
const GLuint firstVertex = (GLuint)data->vertices.size();
|
|
|
|
for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
|
|
Vertex vertex;
|
|
vertex.Position = glm::vec3(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
|
|
vertex.Normal = mesh->HasNormals()
|
|
? glm::vec3(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z) : glm::vec3(0.0f, 1.0f, 0.0f);
|
|
vertex.TexCoords = mesh->mTextureCoords[0]
|
|
? glm::vec2(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y) : glm::vec2(0.0f);
|
|
data->vertices.push_back(vertex);
|
|
}
|
|
for (unsigned int f = 0; f < mesh->mNumFaces; f++) {
|
|
for (unsigned int j = 0; j < mesh->mFaces[f].mNumIndices; j++)
|
|
data->indices.push_back(firstVertex + mesh->mFaces[f].mIndices[j]);
|
|
}
|
|
}
|
|
}
|
|
|
|
meshes[path] = data;
|
|
return data;
|
|
}
|
|
|
|
Texture* ResourceManager::CreateTexture(int width, int height)
|
|
{
|
|
createdTextures.push_back(new Texture(width, height));
|
|
return createdTextures.back();
|
|
}
|
|
|
|
Texture* ResourceManager::CopyTexture(const Texture& source)
|
|
{
|
|
createdTextures.push_back(new Texture(source));
|
|
return createdTextures.back();
|
|
}
|
|
|
|
// Failed loads are cached as nullptr too, so a missing file only gets reported once
|
|
Texture* ResourceManager::GetTexture(const std::string& path)
|
|
{
|
|
auto existing = textures.find(path);
|
|
if (existing != textures.end())
|
|
return existing->second;
|
|
|
|
Texture* texture = nullptr;
|
|
try {
|
|
texture = new Texture(path.c_str());
|
|
}
|
|
catch (const std::exception& error) {
|
|
std::cout << "RESOURCE MANAGER: " << error.what() << "\n";
|
|
}
|
|
textures[path] = texture;
|
|
return texture;
|
|
}
|
|
|
|
Font* ResourceManager::GetFont(const std::string& path)
|
|
{
|
|
auto existing = fonts.find(path);
|
|
if (existing != fonts.end())
|
|
return existing->second;
|
|
|
|
Font* font = nullptr;
|
|
try {
|
|
font = new Font(path.c_str());
|
|
}
|
|
catch (const std::exception& error) {
|
|
std::cout << "RESOURCE MANAGER: " << error.what() << ": " << path << "\n";
|
|
}
|
|
fonts[path] = font;
|
|
return font;
|
|
}
|