diff --git a/demos/test/simplex.cpp b/demos/test/simplex.cpp index f9bcae61..cb0be2e6 100644 --- a/demos/test/simplex.cpp +++ b/demos/test/simplex.cpp @@ -33,17 +33,17 @@ int main(int argc, char **argv) array2d &data = img.Lock2D(); /* Declare plenty of allocators */ - simplex_interpolator<2> s2; - simplex_interpolator<3> s3; - simplex_interpolator<4> s4; - simplex_interpolator<5> s5; - simplex_interpolator<6> s6; - simplex_interpolator<7> s7; - simplex_interpolator<8> s8; - simplex_interpolator<9> s9; - simplex_interpolator<10> s10; - simplex_interpolator<11> s11; - simplex_interpolator<12> s12; + simplex_noise<2> s2; + simplex_noise<3> s3; + simplex_noise<4> s4; + simplex_noise<5> s5; + simplex_noise<6> s6; + simplex_noise<7> s7; + simplex_noise<8> s8; + simplex_noise<9> s9; + simplex_noise<10> s10; + simplex_noise<11> s11; + simplex_noise<12> s12; /* Fill image with simplex noise */ for (int j = 0; j < size.y; ++j) diff --git a/src/Makefile.am b/src/Makefile.am index a39b2bfb..156d03cd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -44,7 +44,8 @@ liblolcore_headers = \ lol/math/functions.h lol/math/vector.h lol/math/half.h lol/math/real.h \ lol/math/geometry.h lol/math/interp.h lol/math/rand.h lol/math/array2d.h \ lol/math/array3d.h lol/math/constants.h lol/math/matrix.h lol/math/ops.h \ - lol/math/transform.h lol/math/polynomial.h lol/math/simplex_interpolator.h \ + lol/math/transform.h lol/math/polynomial.h \ + lol/math/noise/gradient.h lol/math/noise/simplex.h \ \ lol/algorithm/all.h \ lol/algorithm/sort.h lol/algorithm/portal.h lol/algorithm/aabb_tree.h \ diff --git a/src/lol/math/all.h b/src/lol/math/all.h index da3e1210..6b064db3 100644 --- a/src/lol/math/all.h +++ b/src/lol/math/all.h @@ -23,4 +23,6 @@ #include #include #include -#include + +#include +#include diff --git a/src/lol/math/noise/gradient.h b/src/lol/math/noise/gradient.h new file mode 100644 index 00000000..f2457d85 --- /dev/null +++ b/src/lol/math/noise/gradient.h @@ -0,0 +1,95 @@ +// +// Lol Engine +// +// Copyright: (c) 2010-2014 Sam Hocevar +// (c) 2013-2014 Benjamin "Touky" Huet +// (c) 2013-2014 Guillaume Bittoun +// This program is free software; you can redistribute it and/or +// modify it under the terms of the Do What The Fuck You Want To +// Public License, Version 2, as published by Sam Hocevar. See +// http://www.wtfpl.net/ for more details. +// + +#pragma once + +#include + +namespace lol +{ + +template +class gradient_provider +{ +public: + gradient_provider(int seed = 0) + : m_seed(seed) + { + } + +protected: + vec_t get_gradient(vec_t origin) const + { + /* Quick shuffle table: + * strings /dev/urandom | grep . -nm256 | sort -k2 -t: | sed 's|:.*|,|' + * Then just replace “256” with “0”. */ + static int const shuffle[256] = + { + 111, 14, 180, 186, 221, 114, 219, 79, 66, 46, 152, 81, 246, 200, + 141, 172, 85, 244, 112, 92, 34, 106, 218, 205, 236, 7, 121, 115, + 109, 131, 10, 96, 188, 148, 17, 107, 94, 182, 235, 163, 143, 63, + 248, 202, 52, 154, 37, 241, 53, 129, 25, 159, 242, 38, 171, 213, + 6, 203, 255, 193, 42, 209, 28, 176, 210, 60, 54, 144, 3, 71, 89, + 116, 12, 237, 67, 216, 252, 178, 174, 164, 98, 234, 32, 26, 175, + 24, 130, 128, 113, 99, 212, 62, 11, 75, 185, 73, 93, 31, 30, 44, + 122, 173, 139, 91, 136, 162, 194, 41, 56, 101, 68, 69, 211, 151, + 97, 55, 83, 33, 50, 119, 156, 149, 208, 157, 253, 247, 161, 133, + 230, 166, 225, 204, 224, 13, 110, 123, 142, 64, 65, 155, 215, 9, + 197, 140, 58, 77, 214, 126, 195, 179, 220, 232, 125, 147, 8, 39, + 187, 27, 217, 100, 134, 199, 88, 206, 231, 250, 74, 2, 135, 120, + 21, 245, 118, 243, 82, 183, 238, 150, 158, 61, 4, 177, 146, 153, + 117, 249, 254, 233, 90, 222, 207, 48, 15, 18, 20, 16, 47, 0, 51, + 165, 138, 127, 169, 72, 1, 201, 145, 191, 192, 239, 49, 19, 160, + 226, 228, 84, 181, 251, 36, 87, 22, 43, 70, 45, 105, 5, 189, 95, + 40, 196, 59, 57, 190, 80, 104, 167, 78, 124, 103, 240, 184, 170, + 137, 29, 23, 223, 108, 102, 86, 198, 227, 35, 229, 76, 168, 132, + }; + + /* Generate 2^(N+2) random vectors, but at least 2^5 (32) and not + * more than 2^20 (~ 1 million). */ + int const gradient_count = 1 << min(max(N + 2, 5), 20); + + static auto build_gradients = [&]() + { + array> ret; + for (int k = 0; k < gradient_count; ++k) + { + vec_t v; + for (int i = 0; i < N; ++i) + v[i] = rand(-1.f, 1.f); + ret << normalize(v); + } + return ret; + }; + + static array> const gradients = build_gradients(); + + int idx = m_seed; + for (int i = 0; i < N; ++i) + idx ^= shuffle[(idx + origin[i]) & 255]; + + idx &= (gradient_count - 1); +#if 0 + // DEBUG: only output a few gradients + if (idx > 2) + return vec_t(0); +#endif + return gradients[idx]; + } + +private: + /* A user-provided random seed. Defaults to zero. */ + int m_seed; +}; + +} + diff --git a/src/lol/math/simplex_interpolator.h b/src/lol/math/noise/simplex.h similarity index 81% rename from src/lol/math/simplex_interpolator.h rename to src/lol/math/noise/simplex.h index 666c016a..423a3b41 100644 --- a/src/lol/math/simplex_interpolator.h +++ b/src/lol/math/noise/simplex.h @@ -12,7 +12,7 @@ #pragma once -#include +#include namespace lol { @@ -39,17 +39,22 @@ namespace lol */ template -class simplex_interpolator +class simplex_noise : public gradient_provider { public: - simplex_interpolator(int seed = 0) - : m_seed(seed) + simplex_noise() + : gradient_provider() { #if 0 debugprint(); #endif } + simplex_noise(int seed) + : gradient_provider(seed) + { + } + /* Evaluate noise at a given point */ inline float eval(vec_t position) const { @@ -145,16 +150,15 @@ protected: //d = (3.f - 2.f * d) * d * d; //d = ((6 * d - 15) * d + 10) * d * d * d; - result += d * dot(get_gradient(origin), + result += d * dot(this->get_gradient(origin), world_pos - world_corner); sum += d; } if (i < N) { - vec_t v(0.f); - v[traversal_order[i]] = 1.f; - world_corner += unskew(v); + auto axis = vec_t::axis(traversal_order[i]); + world_corner += unskew(axis); origin[traversal_order[i]] += 1; } } @@ -185,65 +189,6 @@ protected: : /* 7+ */ 6.7958f; } - inline vec_t get_gradient(vec_t origin) const - { - /* Quick shuffle table: - * strings /dev/urandom | grep . -nm256 | sort -k2 -t: | sed 's|:.*|,|' - * Then just replace “256” with “0”. */ - static int const shuffle[256] = - { - 111, 14, 180, 186, 221, 114, 219, 79, 66, 46, 152, 81, 246, 200, - 141, 172, 85, 244, 112, 92, 34, 106, 218, 205, 236, 7, 121, 115, - 109, 131, 10, 96, 188, 148, 17, 107, 94, 182, 235, 163, 143, 63, - 248, 202, 52, 154, 37, 241, 53, 129, 25, 159, 242, 38, 171, 213, - 6, 203, 255, 193, 42, 209, 28, 176, 210, 60, 54, 144, 3, 71, 89, - 116, 12, 237, 67, 216, 252, 178, 174, 164, 98, 234, 32, 26, 175, - 24, 130, 128, 113, 99, 212, 62, 11, 75, 185, 73, 93, 31, 30, 44, - 122, 173, 139, 91, 136, 162, 194, 41, 56, 101, 68, 69, 211, 151, - 97, 55, 83, 33, 50, 119, 156, 149, 208, 157, 253, 247, 161, 133, - 230, 166, 225, 204, 224, 13, 110, 123, 142, 64, 65, 155, 215, 9, - 197, 140, 58, 77, 214, 126, 195, 179, 220, 232, 125, 147, 8, 39, - 187, 27, 217, 100, 134, 199, 88, 206, 231, 250, 74, 2, 135, 120, - 21, 245, 118, 243, 82, 183, 238, 150, 158, 61, 4, 177, 146, 153, - 117, 249, 254, 233, 90, 222, 207, 48, 15, 18, 20, 16, 47, 0, 51, - 165, 138, 127, 169, 72, 1, 201, 145, 191, 192, 239, 49, 19, 160, - 226, 228, 84, 181, 251, 36, 87, 22, 43, 70, 45, 105, 5, 189, 95, - 40, 196, 59, 57, 190, 80, 104, 167, 78, 124, 103, 240, 184, 170, - 137, 29, 23, 223, 108, 102, 86, 198, 227, 35, 229, 76, 168, 132, - }; - - /* Generate 2^(N+2) random vectors, but at least 2^5 (32) and not - * more than 2^20 (~ 1 million). */ - int const gradient_count = 1 << min(max(N + 2, 5), 20); - - static auto build_gradients = [&]() - { - array> ret; - for (int k = 0; k < gradient_count; ++k) - { - vec_t v; - for (int i = 0; i < N; ++i) - v[i] = rand(-1.f, 1.f); - ret << normalize(v); - } - return ret; - }; - - static array> const gradients = build_gradients(); - - int idx = m_seed; - for (int i = 0; i < N; ++i) - idx ^= shuffle[(idx + origin[i]) & 255]; - - idx &= (gradient_count - 1); -#if 0 - // DEBUG: only output a few gradients - if (idx > 2) - return vec_t(0); -#endif - return gradients[idx]; - } - static inline vec_t skew(vec_t const &v) { /* Quoting Perlin in “Hardware Noise” (2-18): @@ -365,7 +310,7 @@ private: * full of zeroes except at position i. So we build a vector * full of zeroes except at position i, and multiply it by the * matrix inverse. */ -#if 0 +#if 1 int i0 = (i == 0) ? 1 : 0; mat_t m; for (int j = 0; j < N; ++j) @@ -374,9 +319,8 @@ private: for (int k = 0; k < N; ++k) m[k][j] = v[k]; } - vec_t p(0.f); - p[i < i0 ? i : i - 1] = 1.f; - auto normal = normalize(inverse(m) * p); + auto axis = vec_t::axis(i < i0 ? i : i - 1); + auto normal = normalize(inverse(m) * axis); /* Find distance from current vertex to the opposite hyperplane. * Just use the projection theorem in N dimensions. */ @@ -402,8 +346,7 @@ private: array> deltas; for (int i = 0; i < N; ++i) { - vec_t v(0.f); - v[i] = 1.f; + auto v = vec_t::axis(i); deltas << v << -v; } for (int run = 0; run < 1000; ++run) @@ -449,9 +392,6 @@ private: printf("\n"); } - - /* A user-provided random seed. Defaults to zero. */ - int m_seed; }; } diff --git a/src/lolcore.vcxproj b/src/lolcore.vcxproj index d09d7539..ce2f6e72 100644 --- a/src/lolcore.vcxproj +++ b/src/lolcore.vcxproj @@ -332,12 +332,13 @@ + + - diff --git a/src/lolcore.vcxproj.filters b/src/lolcore.vcxproj.filters index 90497147..486af36e 100644 --- a/src/lolcore.vcxproj.filters +++ b/src/lolcore.vcxproj.filters @@ -40,6 +40,9 @@ {1e0b7a4c-425f-4d4f-945e-ba2ac9386ce0} + + {97d023b5-9715-4f30-bacb-846d89025f5b} + {2caadbda-b9f1-446d-bbd2-55c959db342c} @@ -450,6 +453,12 @@ lol\math + + lol\math\noise + + + lol\math\noise + lol\math @@ -465,9 +474,6 @@ lol\math - - lol\math - lol\math diff --git a/src/t/Makefile.am b/src/t/Makefile.am index 665f23a1..4ef58988 100644 --- a/src/t/Makefile.am +++ b/src/t/Makefile.am @@ -20,8 +20,7 @@ test_math_SOURCES = test-common.cpp \ math/array2d.cpp math/array3d.cpp math/arraynd.cpp math/box.cpp \ math/cmplx.cpp math/half.cpp math/interp.cpp math/matrix.cpp \ math/quat.cpp math/rand.cpp math/real.cpp math/rotation.cpp \ - math/trig.cpp math/vector.cpp math/simplex_interpolator.cpp \ - math/polynomial.cpp + math/trig.cpp math/vector.cpp math/polynomial.cpp math/noise/simplex.cpp test_math_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/tools/lolunit test_math_DEPENDENCIES = @LOL_DEPS@ diff --git a/src/t/math/simplex_interpolator.cpp b/src/t/math/noise/simplex.cpp similarity index 86% rename from src/t/math/simplex_interpolator.cpp rename to src/t/math/noise/simplex.cpp index e828ebc6..1ed3b338 100644 --- a/src/t/math/simplex_interpolator.cpp +++ b/src/t/math/noise/simplex.cpp @@ -12,14 +12,12 @@ #include -#include - #include namespace lol { -lolunit_declare_fixture(SimplexevalolatorTest) +lolunit_declare_fixture(SimplexNoise) { void SetUp() {} diff --git a/src/t/test-math.vcxproj b/src/t/test-math.vcxproj index 9e6c3a4b..a3996025 100644 --- a/src/t/test-math.vcxproj +++ b/src/t/test-math.vcxproj @@ -52,12 +52,12 @@ + -