summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Math/Matrix.hpp24
-rw-r--r--src/Math/Tensor.hpp43
-rw-r--r--src/World/Generator.cpp49
-rw-r--r--src/World/Generator.hpp29
4 files changed, 88 insertions, 57 deletions
diff --git a/src/Math/Matrix.hpp b/src/Math/Matrix.hpp
index 276dc4a..69241d3 100644
--- a/src/Math/Matrix.hpp
+++ b/src/Math/Matrix.hpp
@@ -2,23 +2,21 @@
#include <sstream>
#include <cstddef>
-#include <iostream>
#include "Rotation.hpp"
#include "Trig.hpp"
template <size_t R, size_t C, typename T = float>
struct Matrix {
-public:
- Matrix<R, C, T>() : elements{} {};
+ Matrix() : elements{} {};
- Matrix<R, C, T>(T scalar) {
+ explicit Matrix(T scalar) {
std::fill(elements, elements + R * C, scalar);
};
- template<typename ...Args, typename std::enable_if<sizeof...(Args) == R * C, int>::type = 0>
- Matrix<R, C, T>(Args... args): elements{ args... } {};
+ template<typename ...Args, typename std::enable_if_t<sizeof...(Args) == R * C, int> = 0>
+ Matrix(Args... args): elements{ args... } {};
- Matrix<R, C, T>(T values[R * C]) {
+ explicit Matrix(T values[R * C]) {
std::copy(values, values + R * C, elements);
};
@@ -81,8 +79,8 @@ public:
return result;
}
- Matrix<R, C, T> transpose() {
- Matrix<R, C, T> result{};
+ Matrix transpose() {
+ Matrix result{};
for (int y = 0; y < R; y++) {
for (int x = 0; x < C; x++) {
result(x, y) = this->operator()(y, x);
@@ -91,16 +89,16 @@ public:
return result;
}
- Matrix<R, C, T> operator+(Matrix<R, C, T> other) {
- Matrix<R, C, T> result{};
+ Matrix operator+(Matrix other) {
+ Matrix result{};
for (int i = 0; i < R * C; i++) {
result.elements[i] = elements[i] + other.elements[i];
}
return result;
}
- Matrix<R, C, T> operator*(float scalar) {
- Matrix<R, C, T> result{};
+ Matrix operator*(float scalar) {
+ Matrix result{};
for (int i = 0; i < R * C; i++) {
result.elements[i] = elements[i] * scalar;
}
diff --git a/src/Math/Tensor.hpp b/src/Math/Tensor.hpp
new file mode 100644
index 0000000..e373c1f
--- /dev/null
+++ b/src/Math/Tensor.hpp
@@ -0,0 +1,43 @@
+#pragma once
+
+template<size_t O, typename T, size_t ...S>
+struct Tensor {
+ static constexpr size_t element_size = (S*...);
+
+ template<typename ...Args>
+ using EnableArgs = std::enable_if_t<sizeof...(Args) == O, bool>;
+ template<typename ...Args>
+ using EnableArgsPerElement = std::enable_if_t<sizeof...(Args) == element_size, bool>;
+ using Enable = std::enable_if_t<sizeof...(S) == O, bool>;
+
+ template<Enable = true>
+ Tensor() : elements{} {}
+
+ template<Enable = true>
+ explicit Tensor(T scalar) {
+ std::fill(elements, elements + element_size, scalar);
+ }
+
+ template<Enable = true, typename ...Args, EnableArgsPerElement<Args...> = true>
+ Tensor(Args... args) : elements{ args... } {}
+
+ template<typename ...Args, EnableArgs<Args...> = true>
+ auto& operator()(Args... args) {
+ return elements[pos(args...)];
+ }
+
+ template<typename ...Args, EnableArgs<Args...> = true>
+ static constexpr size_t pos(Args... args) {
+ size_t positions[O] = {static_cast<size_t>(args)...};
+ size_t dimensions[O] = {S...};
+
+ size_t p = 0;
+ for (int i = 0; i < O; i++) {
+ p *= dimensions[i];
+ p += positions[i];
+ }
+ return p;
+ }
+
+ T elements[element_size];
+};
diff --git a/src/World/Generator.cpp b/src/World/Generator.cpp
index f528278..ada2b7b 100644
--- a/src/World/Generator.cpp
+++ b/src/World/Generator.cpp
@@ -16,62 +16,63 @@ Chunk Generator::generate(int64_t chunk_x, int64_t chunk_y) {
decorate_soil(chunk, biome_map, terrain_map);
- chunk.set_details({{landmass_map.map}, {hill_map.map}, {biome_map.map}});
+ chunk.set_details({{landmass_map}, {hill_map}, {biome_map}});
return chunk;
}
-Generator::ChunkMap2D<float> Generator::generate_landmass_map(int64_t chunk_x, int64_t chunk_y) {
- ChunkMap2D<float> landmass_map{};
+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++) {
- landmass_map.set(x, y, get_landmass(chunk_position_to_world_vector(chunk_x, chunk_y, x, 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;
}
-Generator::ChunkMap2D<float> Generator::generate_hill_map(int64_t chunk_x, int64_t chunk_y) {
- ChunkMap2D<float> hill_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.set(x, y, get_hill(chunk_position_to_world_vector(chunk_x, chunk_y, x, y)));
+ hill_map(x, y) = get_hill(chunk_position_to_world_vector(chunk_x, chunk_y, x, y));
}
}
return hill_map;
}
-Generator::ChunkMap2D<float> Generator::generate_height_map(ChunkMap2D<float>& landmass_map, ChunkMap2D<float>& hill_map, int64_t chunk_x, int64_t chunk_y) {
- ChunkMap2D<float> height_map{};
+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{};
for (uint x = 0; x < Chunk::Width; x++) {
for (uint y = 0; y < Chunk::Width; y++) {
- auto landmass_effect = landmass_map.get(x, y);
- auto hill_effect = hill_map.get(x, y);
+ auto landmass_effect = landmass_map(x, y);
+ auto hill_effect = hill_map(x, y);
auto hill = hill_effect * landmass_effect * 1.4 - 0.4;
auto landmass = landmass_effect * 0.6 + 0.4;
auto height = (hill + landmass) / 2.0f;
- height_map.set(x, y, height);
+ height_map(x, y) = height;
}
}
return height_map;
}
-Generator::ChunkMap2D<BiomeType> Generator::generate_biome_map(ChunkMap2D<float>& landmass_map, ChunkMap2D<float>& hill_map, ChunkMap2D<float>& height_map, int64_t chunk_x, int64_t chunk_y) {
- ChunkMap2D<BiomeType> biome_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) {
+ Map2D<BiomeType> biome_map{};
for (uint x = 0; x < Chunk::Width; x++) {
for (uint y = 0; y < Chunk::Width; y++) {
- float landmass = landmass_map.get(x, y);
- float hill = hill_map.get(x, y);
+ 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);
@@ -98,27 +99,27 @@ Generator::ChunkMap2D<BiomeType> Generator::generate_biome_map(ChunkMap2D<float>
else { humidity_zone = HumidityZone::Dry; }
auto biome = lookup_biome(hill_slice, landmass_slice, temparature_zone, humidity_zone);
- biome_map.set(x, y, biome);
+ biome_map(x, y) = biome;
}
}
return biome_map;
}
-Generator::ChunkMap3D<bool> Generator::generate_terrain(ChunkMap2D<float>& height_map, int64_t chunk_x, int64_t chunk_y) {
+Generator::Map3D<bool> Generator::generate_terrain(Map2D<float>& height_map, int64_t chunk_x, int64_t chunk_y) {
float jaggedness = 0.10f;
- ChunkMap3D<bool> terrain_map{};
+ Map3D<bool> terrain_map{};
for (uint x = 0; x < Chunk::Width; x++) {
for (uint z = 0; z < Chunk::Width; z++) {
- auto height = height_map.get(x, z);
+ auto height = height_map(x, z);
for (uint y = 0; y < Chunk::Height; y++) {
float density = get_density({Chunk::Width * chunk_x + (float)x, (float)y, Chunk::Width * chunk_y + (float)z});
float threshold = Math::sigmoid(((float)y / (Chunk::Height * height * 2) - 0.5f) / jaggedness);
if (density > threshold) {
- terrain_map.set(x, y, z, true);
+ terrain_map(x, y, z) = true;
}
}
}
@@ -127,13 +128,13 @@ Generator::ChunkMap3D<bool> Generator::generate_terrain(ChunkMap2D<float>& heigh
return terrain_map;
}
-void Generator::decorate_soil(Chunk& chunk, ChunkMap2D<BiomeType>& biome_map, ChunkMap3D<bool>& terrain_map) {
+void Generator::decorate_soil(Chunk& chunk, Map2D<BiomeType>& biome_map, Map3D<bool>& terrain_map) {
constexpr uint dirt_depth = 4;
constexpr uint water_height = 39;
for (uint x = 0; x < Chunk::Width; x++) {
for (uint z = 0; z < Chunk::Width; z++) {
- auto biome = biome_map.get(x, z);
+ auto biome = biome_map(x, z);
BlockType top_block{};
BlockType soil_block{};
@@ -159,7 +160,7 @@ void Generator::decorate_soil(Chunk& chunk, ChunkMap2D<BiomeType>& biome_map, Ch
auto column_depth = 0;
for (uint y = Chunk::Height - 1; y > 0; y--) {
- auto block = terrain_map.get(x, y, z);
+ auto block = terrain_map(x, y, z);
if (block) {
if (column_depth == 0 && y >= water_height - 1) {
chunk.set(x, y, z, {top_block});
diff --git a/src/World/Generator.hpp b/src/World/Generator.hpp
index 523136a..a90d1bc 100644
--- a/src/World/Generator.hpp
+++ b/src/World/Generator.hpp
@@ -4,6 +4,7 @@
#include "Chunk.hpp"
#include "BiomeType.hpp"
#include "../Math/Perlin.hpp"
+#include "../Math/Tensor.hpp"
namespace MC::World {
@@ -12,30 +13,18 @@ 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> using Map2D = Matrix<Chunk::Width, Chunk::Width, V>;
+ template <typename V> using Map3D = Tensor<3, V, Chunk::Width, Chunk::Height, Chunk::Width>;
- 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; }
- };
+ Map2D<float> generate_landmass_map(int64_t chunk_x, int64_t chunk_y);
+ 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);
- 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);
+ 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);
- 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);
+ Map3D<bool> generate_terrain(Map2D<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);
+ void decorate_soil(Chunk& chunk, Map2D<BiomeType>& biome_map, Map3D<bool>& terrain_map);
[[nodiscard]] float get_landmass(Vector<2> pos) const;
[[nodiscard]] float get_hill(Vector<2> pos) const;