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