1
1
import func Glibc. sin
2
2
import func Glibc. cos
3
3
4
- fileprivate let SQUISH_2D : Double = 0.5 * ( 1 / 3 . squareRoot ( ) - 1 )
5
- fileprivate let STRETCH_2D : Double = 0.5 * ( 3 . squareRoot ( ) - 1 )
4
+ fileprivate
5
+ enum Const
6
+ {
7
+ fileprivate static
8
+ let SQUISH_2D : Double = 0.5 * ( 1 / 3 . squareRoot ( ) - 1 ) ,
9
+ STRETCH_2D : Double = 0.5 * ( 3 . squareRoot ( ) - 1 )
10
+
11
+ // each gradient appears four times to mitigate hashing biases
12
+ fileprivate static
13
+ let GRADIENTS_2D : [ Math . DoubleV2 ] =
14
+ [
15
+ ( 1 , 0 ) , ( 0 , 1 ) , ( - 1 , 0 ) , ( 0 , - 1 ) ,
16
+ ( 0.7 , 0.7 ) , ( - 0.7 , 0.7 ) , ( - 0.7 , - 0.7 ) , ( 0.7 , - 0.7 ) ,
17
+
18
+ ( 0.7 , - 0.7 ) ,
19
+ ( 1 , 0 ) , ( 0 , 1 ) , ( - 1 , 0 ) , ( 0 , - 1 ) ,
20
+ ( 0.7 , 0.7 ) , ( - 0.7 , 0.7 ) , ( - 0.7 , - 0.7 ) ,
21
+
22
+ ( - 0.7 , - 0.7 ) , ( 0.7 , - 0.7 ) ,
23
+ ( 1 , 0 ) , ( 0 , 1 ) , ( - 1 , 0 ) , ( 0 , - 1 ) ,
24
+ ( 0.7 , 0.7 ) , ( - 0.7 , 0.7 ) ,
25
+
26
+ ( - 0.7 , 0.7 ) , ( - 0.7 , - 0.7 ) , ( 0.7 , - 0.7 ) ,
27
+ ( 1 , 0 ) , ( 0 , 1 ) , ( - 1 , 0 ) , ( 0 , - 1 ) ,
28
+ ( 0.7 , 0.7 )
29
+ ]
30
+
31
+ fileprivate static
32
+ let GRADIENTS_3D : [ Math . DoubleV3 ] =
33
+ [
34
+ ( 1 , 1 , 0 ) , ( - 1 , 1 , 0 ) , ( 1 , - 1 , 0 ) , ( - 1 , - 1 , 0 ) ,
35
+ ( 1 , 0 , 1 ) , ( - 1 , 0 , 1 ) , ( 1 , 0 , - 1 ) , ( - 1 , 0 , - 1 ) ,
36
+ ( 0 , 1 , 1 ) , ( 0 , - 1 , 1 ) , ( 0 , 1 , - 1 ) , ( 0 , - 1 , - 1 ) ,
37
+ ( 1 , 1 , 0 ) , ( - 1 , 1 , 0 ) , ( 0 , - 1 , 1 ) , ( 0 , - 1 , - 1 ) ,
38
+
39
+ ( 0 , - 1 , - 1 ) ,
40
+ ( 1 , 1 , 0 ) , ( - 1 , 1 , 0 ) , ( 1 , - 1 , 0 ) , ( - 1 , - 1 , 0 ) ,
41
+ ( 1 , 0 , 1 ) , ( - 1 , 0 , 1 ) , ( 1 , 0 , - 1 ) , ( - 1 , 0 , - 1 ) ,
42
+ ( 0 , 1 , 1 ) , ( 0 , - 1 , 1 ) , ( 0 , 1 , - 1 ) , ( 0 , - 1 , - 1 ) ,
43
+ ( 1 , 1 , 0 ) , ( - 1 , 1 , 0 ) , ( 0 , - 1 , 1 )
44
+ ]
45
+ }
6
46
7
47
fileprivate
8
48
protocol GradientNoise2D : Noise
9
49
{
10
50
var permutation_table : PermutationTable { get }
11
51
12
- static var gradient_table16 : [ Math . DoubleV2 ] { get }
52
+ static var gradient_table32 : [ Math . DoubleV2 ] { get }
13
53
static var radius : Double { get }
54
+
55
+
14
56
}
15
57
16
58
fileprivate
@@ -21,7 +63,7 @@ extension GradientNoise2D
21
63
let dr : Double = Self . radius - Math. dot ( offset, offset)
22
64
if dr > 0
23
65
{
24
- let gradient : Math . DoubleV2 = Self . gradient_table16 [ self . permutation_table. hash ( point) & 15 ] ,
66
+ let gradient : Math . DoubleV2 = Self . gradient_table32 [ self . permutation_table. hash ( point) & 31 ] ,
25
67
drdr : Double = dr * dr
26
68
return drdr * drdr * Math. dot ( gradient, offset)
27
69
}
@@ -36,14 +78,7 @@ public
36
78
struct SimplexNoise2D : GradientNoise2D
37
79
{
38
80
fileprivate static
39
- let gradient_table16 : [ Math . DoubleV2 ] =
40
- [
41
- ( - 1 , - 1 ) , ( 1 , 0 ) , ( - 1 , 0 ) , ( 1 , 1 ) ,
42
- ( - 1 , 1 ) , ( 0 , - 1 ) , ( 0 , 1 ) , ( 1 , - 1 ) ,
43
-
44
- ( - 1 , - 1 ) , ( 1 , 0 ) , ( - 1 , 0 ) , ( 1 , 1 ) ,
45
- ( - 1 , 1 ) , ( 0 , - 1 ) , ( 0 , 1 ) , ( 1 , - 1 )
46
- ]
81
+ let gradient_table32 : [ Math . DoubleV2 ] = Const . GRADIENTS_2D
47
82
48
83
fileprivate static
49
84
let radius : Double = 2
@@ -58,7 +93,7 @@ struct SimplexNoise2D:GradientNoise2D
58
93
public
59
94
init ( amplitude: Double , frequency: Double , seed: Int = 0 )
60
95
{
61
- self . amplitude = 0.096 * amplitude
96
+ self . amplitude = 0.1322 * amplitude
62
97
self . frequency = frequency
63
98
self . permutation_table = PermutationTable ( seed: seed)
64
99
}
@@ -69,7 +104,7 @@ struct SimplexNoise2D:GradientNoise2D
69
104
let sample : Math . DoubleV2 = ( x * self . frequency, y * self . frequency)
70
105
// transform our coordinate system so that the *simplex* (x, y) forms a
71
106
// rectangular grid (u, v)
72
- let squish_offset : Double = ( sample. x + sample. y) * SQUISH_2D,
107
+ let squish_offset : Double = ( sample. x + sample. y) * Const . SQUISH_2D,
73
108
sample_uv : Math . DoubleV2 = ( sample. x + squish_offset, sample. y + squish_offset)
74
109
75
110
// get integral (u, v) coordinates of the rhombus and get position inside
@@ -99,7 +134,7 @@ struct SimplexNoise2D:GradientNoise2D
99
134
// do the same in the original (x, y) coordinate space
100
135
101
136
// stretch back to get (x, y) coordinates of rhombus origin
102
- let stretch_offset : Double = Double ( bin. a + bin. b) * STRETCH_2D,
137
+ let stretch_offset : Double = Double ( bin. a + bin. b) * Const . STRETCH_2D,
103
138
origin : Math . DoubleV2 = ( Double ( bin. a) + stretch_offset, Double ( bin. b) + stretch_offset)
104
139
105
140
// get relative position inside the rhombus relative to (xb, xb)
@@ -114,27 +149,27 @@ struct SimplexNoise2D:GradientNoise2D
114
149
}
115
150
116
151
// contribution from (1, 0)
117
- _inspect ( point_offset: ( 1 , 0 ) , sample_offset: ( 1 + STRETCH_2D, STRETCH_2D) )
152
+ _inspect ( point_offset: ( 1 , 0 ) , sample_offset: ( 1 + Const . STRETCH_2D, Const . STRETCH_2D) )
118
153
119
154
// contribution from (0, 1)
120
- _inspect ( point_offset: ( 0 , 1 ) , sample_offset: ( STRETCH_2D, 1 + STRETCH_2D) )
155
+ _inspect ( point_offset: ( 0 , 1 ) , sample_offset: ( Const . STRETCH_2D, 1 + Const . STRETCH_2D) )
121
156
122
157
// decide which triangle we are in
123
158
let uv_sum : Double = sample_uv_rel. x + sample_uv_rel. y
124
159
if ( uv_sum > 1 ) // we are to the bottom-right of the diagonal line (du = 1 - dv)
125
160
{
126
- _inspect ( point_offset: ( 1 , 1 ) , sample_offset: ( 1 + 2 * STRETCH_2D, 1 + 2 * STRETCH_2D) )
161
+ _inspect ( point_offset: ( 1 , 1 ) , sample_offset: ( 1 + 2 * Const . STRETCH_2D, 1 + 2 * Const . STRETCH_2D) )
127
162
128
163
let center_dist : Double = 2 - uv_sum
129
164
if center_dist < sample_uv_rel. x || center_dist < sample_uv_rel. y
130
165
{
131
166
if sample_uv_rel. x > sample_uv_rel. y
132
167
{
133
- _inspect ( point_offset: ( 2 , 0 ) , sample_offset: ( 2 + 2 * STRETCH_2D, 2 * STRETCH_2D) )
168
+ _inspect ( point_offset: ( 2 , 0 ) , sample_offset: ( 2 + 2 * Const . STRETCH_2D, 2 * Const . STRETCH_2D) )
134
169
}
135
170
else
136
171
{
137
- _inspect ( point_offset: ( 0 , 2 ) , sample_offset: ( 2 * STRETCH_2D, 2 + 2 * STRETCH_2D) )
172
+ _inspect ( point_offset: ( 0 , 2 ) , sample_offset: ( 2 * Const . STRETCH_2D, 2 + 2 * Const . STRETCH_2D) )
138
173
}
139
174
}
140
175
else
@@ -160,7 +195,7 @@ struct SimplexNoise2D:GradientNoise2D
160
195
}
161
196
else
162
197
{
163
- _inspect ( point_offset: ( 1 , 1 ) , sample_offset: ( 1 + 2 * STRETCH_2D, 1 + 2 * STRETCH_2D) )
198
+ _inspect ( point_offset: ( 1 , 1 ) , sample_offset: ( 1 + 2 * Const . STRETCH_2D, 1 + 2 * Const . STRETCH_2D) )
164
199
}
165
200
}
166
201
@@ -192,7 +227,7 @@ struct SuperSimplexNoise2D:GradientNoise2D
192
227
@inline ( __always)
193
228
func _lattice_point( at point: Math . IntV2 ) -> ( Math . IntV2 , Math . DoubleV2 )
194
229
{
195
- let stretch_offset : Double = Double ( point. a + point. b) * SQUISH_2D
230
+ let stretch_offset : Double = Double ( point. a + point. b) * Const . SQUISH_2D
196
231
return ( point, ( Double ( point. a) + stretch_offset, Double ( point. b) + stretch_offset) )
197
232
}
198
233
@@ -212,20 +247,7 @@ struct SuperSimplexNoise2D:GradientNoise2D
212
247
} ( )
213
248
214
249
static
215
- let gradient_table16 : [ Math . DoubleV2 ] =
216
- {
217
- var gradients : [ Math . DoubleV2 ] = [ ]
218
- gradients. reserveCapacity ( 16 )
219
-
220
- let dθ : Double = 2 * Double. pi / Double( 16 )
221
- for i in 0 ..< 16
222
- {
223
- let θ : Double = Double ( i) * dθ
224
- gradients. append ( ( cos ( θ) , sin ( θ) ) )
225
- }
226
-
227
- return gradients
228
- } ( )
250
+ let gradient_table32 : [ Math . DoubleV2 ] = Const . GRADIENTS_2D
229
251
230
252
static
231
253
let radius : Double = 2 / 3
@@ -239,7 +261,7 @@ struct SuperSimplexNoise2D:GradientNoise2D
239
261
public
240
262
init ( amplitude: Double , frequency: Double , seed: Int = 0 )
241
263
{
242
- self . amplitude = 18 * amplitude
264
+ self . amplitude = 18.5 * amplitude
243
265
self . frequency = frequency
244
266
self . permutation_table = PermutationTable ( seed: seed)
245
267
}
@@ -249,7 +271,7 @@ struct SuperSimplexNoise2D:GradientNoise2D
249
271
{
250
272
let sample : Math . DoubleV2 = ( x * self . frequency, y * self . frequency)
251
273
// transform our (x, y) coordinate to (u, v) space
252
- let stretch_offset : Double = ( sample. x + sample. y) * STRETCH_2D,
274
+ let stretch_offset : Double = ( sample. x + sample. y) * Const . STRETCH_2D,
253
275
sample_uv : Math . DoubleV2 = ( sample. x + stretch_offset, sample. y + stretch_offset)
254
276
255
277
// (0, 0) ----- (1, 0)
@@ -358,7 +380,7 @@ struct SuperSimplexNoise2D:GradientNoise2D
358
380
*/
359
381
360
382
// get the relative offset from (0, 0)
361
- let squish_offset : Double = ( sample_uv_rel. x + sample_uv_rel. y) * SQUISH_2D,
383
+ let squish_offset : Double = ( sample_uv_rel. x + sample_uv_rel. y) * Const . SQUISH_2D,
362
384
sample_rel : Math . DoubleV2 = ( sample_uv_rel. x + squish_offset, sample_uv_rel. y + squish_offset)
363
385
364
386
var Σ : Double = 0
@@ -408,13 +430,7 @@ struct SuperSimplexNoise3D:Noise
408
430
} ( )
409
431
410
432
private static
411
- let gradient_table16 : [ Math . DoubleV3 ] =
412
- [
413
- ( 1 , 1 , 0 ) , ( - 1 , 1 , 0 ) , ( 1 , - 1 , 0 ) , ( - 1 , - 1 , 0 ) ,
414
- ( 1 , 0 , 1 ) , ( - 1 , 0 , 1 ) , ( 1 , 0 , - 1 ) , ( - 1 , 0 , - 1 ) ,
415
- ( 0 , 1 , 1 ) , ( 0 , - 1 , 1 ) , ( 0 , 1 , - 1 ) , ( 0 , - 1 , - 1 ) ,
416
- ( 1 , 1 , 0 ) , ( - 1 , 1 , 0 ) , ( 0 , - 1 , 1 ) , ( 0 , - 1 , - 1 )
417
- ]
433
+ let gradient_table32 : [ Math . DoubleV3 ] = Const . GRADIENTS_3D
418
434
419
435
private
420
436
let permutation_table : PermutationTable
@@ -437,7 +453,7 @@ struct SuperSimplexNoise3D:Noise
437
453
let dr : Double = 0.75 - Math. dot ( offset, offset)
438
454
if dr > 0
439
455
{
440
- let gradient : Math . DoubleV3 = SuperSimplexNoise3D . gradient_table16 [ self . permutation_table. hash ( point) & 15 ] ,
456
+ let gradient : Math . DoubleV3 = SuperSimplexNoise3D . gradient_table32 [ self . permutation_table. hash ( point) & 31 ] ,
441
457
drdr : Double = dr * dr
442
458
return drdr * drdr * Math. dot ( gradient, offset)
443
459
}
0 commit comments