Bladeren bron

math: extract the gradient generator from simplex noise so that we

can reuse it for other noise implementations.
undefined
Sam Hocevar 10 jaren geleden
bovenliggende
commit
5d9488182f
10 gewijzigde bestanden met toevoegingen van 141 en 99 verwijderingen
  1. +11
    -11
      demos/test/simplex.cpp
  2. +2
    -1
      src/Makefile.am
  3. +3
    -1
      src/lol/math/all.h
  4. +95
    -0
      src/lol/math/noise/gradient.h
  5. +16
    -76
      src/lol/math/noise/simplex.h
  6. +2
    -1
      src/lolcore.vcxproj
  7. +9
    -3
      src/lolcore.vcxproj.filters
  8. +1
    -2
      src/t/Makefile.am
  9. +1
    -3
      src/t/math/noise/simplex.cpp
  10. +1
    -1
      src/t/test-math.vcxproj

+ 11
- 11
demos/test/simplex.cpp Bestand weergeven

@@ -33,17 +33,17 @@ int main(int argc, char **argv)
array2d<vec4> &data = img.Lock2D<PixelFormat::RGBA_F32>();

/* 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)


+ 2
- 1
src/Makefile.am Bestand weergeven

@@ -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 \


+ 3
- 1
src/lol/math/all.h Bestand weergeven

@@ -23,4 +23,6 @@
#include <lol/math/interp.h>
#include <lol/math/rand.h>
#include <lol/math/polynomial.h>
#include <lol/math/simplex_interpolator.h>

#include <lol/math/noise/gradient.h>
#include <lol/math/noise/simplex.h>

+ 95
- 0
src/lol/math/noise/gradient.h Bestand weergeven

@@ -0,0 +1,95 @@
//
// Lol Engine
//
// Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net>
// (c) 2013-2014 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
// (c) 2013-2014 Guillaume Bittoun <guillaume.bittoun@gmail.com>
// 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 <functional>

namespace lol
{

template<int N>
class gradient_provider
{
public:
gradient_provider(int seed = 0)
: m_seed(seed)
{
}

protected:
vec_t<float, N> get_gradient(vec_t<int, N> 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<vec_t<float, N>> ret;
for (int k = 0; k < gradient_count; ++k)
{
vec_t<float, N> v;
for (int i = 0; i < N; ++i)
v[i] = rand(-1.f, 1.f);
ret << normalize(v);
}
return ret;
};

static array<vec_t<float, N>> 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<float, N>(0);
#endif
return gradients[idx];
}

private:
/* A user-provided random seed. Defaults to zero. */
int m_seed;
};

}


src/lol/math/simplex_interpolator.h → src/lol/math/noise/simplex.h Bestand weergeven

@@ -12,7 +12,7 @@

#pragma once

#include <functional>
#include <lol/math/noise/gradient.h>

namespace lol
{
@@ -39,17 +39,22 @@ namespace lol
*/

template<int N>
class simplex_interpolator
class simplex_noise : public gradient_provider<N>
{
public:
simplex_interpolator(int seed = 0)
: m_seed(seed)
simplex_noise()
: gradient_provider<N>()
{
#if 0
debugprint();
#endif
}

simplex_noise(int seed)
: gradient_provider<N>(seed)
{
}

/* Evaluate noise at a given point */
inline float eval(vec_t<float, N> 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<float, N> v(0.f);
v[traversal_order[i]] = 1.f;
world_corner += unskew(v);
auto axis = vec_t<float, N>::axis(traversal_order[i]);
world_corner += unskew(axis);
origin[traversal_order[i]] += 1;
}
}
@@ -185,65 +189,6 @@ protected:
: /* 7+ */ 6.7958f;
}

inline vec_t<float, N> get_gradient(vec_t<int, N> 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<vec_t<float, N>> ret;
for (int k = 0; k < gradient_count; ++k)
{
vec_t<float, N> v;
for (int i = 0; i < N; ++i)
v[i] = rand(-1.f, 1.f);
ret << normalize(v);
}
return ret;
};

static array<vec_t<float, N>> 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<float, N>(0);
#endif
return gradients[idx];
}

