summary refs log tree commit diff
path: root/src/Math/Perlin.cpp
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2023-06-12 17:09:55 +0200
committerMel <einebeere@gmail.com>2023-06-12 17:14:03 +0200
commitd0de60dc33df75fbcacb53a09568b14d0fd48cb9 (patch)
tree7aefdbb81f114552881834bd5b0d842bc2bdb691 /src/Math/Perlin.cpp
parent23b0bc4d1ddc9fad3c32e8257497ddd13ac6a155 (diff)
downloadmeowcraft-d0de60dc33df75fbcacb53a09568b14d0fd48cb9.tar.zst
meowcraft-d0de60dc33df75fbcacb53a09568b14d0fd48cb9.zip
Multithreaded world generation with Perlin
Diffstat (limited to 'src/Math/Perlin.cpp')
-rw-r--r--src/Math/Perlin.cpp92
1 files changed, 92 insertions, 0 deletions
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