|
|
@@ -34,51 +34,59 @@ public: |
|
|
|
/* Evaluate noise at a given point */ |
|
|
|
inline float eval(vec_t<float, N> position) const |
|
|
|
{ |
|
|
|
int const cells = 1 << N; |
|
|
|
|
|
|
|
/* Retrieve the containing hypercube origin */ |
|
|
|
/* Compute the containing hypercube origin */ |
|
|
|
vec_t<int, N> origin; |
|
|
|
for (int i = 0; i < N; ++i) |
|
|
|
origin[i] = (int)position[i] - (position[i] < 0); |
|
|
|
|
|
|
|
vec_t<float, N> delta = position - (vec_t<float, N>)origin; |
|
|
|
|
|
|
|
/* Apply a smooth step to delta and store it in “t”. */ |
|
|
|
vec_t<float, N> t = delta; |
|
|
|
/* DEBUG: original Perlin noise polynomial */ |
|
|
|
//t = (vec_t<float, N>(3.f) - 2.f * t) * t * t; |
|
|
|
/* Improved polynomial (with null second derivative) */ |
|
|
|
t = ((6.f * t - vec_t<float, N>(15.f)) |
|
|
|
* t + vec_t<float, N>(10.f)) * (t * t * t); |
|
|
|
/* DEBUG: original Perlin noise polynomial */ |
|
|
|
//t = (vec_t<float, N>(3.f) - 2.f * t) * t * t; |
|
|
|
|
|
|
|
/* Compute all gradient contributions */ |
|
|
|
array<float> values; |
|
|
|
values.Resize(cells); |
|
|
|
for (int i = 0; i < cells; ++i) |
|
|
|
/* Premultiply and predivide (1-t)/t and t/(1-t) into “u” and “v”. */ |
|
|
|
vec_t<float, N> u, v; |
|
|
|
float multiplier = 1.f; |
|
|
|
for (int bit = 0; bit < N; ++bit) |
|
|
|
{ |
|
|
|
/* FIXME: find another way to travel the hypercube that |
|
|
|
* causes fewer bit flips, and compute the return value |
|
|
|
* directly without allocating an array value. */ |
|
|
|
vec_t<float, N> v = delta; |
|
|
|
vec_t<int, N> corner = origin; |
|
|
|
for (int bit = 0; bit < N; ++bit) |
|
|
|
if ((1 << bit) & i) |
|
|
|
{ |
|
|
|
++corner[bit]; |
|
|
|
v[bit] = v[bit] - 1.f; |
|
|
|
} |
|
|
|
|
|
|
|
values[i] = dot(v, this->get_gradient(corner)); |
|
|
|
/* Avoid divisions by zero near the hypercube boundaries. */ |
|
|
|
float f = clamp(t[bit], 0.001f, 0.999f); |
|
|
|
|
|
|
|
multiplier *= (1.f - f); |
|
|
|
u[bit] = (1.f - f) / f; |
|
|
|
v[bit] = f / (1.f - f); |
|
|
|
} |
|
|
|
|
|
|
|
/* Interpolate all contributions together */ |
|
|
|
for (int bit = N; bit--; ) |
|
|
|
float ret = 0.f; |
|
|
|
|
|
|
|
/* Compute all gradient contributions, for each of the 2^N corners |
|
|
|
* of the hypercube. */ |
|
|
|
for (int i = 0; i < (1 << N); ++i) |
|
|
|
{ |
|
|
|
for (int i = 0; i < (1 << bit); ++i) |
|
|
|
values[i] = (1.f - t[bit]) * values[i] |
|
|
|
+ t[bit] * values[i + (1 << bit)]; |
|
|
|
/* Accumulate Perlin noise */ |
|
|
|
ret += multiplier * dot(delta, this->get_gradient(origin)); |
|
|
|
|
|
|
|
/* Don’t use the binary pattern for “i” but use its Gray code |
|
|
|
* “j” instead, so we know we only have one component to alter |
|
|
|
* in “origin” and in “delta”. We know which bit was flipped by |
|
|
|
* looking at “k”, the Gray code for the next value of “i”. */ |
|
|
|
int j = i ^ (i >> 1); |
|
|
|
int k = (i + 1) ^ ((i + 1) >> 1); |
|
|
|
|
|
|
|
int bit = 0; |
|
|
|
while ((j ^ k) > (1 << bit)) |
|
|
|
++bit; |
|
|
|
|
|
|
|
origin[bit] += j > k ? -1 : 1; |
|
|
|
delta[bit] += j > k ? 1.f : -1.f; |
|
|
|
multiplier *= (j > k ? u : v)[bit]; |
|
|
|
} |
|
|
|
|
|
|
|
return values[0]; |
|
|
|
return sqrt(2.f) * ret; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|