Explorar el Código

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

can reuse it for other noise implementations.
undefined
Sam Hocevar hace 10 años
padre
commit
5d9488182f
Se han modificado 10 ficheros con 141 adiciones y 99 borrados
  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 Ver fichero

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

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

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

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

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

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

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

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

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

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


Cargando…
Cancelar
Guardar