Line data Source code
1 : #include <shared.hpp>
2 : #include <cmath>
3 : #include <random>
4 : #include <algorithm>
5 : #include <numeric>
6 :
7 : // THIS IS A DIRECT TRANSLATION TO C++11 FROM THE REFERENCE
8 : // JAVA IMPLEMENTATION OF THE IMPROVED PERLIN FUNCTION (see http://mrl.nyu.edu/~perlin/noise/)
9 : // THE ORIGINAL JAVA IMPLEMENTATION IS COPYRIGHT 2002 KEN PERLIN
10 :
11 : using namespace shared;
12 :
13 : // Generate a new permutation vector based on the value of seed
14 3 : PerlinNoise::PerlinNoise(unsigned int seed)
15 : {
16 3 : p.resize(256);
17 :
18 : // Fill p with values from 0 to 255
19 3 : std::iota(p.begin(), p.end(), 0);
20 :
21 : // Initialize a random engine with seed
22 3 : std::default_random_engine engine(seed);
23 :
24 : // Suffle using the above random engine
25 3 : std::shuffle(p.begin(), p.end(), engine);
26 :
27 : // Duplicate the permutation vector
28 3 : p.insert(p.end(), p.begin(), p.end());
29 3 : }
30 :
31 500 : double PerlinNoise::noise(double x, double y, double z)
32 : {
33 : // Find the unit cube that contains the point
34 500 : int X = (int)floor(x) & 255;
35 500 : int Y = (int)floor(y) & 255;
36 500 : int Z = (int)floor(z) & 255;
37 :
38 : // Find relative x, y,z of point in cube
39 500 : x -= floor(x);
40 500 : y -= floor(y);
41 500 : z -= floor(z);
42 :
43 : // Compute fade curves for each of x, y, z
44 500 : double u = fade(x);
45 500 : double v = fade(y);
46 500 : double w = fade(z);
47 :
48 : // Hash coordinates of the 8 cube corners
49 500 : int A = p[X] + Y;
50 500 : int AA = p[A] + Z;
51 500 : int AB = p[A + 1] + Z;
52 500 : int B = p[X + 1] + Y;
53 500 : int BA = p[B] + Z;
54 500 : int BB = p[B + 1] + Z;
55 :
56 : // Add blended results from 8 corners of cube
57 500 : double res = lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z), grad(p[BA], x - 1, y, z)), lerp(u, grad(p[AB], x, y - 1, z), grad(p[BB], x - 1, y - 1, z))), lerp(v, lerp(u, grad(p[AA + 1], x, y, z - 1), grad(p[BA + 1], x - 1, y, z - 1)), lerp(u, grad(p[AB + 1], x, y - 1, z - 1), grad(p[BB + 1], x - 1, y - 1, z - 1))));
58 500 : return (res + 1.0) / 2.0;
59 : }
60 :
61 1500 : double PerlinNoise::fade(double t)
62 : {
63 1500 : return t * t * t * (t * (t * 6 - 15) + 10);
64 : }
65 :
66 3500 : double PerlinNoise::lerp(double t, double a, double b)
67 : {
68 3500 : return a + t * (b - a);
69 : }
70 :
71 4000 : double PerlinNoise::grad(int hash, double x, double y, double z)
72 : {
73 4000 : int h = hash & 15;
74 : // Convert lower 4 bits of hash into 12 gradient directions
75 4000 : double u = h < 8 ? x : y,
76 4000 : v = h < 4 ? y : h == 12 || h == 14 ? x
77 : : z;
78 4000 : return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
79 : }
|