#include "ModelManager.hpp" #include "Log/Log.hpp" ModelManager::StaticModel::StaticModel(const std::vector& voxels, std::string name): name_(std::move(name)), voxels_(voxels) { glm::ivec3 sum_moments{0, 0, 0}; int sum_masses = 0; for (auto& i : voxels_) { sum_moments += glm::ivec3{i.loc.x * i.mass, i.loc.y * i.mass, i.loc.z * i.mass}; sum_masses += i.mass; } if(sum_masses != 0) sum_moments /= sum_masses; else if (!voxels_.empty()) { sum_moments.x /= static_cast(voxels_.size()); sum_moments.y /= static_cast(voxels_.size()); sum_moments.z /= static_cast(voxels_.size()); } mass_center_ = sum_moments; } ModelManager::StaticModel::~StaticModel() { OnDestroy.Call(name_); } ModelManager::owner_counter::owner_counter(const owner_counter& other) : counter(other.counter.load()), model(other.model) { } unsigned int ModelManager::FNV1aHash(const char* buf) { unsigned int h_val = 0x811c9dc5; while (*buf) { h_val ^= static_cast(*buf++); h_val *= 0x01000193; } return h_val; } void ModelManager::OnDestroySometimeModelCaller(const std::string& name) { Loging::Log("Free model: " + name); OnDestroySometimeModel.Call(name); } ModelManager::~ModelManager() { for (const auto& [it, counter] : models) { counter.model->OnDestroy.unbind(this, &ModelManager::OnDestroySometimeModelCaller); } models.clear(); } ModelManager::StaticModel* ModelManager::LoadModel(const std::string& name) { if (name.empty()) return nullptr; unsigned int hash = FNV1aHash(name.c_str()); auto counter = models.find(hash); if (counter != models.cend()) { ++counter->second.counter; return counter->second.model; } Loging::Log("Load new model: " + name); std::vector model_data; // Load model_data owner_counter new_counter; new_counter.counter.store(1); new_counter.model = new StaticModel(model_data, name); new_counter.model->OnDestroy.bind(this, &ModelManager::OnDestroySometimeModelCaller); models.try_emplace(hash, new_counter); OnLoadSometimeModel.Call(new_counter.model); return new_counter.model; } void ModelManager::FreeModel(const std::string& name) { if (name.empty()) return; unsigned int hash = FNV1aHash(name.c_str()); auto counter = models.find(hash); --counter->second.counter; StaticModel* model = counter->second.model; if (counter->second.counter.load() == 0) { models.erase(hash); delete model; } }