#pragma once #include #include "Chunk.hpp" #include "BiomeType.hpp" #include "../Math/Perlin.hpp" namespace MC::World { class Generator { public: Generator() = default; Chunk generate(int64_t chunk_x, int64_t chunk_y); private: template struct ChunkMap2D { V map[Chunk::Width * Chunk::Width]; void set(uint x, uint y, V v) { map[x * Chunk::Width + y] = v; } V get(uint x, uint y) { return map[x * Chunk::Width + y]; } }; template struct ChunkMap3D { V map[Chunk::Width * Chunk::Width * Chunk::Height]; void set(uint x, uint y, uint z, V v) { map[pos(x, y, z)] = v; } V get(uint x, uint y, uint z) { return map[pos(x, y, z)]; } static uint pos(uint x, uint y, uint z) { return x + Chunk::Width * y + Chunk::Width * Chunk::Height * z; } }; ChunkMap2D generate_landmass_map(int64_t chunk_x, int64_t chunk_y); ChunkMap2D generate_hill_map(int64_t chunk_x, int64_t chunk_y); ChunkMap2D generate_height_map(ChunkMap2D& landmass_map, ChunkMap2D& hill_map, int64_t chunk_x, int64_t chunk_y); ChunkMap2D generate_biome_map(ChunkMap2D& landmass_map, ChunkMap2D& hill_map, ChunkMap2D& height_map, int64_t chunk_x, int64_t chunk_y); ChunkMap3D generate_terrain(ChunkMap2D& height_map, int64_t chunk_x, int64_t chunk_y); void decorate_soil(Chunk& chunk, ChunkMap2D& biome_map, ChunkMap3D& terrain_map); [[nodiscard]] float get_landmass(Vector<2> pos) const; [[nodiscard]] float get_hill(Vector<2> pos) const; [[nodiscard]] float get_humidity(Vector<2> pos) const; [[nodiscard]] float get_temperature(Vector<2> pos) const; [[nodiscard]] float get_density(Vector<3> pos) const; static Vector<2> chunk_position_to_world_vector(int64_t chunk_x, int64_t chunk_y, uint x, uint y); Math::Perlin::Noise<2> m_landmass_noise{.scale=800.0f, .octaves=4, .persistence=0.3f, .lacunarity=3.5f}; Math::Perlin::Noise<2> m_hill_noise{.scale=400.0f, .octaves=3, .persistence=0.5f, .lacunarity=2.0f}; Math::Perlin::Noise<2> m_temperature_noise{.scale=700.0f, .octaves=3, .persistence=0.5f, .lacunarity=2.0f}; Math::Perlin::Noise<2> m_humidity_noise{.scale=400.0f, .octaves=2, .persistence=0.5f, .lacunarity=2.0f}; Math::Perlin::Noise<3> m_density_noise{.scale=30.0f, .octaves=2, .persistence=0.7f, .lacunarity=2.0f}; enum class HillSlice { Mountain, Middle, Valley }; enum class LandmassSlice { Land, Beach, Ocean }; enum class TemperatureZone { Hot, Fair, Cold }; enum class HumidityZone { Wet, Lush, Temperate, Dry }; static constexpr uint HillSliceSize = (uint)HillSlice::Valley + 1; static constexpr uint LandmassSliceSize = (uint)LandmassSlice::Ocean + 1; static constexpr uint TemperatureZoneSize = (uint)TemperatureZone::Cold + 1; static constexpr uint HumidityZoneSize = (uint)HumidityZone::Dry + 1; static constexpr size_t biome_lookup_table_size = (size_t)HillSliceSize * (size_t)LandmassSliceSize * (size_t)TemperatureZoneSize * (size_t)HumidityZoneSize; static std::array create_biome_lookup_table(); static size_t biome_lookup_table_index(HillSlice hill_slice, LandmassSlice landmass_slice, TemperatureZone temperature_zone, HumidityZone humidity_zone); static BiomeType lookup_biome(HillSlice hill_slice, LandmassSlice landmass_slice, TemperatureZone temperature_zone, HumidityZone humidity_zone); static inline std::array biome_lookup_table = create_biome_lookup_table(); }; }