From 47f13ca99522567202c052579f3fe24c23b58010 Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Sun, 21 Jun 2026 17:42:59 +0800 Subject: [PATCH] feat(world): add ChunkLoadStyle enum and rename chunk_pos to get_chunk_pos --- include/Cubed/dev_panel.hpp | 1 + include/Cubed/gameplay/world.hpp | 8 +++- src/dev_panel.cpp | 6 +++ src/gameplay/chunk.cpp | 2 +- src/gameplay/player.cpp | 2 +- src/gameplay/world.cpp | 79 +++++++++++++++++++++++++++----- 6 files changed, 82 insertions(+), 16 deletions(-) diff --git a/include/Cubed/dev_panel.hpp b/include/Cubed/dev_panel.hpp index e56956d..75d2c96 100644 --- a/include/Cubed/dev_panel.hpp +++ b/include/Cubed/dev_panel.hpp @@ -49,6 +49,7 @@ private: bool m_tick_frezze = false; int m_samples_idx = 1; int m_threads = 1; + int m_chunk_style = 0; void show_about_table_bar(); void show_biome_table_bar(); void show_time_table_bar(); diff --git a/include/Cubed/gameplay/world.hpp b/include/Cubed/gameplay/world.hpp index 075fd2e..0cc926f 100644 --- a/include/Cubed/gameplay/world.hpp +++ b/include/Cubed/gameplay/world.hpp @@ -35,6 +35,8 @@ class Player; class TextureManager; class World { private: + enum class ChunkLoadStyle { RANDOM, CENTER }; + struct PendingChunk { Chunk chunk; std::future future; @@ -85,7 +87,7 @@ private: std::atomic m_pool_threads{1}; std::atomic m_max_threads{1}; std::atomic m_game_ticks{0}; - + std::atomic m_chunk_load_style{ChunkLoadStyle::RANDOM}; std::vector m_dirty_queue; std::vector m_render_snapshots; std::vector> m_new_finished_chunk; @@ -124,7 +126,7 @@ public: bool is_solid(const glm::ivec3& block_pos) const; bool can_pass_block(const glm::ivec3& block_pos) const; BlockType get_block_tpye(const glm::ivec3& block_pos) const; - static ChunkPos chunk_pos(int world_x, int world_z); + static ChunkPos get_chunk_pos(int world_x, int world_z); void need_gen(); @@ -163,6 +165,8 @@ public: int pool_threads() const; int max_threads() const; void change_pool_threads(int threads); + int chunk_load_style() const; + void set_chunk_load_style(int id); }; } // namespace Cubed diff --git a/src/dev_panel.cpp b/src/dev_panel.cpp index c68484c..7ac6341 100644 --- a/src/dev_panel.cpp +++ b/src/dev_panel.cpp @@ -480,6 +480,12 @@ void DevPanel::show_world_tab_item() { "threads minus reserved threads), \nit may cause stuttering."); } + static const char* chunk_load_style[] = {"Random", "Center"}; + m_chunk_style = m_app.world().chunk_load_style(); + if (ImGui::Combo("ChunkLoadStyle", &m_chunk_style, chunk_load_style, + IM_ARRAYSIZE(chunk_load_style))) { + m_app.world().set_chunk_load_style(m_chunk_style); + } if (ImGui::Button("Rebuild World")) { m_app.world().rebuild_world(); } diff --git a/src/gameplay/chunk.cpp b/src/gameplay/chunk.cpp index 24dcdc3..58f5758 100644 --- a/src/gameplay/chunk.cpp +++ b/src/gameplay/chunk.cpp @@ -299,7 +299,7 @@ void Chunk::gen_vertices(const OptionalBlockVectorArray& neighbor_block) { int world_nz = world_z + DIR[face].z; auto [neighbor_x, neighbor_z] = - World::chunk_pos(world_nx, world_nz); + World::get_chunk_pos(world_nx, world_nz); auto is_culled = [&](const std::optional>& diff --git a/src/gameplay/player.cpp b/src/gameplay/player.cpp index c785f80..68793a7 100644 --- a/src/gameplay/player.cpp +++ b/src/gameplay/player.cpp @@ -247,7 +247,7 @@ void Player::update_front_vec(float offset_x, float offset_y) { } void Player::check_player_chunk_transition() { - ChunkPos cur_pos = m_world.chunk_pos(m_player_pos.x, m_player_pos.z); + ChunkPos cur_pos = m_world.get_chunk_pos(m_player_pos.x, m_player_pos.z); if (cur_pos != m_player_chunk_pos) { m_world.need_gen(); m_player_chunk_pos = cur_pos; diff --git a/src/gameplay/world.cpp b/src/gameplay/world.cpp index ef73553..63d4fd7 100644 --- a/src/gameplay/world.cpp +++ b/src/gameplay/world.cpp @@ -9,6 +9,7 @@ #include using namespace std::chrono; using namespace std::chrono_literals; + namespace Cubed { struct ChunkRenderData { @@ -115,7 +116,7 @@ void World::init_chunks() { } } -ChunkPos World::chunk_pos(int world_x, int world_z) { +ChunkPos World::get_chunk_pos(int world_x, int world_z) { int chunk_x, chunk_z; if (world_x < 0) { chunk_x = (world_x + 1) / CHUNK_SIZE - 1; @@ -209,7 +210,7 @@ void World::compute_required_chunks(ChunkPosSet& required_chunks, int x = std::floor(player_pos.x); int z = std::floor(player_pos.z); - auto [chunk_x, chunk_z] = chunk_pos(x, z); + auto [chunk_x, chunk_z] = get_chunk_pos(x, z); int radius = m_rendering_distance; int r2 = radius * radius; required_chunks.reserve(radius * radius); @@ -255,16 +256,49 @@ void World::sync_and_collect_missing_chunks( } void World::submit_new_chunks() { + using enum ChunkLoadStyle; std::lock_guard lock(m_new_chunk_mutex); auto pool_ptr = m_gen_thread_pool.load(); if (!pool_ptr) { return; } - for (auto& [pos, task] : new_chunks) { - if (!task.future.valid()) { - task.future = - pool_ptr->enqueue([&task]() { task.chunk.gen_chunk(); }); + switch (m_chunk_load_style) { + case RANDOM: + for (auto& [pos, task] : new_chunks) { + if (!task.future.valid()) { + task.future = + pool_ptr->enqueue([&task]() { task.chunk.gen_chunk(); }); + } } + break; + case CENTER: { + std::vector> tasks; + for (auto& [pos, task] : new_chunks) { + if (!task.future.valid()) { + tasks.emplace_back(pos, &task); + } + } + glm::vec3 player_pos; + sync_player_pos(player_pos); + auto dist2 = [player_pos](ChunkPos chunk_pos) { + ChunkPos player_chunk_pos = + get_chunk_pos(player_pos.x, player_pos.z); + float dx = player_chunk_pos.x - chunk_pos.x; + float dz = player_chunk_pos.z - chunk_pos.z; + return dx * dx + dz * dz; + }; + + std::sort(tasks.begin(), tasks.end(), + [&dist2](const auto& a, const auto& b) { + return dist2(a.first) < dist2(b.first); + }); + for (auto& [pos, task] : tasks) { + if (!task->future.valid()) { + task->future = + pool_ptr->enqueue([task]() { task->chunk.gen_chunk(); }); + } + } + } } } @@ -363,7 +397,7 @@ void World::need_gen() { } int World::get_block(const glm::ivec3& block_pos) const { - auto [chunk_x, chunk_z] = chunk_pos(block_pos.x, block_pos.z); + auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z); std::lock_guard lk(m_chunks_mutex); auto it = m_chunks.find(ChunkPos{chunk_x, chunk_z}); @@ -381,7 +415,7 @@ int World::get_block(const glm::ivec3& block_pos) const { } bool World::is_solid(const glm::ivec3& block_pos) const { - auto [chunk_x, chunk_z] = chunk_pos(block_pos.x, block_pos.z); + auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z); std::lock_guard lk(m_chunks_mutex); auto it = m_chunks.find(ChunkPos{chunk_x, chunk_z}); @@ -403,7 +437,7 @@ bool World::is_solid(const glm::ivec3& block_pos) const { } bool World::can_pass_block(const glm::ivec3& block_pos) const { - auto [chunk_x, chunk_z] = chunk_pos(block_pos.x, block_pos.z); + auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z); std::lock_guard lk(m_chunks_mutex); auto it = m_chunks.find(ChunkPos{chunk_x, chunk_z}); @@ -421,7 +455,7 @@ bool World::can_pass_block(const glm::ivec3& block_pos) const { } BlockType World::get_block_tpye(const glm::ivec3& block_pos) const { - auto [chunk_x, chunk_z] = chunk_pos(block_pos.x, block_pos.z); + auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z); std::lock_guard lk(m_chunks_mutex); auto it = m_chunks.find(ChunkPos{chunk_x, chunk_z}); @@ -448,7 +482,7 @@ void World::set_block(const glm::ivec3& block_pos, unsigned id) { world_y = block_pos.y; world_z = block_pos.z; - auto [chunk_x, chunk_z] = chunk_pos(world_x, world_z); + auto [chunk_x, chunk_z] = get_chunk_pos(world_x, world_z); std::lock_guard lk(m_chunks_mutex); auto it = m_chunks.find(ChunkPos{chunk_x, chunk_z}); @@ -471,7 +505,7 @@ void World::set_block(const glm::ivec3& block_pos, unsigned id) { for (const auto& dir : NEIGHBOR_DIRS) { glm::ivec3 neighbor = block_pos + dir; - auto [cx, cz] = chunk_pos(neighbor.x, neighbor.z); + auto [cx, cz] = get_chunk_pos(neighbor.x, neighbor.z); auto it = m_chunks.find({cx, cz}); if (it != m_chunks.end()) { it->second.mark_dirty(); @@ -670,4 +704,25 @@ void World::change_pool_threads(int threads) { m_gen_thread_pool.store(std::make_shared(used_thread)); m_pool_threads = used_thread; } +int World::chunk_load_style() const { + return std::to_underlying(m_chunk_load_style.load()); +} +void World::set_chunk_load_style(int id) { + using enum ChunkLoadStyle; + using std::to_underlying; + switch (m_chunk_load_style.load()) { + case RANDOM: + if (id == to_underlying(RANDOM)) { + m_chunk_load_style = RANDOM; + return; + } + case CENTER: + if (id == to_underlying(CENTER)) { + m_chunk_load_style = CENTER; + return; + } + } + Logger::error("Can,t Find Chunk Load Style Id {}, Nothing Will Do", id); +} + } // namespace Cubed \ No newline at end of file