From 30a4713092f816c79dc6484a6d1b918013fe4950 Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Fri, 17 Apr 2026 22:45:44 +0800 Subject: [PATCH] refactor: extract biome logic into separate --- include/Cubed/config.hpp | 1 - .../gameplay/{chunk_status.hpp => biome.hpp} | 73 ++++++++++++------- include/Cubed/gameplay/chunk.hpp | 3 +- include/Cubed/gameplay/chunk_pos.hpp | 30 ++++++++ include/Cubed/gameplay/player.hpp | 2 +- include/Cubed/tools/math_tools.hpp | 1 - src/gameplay/chunk.cpp | 2 +- src/tools/math_tools.cpp | 47 +----------- 8 files changed, 81 insertions(+), 78 deletions(-) rename include/Cubed/gameplay/{chunk_status.hpp => biome.hpp} (57%) create mode 100644 include/Cubed/gameplay/chunk_pos.hpp diff --git a/include/Cubed/config.hpp b/include/Cubed/config.hpp index 6cf2c12..03dbb5a 100644 --- a/include/Cubed/config.hpp +++ b/include/Cubed/config.hpp @@ -10,7 +10,6 @@ constexpr int MAX_CHARACTER = 128; constexpr float NORMAL_FOV = 70.0f; constexpr int MAX_BIOME_SUM = 4; -constexpr float BIOME_NOISE_FREQUENCY = 0.003f; constexpr float VERTICES_POS[6][6][3] = { // ===== front (z = +1) ===== diff --git a/include/Cubed/gameplay/chunk_status.hpp b/include/Cubed/gameplay/biome.hpp similarity index 57% rename from include/Cubed/gameplay/chunk_status.hpp rename to include/Cubed/gameplay/biome.hpp index 95728bc..6879c88 100644 --- a/include/Cubed/gameplay/chunk_status.hpp +++ b/include/Cubed/gameplay/biome.hpp @@ -1,34 +1,14 @@ #pragma once -#include #include -#include +#include #include +#include -#include #include -struct ChunkPos { - int x; - int z; - - bool operator==(const ChunkPos&) const = default; - struct Hash { - std::size_t operator()(const ChunkPos& pos) const{ - std::size_t h1 = std::hash{}(pos.x); - std::size_t h2 = std::hash{}(pos.z); - return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2)); - } - }; +#include +#include - ChunkPos operator+(const ChunkPos& pos) const{ - return ChunkPos{x + pos.x, z + pos.z}; - } - - ChunkPos& operator+=(const ChunkPos& pos) { - x += pos.x; - z += pos.z; - return *this; - }; -}; +constexpr float BIOME_NOISE_FREQUENCY = 0.003f; constexpr float PLAIN_FREQ = 0.5f; constexpr float FOREST_FREQ = 1.0f; @@ -47,7 +27,7 @@ struct BiomeHeightRange { int amplitude; }; -constexpr inline std::string get_biome_str(Biome biome) { +inline std::string get_biome_str(Biome biome) { std::string str; using enum Biome; switch (biome) { @@ -131,6 +111,45 @@ inline Biome safe_int_to_biome(int x) { return it->second; } - +inline int get_interpolated_height(float world_x, float world_z, float temp, float humid) { + + auto weight = [](float t, float h, float ct, float ch) -> float { + float dt = t - ct; + float dh = h - ch; + float dist = std::sqrt(dt*dt + dh*dh); + return std::max(0.0f, 0.5f - dist); + }; + + float w_mountain = weight(temp, humid, 0.25f, 0.15f); + float w_plain = weight(temp, humid, 0.50f, 0.40f); + float w_desert = weight(temp, humid, 0.75f, 0.15f); + float w_forest = weight(temp, humid, 0.75f, 0.75f); + // adjust transitions between chunks + float pow_n = 8.0f; // the larger n is, the purer the biome + w_mountain = std::pow(w_mountain, pow_n) * MOUNTAIN_FREQ; + w_plain = std::pow(w_plain, pow_n) * PLAIN_FREQ; + w_desert = std::pow(w_desert, pow_n) * DESERT_FREQ; + w_forest = std::pow(w_forest, pow_n) * FOREST_FREQ; + + float total = w_mountain + w_plain + w_desert + w_forest; + w_mountain /= total; w_plain /= total; w_desert /= total; w_forest /= total; + + auto sample_height = [&](Biome b) -> float { + auto range = get_biome_height_range(b); + auto [f1, f2, f3] = get_noise_frequencies_for_biome(b); + float n = + 1.00f * PerlinNoise::noise(world_x * f1, 0.5f, world_z * f1) + + 0.50f * PerlinNoise::noise(world_x * f2, 0.5f, world_z * f2) + + 0.25f * PerlinNoise::noise(world_x * f3, 0.5f, world_z * f3); + n /= 1.75f; + return range.base_y + n * range.amplitude; + }; + + float h = w_mountain * sample_height(Biome::MOUNTAIN) + + w_plain * sample_height(Biome::PLAIN) + + w_desert * sample_height(Biome::DESERT) + + w_forest * sample_height(Biome::FOREST); + return static_cast(h); + } diff --git a/include/Cubed/gameplay/chunk.hpp b/include/Cubed/gameplay/chunk.hpp index 17172ae..19944cb 100644 --- a/include/Cubed/gameplay/chunk.hpp +++ b/include/Cubed/gameplay/chunk.hpp @@ -4,7 +4,8 @@ #include #include -#include +#include +#include #include class World; diff --git a/include/Cubed/gameplay/chunk_pos.hpp b/include/Cubed/gameplay/chunk_pos.hpp new file mode 100644 index 0000000..e16b776 --- /dev/null +++ b/include/Cubed/gameplay/chunk_pos.hpp @@ -0,0 +1,30 @@ +#pragma once +#include + + +#include +#include +struct ChunkPos { + int x; + int z; + + bool operator==(const ChunkPos&) const = default; + struct Hash { + std::size_t operator()(const ChunkPos& pos) const{ + std::size_t h1 = std::hash{}(pos.x); + std::size_t h2 = std::hash{}(pos.z); + return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2)); + } + }; + + ChunkPos operator+(const ChunkPos& pos) const{ + return ChunkPos{x + pos.x, z + pos.z}; + } + + ChunkPos& operator+=(const ChunkPos& pos) { + x += pos.x; + z += pos.z; + return *this; + }; +}; + diff --git a/include/Cubed/gameplay/player.hpp b/include/Cubed/gameplay/player.hpp index 476560b..c0b72e9 100644 --- a/include/Cubed/gameplay/player.hpp +++ b/include/Cubed/gameplay/player.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include diff --git a/include/Cubed/tools/math_tools.hpp b/include/Cubed/tools/math_tools.hpp index 60416dd..9935d70 100644 --- a/include/Cubed/tools/math_tools.hpp +++ b/include/Cubed/tools/math_tools.hpp @@ -2,5 +2,4 @@ #include namespace Math { void extract_frustum_planes(const glm::mat4& mvp_matrix, std::vector& planes); - int get_interpolated_height(float world_x, float world_z, float temp, float humid); } \ No newline at end of file diff --git a/src/gameplay/chunk.cpp b/src/gameplay/chunk.cpp index b35fbfa..0edfe1f 100644 --- a/src/gameplay/chunk.cpp +++ b/src/gameplay/chunk.cpp @@ -283,7 +283,7 @@ void Chunk::resolve_blocks() { float temp = PerlinNoise::noise(world_x * BIOME_NOISE_FREQUENCY, 0.0f, world_z * BIOME_NOISE_FREQUENCY); float humid = PerlinNoise::noise(world_x * BIOME_NOISE_FREQUENCY, 1.0f, world_z * BIOME_NOISE_FREQUENCY); - int height = Math::get_interpolated_height(world_x, world_z, temp, humid); + int height = get_interpolated_height(world_x, world_z, temp, humid); auto biome = get_biome_from_noise(temp, humid); for (int y = 5; y < height - 5; y++) { m_blocks[get_index(x, y, z)] = 3; diff --git a/src/tools/math_tools.cpp b/src/tools/math_tools.cpp index 5f14c39..68ddb04 100644 --- a/src/tools/math_tools.cpp +++ b/src/tools/math_tools.cpp @@ -2,12 +2,6 @@ #include -#include - -#include -#include -#include - namespace Math { void extract_frustum_planes(const glm::mat4& mvp_matrix, std::vector& planes) { if (planes.size() != 6) { @@ -34,44 +28,5 @@ namespace Math { } } - int get_interpolated_height(float world_x, float world_z, float temp, float humid) { - - auto weight = [](float t, float h, float ct, float ch) -> float { - float dt = t - ct; - float dh = h - ch; - float dist = std::sqrt(dt*dt + dh*dh); - return std::max(0.0f, 0.5f - dist); - }; - - float w_mountain = weight(temp, humid, 0.25f, 0.15f); - float w_plain = weight(temp, humid, 0.50f, 0.40f); - float w_desert = weight(temp, humid, 0.75f, 0.15f); - float w_forest = weight(temp, humid, 0.75f, 0.75f); - // adjust transitions between chunks - float pow_n = 8.0f; // the larger n is, the purer the biome - w_mountain = std::pow(w_mountain, pow_n) * MOUNTAIN_FREQ; - w_plain = std::pow(w_plain, pow_n) * PLAIN_FREQ; - w_desert = std::pow(w_desert, pow_n) * DESERT_FREQ; - w_forest = std::pow(w_forest, pow_n) * FOREST_FREQ; - - float total = w_mountain + w_plain + w_desert + w_forest; - w_mountain /= total; w_plain /= total; w_desert /= total; w_forest /= total; - - auto sample_height = [&](Biome b) -> float { - auto range = get_biome_height_range(b); - auto [f1, f2, f3] = get_noise_frequencies_for_biome(b); - float n = - 1.00f * PerlinNoise::noise(world_x * f1, 0.5f, world_z * f1) + - 0.50f * PerlinNoise::noise(world_x * f2, 0.5f, world_z * f2) + - 0.25f * PerlinNoise::noise(world_x * f3, 0.5f, world_z * f3); - n /= 1.75f; - return range.base_y + n * range.amplitude; - }; - - float h = w_mountain * sample_height(Biome::MOUNTAIN) - + w_plain * sample_height(Biome::PLAIN) - + w_desert * sample_height(Biome::DESERT) - + w_forest * sample_height(Biome::FOREST); - return static_cast(h); - } + } \ No newline at end of file