summaryrefslogtreecommitdiff
path: root/src/World
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2023-07-07 21:39:42 +0200
committerMel <einebeere@gmail.com>2023-07-07 21:39:42 +0200
commitf1fc192ddc4c739fa8b4b376c759b7d3218a34eb (patch)
tree9e9afb9a21ba3ca27d1f25d46230aa9d27f8be39 /src/World
parent24b8124469350d1c80d0553cf3f4bf58cdb1489b (diff)
downloadmeowcraft-f1fc192ddc4c739fa8b4b376c759b7d3218a34eb.tar.zst
meowcraft-f1fc192ddc4c739fa8b4b376c759b7d3218a34eb.zip
Chunk-bound tree decoration
Diffstat (limited to 'src/World')
-rw-r--r--src/World/BlockType.hpp2
-rw-r--r--src/World/Chunk.cpp155
-rw-r--r--src/World/Chunk.hpp15
-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.cpp97
-rw-r--r--src/World/Generation/Decoration.hpp34
-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.cpp4
-rw-r--r--src/World/World.hpp4
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;