1
1
public
2
2
struct CellNoise2D : Noise
3
3
{
4
+ private
5
+ typealias IntV2 = ( a: Int , b: Int )
6
+ private
7
+ typealias DoubleV2 = ( x: Double , y: Double )
8
+
4
9
private
5
10
let permutation_table : PermutationTable ,
6
11
amplitude : Double ,
@@ -15,7 +20,7 @@ struct CellNoise2D:Noise
15
20
}
16
21
17
22
private
18
- func distance( from sample_point: ( x : Double , y : Double ) , generating_point: ( a : Int , b : Int ) ) -> Double
23
+ func distance( from sample_point: DoubleV2 , generating_point: IntV2 ) -> Double
19
24
{
20
25
let hash : Int = self . permutation_table. hash ( generating_point. a, generating_point. b)
21
26
// hash is within 0 ... 255, take it to 0 ... 0.5
@@ -37,10 +42,10 @@ struct CellNoise2D:Noise
37
42
public
38
43
func evaluate( _ x: Double , _ y: Double ) -> Double
39
44
{
40
- let sample : ( x : Double , y : Double ) = ( x * self . frequency, y * self . frequency)
45
+ let sample : DoubleV2 = ( x * self . frequency, y * self . frequency)
41
46
42
- let bin : ( a : Int , b : Int ) = ( floor ( sample. x) , floor ( sample. y) ) ,
43
- offset : ( x : Double , y : Double ) = ( sample. x - Double( bin. a) , sample. y - Double( bin. b) )
47
+ let bin : IntV2 = ( floor ( sample. x) , floor ( sample. y) ) ,
48
+ offset : DoubleV2 = ( sample. x - Double( bin. a) , sample. y - Double( bin. b) )
44
49
45
50
// determine kernel
46
51
@@ -75,16 +80,16 @@ struct CellNoise2D:Noise
75
80
// found.
76
81
77
82
let quadrant : ( x: Bool , y: Bool ) = ( offset. x > 0.5 , offset. y > 0.5 ) ,
78
- near : ( a : Int , b : Int ) = ( bin. a + ( quadrant. x ? 1 : 0 ) , bin. b + ( quadrant. y ? 1 : 0 ) ) ,
79
- far : ( a : Int , b : Int ) = ( bin. a + ( quadrant. x ? 0 : 1 ) , bin. b + ( quadrant. y ? 0 : 1 ) )
83
+ near : IntV2 = ( bin. a + ( quadrant. x ? 1 : 0 ) , bin. b + ( quadrant. y ? 1 : 0 ) ) ,
84
+ far : IntV2 = ( bin. a + ( quadrant. x ? 0 : 1 ) , bin. b + ( quadrant. y ? 0 : 1 ) )
80
85
81
- let nearpoint_disp : ( x : Double , y : Double ) = ( abs ( offset. x - ( quadrant. x ? 1 : 0 ) ) ,
86
+ let nearpoint_disp : DoubleV2 = ( abs ( offset. x - ( quadrant. x ? 1 : 0 ) ) ,
82
87
abs ( offset. y - ( quadrant. y ? 1 : 0 ) ) )
83
88
84
89
var r2_min : Double = self . distance ( from: sample, generating_point: near)
85
90
86
91
@inline ( __always)
87
- func test( generating_point: ( a : Int , b : Int ) )
92
+ func test( generating_point: IntV2 )
88
93
{
89
94
let r2 : Double = self . distance ( from: sample, generating_point: generating_point)
90
95
@@ -136,8 +141,8 @@ struct CellNoise2D:Noise
136
141
// | | | | | | |
137
142
// inner ----- B ------- C --------+
138
143
139
- let inner : ( a : Int , b : Int ) = ( bin. a + ( quadrant. x ? 2 : - 1 ) , bin. b + ( quadrant. y ? 2 : - 1 ) ) ,
140
- outer : ( a : Int , b : Int ) = ( bin. a + ( quadrant. x ? - 1 : 2 ) , bin. b + ( quadrant. y ? - 1 : 2 ) )
144
+ let inner : IntV2 = ( bin. a + ( quadrant. x ? 2 : - 1 ) , bin. b + ( quadrant. y ? 2 : - 1 ) ) ,
145
+ outer : IntV2 = ( bin. a + ( quadrant. x ? - 1 : 2 ) , bin. b + ( quadrant. y ? - 1 : 2 ) )
141
146
142
147
// B points
143
148
if ( nearpoint_disp. x + 0.5 ) * ( nearpoint_disp. x + 0.5 ) < r2_min
@@ -206,17 +211,9 @@ public
206
211
struct CellNoise3D : Noise
207
212
{
208
213
private
209
- struct Point3
210
- {
211
- let x : Double , y : Double , z : Double
212
-
213
- init ( _ x: Double , _ y: Double , _ z: Double )
214
- {
215
- self . x = x
216
- self . y = y
217
- self . z = z
218
- }
219
- }
214
+ typealias IntV3 = ( a: Int , b: Int , c: Int )
215
+ private
216
+ typealias DoubleV3 = ( x: Double , y: Double , z: Double )
220
217
221
218
private
222
219
let permutation_table : PermutationTable ,
@@ -226,13 +223,13 @@ struct CellNoise3D:Noise
226
223
public
227
224
init ( amplitude: Double , frequency: Double , seed: Int = 0 )
228
225
{
229
- self . amplitude = 2 . squareRoot ( ) * amplitude
226
+ self . amplitude = amplitude * 1 / 3 . squareRoot ( )
230
227
self . frequency = frequency
231
228
self . permutation_table = PermutationTable ( seed: seed)
232
229
}
233
230
234
231
private
235
- func distance( from sample_point: ( x : Double , y : Double , z : Double ) , generating_point: ( a : Int , b : Int , c : Int ) ) -> Double
232
+ func distance( from sample_point: DoubleV3 , generating_point: IntV3 ) -> Double
236
233
{
237
234
let hash : Int = self . permutation_table. hash ( generating_point. a, generating_point. b, generating_point. c)
238
235
// hash is within 0 ... 255, take it to 0 ... 0.5
@@ -258,17 +255,109 @@ struct CellNoise3D:Noise
258
255
public
259
256
func evaluate( _ x: Double , _ y: Double ) -> Double
260
257
{
261
- return 0
258
+ return self . evaluate ( x , y , 0 )
262
259
}
263
260
264
261
public
265
- func evaluate( _ x: Double , _ y: Double , _: Double ) -> Double
262
+ func evaluate( _ x: Double , _ y: Double , _ z : Double ) -> Double
266
263
{
267
- return self . evaluate ( x, y)
264
+ let sample : DoubleV3 = ( x * self . frequency, y * self . frequency, z * self . frequency)
265
+
266
+ let bin : IntV3 = ( floor ( sample. x) , floor ( sample. y) , floor ( sample. z) ) ,
267
+ offset : DoubleV3 = ( sample. x - Double( bin. a) , sample. y - Double( bin. b) , sample. z - Double( bin. c) )
268
+
269
+ // determine kernel
270
+
271
+ // Same idea as with the 2D points, except in 3 dimensions
272
+
273
+ // near - quadrant ---- near - quadrant.y
274
+ // | | |
275
+ // |----+----|
276
+ // | | * |
277
+ // near - quadrant.x -- near quadrant →
278
+ // ↓
279
+
280
+ let quadrant : IntV3 = ( offset. x > 0.5 ? 1 : - 1 , offset. y > 0.5 ? 1 : - 1 , offset. z > 0.5 ? 1 : - 1 ) ,
281
+ near : IntV3 = ( bin. a + ( quadrant. a + 1 ) >> 1 , bin. b + ( quadrant. b + 1 ) >> 1 , bin. c + ( quadrant. c + 1 ) >> 1 )
282
+
283
+ let nearpoint_disp : DoubleV3 = ( abs ( offset. x - Double( ( quadrant. a + 1 ) >> 1 ) ) ,
284
+ abs ( offset. y - Double( ( quadrant. b + 1 ) >> 1 ) ) ,
285
+ abs ( offset. z - Double( ( quadrant. c + 1 ) >> 1 ) ) )
286
+
287
+ var r2_min : Double = self . distance ( from: sample, generating_point: near)
288
+
289
+ let kernel : [ ( r: Double , cell_offsets: [ ( Int , Int , Int ) ] ) ] =
290
+ [
291
+ ( 0.0 , [ /*(0, 0, 0), */( - 1 , 0 , 0 ) , ( 0 , - 1 , 0 ) , ( - 1 , - 1 , 0 ) , ( 0 , 0 , - 1 ) , ( - 1 , 0 , - 1 ) , ( 0 , - 1 , - 1 ) , ( - 1 , - 1 , - 1 ) ] ) ,
292
+ ( 0.25 , [ ( 0 , 0 , 1 ) , ( - 1 , 0 , 1 ) , ( 0 , - 1 , 1 ) , ( - 1 , - 1 , 1 ) , ( 0 , 1 , 0 ) , ( - 1 , 1 , 0 ) , ( 1 , 0 , 0 ) , ( 1 , - 1 , 0 ) ,
293
+ ( 0 , 1 , - 1 ) , ( - 1 , 1 , - 1 ) , ( 1 , 0 , - 1 ) , ( 1 , - 1 , - 1 ) ] ) ,
294
+ ( 0.5 , [ ( 0 , 1 , 1 ) , ( - 1 , 1 , 1 ) , ( 1 , 0 , 1 ) , ( 1 , - 1 , 1 ) , ( 1 , 1 , 0 ) , ( 1 , 1 , - 1 ) ] ) ,
295
+ ( 0.75 , [ ( 1 , 1 , 1 ) ] ) ,
296
+ ( 1.0 , [ ( - 2 , 0 , 0 ) , ( - 2 , - 1 , 0 ) , ( 0 , - 2 , 0 ) , ( - 1 , - 2 , 0 ) , ( - 2 , 0 , - 1 ) , ( - 2 , - 1 , - 1 ) , ( 0 , - 2 , - 1 ) , ( - 1 , - 2 , - 1 ) ,
297
+ ( 0 , 0 , - 2 ) , ( - 1 , 0 , - 2 ) , ( 0 , - 1 , - 2 ) , ( - 1 , - 1 , - 2 ) ] ) ,
298
+ ( 1.25 , [ ( - 2 , 0 , 1 ) , ( - 2 , - 1 , 1 ) , ( 0 , - 2 , 1 ) , ( - 1 , - 2 , 1 ) , ( - 2 , 1 , 0 ) , ( 1 , - 2 , 0 ) , ( - 2 , 1 , - 1 ) , ( 1 , - 2 , - 1 ) ,
299
+ ( 0 , 1 , - 2 ) , ( - 1 , 1 , - 2 ) , ( 1 , 0 , - 2 ) , ( 1 , - 1 , - 2 ) ] ) ,
300
+ ( 1.5 , [ ( - 2 , 1 , 1 ) , ( 1 , - 2 , 1 ) , ( 1 , 1 , - 2 ) ] ) ,
301
+ ( 2.0 , [ ( - 2 , - 2 , 0 ) , ( - 2 , - 2 , - 1 ) , ( - 2 , 0 , - 2 ) , ( - 2 , - 1 , - 2 ) , ( 0 , - 2 , - 2 ) , ( - 1 , - 2 , - 2 ) ] ) ,
302
+ ( 2.25 , [ ( 0 , 0 , 2 ) , ( - 1 , 0 , 2 ) , ( 0 , - 1 , 2 ) , ( - 1 , - 1 , 2 ) , ( - 2 , - 2 , 1 ) , ( 0 , 2 , 0 ) , ( - 1 , 2 , 0 ) , ( 2 , 0 , 0 ) ,
303
+ ( 2 , - 1 , 0 ) , ( 0 , 2 , - 1 ) , ( - 1 , 2 , - 1 ) , ( 2 , 0 , - 1 ) , ( 2 , - 1 , - 1 ) , ( - 2 , 1 , - 2 ) , ( 1 , - 2 , - 2 ) ] ) ,
304
+ ( 2.5 , [ ( 0 , 1 , 2 ) , ( - 1 , 1 , 2 ) , ( 1 , 0 , 2 ) , ( 1 , - 1 , 2 ) , ( 0 , 2 , 1 ) , ( - 1 , 2 , 1 ) , ( 2 , 0 , 1 ) , ( 2 , - 1 , 1 ) ,
305
+ ( 1 , 2 , 0 ) , ( 2 , 1 , 0 ) , ( 1 , 2 , - 1 ) , ( 2 , 1 , - 1 ) ] ) ,
306
+ ( 2.75 , [ ( 1 , 1 , 2 ) , ( 1 , 2 , 1 ) , ( 2 , 1 , 1 ) ] )
307
+ ]
308
+
309
+ for (kernel_radius, cell_offsets) : ( r: Double , cell_offsets: [ ( Int , Int , Int ) ] ) in kernel
310
+ {
311
+ if r2_min < kernel_radius
312
+ {
313
+ break // EARLY EXIT
314
+ }
315
+
316
+ for cell_offset : IntV3 in cell_offsets
317
+ {
318
+ // calculate distance from quadrant volume to kernel cell
319
+ var cell_distance2 : Double
320
+ if cell_offset. a == 0
321
+ {
322
+ cell_distance2 = 0
323
+ }
324
+ else
325
+ { // move by 0.5 towards zero
326
+ let dx : Double = Double ( cell_offset. a) + ( cell_offset. a > 0 ? - 0.5 : 0.5 ) + nearpoint_disp. x
327
+ cell_distance2 = dx*dx
328
+ }
329
+
330
+ if cell_offset. b != 0
331
+ { // move by 0.5 towards zero
332
+ let dy : Double = Double ( cell_offset. b) + ( cell_offset. b > 0 ? - 0.5 : 0.5 ) + nearpoint_disp. y
333
+ cell_distance2 += dy*dy
334
+ }
335
+
336
+ if cell_offset. c != 0
337
+ { // move by 0.5 towards zero
338
+ let dz : Double = Double ( cell_offset. c) + ( cell_offset. c > 0 ? - 0.5 : 0.5 ) + nearpoint_disp. z
339
+ cell_distance2 += dz*dz
340
+ }
341
+
342
+ guard cell_distance2 < r2_min
343
+ else
344
+ {
345
+ continue
346
+ }
347
+
348
+ let generating_point : IntV3 = ( near. a + quadrant. a*cell_offset. a,
349
+ near. b + quadrant. b*cell_offset. b,
350
+ near. c + quadrant. c*cell_offset. c)
351
+ let r2 : Double = self . distance ( from: sample, generating_point: generating_point)
352
+ r2_min = min ( r2, r2_min)
353
+ }
354
+ }
355
+
356
+ return self . amplitude * r2_min
268
357
}
269
358
270
359
public
271
- func evaluate( _ x: Double , _ y: Double , _: Double , _: Double ) -> Double
360
+ func evaluate( _ x: Double , _ y: Double , _ z : Double , _: Double ) -> Double
272
361
{
273
362
return self . evaluate ( x, y)
274
363
}
0 commit comments