From e4e50687270a6547bee019e6df18367ee2695c5f Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Sun, 13 Apr 2014 03:42:12 +0200 Subject: [PATCH] Resource manager refactoring --- src/GameWorld.cpp | 5 +- src/Model.cpp | 144 +---------------------------------- src/Model.h | 3 +- src/ResourceManager.cpp | 69 +++++++++-------- src/ResourceManager.h | 38 +++++---- src/Systems/RenderSystem.cpp | 16 ++-- src/World.h | 2 +- 7 files changed, 74 insertions(+), 203 deletions(-) diff --git a/src/GameWorld.cpp b/src/GameWorld.cpp index 40233bd..281dcd6 100755 --- a/src/GameWorld.cpp +++ b/src/GameWorld.cpp @@ -5,9 +5,8 @@ void GameWorld::Initialize() { World::Initialize(); - m_ResourceManager.RegisterResource("Model", "Models/Placeholders/PhysicsTest/Plane.obj"); - m_ResourceManager.RegisterResource("Model", "Models/Placeholders/PhysicsTest/ArrowCube.obj"); - m_ResourceManager.PreCache(); + m_ResourceManager.Preload("Model", "Models/Placeholders/PhysicsTest/Plane.obj"); + m_ResourceManager.Preload("Model", "Models/Placeholders/PhysicsTest/ArrowCube.obj"); RegisterComponents(); diff --git a/src/Model.cpp b/src/Model.cpp index 11fb426..5f10f29 100755 --- a/src/Model.cpp +++ b/src/Model.cpp @@ -1,13 +1,7 @@ #include "PrecompiledHeader.h" #include "Model.h" -Model::Model(const char* path) -{ - Loadobj(path, Vertices, Normals, TextureCoords); - CreateBuffers(Vertices, Normals, TextureCoords); -} - -Model::Model(OBJ &obj) +Model::Model(OBJ &obj, ResourceManager* rm) { OBJ::MaterialInfo* currentMaterial = nullptr; TextureGroup* currentTexGroup = nullptr; @@ -24,7 +18,7 @@ Model::Model(OBJ &obj) { currentMaterial = face.Material; // Load texture - std::shared_ptr texture = std::make_shared(currentMaterial->TextureFile); + auto texture = std::shared_ptr(rm->Load("Texture", currentMaterial->TextureFile)); // TODO: Load material parameters // Create new texture group (start index of new group is upcoming index) TextureGroup texGroup = { texture, index, index }; @@ -63,142 +57,12 @@ Model::Model(OBJ &obj) { CreateBuffers(Vertices, Normals, TextureCoords); } -} - -bool Model::Loadobj(const char* path, std::vector &out_vertices, std::vector &out_normals, std::vector &out_TextureCoords) -{ - std::vector< unsigned int > vertexIndices, TextureCoordIndices, normalIndices; - std::vector< glm::vec3 > temp_vertices; - std::vector< glm::vec2 > temp_TextureCoords; - std::vector< glm::vec3 > temp_normals; - - FILE* file = fopen(path, "r"); - LOG_INFO("Loading .obj file"); - if( file == NULL ) + else { - LOG_INFO("Load .obj file: failed"); - return false; + LOG_WARNING("Loaded OBJ with no vertices!"); } - char lineHeader[512]; - - while(true) - { - - //read the first word of the line - int res = fscanf(file, "%s", lineHeader); - - if( res == EOF ) // EOF - End Of File - { - for( unsigned int i = 0; i < vertexIndices.size(); i++ ) - { - unsigned int vertexIndex = vertexIndices[i]; - glm::vec3 vertex = temp_vertices[ vertexIndex-1]; - out_vertices.push_back(vertex); - - } - - for( unsigned int i = 0; i < TextureCoordIndices.size(); i++ ) - { - unsigned int TextureCoordIndex = TextureCoordIndices[i]; - glm::vec2 TextureCoord = temp_TextureCoords[ TextureCoordIndex-1]; - out_TextureCoords.push_back(TextureCoord); - } - - for( unsigned int i = 0; i < normalIndices.size(); i++ ) - { - unsigned int normalIndex = normalIndices[i]; - glm::vec3 normal = temp_normals[ normalIndex-1]; - out_normals.push_back(normal); - } - - - LOG_INFO("Model Loaded\n"); - break; - } - - if( strcmp( lineHeader, "v" ) == 0 ) // vertex - { - glm::vec3 vertex; - fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z); - temp_vertices.push_back(vertex); - } - else if ( strcmp( lineHeader, "vt" ) == 0 ) // texture coordinate - { - glm::vec2 TextureCoord; - fscanf(file, "%f %f\n", &TextureCoord.x, &TextureCoord.y ); - temp_TextureCoords.push_back(TextureCoord); - } - else if( strcmp( lineHeader, "vn" ) == 0 ) // normal - { - glm::vec3 normal; - fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z ); - temp_normals.push_back(normal); - } - else if( strcmp( lineHeader, "f" ) == 0) - { - unsigned int vertexIndex[3], TextureCoordIndex[3], normalIndex[3]; - int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIndex[0], &TextureCoordIndex[0], &normalIndex[0], &vertexIndex[1], &TextureCoordIndex[1], &normalIndex[1],&vertexIndex[2], &TextureCoordIndex[2], &normalIndex[2]); - if(matches != 9) - { - printf("File can't be read, try exporting with other options\n"); - return false; - } - vertexIndices.push_back(vertexIndex[0]); - vertexIndices.push_back(vertexIndex[1]); - vertexIndices.push_back(vertexIndex[2]); - TextureCoordIndices.push_back(TextureCoordIndex[0]); - TextureCoordIndices.push_back(TextureCoordIndex[1]); - TextureCoordIndices.push_back(TextureCoordIndex[2]); - normalIndices.push_back(normalIndex[0]); - normalIndices.push_back(normalIndex[1]); - normalIndices.push_back(normalIndex[2]); - - } - else if ( strcmp( lineHeader, "mtllib" ) == 0 ) - { - - char fileName[512]; - fscanf(file, "%s\n", &fileName); - - - FILE* mtlfile = fopen(fileName, "r"); - LOG_INFO("Loading .mtl file"); - if( mtlfile == NULL ) - { - LOG_INFO("Load .mtl file: failed"); - return false; - } - - char mtllineHeader[512]; - //read the first word of the line - - while (true) - { - int mtlres = fscanf(mtlfile, "%s", mtllineHeader); - - if( mtlres == EOF ) // EOF - End Of File - { - - break; - } - else if ( strcmp( mtllineHeader, "map_Kd" ) == 0 ) - { - char textureFileName[512]; - fscanf(mtlfile, "%s", textureFileName); - texture.push_back(std::make_shared(textureFileName)); - LOG_INFO("Texture Loaded\n"); - } - } - - - - } - } - return true; - } - void Model::CreateBuffers( std::vector vertices, std::vector normals, std::vectortextureCoords) { diff --git a/src/Model.h b/src/Model.h index 008e689..e1d7fa6 100755 --- a/src/Model.h +++ b/src/Model.h @@ -17,8 +17,7 @@ class Model : public Resource { public: - Model(OBJ &obj); - Model(const char* path); + Model(OBJ &obj, ResourceManager* rm); struct TextureGroup { diff --git a/src/ResourceManager.cpp b/src/ResourceManager.cpp index 8682add..4b864d6 100644 --- a/src/ResourceManager.cpp +++ b/src/ResourceManager.cpp @@ -3,49 +3,48 @@ Resource* ResourceManager::CreateResource(std::string resourceType, std::string resourceName) { - auto it = m_FactoryFunctions.find(resourceType); - if (it != m_FactoryFunctions.end()) - { - return it->second(resourceName); - } - else + auto facIt = m_FactoryFunctions.find(resourceType); + if (facIt == m_FactoryFunctions.end()) { + LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": Type not registered", resourceName.c_str(), resourceType.c_str()); return nullptr; } -} -void ResourceManager::PreCache() -{ - LOG_INFO("Pre-caching resources..."); - for (auto pair : m_RegisteredResources) - { - std::string name = pair.first; - std::string type = pair.second; + auto resIt = m_ResourceCache.find(resourceName); + if (resIt != m_ResourceCache.end()) + return resIt->second; + + // Call the factory function + Resource* resource = facIt->second(resourceName); + // Store IDs + resource->TypeID = GetTypeID(resourceType); + resource->ResourceID = GetNewResourceID(resource->TypeID); + // Cache + m_ResourceCache[resourceName] = resource; - Resource* resource = CreateResource(type, name); - if (resource == nullptr) - { - LOG_WARNING("Failed to pre-cache %s resource \"%s\": Resource not registered!", type.c_str(), name.c_str()); - continue; - } - - unsigned int typeID = m_ResourceTypeIDs[type]; - unsigned int resourceID = m_ResourceCount[typeID]++; - resource->TypeID = typeID; - resource->ResourceID = resourceID; - m_ResourceIDs[name] = resourceID; - - m_ResourceCache[name] = resource; - } -} - -void ResourceManager::RegisterResource(std::string resourceType, std::string resourceName) -{ - m_RegisteredResources[resourceName] = resourceType; - m_ResourceTypeIDs[resourceName] = m_ResourceTypeCount++; + return resource; } void ResourceManager::RegisterType(std::string resourceType, std::function factoryFunction) { m_FactoryFunctions[resourceType] = factoryFunction; } + +void ResourceManager::Preload(std::string resourceType, std::string resourceName) +{ + CreateResource(resourceType, resourceName); +} + +unsigned int ResourceManager::GetTypeID(std::string resourceType) +{ + if (m_ResourceTypeIDs.find(resourceType) == m_ResourceTypeIDs.end()) + { + m_ResourceTypeIDs[resourceType] = m_CurrentResourceTypeID++; + } + return m_ResourceTypeIDs[resourceType]; +} + +unsigned int ResourceManager::GetNewResourceID(unsigned int typeID) +{ + return m_ResourceCount[typeID]++; +} diff --git a/src/ResourceManager.h b/src/ResourceManager.h index 6796cec..6c2cf9f 100644 --- a/src/ResourceManager.h +++ b/src/ResourceManager.h @@ -21,34 +21,46 @@ public: // Registers the factory function of a resource type void RegisterType(std::string resourceType, std::function factoryFunction); - // Registers a future instance of a resource - void RegisterResource(std::string resourceType, std::string resourceName); - - // Loads all registered resources and caches them - void PreCache(); - + // Loads a resource and caches it for future use + void Preload(std::string resourceType, std::string resourceName); + template + // Hot-loads a resource and caches it for future use + T* Load(std::string resourceType, std::string resourceName); + + template + // Fetches a preloaded resource T* Fetch(std::string resourceName) const; private: - unsigned int m_ResourceTypeCount = 0; - std::unordered_map m_ResourceTypeIDs; - std::unordered_map m_ResourceCount; - std::unordered_map m_ResourceIDs; - std::unordered_map> m_FactoryFunctions; // type -> factory function - std::unordered_map m_RegisteredResources; // name -> type std::unordered_map m_ResourceCache; // name -> resource + // TODO: Getters for IDs + unsigned int m_CurrentResourceTypeID = 0; + std::unordered_map m_ResourceTypeIDs; + // Number of resources of a type. Doubles as local ID. + std::unordered_map m_ResourceCount; + + unsigned int GetTypeID(std::string resourceType); + unsigned int GetNewResourceID(unsigned int typeID); + + // Internal: Create a resource and cache it Resource* CreateResource(std::string resourceType, std::string resourceName); }; +template +T* ResourceManager::Load(std::string resourceType, std::string resourceName) +{ + return static_cast(CreateResource(resourceType, resourceName)); +} + template T* ResourceManager::Fetch(std::string resourceName) const { if (m_ResourceCache.find(resourceName) == m_ResourceCache.end()) { - LOG_ERROR("Failed to load resource \"%s\": Resource not precached!", resourceName.c_str()); + LOG_ERROR("Failed to fetch resource \"%s\": Resource not loaded!", resourceName.c_str()); return nullptr; } else diff --git a/src/Systems/RenderSystem.cpp b/src/Systems/RenderSystem.cpp index ca4f807..c80f77a 100755 --- a/src/Systems/RenderSystem.cpp +++ b/src/Systems/RenderSystem.cpp @@ -20,16 +20,14 @@ void Systems::RenderSystem::UpdateEntity(double dt, EntityID entity, EntityID pa auto modelComponent = m_World->GetComponent(entity, "Model"); if (modelComponent != nullptr) { - if (m_CachedModels.find(modelComponent->ModelFile) == m_CachedModels.end()) + auto model = m_World->GetResourceManager()->Load("Model", modelComponent->ModelFile); + if (model != nullptr) { - m_CachedModels[modelComponent->ModelFile] = std::make_shared(OBJ(modelComponent->ModelFile)); + glm::vec3 position = m_TransformSystem->AbsolutePosition(entity); + glm::quat orientation = m_TransformSystem->AbsoluteOrientation(entity); + glm::vec3 scale = m_TransformSystem->AbsoluteScale(entity); + m_Renderer->AddModelToDraw(model, position, orientation, scale, modelComponent->Visible, modelComponent->ShadowCaster); } - - auto model = m_World->GetResourceManager()->Fetch(modelComponent->ModelFile); - glm::vec3 position = m_TransformSystem->AbsolutePosition(entity); - glm::quat orientation = m_TransformSystem->AbsoluteOrientation(entity); - glm::vec3 scale = m_TransformSystem->AbsoluteScale(entity); - m_Renderer->AddModelToDraw(model, position, orientation, scale, modelComponent->Visible, modelComponent->ShadowCaster); } auto pointLightComponent = m_World->GetComponent(entity, "PointLight"); @@ -74,8 +72,8 @@ void Systems::RenderSystem::RegisterComponents(ComponentFactory* cf) void Systems::RenderSystem::RegisterResourceTypes(ResourceManager* rm) { + rm->RegisterType("Model", [rm](std::string resourceName) { return new Model(OBJ(resourceName), rm); }); rm->RegisterType("Texture", [](std::string resourceName) { return new Texture(resourceName); }); - rm->RegisterType("Model", [](std::string resourceName) { return new Model(OBJ(resourceName)); }); } diff --git a/src/World.h b/src/World.h index bbee8bf..9deeab9 100755 --- a/src/World.h +++ b/src/World.h @@ -72,7 +72,7 @@ public: std::unordered_map* GetEntities() { return &m_EntityParents; } - const ResourceManager* GetResourceManager() const { return &m_ResourceManager; } + ResourceManager* GetResourceManager() { return &m_ResourceManager; } protected: SystemFactory m_SystemFactory;