1 module armos.math.noise;
2 import std.random;
3 import armos.math;
4 
5 /++
6 ノイズを生成します.
7 +/
8 struct PerlinNoise(T, int Dim) {
9     private{
10         alias V = Vector!(T, Dim);
11         alias Vi = Vector!(int, Dim);
12         import std.math:sqrt;
13         import std.conv:to;
14         enum R = sqrt(1f/Dim.to!T);
15     }
16     public{
17         ///
18         T eval(T[] args ...){
19             import std.conv;
20             V localCoord;
21             localCoord.elements = args;
22             _vi = (localCoord.to!Vi%T(255));
23             _vf = localCoord - localCoord.to!Vi.to!V;
24             _faded = _vf.fade;
25             // return (lerp()+T(1))*T(0.5);
26             return lerp();
27         }
28     }//public
29 
30     private{
31         int[] _permutationTable = defaultPermutationTable ~ defaultPermutationTable;
32         float _repeat = 1f;
33         
34         Vi _vi;
35         V _vf;
36         V _faded;
37         
38         T lerp(T)(in T a, in T b, in T x)const{
39             return a+x*(b-a);
40         }
41         
42         T lerp()const{
43             return lerpR!(Dim-1, hypercubeVertices!(T, Dim));
44         }
45         
46         T lerpR(int currentDim, V[] HyperCubeVertices)()const{
47             static if(currentDim == 0){
48                 import std.conv;
49                 return lerp(
50                     grad((_vi+HyperCubeVertices[0].to!Vi).hash(_permutationTable), _vf-HyperCubeVertices[0]),
51                     grad((_vi+HyperCubeVertices[1].to!Vi).hash(_permutationTable), _vf-HyperCubeVertices[1]),
52                     _faded[currentDim]
53                 );
54             }else{
55                 return lerp(
56                     lerpR!(currentDim-1, HyperCubeVertices[0..$/2]), 
57                     lerpR!(currentDim-1, HyperCubeVertices[$/2..$]), 
58                     _faded[currentDim]
59                 );
60             }
61         }
62     }//private
63 }//struct PerlinNoise
64 
65 private{
66     int hash(Vi:Vector!(int, Dim), int Dim)(in Vi vi, in int[] permutationTable){
67         return hashR!(Vi, Dim, Dim-1)(vi, permutationTable);
68     }
69     
70     int hashR(Vi:Vector!(int, Dim), int Dim, int currentDim)(in Vi vi, in int[] permutationTable){
71         static if(currentDim == 0){
72             return permutationTable[vi[0]];
73         }else{
74             return permutationTable[hashR!(Vi, Dim, currentDim-1)(vi, permutationTable)+vi[currentDim]];
75         }
76     }
77     
78     V fade(V:Vector!(T, Dim), T, int Dim)(in V t){
79         return t * t * t * (t * (t * T(6) - T(15)) + T(10));
80     }
81     
82     
83 
84     T grad(V:Vector!(T, Dim), T, int Dim: 1)(in int hash, in V vec){
85         int h = hash & 0xF;
86         T g= T(1) + (h & 7);
87         if(h&8) g =- g;
88         return g * vec.x;
89     }
90     
91     T grad(V:Vector!(T, Dim), T, int Dim: 2)(in int hash, in V vec){
92         int h = hash & 0x7;
93         T u = h<4 ? vec.x : vec.y;
94         T v = h<4 ? vec.y : vec.x;
95         return ((h&1)? -u : u) + ((h&2)? -2.0f*v : 2.0f*v);
96     }
97     
98     T grad(V:Vector!(T, Dim), T, int Dim: 3)(in int hash, in V vec){
99         int h = hash & 0xF;
100         T u = h<8 ? vec.x : vec.y;
101         T v = h<4 ? vec.y : h==12||h==14 ? vec.x : vec.z;
102         return ((h&1)? -u : u) + ((h&2)? -v : v);
103     }
104     
105     T grad(V:Vector!(T, Dim), T, int Dim: 4)(in int hash, in V vec){
106         int h = hash & 0x1F;
107         T u = h<24 ? vec.x : vec.y;
108         T v = h<16 ? vec.y : vec.z;
109         T w = h<8 ? vec.z : vec.w;
110         return ((h&1)? -u : u) + ((h&2)? -v : v) + ((h&4)? -w : w);
111     }
112     
113     armos.math.Vector!(T, Dim)[] hypercubeVertices(T, int Dim)(){
114         armos.math.Vector!(T, Dim)[] hypercubeVerticesR(T, int Dim)(in ulong verticesIndex){
115             if(verticesIndex<2^^Dim){
116                 import std.conv:to;
117                 import std.array:split;
118                 import std.format:format;
119                 import std.algorithm.mutation:foo = reverse;
120                 T[] array = format("%." ~ Dim.to!string ~ "b", verticesIndex).split("").to!(T[]).reverseArray(Dim);
121                 auto v = armos.math.Vector!(T, Dim)(array);
122                 return v ~ hypercubeVerticesR!(T, Dim)(verticesIndex + 1);
123             }else{
124                 armos.math.Vector!(T, Dim)[] array;
125                 return array;
126             }
127         }
128 
129         return hypercubeVerticesR!(T, Dim)(0);
130     }
131     
132     static unittest{
133         import std.stdio;
134         alias V = Vector3i;
135         assert(hypercubeVertices!(int, 3) == [
136             V(0, 0, 0), 
137             V(1, 0, 0), 
138             V(0, 1, 0), 
139             V(1, 1, 0), 
140             V(0, 0, 1), 
141             V(1, 0, 1), 
142             V(0, 1, 1), 
143             V(1, 1, 1), 
144         ]);
145     }
146     
147     T[] reverseArray(T)(T[] array, in int index){
148         if(index > 1){
149             return reverseArray(array[1..$], index-1) ~  array[0] ;
150         }else{
151             return array;
152         }
153     }
154 
155     static immutable int[] defaultPermutationTable = [
156         151, 160, 137, 91,  90,  15,  131, 13,  201, 95,  96,  53,  194, 233, 7,   225,
157         140, 36,  103, 30,  69,  142, 8,   99,  37,  240, 21,  10,  23,  190, 6,   148,
158         247, 120, 234, 75,  0,   26,  197, 62,  94,  252, 219, 203, 117, 35,  11,  32,
159         57,  177, 33,  88,  237, 149, 56,  87,  174, 20,  125, 136, 171, 168, 68,  175,
160         74,  165, 71,  134, 139, 48,  27,  166, 77,  146, 158, 231, 83,  111, 229, 122,
161         60,  211, 133, 230, 220, 105, 92,  41,  55,  46,  245, 40,  244, 102, 143, 54,
162         65,  25,  63,  161, 1,   216, 80,  73,  209, 76,  132, 187, 208, 89,  18,  169,
163         200, 196, 135, 130, 116, 188, 159, 86,  164, 100, 109, 198, 173, 186, 3,   64,
164         52,  217, 226, 250, 124, 123, 5,   202, 38,  147, 118, 126, 255, 82,  85,  212,
165         207, 206, 59,  227, 47,  16,  58,  17,  182, 189, 28,  42,  223, 183, 170, 213,
166         119, 248, 152, 2,   44,  154, 163, 70,  221, 153, 101, 155, 167, 43,  172, 9,
167         129, 22,  39,  253, 19,  98,  108, 110, 79,  113, 224, 232, 178, 185, 112, 104,
168         218, 246, 97,  228, 251, 34,  242, 193, 238, 210, 144, 12,  191, 179, 162, 241,
169         81,  51,  145, 235, 249, 14,  239, 107, 49,  192, 214, 31,  181, 199, 106, 157,
170         184, 84,  204, 176, 115, 121, 50,  45,  127, 4,   150, 254, 138, 236, 205, 93,
171         222, 114, 67,  29,  24,  72,  243, 141, 128, 195, 78,  66,  215, 61,  156, 180,
172     ];
173 }
174 
175 // #define FASTFLOOR(x) ( ((x)>0) ? ((int)x) : (((int)x)-1) )