diff options
| author | Mel <einebeere@gmail.com> | 2023-07-01 22:03:51 +0200 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2023-07-01 22:03:51 +0200 |
| commit | 221f632d6600ce03e09c2a44074ae100a507dd92 (patch) | |
| tree | 462663c1f03582e8a0b5df753bc7c45cbe702aad /src | |
| parent | 424d00eaf7335e1c6427f40260d55782c3fd902c (diff) | |
| download | meowcraft-221f632d6600ce03e09c2a44074ae100a507dd92.tar.zst meowcraft-221f632d6600ce03e09c2a44074ae100a507dd92.zip | |
Replace bespoke Generator maps with tensors and matrices
Diffstat (limited to 'src')
| -rw-r--r-- | src/Math/Matrix.hpp | 24 | ||||
| -rw-r--r-- | src/Math/Tensor.hpp | 43 | ||||
| -rw-r--r-- | src/World/Generator.cpp | 49 | ||||
| -rw-r--r-- | src/World/Generator.hpp | 37 |
4 files changed, 92 insertions, 61 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> - 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); + 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>; + + 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); + + 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); + + Map3D<bool> generate_terrain(Map2D<float>& height_map, int64_t chunk_x, int64_t chunk_y); + + 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; |
