From 90273e87f2b8fce99ed41a9c75eeaacd5f5949b1 Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Tue, 28 Jul 2026 14:28:22 +0800 Subject: [PATCH] refactor(gameplay): integrate model and hitbox ID system into Entity - Introduce HitboxID, EntityID, and ModelID types for safer ID-based lookups - Replace AABB struct with Hitbox (includes HitboxID) - Convert ModelManager and HitboxManager to singletons with Handle structs - Update Entity to store IDs for model and hitbox, removing direct references - Reorganize creature model assets into subdirectories per entity type - Add player model (player.glb) and collision data for pig - Remove ModelManager dependency from App and Renderer - Add namespace parsing utility for asset paths - Mark sparse_vector::insert() with [[nodiscard]] --- .../model/creature/{ => pig}/collision.json | 0 assets/model/creature/{ => pig}/pig.glb | Bin assets/model/creature/player/player.glb | Bin 0 -> 15992 bytes include/Cubed/app.hpp | 2 - include/Cubed/gameplay/entity.hpp | 17 ++-- .../Cubed/{AABB.hpp => gameplay/hitbox.hpp} | 8 +- include/Cubed/gameplay/hitbox_manager.hpp | 33 ++++--- include/Cubed/gameplay/world.hpp | 4 +- include/Cubed/render/model_manager.hpp | 18 +++- include/Cubed/render/model_renderer.hpp | 7 +- include/Cubed/render/renderer.hpp | 5 +- include/Cubed/tools/name_space.hpp | 19 ++++ include/Cubed/tools/sparse_vector.hpp | 2 +- src/app.cpp | 4 +- src/gameplay/client_player.cpp | 11 +-- src/gameplay/client_world.cpp | 8 +- src/gameplay/entity.cpp | 14 +++ src/gameplay/hitbox_manager.cpp | 81 ++++++++++++++---- src/gameplay/systems/physical_system.cpp | 26 +++--- src/render/model_manager.cpp | 48 +++++++---- src/render/model_renderer.cpp | 10 +-- src/render/renderer.cpp | 8 +- 22 files changed, 223 insertions(+), 102 deletions(-) rename assets/model/creature/{ => pig}/collision.json (100%) rename assets/model/creature/{ => pig}/pig.glb (100%) create mode 100644 assets/model/creature/player/player.glb rename include/Cubed/{AABB.hpp => gameplay/hitbox.hpp} (78%) create mode 100644 include/Cubed/tools/name_space.hpp diff --git a/assets/model/creature/collision.json b/assets/model/creature/pig/collision.json similarity index 100% rename from assets/model/creature/collision.json rename to assets/model/creature/pig/collision.json diff --git a/assets/model/creature/pig.glb b/assets/model/creature/pig/pig.glb similarity index 100% rename from assets/model/creature/pig.glb rename to assets/model/creature/pig/pig.glb diff --git a/assets/model/creature/player/player.glb b/assets/model/creature/player/player.glb new file mode 100644 index 0000000000000000000000000000000000000000..b94f8d9f5cdbde09adc2e071fea37ff1ea4e7c95 GIT binary patch literal 15992 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 literal 0 HcmV?d00001 diff --git a/include/Cubed/app.hpp b/include/Cubed/app.hpp index 2d509aa..9fd6c7c 100644 --- a/include/Cubed/app.hpp +++ b/include/Cubed/app.hpp @@ -3,7 +3,6 @@ #include "Cubed/audio/audio_engine.hpp" #include "Cubed/config.hpp" #include "Cubed/dev_panel.hpp" -#include "Cubed/render/model_manager.hpp" #include "Cubed/render/renderer.hpp" #include "Cubed/scene/scene_manager.hpp" #include "Cubed/texture_manager.hpp" @@ -50,7 +49,6 @@ private: Window m_window; TextureManager m_texture_manager; - ModelManager m_model_manager; AudioEngine m_audio; Renderer m_renderer; diff --git a/include/Cubed/gameplay/entity.hpp b/include/Cubed/gameplay/entity.hpp index e600bf2..d13860e 100644 --- a/include/Cubed/gameplay/entity.hpp +++ b/include/Cubed/gameplay/entity.hpp @@ -1,12 +1,13 @@ #pragma once -#include "Cubed/AABB.hpp" #include "Cubed/constants.hpp" +#include "Cubed/gameplay/hitbox.hpp" +#include "Cubed/gameplay/model.hpp" #include "Cubed/gameplay/player.hpp" #include #include namespace Cubed { - +using EntityID = uint64_t; struct Position { glm::vec3 value{0.0f}; }; @@ -22,6 +23,9 @@ struct WalkPose { struct EntityInfo { std::string name; std::string uuid; + EntityID id; + HitboxID hitbox; + ModelID model; }; struct Health { @@ -40,10 +44,6 @@ struct Velocity { glm::vec3 max{4.5f, 7.5f, 7.5f}; }; -struct HitBoxes { - std::vector boxex; -}; - struct Movement { float acceleration = DEFAULT_ACCELERATION; float deceleration = DEFAULT_DECELERATION; @@ -72,6 +72,8 @@ struct Direction { class Entity { public: + Entity(EntityID id, const std::string& name); + glm::vec3& max_speed(); float& acceleration(); float& deceleration(); @@ -91,6 +93,7 @@ public: Gravity& gravity(); MoveState& move_state(); Direction& direction(); + EntityInfo& info(); const Velocity& velocity() const; const Position& pos() const; @@ -100,8 +103,10 @@ public: const Gravity& gravity() const; const MoveState& move_state() const; const Direction& direction() const; + const EntityInfo& info() const; protected: + EntityInfo m_info; Position m_pos; WalkPose m_walk_pose; Velocity m_velocity; diff --git a/include/Cubed/AABB.hpp b/include/Cubed/gameplay/hitbox.hpp similarity index 78% rename from include/Cubed/AABB.hpp rename to include/Cubed/gameplay/hitbox.hpp index fd32468..70ab592 100644 --- a/include/Cubed/AABB.hpp +++ b/include/Cubed/gameplay/hitbox.hpp @@ -3,18 +3,20 @@ namespace Cubed { -struct AABB { +using HitboxID = uint32_t; + +struct Hitbox { glm::vec3 center{0.0f}; glm::vec3 half{0.0f}; - AABB(glm::vec3 center_point, glm::vec3 half_size) + Hitbox(glm::vec3 center_point, glm::vec3 half_size) : center(center_point), half(half_size) {} glm::vec3 min() const { return center - half; } glm::vec3 max() const { return center + half; } - bool intersects(const AABB& other) const { + bool intersects(const Hitbox& other) const { return (glm::abs(center.x - other.center.x) <= half.x + other.half.x) && (glm::abs(center.y - other.center.y) <= half.y + other.half.y) && (glm::abs(center.z - other.center.z) <= half.z + other.half.z); diff --git a/include/Cubed/gameplay/hitbox_manager.hpp b/include/Cubed/gameplay/hitbox_manager.hpp index d62f0e5..b8a2292 100644 --- a/include/Cubed/gameplay/hitbox_manager.hpp +++ b/include/Cubed/gameplay/hitbox_manager.hpp @@ -1,24 +1,37 @@ #pragma once -#include "Cubed/AABB.hpp" +#include "Cubed/gameplay/hitbox.hpp" #include namespace Cubed { class HitboxManager { public: + struct Handle { + Hitbox box; + HitboxID id = 0; + }; HitboxManager(); ~HitboxManager(); static HitboxManager& instance(); - AABB get_aabb(const std::string& key); - - static AABB aabb(const std::string& key); + [[nodiscard]] + Handle get_hitbox(const std::string& key); + [[nodiscard]] + Handle get_hitbox(HitboxID id); + [[nodiscard]] + static Handle hitbox(const std::string& name); + [[nodiscard]] + static Handle hitbox(HitboxID id); + HitboxID get_hitbox_id(const std::string& name); + const std::string& get_hitbox_name(HitboxID id); private: - using HitBoxMap = tbb::concurrent_hash_map; - using cacc = HitBoxMap::const_accessor; - using acc = HitBoxMap::accessor; - HitBoxMap m_hitboxes; - - AABB load(const std::string& path); + using HitboxMap = tbb::concurrent_hash_map; + using IDMap = tbb::concurrent_hash_map; + using NameMap = tbb::concurrent_hash_map; + HitboxID m_next = 0; + IDMap m_id_map; + NameMap m_name_map; + HitboxMap m_hitboxes; + Handle load(std::string_view name); }; } // namespace Cubed \ No newline at end of file diff --git a/include/Cubed/gameplay/world.hpp b/include/Cubed/gameplay/world.hpp index 038cee1..69ffd7c 100644 --- a/include/Cubed/gameplay/world.hpp +++ b/include/Cubed/gameplay/world.hpp @@ -1,6 +1,6 @@ #pragma once -#include "Cubed/AABB.hpp" #include "Cubed/gameplay/block.hpp" +#include "Cubed/gameplay/hitbox.hpp" #include namespace Cubed { @@ -19,7 +19,7 @@ public: virtual BlockType get_block_tpye(const glm::ivec3& block_pos) const = 0; virtual int get_per_tick_time() const = 0; - static AABB get_block_aabb(const glm::ivec3& pos) { + static Hitbox get_block_aabb(const glm::ivec3& pos) { return {glm::vec3{static_cast(pos.x) + 0.5f, static_cast(pos.y) + 0.5f, static_cast(pos.z) + 0.5f}, diff --git a/include/Cubed/render/model_manager.hpp b/include/Cubed/render/model_manager.hpp index ab78f6e..3a01382 100644 --- a/include/Cubed/render/model_manager.hpp +++ b/include/Cubed/render/model_manager.hpp @@ -7,14 +7,26 @@ namespace Cubed { class ModelManager { public: + struct Handle { + const ModelNode& node; + ModelID id = 0; + }; + ModelManager(); ModelManager(const ModelManager&) = delete; ModelManager(ModelManager&&) = delete; ModelManager& operator=(const ModelManager&) = delete; ModelManager& operator=(ModelManager&&) = delete; + static ModelManager& instance(); ~ModelManager(); - const ModelNode& get_model(const std::string& model_name); - const ModelNode& get_model(ModelID id); + [[nodiscard]] + Handle get_model(const std::string& model_name); + [[nodiscard]] + Handle get_model(ModelID id); + [[nodiscard]] + static Handle model(const std::string& model_name); + [[nodiscard]] + static Handle model(ModelID id); ModelID get_model_id(const std::string& name); const std::string& get_model_name(ModelID id); void init(); @@ -28,6 +40,6 @@ private: ModelMap m_models; IDMap m_id_map; NameMap m_name_map; - const ModelNode& load_model(std::string_view model_name); + Handle load_model(std::string_view model_name); }; } // namespace Cubed \ No newline at end of file diff --git a/include/Cubed/render/model_renderer.hpp b/include/Cubed/render/model_renderer.hpp index fc62ae0..b6ae802 100644 --- a/include/Cubed/render/model_renderer.hpp +++ b/include/Cubed/render/model_renderer.hpp @@ -1,5 +1,6 @@ #pragma once +#include "Cubed/gameplay/model.hpp" #include "Cubed/render/model_node.hpp" #include "Cubed/shader.hpp" @@ -10,11 +11,9 @@ class Camera; class ModelRender { public: ModelRender(Renderer& renderer); - void render_model(const std::string& name, const glm::vec3& pos, - Camera& camera); + void render_model(ModelID id, const glm::vec3& pos, Camera& camera); - void shadow_pass(const std::string& name, const glm::vec3& pos, - Camera& camera); + void shadow_pass(ModelID id, const glm::vec3& pos, Camera& camera); private: Renderer& m_renderer; diff --git a/include/Cubed/render/renderer.hpp b/include/Cubed/render/renderer.hpp index df772f1..b2deb3f 100644 --- a/include/Cubed/render/renderer.hpp +++ b/include/Cubed/render/renderer.hpp @@ -26,8 +26,7 @@ class Renderer { public: constexpr static int NUM_VAO = 7; - Renderer(TextureManager& texture_manager, Config& config, - ModelManager& model_manager); + Renderer(TextureManager& texture_manager, Config& config); ~Renderer(); void reload_config(); void init(); @@ -82,12 +81,10 @@ public: bool handle_event(const Event& e); - ModelManager& model_manager(); ModelRender& model_renderer(); private: TextureManager& m_texture_manager; - ModelManager& m_model_manager; bool m_init = false; float m_aspect = 0.0f; diff --git a/include/Cubed/tools/name_space.hpp b/include/Cubed/tools/name_space.hpp new file mode 100644 index 0000000..10c9d50 --- /dev/null +++ b/include/Cubed/tools/name_space.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include +#include +namespace Cubed { +inline std::vector parse_namespace(std::string_view str) { + std::vector space; + space.reserve(4); + std::size_t p = str.find(':'); + std::size_t start = 0; + while (p != std::string_view::npos) { + space.emplace_back(str.substr(start, p)); + start = p + 1; + p = str.find(':', p + 1); + } + space.emplace_back(str.substr(start)); + return space; +} +} // namespace Cubed \ No newline at end of file diff --git a/include/Cubed/tools/sparse_vector.hpp b/include/Cubed/tools/sparse_vector.hpp index f70e4a3..3b57c61 100644 --- a/include/Cubed/tools/sparse_vector.hpp +++ b/include/Cubed/tools/sparse_vector.hpp @@ -236,7 +236,7 @@ public: } }; - template Handle insert(U&& value) { + template [[nodiscard]] Handle insert(U&& value) { uint32_t id; if (!m_free_list.empty()) { id = m_free_list.back(); diff --git a/src/app.cpp b/src/app.cpp index 2ae7ddc..1abc51a 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -20,8 +20,7 @@ App::App() : m_game_config(ASSETS_PATH "config.toml"), m_window(m_game_config), m_texture_manager(m_game_config), m_audio(m_game_config), - m_renderer(m_texture_manager, m_game_config, m_model_manager), - m_scene_manager(*this) {} + m_renderer(m_texture_manager, m_game_config), m_scene_manager(*this) {} App::~App() { stop_text_input(); @@ -86,7 +85,6 @@ void App::init(int argc, char** argv) { Logger::info("Renderer Init Success"); // MapTable::init_map(); m_texture_manager.init_texture(); - m_model_manager.init(); Logger::info("Texture Load Success"); m_scene_manager.request_push(SceneType::MAIN_MENU); diff --git a/src/gameplay/client_player.cpp b/src/gameplay/client_player.cpp index b9fb33b..fe073b0 100644 --- a/src/gameplay/client_player.cpp +++ b/src/gameplay/client_player.cpp @@ -10,7 +10,8 @@ namespace {} // namespace namespace Cubed { -ClientPlayer::ClientPlayer(ClientWorld& world) : m_world(world) {} +ClientPlayer::ClientPlayer(ClientWorld& world) + : Entity(0, "cubed:player"), m_world(world) {} ClientPlayer::~ClientPlayer() {} const glm::vec3& ClientPlayer::get_front() const { return m_front; } @@ -312,10 +313,10 @@ void ClientPlayer::place_block(float dt) { if (type != 0) { glm::ivec3 near_pos = m_look_block->pos + m_look_block->normal; if (!m_world.is_solid(near_pos)) { - AABB block_box = ClientWorld::get_block_aabb(near_pos); - AABB player_box = HitboxManager::aabb("cubed:player"); - player_box.center += get_player_pos(); - if (!player_box.intersects(block_box)) { + Hitbox block_box = ClientWorld::get_block_aabb(near_pos); + auto player_box = HitboxManager::hitbox("cubed:player"); + player_box.box.center += get_player_pos(); + if (!player_box.box.intersects(block_box)) { m_world.report_block_change(near_pos, type); } } diff --git a/src/gameplay/client_world.cpp b/src/gameplay/client_world.cpp index 58ca240..e119c7b 100644 --- a/src/gameplay/client_world.cpp +++ b/src/gameplay/client_world.cpp @@ -295,14 +295,14 @@ void ClientWorld::push_delete_vao(std::unique_ptr& vao) { void ClientWorld::report_block_change(const glm::ivec3& pos, unsigned id) const { if (id != 0) { - AABB block_box = get_block_aabb(pos); + Hitbox block_box = get_block_aabb(pos); std::shared_lock lock(m_players_date_mutex); for (const auto& player : m_players_data) { - AABB box = HitboxManager::aabb("cubed:player"); - box.center += player.pos.value; - if (box.intersects(block_box)) { + auto box = HitboxManager::hitbox("cubed:player"); + box.box.center += player.pos.value; + if (box.box.intersects(block_box)) { return; } } diff --git a/src/gameplay/entity.cpp b/src/gameplay/entity.cpp index 7ea7030..2d98c92 100644 --- a/src/gameplay/entity.cpp +++ b/src/gameplay/entity.cpp @@ -1,6 +1,18 @@ #include "Cubed/gameplay/entity.hpp" +#include "Cubed/gameplay/hitbox_manager.hpp" +#include "Cubed/render/model_manager.hpp" namespace Cubed { + +Entity::Entity(EntityID id, const std::string& name) { + m_info.id = id; + m_info.name = name; + auto h = ModelManager::model(name); + m_info.model = h.id; + auto b = HitboxManager::hitbox(name); + m_info.hitbox = b.id; +} + glm::vec3& Entity::max_speed() { return m_velocity.max; } float& Entity::acceleration() { return m_movement.acceleration; } float& Entity::deceleration() { return m_movement.deceleration; } @@ -20,6 +32,7 @@ Movement& Entity::movement() { return m_movement; } Gravity& Entity::gravity() { return m_gravity; } MoveState& Entity::move_state() { return m_move_state; } Direction& Entity::direction() { return m_direction; } +EntityInfo& Entity::info() { return m_info; } const Velocity& Entity::velocity() const { return m_velocity; } const Position& Entity::pos() const { return m_pos; } @@ -29,5 +42,6 @@ const Movement& Entity::movement() const { return m_movement; } const Gravity& Entity::gravity() const { return m_gravity; } const MoveState& Entity::move_state() const { return m_move_state; } const Direction& Entity::direction() const { return m_direction; } +const EntityInfo& Entity::info() const { return m_info; } } // namespace Cubed \ No newline at end of file diff --git a/src/gameplay/hitbox_manager.cpp b/src/gameplay/hitbox_manager.cpp index a340709..f12a10d 100644 --- a/src/gameplay/hitbox_manager.cpp +++ b/src/gameplay/hitbox_manager.cpp @@ -1,7 +1,9 @@ #include "Cubed/gameplay/hitbox_manager.hpp" #include "Cubed/gameplay/player.hpp" +#include "Cubed/tools/cubed_assert.hpp" #include "Cubed/tools/log.hpp" +#include "Cubed/tools/name_space.hpp" #include namespace fs = std::filesystem; @@ -12,7 +14,13 @@ HitboxManager::HitboxManager() { glm::vec3 half = PLAYER_SIZE * 0.5f; glm::vec3 center{0.0f, half.y, 0.0f}; - m_hitboxes.emplace("cubed:player", AABB{center, half}); + + HitboxMap::accessor a; + if (m_hitboxes.insert( + a, std::pair{m_next++, Hitbox{center, half}})) { + m_name_map.emplace(a->first, "cubed:player"); + m_id_map.emplace("cubed:player", a->first); + } } HitboxManager::~HitboxManager() {} @@ -22,23 +30,56 @@ HitboxManager& HitboxManager::instance() { return inst; } -AABB HitboxManager::aabb(const std::string& key) { - return instance().get_aabb(key); +HitboxManager::Handle HitboxManager::hitbox(const std::string& key) { + return instance().get_hitbox(key); } -AABB HitboxManager::get_aabb(const std::string& key) { +HitboxManager::Handle HitboxManager::hitbox(HitboxID id) { + return instance().get_hitbox(id); +} +HitboxID HitboxManager::get_hitbox_id(const std::string& name) { + IDMap::const_accessor cacc; + if (m_id_map.find(cacc, name)) { + return cacc->second; + } + return load(name).id; +} +const std::string& HitboxManager::get_hitbox_name(HitboxID id) { + NameMap::const_accessor cacc; + if (m_name_map.find(cacc, id)) { + return cacc->second; + } + ASSERT_MSG(false, std::format("ModelManager: Can't find {}", id)); + static std::string n = ""; + return n; +} + +HitboxManager::Handle HitboxManager::get_hitbox(HitboxID id) { { - cacc c; - if (m_hitboxes.find(c, key)) { - return c->second; + HitboxMap::const_accessor c; + if (m_hitboxes.find(c, id)) { + return {c->second, c->first}; } } - return load(key); + return load(get_hitbox_name(id)); } +HitboxManager::Handle HitboxManager::get_hitbox(const std::string& name) { + return get_hitbox(get_hitbox_id(name)); +} +HitboxManager::Handle HitboxManager::load(std::string_view name) { + + auto space = parse_namespace(name); + ASSERT(space.size() >= 2); + fs::path p; + if (space[0] == "cubed") { + p = std::format("{}model/creature/{}/collision.json", ASSETS_PATH, + space[1]); + } else { + p = std::format("{}/model/creature/{}/collision.json", space[0], + space[1]); + } -AABB HitboxManager::load(const std::string& path) { - fs::path p = ASSETS_PATH + path; try { glm::vec3 center; glm::vec3 half; @@ -56,16 +97,24 @@ AABB HitboxManager::load(const std::string& path) { half.z = j["boxes"]["half"].at(2).get(); } } - acc a; - if (m_hitboxes.insert( - a, std::pair{path, AABB{center, half}})) { - return a->second; + { + HitboxMap::accessor a; + if (m_hitboxes.insert(a, std::pair{ + m_next++, Hitbox{center, half}})) { + m_name_map.emplace(a->first, name); + m_id_map.emplace(name, a->first); + return {a->second, a->first}; + } + } + HitboxMap::const_accessor cacc; + if (m_hitboxes.find(cacc, get_hitbox_id(std::string(name)))) { + return {cacc->second, cacc->first}; } } catch (const std::exception& e) { Logger::error("Load Hitbox error {}", e.what()); } - Logger::error("Load hitbox {} Failed", path); - return AABB{glm::vec3(0.0f), glm::vec3(0.0f)}; + Logger::error("Load hitbox {} Failed", name); + return {Hitbox{glm::vec3(0.0f), glm::vec3(0.0f)}, 0}; } } // namespace Cubed \ No newline at end of file diff --git a/src/gameplay/systems/physical_system.cpp b/src/gameplay/systems/physical_system.cpp index ed126d4..1115ccb 100644 --- a/src/gameplay/systems/physical_system.cpp +++ b/src/gameplay/systems/physical_system.cpp @@ -6,10 +6,10 @@ namespace Cubed { namespace { bool update_x(const glm::vec3& pos, const glm::vec3& distance, World& world, - const AABB& box) { + const Hitbox& box) { glm::vec3 p = pos; p.x += distance.x; - AABB b = box; + Hitbox b = box; b.center += p; glm::vec3 min = b.min(); glm::vec3 max = b.max(); @@ -25,7 +25,7 @@ bool update_x(const glm::vec3& pos, const glm::vec3& distance, World& world, for (int z = minz; z <= maxz; ++z) { glm::ivec3 block_pos{x, y, z}; if (!world.can_pass_block(block_pos)) { - AABB block_box = World::get_block_aabb(block_pos); + Hitbox block_box = World::get_block_aabb(block_pos); if (b.intersects(block_box)) { return false; } @@ -37,10 +37,10 @@ bool update_x(const glm::vec3& pos, const glm::vec3& distance, World& world, } bool update_y(const glm::vec3& pos, const glm::vec3& distance, World& world, - const AABB& box) { + const Hitbox& box) { glm::vec3 p = pos; p.y += distance.y; - AABB b = box; + Hitbox b = box; b.center += p; glm::vec3 min = b.min(); glm::vec3 max = b.max(); @@ -56,7 +56,7 @@ bool update_y(const glm::vec3& pos, const glm::vec3& distance, World& world, for (int z = minz; z <= maxz; ++z) { glm::ivec3 block_pos{x, y, z}; if (!world.can_pass_block(block_pos)) { - AABB block_box = World::get_block_aabb(block_pos); + Hitbox block_box = World::get_block_aabb(block_pos); if (b.intersects(block_box)) { return false; } @@ -68,10 +68,10 @@ bool update_y(const glm::vec3& pos, const glm::vec3& distance, World& world, } bool update_z(const glm::vec3& pos, const glm::vec3& distance, World& world, - const AABB& box) { + const Hitbox& box) { glm::vec3 p = pos; p.z += distance.z; - AABB b = box; + Hitbox b = box; b.center += p; glm::vec3 min = b.min(); glm::vec3 max = b.max(); @@ -87,7 +87,7 @@ bool update_z(const glm::vec3& pos, const glm::vec3& distance, World& world, for (int z = minz; z <= maxz; ++z) { glm::ivec3 block_pos{x, y, z}; if (!world.can_pass_block(block_pos)) { - AABB block_box = World::get_block_aabb(block_pos); + Hitbox block_box = World::get_block_aabb(block_pos); if (b.intersects(block_box)) { return false; } @@ -113,18 +113,18 @@ std::tuple PhysicalSystem::update(float dt, Entity& e, auto distance = get_move_distance(dt, e); auto& m_velocity = e.velocity(); auto& m_move_state = e.move_state(); - AABB box = HitboxManager::aabb("cubed:player"); + auto box = HitboxManager::hitbox(e.info().hitbox); bool x = false; bool y = false; bool z = false; - if (update_x(moved_pos, distance, world, box)) { + if (update_x(moved_pos, distance, world, box.box)) { moved_pos.x += distance.x; x = true; } else { m_velocity.value.x = 0.0f; } - if (update_y(moved_pos, distance, world, box)) { + if (update_y(moved_pos, distance, world, box.box)) { moved_pos.y += distance.y; y = true; } else { @@ -135,7 +135,7 @@ std::tuple PhysicalSystem::update(float dt, Entity& e, } } - if (update_z(moved_pos, distance, world, box)) { + if (update_z(moved_pos, distance, world, box.box)) { moved_pos.z += distance.z; z = true; } else { diff --git a/src/render/model_manager.cpp b/src/render/model_manager.cpp index 6cd047f..0201783 100644 --- a/src/render/model_manager.cpp +++ b/src/render/model_manager.cpp @@ -2,9 +2,24 @@ #include "Cubed/tools/cubed_assert.hpp" #include "Cubed/tools/log.hpp" +#include "Cubed/tools/name_space.hpp" namespace Cubed { -ModelManager::ModelManager() {} +ModelManager& ModelManager::instance() { + static ModelManager inst; + return inst; +} + +[[nodiscard]] +ModelManager::Handle ModelManager::model(const std::string& model_name) { + return instance().get_model(model_name); +} +[[nodiscard]] +ModelManager::Handle ModelManager::model(ModelID id) { + return instance().get_model(id); +} + +ModelManager::ModelManager() { init(); } ModelManager::~ModelManager() {} @@ -12,15 +27,15 @@ void ModelManager::init() { }; -const ModelNode& ModelManager::get_model(const std::string& model_name) { +ModelManager::Handle ModelManager::get_model(const std::string& model_name) { return get_model(get_model_id(model_name)); } -const ModelNode& ModelManager::get_model(ModelID id) { +ModelManager::Handle ModelManager::get_model(ModelID id) { ModelMap::const_accessor cacc; if (!m_models.find(cacc, id)) { - return cacc->second; + return {cacc->second, cacc->first}; } return load_model(get_model_name(id)); } @@ -32,8 +47,7 @@ ModelID ModelManager::get_model_id(const std::string& name) { if (m_id_map.find(cacc, name)) { return cacc->second; } - ASSERT_MSG(false, std::format("ModelManager: Can't find {}", name)); - return 0; + return load_model(name).id; } const std::string& ModelManager::get_model_name(ModelID id) { @@ -46,23 +60,24 @@ const std::string& ModelManager::get_model_name(ModelID id) { return n; } -const ModelNode& ModelManager::load_model(std::string_view model_name) { +ModelManager::Handle ModelManager::load_model(std::string_view model_name) { auto p = model_name.find(':'); if (p == std::string::npos) { Logger::error("Can't Parse Model name {}", model_name); ASSERT(false); } - auto name = model_name.substr(p + 1); - auto space = model_name.substr(0, p); - if (name.empty()) { + auto space = parse_namespace(model_name); + if (space.size() < 2) { Logger::error("Can't Parse Model name {}", model_name); ASSERT(false); } std::string path; - if (space == "cubed") { - path = std::format("{}model/creature/{}", ASSETS_PATH, name); + if (space[0] == "cubed") { + path = std::format("{}model/creature/{}/{}.gbl", ASSETS_PATH, space[1], + space[1]); } else { - path = std::format("./{}/model/creature/{}", space, name); + path = std::format("./{}/model/creature/{}/{}.gbl", space[0], space[1], + space[1]); } auto model = m_loader.load(path); ModelMap::accessor acc; @@ -70,11 +85,14 @@ const ModelNode& ModelManager::load_model(std::string_view model_name) { acc->second = std::move(model); } else { Logger::error("Can't Insert Model {}", model_name); - ASSERT(false); + ModelMap::const_accessor cacc; + if (m_models.find(cacc, get_model_id(std::string(model_name)))) { + return {cacc->second, cacc->first}; + } } m_id_map.emplace(model_name, acc->first); m_name_map.emplace(acc->first, model_name); - return acc->second; + return {acc->second, acc->first}; } } // namespace Cubed \ No newline at end of file diff --git a/src/render/model_renderer.cpp b/src/render/model_renderer.cpp index 1487f72..66bc4fd 100644 --- a/src/render/model_renderer.cpp +++ b/src/render/model_renderer.cpp @@ -6,10 +6,9 @@ namespace Cubed { ModelRender::ModelRender(Renderer& renderer) : m_renderer(renderer) {} -void ModelRender::render_model(const std::string& name, const glm::vec3& pos, +void ModelRender::render_model(ModelID id, const glm::vec3& pos, Camera& camera) { - auto& model_manager = m_renderer.model_manager(); - auto& root = model_manager.get_model(name); + auto& root = ModelManager::model(id).node; glm::mat4 transform = glm::translate(glm::mat4(1.0f), pos); auto& shader = m_renderer.get_shader("model_shader"); glm::mat4 view = camera.get_camera_lookat(); @@ -17,10 +16,9 @@ void ModelRender::render_model(const std::string& name, const glm::vec3& pos, render_node(root, transform, view, shader, false); } -void ModelRender::shadow_pass(const std::string& name, const glm::vec3& pos, +void ModelRender::shadow_pass(ModelID id, const glm::vec3& pos, Camera& camera) { - auto& model_manager = m_renderer.model_manager(); - auto& root = model_manager.get_model(name); + auto& root = ModelManager::model(id).node; glm::mat4 transform = glm::translate(glm::mat4(1.0f), pos); auto& shader = m_renderer.get_shader("depth_model"); glm::mat4 view = camera.get_camera_lookat(); diff --git a/src/render/renderer.cpp b/src/render/renderer.cpp index 494a5fa..b6d974c 100644 --- a/src/render/renderer.cpp +++ b/src/render/renderer.cpp @@ -15,10 +15,9 @@ namespace Cubed { -Renderer::Renderer(TextureManager& texture_manager, Config& config, - ModelManager& model_manager) - : m_texture_manager(texture_manager), m_model_manager(model_manager), - m_world_renderer(*this), m_model_renderer(*this), m_config(config) {} +Renderer::Renderer(TextureManager& texture_manager, Config& config) + : m_texture_manager(texture_manager), m_world_renderer(*this), + m_model_renderer(*this), m_config(config) {} Renderer::~Renderer() { if (m_init) { @@ -341,6 +340,5 @@ float Renderer::frame_height() const { return m_frame_height; } float Renderer::frame_width() const { return m_frame_width; } const glm::mat4& Renderer::p_mat() const { return m_world_proj_matrix; } const std::vector& Renderer::vao() const { return m_vao; } -ModelManager& Renderer::model_manager() { return m_model_manager; } ModelRender& Renderer::model_renderer() { return m_model_renderer; } } // namespace Cubed \ No newline at end of file