feat(world): add ChunkLoadStyle enum and rename chunk_pos to get_chunk_pos

This commit is contained in:
2026-06-21 17:42:59 +08:00
parent 4f6c5303ec
commit 47f13ca995
6 changed files with 82 additions and 16 deletions

View File

@@ -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();

View File

@@ -35,6 +35,8 @@ class Player;
class TextureManager;
class World {
private:
enum class ChunkLoadStyle { RANDOM, CENTER };
struct PendingChunk {
Chunk chunk;
std::future<void> future;
@@ -85,7 +87,7 @@ private:
std::atomic<int> m_pool_threads{1};
std::atomic<int> m_max_threads{1};
std::atomic<TickType> m_game_ticks{0};
std::atomic<ChunkLoadStyle> m_chunk_load_style{ChunkLoadStyle::RANDOM};
std::vector<ChunkPos> m_dirty_queue;
std::vector<ChunkRenderSnapshot> m_render_snapshots;
std::vector<std::pair<ChunkPos, Chunk>> 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

View File

@@ -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();
}

View File

@@ -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<std::vector<BlockType>>&

View File

@@ -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;

View File

@@ -9,6 +9,7 @@
#include <numbers>
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,17 +256,50 @@ 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;
}
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<std::pair<ChunkPos, PendingChunk*>> 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(); });
}
}
}
}
}
void World::poll_finished_chunks() {
@@ -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<ThreadPool>(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