1  /**
2     Holds the noise generator. Mostly a copy and reimplementation of https://gist.github.com/KdotJPG/b1270127455a94ac5d19 and http://uniblock.tumblr.com/  
3  */
4 module dosimplex.generator;
5 
6 import dosimplex.osimplex2d;
7 import dosimplex.osimplex3d;
8 import dosimplex.osimplex4d;
9 import dosimplex.seed;
10 import dosimplex.util;
11 
12 
13 /**
14     The noise generator. 
15     somehow impelments OpenSimplexNoise - https://gist.github.com/KdotJPG/b1270127455a94ac5d19 and http://uniblock.tumblr.com/  
16 */
17 struct SNoiseGenerator
18 {    
19     /// (Default) Values for noise generation
20     enum : long {
21         DEFAULT_SEED = 1787569, /// why not
22     };
23     
24     /// Disabled Default struct constructor
25     @disable this();
26     
27     /// Initializes a generator from a long seed 
28     @nogc @safe this(long seed)
29     {
30         short[256] source;
31         for (short i=0; i<256; i++) {
32             source[i]=i;
33         }
34         seed = seed * 6364136223846793005L + 1442695040888963407L;
35 		seed = seed * 6364136223846793005L + 1442695040888963407L;
36 		seed = seed * 6364136223846793005L + 1442695040888963407L;
37         for (int i = 255; i >= 0; i--) {
38 			seed = seed * 6364136223846793005L + 1442695040888963407L;
39 			int r = ((seed + 31) % (i + 1));
40 			if (r < 0)
41 				r += (i + 1);
42 			_perm[i] = source[r];
43 			_permGradIndex3D[i] = cast(short)((_perm[i] % (GRADIENTS.GRADIENTS_3D.length / 3)) * 3);
44 			source[r] = source[i];
45 		}
46     }
47     
48     /// Initializes a generator from a Seed struct 
49     @nogc @safe this(Seed seed)
50     {
51         this(seed.seed);
52     }
53     
54     /// Initializes a generator from a given permutation array
55     @nogc @safe this(short[256] perm) 
56     {
57         _perm = perm;
58         for (int i = 0; i < 256; i++) {
59 			//Since 3D has 24 gradients, simple bitmask won't work, so precompute modulo array.
60 			_permGradIndex3D[i] = cast(short)((_perm[i] % (GRADIENTS.GRADIENTS_3D.length / 3)) * 3);
61 		}
62     }
63     
64     /// 2D OpenSimplexNoise
65     @nogc @safe pure double noise2D(double x, double y)
66     {
67         return osNoise2D(x,y,_perm);
68     }
69     /// Ditto
70     @nogc @safe pure double noise2D(const double[2] p)
71     {
72         return osNoise2D(p[0],p[1],_perm);
73     }
74 
75     /// 3D OpenSimplexNoise
76     @nogc @safe pure double noise3D(double x, double y, double z)
77     {
78         return osNoise3D(x,y,z,_perm,_permGradIndex3D);
79     }
80     /// Ditto
81     @nogc @safe pure double noise3D(const double[3] p)
82     {
83         return osNoise3D(p[0],p[1],p[2],_perm,_permGradIndex3D);
84     }
85     
86     /// 3D OpenSimplexNoise
87     @nogc @safe pure double noise4D(double x, double y, double z, double w)
88     {
89         return osNoise4D(x,y,z,w,_perm);
90     }
91     /// Ditto
92     @nogc @safe pure double noise4D(const double[4] p)
93     {
94         return osNoise4D(p[0],p[1],p[2],p[3],_perm);
95     }
96 
97 private:
98     /// Permutation Array
99     short[256] _perm;
100     /// Grad index precomputed for 3D noise
101     short[256] _permGradIndex3D;
102 }
103