feat: add ChunkGenerator

This commit is contained in:
2026-04-26 14:10:09 +08:00
parent a3eb19e58f
commit c5a78185ba
15 changed files with 523 additions and 336 deletions

View File

@@ -20,6 +20,7 @@ enum class Biome {
NONE
};
struct BiomeHeightRange {
int base_y;
int amplitude;
@@ -31,6 +32,13 @@ struct BiomeNonAdjacent {
Biome replace;
};
static inline const std::vector<BiomeNonAdjacent> NON_ADJACENT {{
{Biome::PLAIN, {Biome::NONE}, Biome::PLAIN},
{Biome::FOREST, {Biome::DESERT}, Biome::PLAIN},
{Biome::DESERT, {Biome::MOUNTAIN, Biome::FOREST}, Biome::PLAIN},
{Biome::MOUNTAIN, {Biome::DESERT}, Biome::PLAIN}
}};
struct BaseBiomeParams {
Biome biome;
std::pair<float, float> temp;

View File

@@ -6,6 +6,7 @@
#include <Cubed/config.hpp>
#include <Cubed/primitive_data.hpp>
#include <Cubed/gameplay/biome.hpp>
#include <Cubed/gameplay/chunk_generator.hpp>
#include <Cubed/gameplay/chunk_pos.hpp>
#include <Cubed/gameplay/block.hpp>
@@ -19,22 +20,17 @@ private:
static constexpr int SIZE_X = CHUCK_SIZE;
static constexpr int SIZE_Y = WORLD_SIZE_Y;
static constexpr int SIZE_Z = CHUCK_SIZE;
static inline const std::vector<BiomeNonAdjacent> NON_ADJACENT {{
{Biome::PLAIN, {Biome::NONE}, Biome::PLAIN},
{Biome::FOREST, {Biome::DESERT}, Biome::PLAIN},
{Biome::DESERT, {Biome::MOUNTAIN, Biome::FOREST}, Biome::PLAIN},
{Biome::MOUNTAIN, {Biome::DESERT}, Biome::PLAIN}
}
};
using HeightMapArray = std::array<std::array<float, SIZE_Z>, SIZE_X>;
std::atomic<bool> m_dirty {false};
std::atomic<bool> m_need_upload{true};
std::atomic<bool> m_is_on_gen_vertex_data {false};
std::atomic<size_t> m_vertex_sum = 0;
std::atomic<Biome> m_biome = Biome::PLAIN;
std::mutex m_vertexs_data_mutex;
std::atomic<Biome> m_biome = Biome::PLAIN;
std::unique_ptr<ChunkGenerator> m_generator;
ChunkPos m_chunk_pos;
World& m_world;
HeightMapArray m_heightmap;
@@ -57,25 +53,25 @@ public:
Chunk& operator=(Chunk&&) noexcept;
Biome get_biome() const;
ChunkPos get_chunk_pos() const;
const std::vector<uint8_t>& get_chunk_blocks() const;
HeightMapArray get_heightmap() const;
static int get_index(int x, int y, int z);
static int get_index(const glm::vec3& pos);
// Init Chunk
// Generate Biome
// Determine biome from temperature and humidity noise
void gen_phase_one();
// Adjust Biome
// Resolve biome adjacency conflicts with neighbor chunks
void gen_phase_two(const std::array<const Chunk*, 4>& adj_chunks);
// Generate Heightmap
// Generate heightmap using biome-specific noise
void gen_phase_three();
// Adjust Height
// Blend heightmap with neighbors for smooth transitions
void gen_phase_four(const std::array<std::optional<HeightMapArray>, 4>& neighbor_heightmap);
// Generate Block
// Generate terrain blocks from heightmap and biome
void gen_phase_five();
// Adjust Block;
// Blend surface blocks at chunk borders with neighbors
void gen_phase_six(const std::array<std::optional<std::vector<uint8_t>>, 4>& neighbor_block);
// Generate Structure
// Generate biome-specific vegetation/structures
void gen_phase_seven();
//void gen_vertex_data();
// 0 : (1, 0)
@@ -96,6 +92,11 @@ public:
void set_chunk_block(int index, unsigned id);
ChunkPos chunk_pos() const;
Biome biome() const;
void biome(Biome b);
HeightMapArray& heightmap();
std::vector<uint8_t>& blocks();
};

View File

@@ -0,0 +1,50 @@
#pragma once
#include <Cubed/constants.hpp>
#include <Cubed/tools/cubed_random.hpp>
#include <atomic>
#include <optional>
namespace Cubed {
class Chunk;
class ChunkGenerator {
static constexpr int SIZE_X = CHUCK_SIZE;
static constexpr int SIZE_Y = WORLD_SIZE_Y;
static constexpr int SIZE_Z = CHUCK_SIZE;
using HeightMapArray = std::array<std::array<float, CHUCK_SIZE>, CHUCK_SIZE>;
public:
ChunkGenerator(Chunk& chunk);
static void init();
static void reload();
static const unsigned& seed();
static void seed(unsigned s);
// Generate Biome
void assign_chunk_biome();
// Adjust Biome
void resolve_biome_adjacency_conflict(const std::array<const Chunk*, 4>& adj_chunks);
// Generate Heightmap
void generate_heightmap();
// Adjust Height
void blend_heightmap_boundaries(const std::array<std::optional<HeightMapArray>, 4>& neighbor_heightmap);
// Generate Block
void generate_terrain_blocks();
// Adjust Block;
void blend_surface_blocks_borders(const std::array<std::optional<std::vector<uint8_t>>, 4>& neighbor_block);
// Generate Structure
void generate_vegetation();
private:
static inline std::atomic<bool> is_init {false};
static inline unsigned m_generator_seed {0};
static inline std::atomic<bool> is_seed_change {false};
Chunk& m_chunk;
Random m_random;
};
}

View File

@@ -1,6 +1,6 @@
#pragma once
#include <string_view>
#include <cstdint>
namespace Cubed {
@@ -8,7 +8,26 @@ namespace HASH {
inline std::size_t str(std::string_view value) {
return std::hash<std::string_view>{}(value);
}
inline uint32_t mix_hash(int32_t a, int32_t b, uint32_t fixed_seed) {
uint32_t h = fixed_seed;
h ^= (uint32_t)a * 0xcc9e2d51u;
h = (h << 15) | (h >> 17); // rotl 15
h *= 0x1b873593u;
h ^= (uint32_t)b * 0xcc9e2d51u;
h = (h << 15) | (h >> 17); // rotl 15
h *= 0x1b873593u;
// Finalizationavalanche
h ^= h >> 16;
h *= 0x85ebca6bu;
h ^= h >> 13;
h *= 0xc2b2ae35u;
h ^= h >> 16;
return h;
}
}
}

View File

@@ -4,16 +4,15 @@ namespace Cubed {
class Random {
public:
static unsigned get_base_seed();
static unsigned get_thread_seed();
static Random& get();
Random();
bool random_bool(double probability);
std::mt19937& engine();
unsigned seed();
void init(unsigned seed);
private:
Random();
unsigned int m_seed = 0;
std::mt19937 m_engine;
};

View File

@@ -7,16 +7,12 @@ namespace Cubed {
class PerlinNoise {
public:
static void init();
static void init(unsigned seed);
static float noise(float x, float y, float z);
static void reload();
static const unsigned& seed();
static void seed(unsigned seed);
static void reload(unsigned seed);
private:
static inline std::atomic<bool> is_init = false;
static inline std::vector<int> p;
static inline unsigned m_seed = 0;
static inline bool is_seed_change = false;
static float fade(float t);
static float lerp(float t, float a, float b);
static float grad(int hash, float x, float y, float z);