diff options
| author | Mel <einebeere@gmail.com> | 2023-07-07 21:39:42 +0200 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2023-07-07 21:39:42 +0200 |
| commit | f1fc192ddc4c739fa8b4b376c759b7d3218a34eb (patch) | |
| tree | 9e9afb9a21ba3ca27d1f25d46230aa9d27f8be39 /src/World | |
| parent | 24b8124469350d1c80d0553cf3f4bf58cdb1489b (diff) | |
| download | meowcraft-f1fc192ddc4c739fa8b4b376c759b7d3218a34eb.tar.zst meowcraft-f1fc192ddc4c739fa8b4b376c759b7d3218a34eb.zip | |
Chunk-bound tree decoration
Diffstat (limited to 'src/World')
| -rw-r--r-- | src/World/BlockType.hpp | 2 | ||||
| -rw-r--r-- | src/World/Chunk.cpp | 155 | ||||
| -rw-r--r-- | src/World/Chunk.hpp | 15 | ||||
| -rw-r--r-- | src/World/Generation/ChunkMeshing.cpp (renamed from src/World/ChunkMeshing.cpp) | 19 | ||||
| -rw-r--r-- | src/World/Generation/ChunkMeshing.hpp (renamed from src/World/ChunkMeshing.hpp) | 6 | ||||
| -rw-r--r-- | src/World/Generation/Decoration.cpp | 97 | ||||
| -rw-r--r-- | src/World/Generation/Decoration.hpp | 34 | ||||
| -rw-r--r-- | src/World/Generation/Generator.cpp (renamed from src/World/Generator.cpp) | 92 | ||||
| -rw-r--r-- | src/World/Generation/Generator.hpp (renamed from src/World/Generator.hpp) | 29 | ||||
| -rw-r--r-- | src/World/World.cpp | 4 | ||||
| -rw-r--r-- | src/World/World.hpp | 4 |
11 files changed, 241 insertions, 216 deletions
diff --git a/src/World/BlockType.hpp b/src/World/BlockType.hpp index dcb8e44..472523f 100644 --- a/src/World/BlockType.hpp +++ b/src/World/BlockType.hpp @@ -14,6 +14,8 @@ public: Stone, Sand, Snow, + Wood, + Leaves, Water, }; diff --git a/src/World/Chunk.cpp b/src/World/Chunk.cpp index 9642fa9..b75516f 100644 --- a/src/World/Chunk.cpp +++ b/src/World/Chunk.cpp @@ -11,163 +11,16 @@ Chunk::BlockData Chunk::get(uint32_t x, uint32_t y, uint32_t z) const { return m_blocks.at(pos(x, y, z)); } -GFX::Mesh Chunk::mesh() { - std::vector<Vector<3>> positions{}; - std::vector<Vector<3>> normals{}; - std::vector<Vector<2>> tex_coords{}; - std::vector<uint32_t> indices{}; - - for (int x = 0; x < Width; x++) { - for (int y = 0; y < Height; y++) { - for (int z = 0; z < Width; z++) { - auto type = get(x, y, z).type; - if (type == BlockType::Air) { - continue; - } - - for (auto side: BlockSide::all()) { - if (!is_face_visible(x, y, z, side)) { - continue; - } - - auto side_positions = side.face(); - auto side_normals = face_normals(side); - auto side_tex_coords = face_tex_coords(type, side); - - for (auto& position : side_positions) { - position = position + Vector<3>{static_cast<float>(x), static_cast<float>(y), static_cast<float>(z)}; - } - - uint32_t s = positions.size(); - - positions.insert(positions.end(), side_positions.begin(), side_positions.end()); - normals.insert(normals.end(), side_normals.begin(), side_normals.end()); - tex_coords.insert(tex_coords.end(), side_tex_coords.begin(), side_tex_coords.end()); - indices.insert(indices.end(), {s, s + 1, s + 3, s + 1, s + 2, s + 3}); - } - } - } - } - - return { - {positions, normals, tex_coords}, - indices, - }; +bool Chunk::is_empty(uint32_t x, uint32_t y, uint32_t z) const { + return get(x, y, z).empty(); } Vector<3> Chunk::position() { return m_position; } -bool Chunk::is_face_visible(uint32_t x, uint32_t y, uint32_t z, BlockSide side) { - Vector<3, int32_t> offset{}; - switch (side) { - case BlockSide::Front: - offset[2] = 1; - break; - case BlockSide::Back: - offset[2] = -1; - break; - case BlockSide::Top: - offset[1] = 1; - break; - case BlockSide::Bottom: - offset[1] = -1; - break; - case BlockSide::Left: - offset[0] = -1; - break; - case BlockSide::Right: - offset[0] = 1; - break; - } - - Vector<3, uint32_t> neighbor_pos{ - x + offset.x(), y + offset.y(), z + offset.z(), - }; - - if ( - neighbor_pos.x() >= Width || neighbor_pos.x() < 0 || - neighbor_pos.y() >= Height || neighbor_pos.y() < 0 || - neighbor_pos.z() >= Width || neighbor_pos.z() < 0 - ) { - return true; - } - - auto neighbor = get(neighbor_pos.x(), neighbor_pos.y(), neighbor_pos.z()); - if (neighbor.type == BlockType::Air) { - return true; - } - - return false; -} - -std::array<Vector<2>, 4> Chunk::face_tex_coords(BlockType type, BlockSide side) { - uint8_t atlas_width = 4; - uint8_t atlas_height = 4; - - float width_step = 1.0f / atlas_width; - float height_step = 1.0f / atlas_height; - - auto block_coords = [=](uint8_t x, uint8_t y) { - auto t = y * height_step; - auto l = x * width_step; - auto b = t + height_step; - auto r = l + width_step; - - return std::array<Vector<2>, 4>{{ - {l, b}, {r, b}, {r, t}, {l, t}, - }}; - }; - - switch (type) { - case BlockType::Dirt: - return block_coords(1, 0); - case BlockType::Grass: - switch (side) { - case BlockSide::Front: - case BlockSide::Back: - case BlockSide::Left: - case BlockSide::Right: - return block_coords(2, 0); - case BlockSide::Bottom: - return block_coords(1, 0); - case BlockSide::Top: - return block_coords(0, 0); - } - case BlockType::Stone: - return block_coords(3, 0); - case BlockType::Sand: - return block_coords(0, 1); - case BlockType::Water: - return block_coords(1, 1); - case BlockType::Snow: - switch (side) { - case BlockSide::Front: - case BlockSide::Back: - case BlockSide::Left: - case BlockSide::Right: - return block_coords(3, 1); - case BlockSide::Bottom: - return block_coords(1, 0); - case BlockSide::Top: - return block_coords(2, 1); - } - case BlockType::Air: - return {}; - } -} - -std::array<Vector<3>, 4> Chunk::face_normals(BlockSide side) { - auto is_side = [=](BlockSide s) -> float { return s == side; }; - - Vector<3> normal = { - is_side(BlockSide::Right) - is_side(BlockSide::Left), - is_side(BlockSide::Top) - is_side(BlockSide::Bottom), - is_side(BlockSide::Front) - is_side(BlockSide::Back), - }; - - return {normal, normal, normal, normal}; +bool Chunk::is_valid_position(uint32_t x, uint32_t y, uint32_t z) { + return x < Width && y < Height && z < Width; } uint64_t Chunk::pos(uint32_t x, uint32_t y, uint32_t z) { diff --git a/src/World/Chunk.hpp b/src/World/Chunk.hpp index d200039..8780700 100644 --- a/src/World/Chunk.hpp +++ b/src/World/Chunk.hpp @@ -19,27 +19,30 @@ public: struct BlockData { BlockType type; + + bool empty() const { return type == BlockType::Air; } }; void set(uint32_t x, uint32_t y, uint32_t z, BlockData data); BlockData get(uint32_t x, uint32_t y, uint32_t z) const; + bool is_empty(uint32_t x, uint32_t y, uint32_t z) const; struct Details { Matrix<Width, Width> landmass_values{}; Matrix<Width, Width> hill_values{}; + + Matrix<Width, Width> temperature_values{}; + Matrix<Width, Width> humidity_values{}; + Matrix<Width, Width, BiomeType> biome_values{}; }; void set_details(const Details& details) { m_details = details; } Details& details(){ return m_details; } Vector<3> position(); - GFX::Mesh mesh(); -private: - bool is_face_visible(uint32_t x, uint32_t y, uint32_t z, BlockSide side); - - static std::array<Vector<2>, 4> face_tex_coords(BlockType type, BlockSide side); - static std::array<Vector<3>, 4> face_normals(BlockSide side); + static bool is_valid_position(uint32_t x, uint32_t y, uint32_t z); +private: static uint64_t pos(uint32_t x, uint32_t y, uint32_t z); Vector<3> m_position; diff --git a/src/World/ChunkMeshing.cpp b/src/World/Generation/ChunkMeshing.cpp index 3e50427..54abc85 100644 --- a/src/World/ChunkMeshing.cpp +++ b/src/World/Generation/ChunkMeshing.cpp @@ -1,6 +1,6 @@ #include "ChunkMeshing.hpp" -namespace MC::World { +namespace MC::World::Generation { std::array<Vector<2>, 4> face_tex_coords(BlockType type, BlockSide side) { uint8_t atlas_width = 4; @@ -38,9 +38,9 @@ std::array<Vector<2>, 4> face_tex_coords(BlockType type, BlockSide side) { case BlockType::Stone: return block_coords(3, 0); case BlockType::Sand: - return block_coords(0, 1); - case BlockType::Water: return block_coords(1, 1); + case BlockType::Water: + return block_coords(0, 1); case BlockType::Snow: switch (side) { case BlockSide::Front: @@ -53,6 +53,19 @@ std::array<Vector<2>, 4> face_tex_coords(BlockType type, BlockSide side) { case BlockSide::Top: return block_coords(2, 1); } + case BlockType::Wood: + switch (side) { + case BlockSide::Front: + case BlockSide::Back: + case BlockSide::Right: + case BlockSide::Left: + return block_coords(0, 2); + case BlockSide::Bottom: + case BlockSide::Top: + return block_coords(1, 2); + } + case BlockType::Leaves: + return block_coords(2, 2); case BlockType::Air: return {}; } diff --git a/src/World/ChunkMeshing.hpp b/src/World/Generation/ChunkMeshing.hpp index 1348817..a4fed25 100644 --- a/src/World/ChunkMeshing.hpp +++ b/src/World/Generation/ChunkMeshing.hpp @@ -1,9 +1,9 @@ #pragma once -#include "../GFX/Mesh.hpp" -#include "Chunk.hpp" +#include "../../GFX/Mesh.hpp" +#include "../Chunk.hpp" -namespace MC::World::ChunkMeshing { +namespace MC::World::Generation::ChunkMeshing { struct ChunkNeighbors { Chunk &north, &east, &south, &west; }; GFX::Mesh create_mesh_for_chunk(Chunk& chunk, ChunkNeighbors neighbors); diff --git a/src/World/Generation/Decoration.cpp b/src/World/Generation/Decoration.cpp new file mode 100644 index 0000000..26eb397 --- /dev/null +++ b/src/World/Generation/Decoration.cpp @@ -0,0 +1,97 @@ +#include "Decoration.hpp" + +#include <iostream> + +namespace MC::World::Generation { +void Decorator::put_block(Chunk& chunk, Pos pos, BlockType block) { + if (!Chunk::is_valid_position(pos.x(), pos.y(), pos.z())) { + return; + } + if (chunk.is_empty(pos.x(), pos.y(), pos.z())) { + chunk.set(pos.x(), pos.y(), pos.z(), {block}); + } +} + +void Decorator::draw_column(Chunk& chunk, Pos pos, uint height, BlockType block) { + Pos current_pos = pos; + for (uint i = 0; i < height; i++) { + put_block(chunk, current_pos, block); + current_pos += Pos::up(); + } +} + +void Decorator::draw_circle(Chunk& chunk, Pos pos, Vector<3> axis, float radius, BlockType block) { + auto normalized_axis = axis.normalize(); + + auto ortho1 = normalized_axis.any_orthogonal(); + auto ortho2 = normalized_axis.cross(ortho1); + + auto r = [](const float x) { return static_cast<uint>(std::round(x)); }; + + int radius_round = std::round(radius); + for (int32_t d1 = -radius_round; d1 <= radius_round; d1++) { + float height = std::sqrt(radius * radius - d1 * d1); + for (int32_t d2 = -height; d2 <= (int)height; d2++) { + auto p = ortho1 * d1 + ortho2 * d2; + Pos block_pos = pos + Pos{r(p.x()), r(p.y()), r(p.z())}; + put_block(chunk, block_pos, block); + } + } +} + +void TreeDecorator::decorate_chunk(Chunk& chunk) { + Pos last_tree = Pos::max(); + for (uint x = 0; x < Chunk::Width; x++) { + for (uint z = 0; z < Chunk::Width; z++) { + for (uint y = Chunk::Height; y > 1; y--) { + Pos pos{x, y, z}; + if (!is_valid_position(pos)) + continue; + + auto block_below = chunk.get(x, y-1, z); + if (block_below.empty()) + continue; + + auto type = block_below.type; + if (type != BlockType::Snow && type != BlockType::Grass && type != BlockType::Dirt) + break; + + auto noise = m_tree_noise.at({(float)x, (float)z}); + if (noise < 0.8f) + continue; + + if (last_tree.distance(pos) < s_tree_radius * 3) + continue; + + draw_tree(chunk, pos); + chunk.set(x, y-1, z, {BlockType::Dirt}); + last_tree = pos; + break; + } + } + } +} + +void TreeDecorator::draw_tree(Chunk& chunk, Pos pos) const { + auto noise = m_tree_noise.at({(float)pos.x(), (float)pos.z()}); + uint height = std::round(10 * noise - 4.75f); + + draw_column(chunk, pos, height, BlockType::Wood); + + uint max_leaf_height = 4; + for (int x = 0; x < max_leaf_height; x++) { + Pos p{pos.x(), pos.y() + height + x - 2, pos.z()}; + float radius = s_tree_radius - 0.5f + x * ((0.3f * x - 1.45f) * x + 1.25f); + draw_circle(chunk, p, Vector<3>::up(), radius, BlockType::Leaves); + } +} + +bool TreeDecorator::is_valid_position(Vector<3, uint> pos) { + int tree_radius = s_tree_radius; + return (int)pos.x() - tree_radius >= 0 + && pos.x() + tree_radius <= Chunk::Width + && (int)pos.z() - tree_radius >= 0 + && pos.z() + tree_radius <= Chunk::Width; +} + +} diff --git a/src/World/Generation/Decoration.hpp b/src/World/Generation/Decoration.hpp new file mode 100644 index 0000000..a592e72 --- /dev/null +++ b/src/World/Generation/Decoration.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "../Chunk.hpp" +#include "../../Math/Random.hpp" + +namespace MC::World::Generation { + +class Decorator { +public: + using Pos = Vector<3, uint>; + + virtual ~Decorator() = default; + + virtual void decorate_chunk(Chunk& chunk) = 0; + + static void put_block(Chunk& chunk, Pos pos, BlockType block); + static void draw_column(Chunk& chunk, Pos pos, uint height, BlockType block); + static void draw_circle(Chunk& chunk, Pos pos, Vector<3> axis, float radius, BlockType block); +}; + +class TreeDecorator final : public Decorator { +public: + void decorate_chunk(Chunk& chunk) override; +private: + void draw_tree(Chunk& chunk, Pos pos) const; + + static bool is_valid_position(Pos pos); + + static constexpr uint s_tree_radius = 3; + + Math::Random::Noise<2> m_tree_noise; +}; + +} diff --git a/src/World/Generator.cpp b/src/World/Generation/Generator.cpp index ada2b7b..af3c54d 100644 --- a/src/World/Generator.cpp +++ b/src/World/Generation/Generator.cpp @@ -1,8 +1,8 @@ #include "Generator.hpp" -#include "../Math/Interpolation.hpp" -#include "../Math/Sigmoid.hpp" +#include "../../Math/Interpolation.hpp" +#include "../../Math/Sigmoid.hpp" -namespace MC::World { +namespace MC::World::Generation { Chunk Generator::generate(int64_t chunk_x, int64_t chunk_y) { Chunk chunk(chunk_x, chunk_y); @@ -11,40 +11,32 @@ Chunk Generator::generate(int64_t chunk_x, int64_t chunk_y) { auto hill_map = generate_hill_map(chunk_x, chunk_y); auto height_map = generate_height_map(landmass_map, hill_map, chunk_x, chunk_y); - auto biome_map = generate_biome_map(landmass_map, hill_map, height_map, chunk_x, chunk_y); + auto temperature_map = generate_temperature_map(chunk_x, chunk_y); + auto humidity_map = generate_humidity_map(chunk_x, chunk_y); + auto biome_map = generate_biome_map(landmass_map, hill_map, temperature_map, humidity_map, chunk_x, chunk_y); auto terrain_map = generate_terrain(height_map, chunk_x, chunk_y); decorate_soil(chunk, biome_map, terrain_map); - chunk.set_details({{landmass_map}, {hill_map}, {biome_map}}); + chunk.set_details({landmass_map, hill_map, temperature_map, humidity_map, biome_map}); return chunk; } -Generator::Map2D<float> Generator::generate_landmass_map(int64_t chunk_x, int64_t chunk_y) { - Matrix<Chunk::Width, Chunk::Width> landmass_map{}; - - for (uint x = 0; x < Chunk::Width; x++) { - for (uint y = 0; y < Chunk::Width; y++) { - auto world_pos = chunk_position_to_world_vector(chunk_x, chunk_y, x, y); - landmass_map(x, y) = get_landmass(world_pos); - } - } - - return landmass_map; +#define SIMPLE_MAP_GENERATOR(name, getter) \ +Generator::Map2D<float> Generator::name(int64_t chunk_x, int64_t chunk_y) { \ + Matrix<Chunk::Width, Chunk::Width> map{}; \ + for (uint x = 0; x < Chunk::Width; x++) { \ + for (uint y = 0; y < Chunk::Width; y++) { \ + auto pos = chunk_position_to_world_vector(chunk_x, chunk_y, x, y); \ + map(x, y) = getter(pos); \ + } \ + } \ + return map; \ } -Generator::Map2D<float> Generator::generate_hill_map(int64_t chunk_x, int64_t chunk_y) { - Map2D<float> hill_map{}; - - for (uint x = 0; x < Chunk::Width; x++) { - for (uint y = 0; y < Chunk::Width; y++) { - hill_map(x, y) = get_hill(chunk_position_to_world_vector(chunk_x, chunk_y, x, y)); - } - } - - return hill_map; -} +SIMPLE_MAP_GENERATOR(generate_landmass_map, get_landmass) +SIMPLE_MAP_GENERATOR(generate_hill_map, get_hill) Generator::Map2D<float> Generator::generate_height_map(Map2D<float>& landmass_map, Map2D<float>& hill_map, int64_t chunk_x, int64_t chunk_y) { Map2D<float> height_map{}; @@ -66,7 +58,14 @@ Generator::Map2D<float> Generator::generate_height_map(Map2D<float>& landmass_ma return height_map; } -Generator::Map2D<BiomeType> Generator::generate_biome_map(Map2D<float>& landmass_map, Map2D<float>& hill_map, Map2D<float>& height_map, int64_t chunk_x, int64_t chunk_y) { +SIMPLE_MAP_GENERATOR(generate_temperature_map, get_temperature) +SIMPLE_MAP_GENERATOR(generate_humidity_map, get_humidity) + +Generator::Map2D<BiomeType> Generator::generate_biome_map( + Map2D<float>& landmass_map, Map2D<float>& hill_map, + Map2D<float>& temperature_map, Map2D<float>& humidity_map, + int64_t chunk_x, int64_t chunk_y +) { Map2D<BiomeType> biome_map{}; for (uint x = 0; x < Chunk::Width; x++) { @@ -74,13 +73,12 @@ Generator::Map2D<BiomeType> Generator::generate_biome_map(Map2D<float>& landmass float landmass = landmass_map(x, y); float hill = hill_map(x, y); - auto world_pos = chunk_position_to_world_vector(chunk_x, chunk_y, x, y); - float temperature = get_temperature(world_pos); - float humidity = get_humidity(world_pos); + float temperature = temperature_map(x, y); + float humidity = humidity_map(x, y); HillSlice hill_slice; - if (hill > 0.9) { hill_slice = HillSlice::Mountain; } - else if (hill > 0.33) { hill_slice = HillSlice::Middle; } + if (hill > 0.55) { hill_slice = HillSlice::Mountain; } + else if (hill > 0.03) { hill_slice = HillSlice::Middle; } else { hill_slice = HillSlice::Valley; } LandmassSlice landmass_slice; @@ -89,8 +87,8 @@ Generator::Map2D<BiomeType> Generator::generate_biome_map(Map2D<float>& landmass else { landmass_slice = LandmassSlice::Ocean; } TemperatureZone temparature_zone; - if (temperature > 0.66) { temparature_zone = TemperatureZone::Hot; } - else if (temperature > 0.33) { temparature_zone = TemperatureZone::Fair; } + if (temperature > 0.6) { temparature_zone = TemperatureZone::Hot; } + else if (temperature > 0.4) { temparature_zone = TemperatureZone::Fair; } else { temparature_zone = TemperatureZone::Cold; } HumidityZone humidity_zone; @@ -130,7 +128,7 @@ Generator::Map3D<bool> Generator::generate_terrain(Map2D<float>& height_map, int void Generator::decorate_soil(Chunk& chunk, Map2D<BiomeType>& biome_map, Map3D<bool>& terrain_map) { constexpr uint dirt_depth = 4; - constexpr uint water_height = 39; + constexpr uint water_height = 40; for (uint x = 0; x < Chunk::Width; x++) { for (uint z = 0; z < Chunk::Width; z++) { @@ -147,8 +145,8 @@ void Generator::decorate_soil(Chunk& chunk, Map2D<BiomeType>& biome_map, Map3D<b case BiomeType::Jungle: case BiomeType::Forest: case BiomeType::Plains: - case BiomeType::River: case BiomeType::Ocean: + case BiomeType::River: top_block = BlockType::Grass; soil_block = BlockType::Dirt; break; @@ -156,6 +154,10 @@ void Generator::decorate_soil(Chunk& chunk, Map2D<BiomeType>& biome_map, Map3D<b top_block = BlockType::Snow; soil_block = BlockType::Dirt; break; + case BiomeType::Shore: + case BiomeType::RockyPeaks: + top_block = BlockType::Stone; + soil_block = BlockType::Stone; } auto column_depth = 0; @@ -179,6 +181,10 @@ void Generator::decorate_soil(Chunk& chunk, Map2D<BiomeType>& biome_map, Map3D<b } } } + + for (auto& decorator : s_decorators) { + decorator->decorate_chunk(chunk); + } } #define CURVE_START(y) constexpr auto lerp = Math::linear_interpolation; float _py = y; float _px = 0.0f; @@ -249,7 +255,11 @@ std::array<BiomeType, Generator::biome_lookup_table_size> Generator::create_biom goto set; } if (landmass_slice == LandmassSlice::Beach) { - biome = BiomeType::Beach; + if (temperature_zone == TemperatureZone::Cold) { + biome = BiomeType::Shore; + } else { + biome = BiomeType::Beach; + } goto set; } @@ -258,10 +268,10 @@ std::array<BiomeType, Generator::biome_lookup_table_size> Generator::create_biom goto set; } if (hill_slice == HillSlice::Mountain) { - if (temperature_zone == TemperatureZone::Hot) { - biome = BiomeType::Desert; - } else { + if (temperature_zone == TemperatureZone::Cold) { biome = BiomeType::Alpine; + } else { + biome = BiomeType::RockyPeaks; } goto set; } diff --git a/src/World/Generator.hpp b/src/World/Generation/Generator.hpp index a90d1bc..464e36f 100644 --- a/src/World/Generator.hpp +++ b/src/World/Generation/Generator.hpp @@ -1,12 +1,14 @@ #pragma once #include <cstdint> -#include "Chunk.hpp" -#include "BiomeType.hpp" -#include "../Math/Perlin.hpp" -#include "../Math/Tensor.hpp" -namespace MC::World { +#include "Decoration.hpp" +#include "../Chunk.hpp" +#include "../BiomeType.hpp" +#include "../../Math/Perlin.hpp" +#include "../../Math/Tensor.hpp" + +namespace MC::World::Generation { class Generator { public: @@ -20,7 +22,14 @@ private: Map2D<float> generate_hill_map(int64_t chunk_x, int64_t chunk_y); Map2D<float> generate_height_map(Map2D<float>& landmass_map, Map2D<float>& hill_map, int64_t chunk_x, int64_t chunk_y); - Map2D<BiomeType> generate_biome_map(Map2D<float>& landmass_map, Map2D<float>& hill_map, Map2D<float>& height_map, int64_t chunk_x, int64_t chunk_y); + Map2D<float> generate_temperature_map(int64_t chunk_x, int64_t chunk_y); + Map2D<float> generate_humidity_map(int64_t chunk_x, int64_t chunk_y); + + Map2D<BiomeType> generate_biome_map( + Map2D<float>& landmass_map, Map2D<float>& hill_map, + Map2D<float>& temperature_map, Map2D<float>& humidity_map, + int64_t chunk_x, int64_t chunk_y + ); Map3D<bool> generate_terrain(Map2D<float>& height_map, int64_t chunk_x, int64_t chunk_y); @@ -36,11 +45,15 @@ private: static Vector<2> chunk_position_to_world_vector(int64_t chunk_x, int64_t chunk_y, uint x, uint y); + static inline std::vector<Decorator*> 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=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<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}; diff --git a/src/World/World.cpp b/src/World/World.cpp index 289d86b..6e8489a 100644 --- a/src/World/World.cpp +++ b/src/World/World.cpp @@ -1,5 +1,5 @@ #include "World.hpp" -#include "ChunkMeshing.hpp" +#include "Generation/ChunkMeshing.hpp" namespace MC::World { @@ -127,7 +127,7 @@ void World::try_to_create_mesh_for_chunk(ChunkData& data) { return; } - data.mesh_data = ChunkMeshing::create_mesh_for_chunk( + data.mesh_data = Generation::ChunkMeshing::create_mesh_for_chunk( data.chunk.value(), {north.chunk.value(), east.chunk.value(), south.chunk.value(), west.chunk.value()} ); diff --git a/src/World/World.hpp b/src/World/World.hpp index e6b3cd2..ae8b37f 100644 --- a/src/World/World.hpp +++ b/src/World/World.hpp @@ -3,7 +3,7 @@ #include <memory> #include <unordered_map> #include <unordered_set> -#include "Generator.hpp" +#include "Generation/Generator.hpp" #include "ChunkIndex.hpp" #include "../GFX/Binder.hpp" #include "../Compute/Queue.hpp" @@ -53,7 +53,7 @@ private: uint64_t generation_duration; }; Compute::Queue<GenerationResult, ChunkIndex> m_queue; - Generator m_generator; + Generation::Generator m_generator; std::unordered_map<ChunkIndex, ChunkData> m_chunks; std::unordered_set<ChunkIndex> m_visible_chunks; |