static inline vec_t<float, N> skew(vec_t<float, N> 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<float, N, N> 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<float, N> p(0.f);
p[i < i0 ? i : i - 1] = 1.f;
auto normal = normalize(inverse(m) * p);
auto axis = vec_t<float, N>::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<vec_t<float, N>> deltas;
for (int i = 0; i < N; ++i)
{
vec_t<float, N> v(0.f);
v[i] = 1.f;
auto v = vec_t<float, N>::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;
};

}

+ 2
- 1
src/lolcore.vcxproj Bestand weergeven

@@ -332,12 +332,13 @@
<ClInclude Include="lol\math\half.h" />
<ClInclude Include="lol\math\interp.h" />
<ClInclude Include="lol\math\matrix.h" />
<ClInclude Include="lol\math\noise\gradient.h" />
<ClInclude Include="lol\math\noise\simplex.h" />
<ClInclude Include="lol\math\ops.h" />
<ClInclude Include="lol\math\polynomial.h" />
<ClInclude Include="lol\math\rand.h" />
<ClInclude Include="lol\math\real.h" />
<ClInclude Include="lol\math\remez.h" />
<ClInclude Include="lol\math\simplex_interpolator.h" />
<ClInclude Include="lol\math\transform.h" />
<ClInclude Include="lol\math\vector.h" />
<ClInclude Include="lol\public.h" />


+ 9
- 3
src/lolcore.vcxproj.filters Bestand weergeven

@@ -40,6 +40,9 @@
<Filter Include="lol\math">
<UniqueIdentifier>{1e0b7a4c-425f-4d4f-945e-ba2ac9386ce0}</UniqueIdentifier>
</Filter>
<Filter Include="lol\math\noise">
<UniqueIdentifier>{97d023b5-9715-4f30-bacb-846d89025f5b}</UniqueIdentifier>
</Filter>
<Filter Include="math">
<UniqueIdentifier>{2caadbda-b9f1-446d-bbd2-55c959db342c}</UniqueIdentifier>
</Filter>
@@ -450,6 +453,12 @@
<ClInclude Include="lol\math\matrix.h">
<Filter>lol\math</Filter>
</ClInclude>
<ClInclude Include="lol\math\noise\gradient.h">
<Filter>lol\math\noise</Filter>
</ClInclude>
<ClInclude Include="lol\math\noise\simplex.h">
<Filter>lol\math\noise</Filter>
</ClInclude>
<ClInclude Include="lol\math\ops.h">
<Filter>lol\math</Filter>
</ClInclude>
@@ -465,9 +474,6 @@
<ClInclude Include="lol\math\remez.h">
<Filter>lol\math</Filter>
</ClInclude>
<ClInclude Include="lol\math\simplex_interpolator.h">
<Filter>lol\math</Filter>
</ClInclude>
<ClInclude Include="lol\math\transform.h">
<Filter>lol\math</Filter>
</ClInclude>


+ 1
- 2
src/t/Makefile.am Bestand weergeven

@@ -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@



src/t/math/simplex_interpolator.cpp → src/t/math/noise/simplex.cpp Bestand weergeven

@@ -12,14 +12,12 @@

#include <lol/engine-internal.h>

#include <lol/math/simplex_interpolator.h>

#include <lolunit.h>

namespace lol
{

lolunit_declare_fixture(SimplexevalolatorTest)
lolunit_declare_fixture(SimplexNoise)
{
void SetUp() {}


+ 1
- 1
src/t/test-math.vcxproj Bestand weergeven

@@ -52,12 +52,12 @@
<ClCompile Include="math\half.cpp" />
<ClCompile Include="math\interp.cpp" />
<ClCompile Include="math\matrix.cpp" />
<ClCompile Include="math\noise\simplex.cpp" />
<ClCompile Include="math\polynomial.cpp" />
<ClCompile Include="math\quat.cpp" />
<ClCompile Include="math\rand.cpp" />
<ClCompile Include="math\real.cpp" />
<ClCompile Include="math\rotation.cpp" />
<ClCompile Include="math\simplex_interpolation.cpp" />
<ClCompile Include="math\trig.cpp" />
<ClCompile Include="math\vector.cpp" />
</ItemGroup>


Laden…
Annuleren
Opslaan