summary refs log tree commit diff
path: root/src/World/Generator.hpp
blob: 523136aa35ec5117c95dcdda97a5190e4aa84b55 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#pragma once

#include <cstdint>
#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 <typename V>
    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 <typename V>
    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<float> generate_landmass_map(int64_t chunk_x, int64_t chunk_y);
    ChunkMap2D<float> generate_hill_map(int64_t chunk_x, int64_t chunk_y);
    ChunkMap2D<float> generate_height_map(ChunkMap2D<float>& landmass_map, ChunkMap2D<float>& hill_map, int64_t chunk_x, int64_t chunk_y);

    ChunkMap2D<BiomeType> generate_biome_map(ChunkMap2D<float>& landmass_map, ChunkMap2D<float>& hill_map, ChunkMap2D<float>& height_map, int64_t chunk_x, int64_t chunk_y);

    ChunkMap3D<bool> generate_terrain(ChunkMap2D<float>& height_map, int64_t chunk_x, int64_t chunk_y);

    void decorate_soil(Chunk& chunk, ChunkMap2D<BiomeType>& biome_map, ChunkMap3D<bool>& 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<BiomeType, biome_lookup_table_size> 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<BiomeType, biome_lookup_table_size> biome_lookup_table = create_biome_lookup_table();
};

}