Ver código fonte

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

can reuse it for other noise implementations.
undefined
Sam Hocevar 10 anos atrás
pai
commit
5d9488182f
10 arquivos alterados com 141 adições e 99 exclusões
  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 arquivo

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

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

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

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

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

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

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

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

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

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


Carregando…
Cancelar
Salvar