#pragma once #include "../../Common/Sizes.hpp" #include "../Chunk.hpp" #include "../BiomeType.hpp" #include "../../Math/Perlin.hpp" #include "../../Math/Tensor.hpp" #include "Decoration.hpp" namespace MC::World::Generation { class Generator { public: Generator() = default; Chunk generate(I64 chunk_x, I64 chunk_y); private: template using Map2D = Matrix; template using Map3D = Tensor<3, V, Chunk::Width, Chunk::Height, Chunk::Width>; Map2D generate_landmass_map(I64 chunk_x, I64 chunk_y); Map2D generate_hill_map(I64 chunk_x, I64 chunk_y); Map2D generate_height_map(Map2D& landmass_map, Map2D& hill_map); Map2D generate_temperature_map(I64 chunk_x, I64 chunk_y); Map2D generate_humidity_map(I64 chunk_x, I64 chunk_y); Map2D generate_biome_map( Map2D& landmass_map, Map2D& hill_map, Map2D& temperature_map, Map2D& humidity_map ); Map3D generate_terrain(Map2D& height_map, I64 chunk_x, I64 chunk_y); void decorate_soil(Chunk& chunk, Map2D& biome_map, Map3D& terrain_map); [[nodiscard]] Real get_landmass(Vector<2> pos) const; [[nodiscard]] Real get_hill(Vector<2> pos) const; [[nodiscard]] Real get_humidity(Vector<2> pos) const; [[nodiscard]] Real get_temperature(Vector<2> pos) const; [[nodiscard]] Real get_density(Vector<3> pos) const; static Vector<2> chunk_position_to_world_vector(I64 chunk_x, I64 chunk_y, UInt x, UInt y); static inline std::vector s_decorators = { new TreeDecorator(), }; 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=4, .persistence=0.4f, .lacunarity=3.0f}; Math::Perlin::Noise<2> m_humidity_noise{.scale=400.0f, .octaves=2, .persistence=0.4f, .lacunarity=3.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 USize biome_lookup_table_size = (USize)HillSliceSize * (USize)LandmassSliceSize * (USize)TemperatureZoneSize * (USize)HumidityZoneSize; static std::array create_biome_lookup_table(); static USize 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(); }; }