From d0de60dc33df75fbcacb53a09568b14d0fd48cb9 Mon Sep 17 00:00:00 2001 From: Mel Date: Mon, 12 Jun 2023 17:09:55 +0200 Subject: Multithreaded world generation with Perlin --- src/Math/Perlin.cpp | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/Math/Perlin.cpp (limited to 'src/Math/Perlin.cpp') diff --git a/src/Math/Perlin.cpp b/src/Math/Perlin.cpp new file mode 100644 index 0000000..e0982cb --- /dev/null +++ b/src/Math/Perlin.cpp @@ -0,0 +1,92 @@ +#include "Perlin.hpp" +#include "Grid.hpp" +#include "Interpolation.hpp" + +namespace Math::Perlin { + +float ease(float t) { + return t * t * t * ((6 * t - 15) * t + 10); +} + +uint8_t hash(uint8_t x) { + auto rot = (x * 5) % 8; + return x << rot | x >> (8 - rot); +} + +Vector<2> gradient(Vector<2> pos) { + Vector<2> gradients[] = { + {1.0f, 1.0f}, {-1.0f, 1.0f}, + {1.0f, -1.0f}, {-1.0f, -1.0f}, + }; + + auto x = hash(hash(pos.x()) + pos.y()); + return gradients[x % 4].normalize(); +} + +float raw(Vector<2> pos) { + auto cell = grid_cell_for_point(pos); + auto uv = pos - cell.top_left(); + + auto unit = grid_cell_for_point({}); + auto l11 = unit.top_left() - uv; + auto l21 = unit.top_right() - uv; + auto l12 = unit.bottom_left() - uv; + auto l22 = unit.bottom_right() - uv; + + auto g11 = gradient(cell.top_left()); + auto g21 = gradient(cell.top_right()); + auto g12 = gradient(cell.bottom_left()); + auto g22 = gradient(cell.bottom_right()); + + auto v = bilinear_interpolation( + {l11 * g11, l21 * g21, l12 * g12, l22 * g22}, + cell, + uv.map(ease) + cell.top_left() + ); + return (v + 1.0f) / 2.0f; +} + +Vector<3> gradient(Vector<3> pos) { + constexpr float e = 0.5773502692; + static Vector<3> gradients[] = { + {e, e, e}, {-e, e, e}, {e, -e, e}, {-e, -e, e}, + {e, e, -e}, {-e, e, -e}, {e, -e, -e}, {-e, -e, -e}, + }; + + auto x = hash(hash(hash(pos.x()) + pos.y()) + pos.z()); + return gradients[x % 8]; +} + +float raw(Vector<3> pos) { + auto cell = cube_cell_for_point(pos); + auto uv = pos - cell.front_top_left(); + + auto unit = cube_cell_for_point({}); + auto l111 = unit.front_top_left() - uv; + auto l211 = unit.front_top_right() - uv; + auto l121 = unit.front_bottom_left() - uv; + auto l221 = unit.front_bottom_right() - uv; + auto l112 = unit.back_top_left() - uv; + auto l212 = unit.back_top_right() - uv; + auto l122 = unit.back_bottom_left() - uv; + auto l222 = unit.back_bottom_right() - uv; + + auto g111 = gradient(cell.front_top_left()); + auto g211 = gradient(cell.front_top_right()); + auto g121 = gradient(cell.front_bottom_left()); + auto g221 = gradient(cell.front_bottom_right()); + auto g112 = gradient(cell.back_top_left()); + auto g212 = gradient(cell.back_top_right()); + auto g122 = gradient(cell.back_bottom_left()); + auto g222 = gradient(cell.back_bottom_right()); + + auto v = trilinear_interpolation( + {l111 * g111, l211 * g211, l121 * g121, l221 * g221}, + {l112 * g112, l212 * g212, l122 * g122, l222 * g222}, + cell, + uv.map(ease) + cell.front_top_left() + ); + return (v + 1.0f) / 2.0f; +} + +} \ No newline at end of file -- cgit 1.4.1