@@ -139,3 +139,149 @@ struct CellNoise2D:Noise
139
139
return self . evaluate ( x, y)
140
140
}
141
141
}
142
+
143
+ public
144
+ struct CellNoise3D : Noise
145
+ {
146
+ private
147
+ struct Point3
148
+ {
149
+ let x : Double , y : Double , z : Double
150
+
151
+ init ( _ x: Double , _ y: Double , _ z: Double )
152
+ {
153
+ self . x = x
154
+ self . y = y
155
+ self . z = z
156
+ }
157
+ }
158
+
159
+ private
160
+ let permutation_table : PermutationTable ,
161
+ amplitude : Double ,
162
+ frequency : Double
163
+
164
+ public
165
+ init ( amplitude: Double , frequency: Double , seed: Int = 0 )
166
+ {
167
+ self . amplitude = 2 . squareRoot ( ) * amplitude
168
+ self . frequency = frequency
169
+ self . permutation_table = PermutationTable ( seed: seed)
170
+ }
171
+
172
+ private
173
+ func distance( from sample_point: ( x: Double , y: Double , z: Double ) , generating_point: ( a: Int , b: Int , c: Int ) ) -> Double
174
+ {
175
+ let hash : Int = self . permutation_table. hash ( generating_point. a, generating_point. b, generating_point. c)
176
+ // hash is within 0 ... 255, take it to 0 ... 0.5
177
+
178
+ // Notice that we have 256 possible hashes, and therefore 8 bits of entropy,
179
+ // to be divided up between three axes. We can assign 3 bits to the x and
180
+ // y axes each (8 levels each), and 2 bits to the z axis (4 levels). To
181
+ // compensate for the lack of z resolution, we bump up every other control
182
+ // point by half a level.
183
+
184
+ // 0b XXX YYY ZZ
185
+
186
+ let dpx : Double = ( Double ( hash >> 5 ) - 3.5 ) * 0.25 ,
187
+ dpy : Double = ( Double ( hash >> 2 & 0b0111 ) - 3.5 ) * 0.25 ,
188
+ dpz : Double = ( Double ( hash << 1 & 0b0111 + ( ( hash >> 5 ^ hash >> 2 ) & 1 ) ) - 3.5 ) * 0.25
189
+
190
+ let dx : Double = Double ( generating_point. a) + dpx - sample_point. x,
191
+ dy : Double = Double ( generating_point. b) + dpy - sample_point. y,
192
+ dz : Double = Double ( generating_point. c) + dpz - sample_point. z
193
+ return dx*dx + dy*dy + dz*dz
194
+ }
195
+
196
+ public
197
+ func evaluate( _ x: Double , _ y: Double ) -> Double
198
+ {
199
+ /*
200
+ let sample:(x:Double, y:Double) = (x * self.frequency, y * self.frequency)
201
+
202
+ let bin:(a:Int, b:Int) = (floor(sample.x), floor(sample.y)),
203
+ offset:(x:Double, y:Double) = (sample.x - Double(bin.a), sample.y - Double(bin.b))
204
+
205
+ // determine kernel
206
+
207
+ // The control points do not live within the grid cells, rather they float
208
+ // around the *corners* of the grid cells (the ‘O’s in the diagram).
209
+ // The grid cell that the sample point has been binned into is shaded.
210
+
211
+ // xb xb + 1
212
+ // +------------------+
213
+ // | | | |
214
+ // yb |---- O//////O ----|
215
+ // | |//////| |
216
+ // yb + 1 |---- O//////O ----|
217
+ // | | | |
218
+ // +------------------+
219
+
220
+ // The bin itself is divided into quadrants to classify the four corners as
221
+ // “near” and “far” points. We call these points the *generating points*.
222
+ // The sample point (example) has been marked with an ‘*’.
223
+
224
+ // O ------- far
225
+ // | | |
226
+ // |----+----|
227
+ // | * | |
228
+ // near ------- O
229
+
230
+ // The actual control points never spawn more than 0.5 normalized units
231
+ // away from the near and far points, and their cross-analogues. Therefore,
232
+ // the quadrants also provide a means of early exit, since if a sample is
233
+ // closer to a control point than the quadrant dividers, it is impossible
234
+ // for the sample to be closer to the control point that lives on the
235
+ // other side of the divider.
236
+
237
+ let quadrant:(x:Bool, y:Bool) = (offset.x > 0.5, offset.y > 0.5),
238
+ near:(a:Int, b:Int) = (bin.a + (quadrant.x ? 1 : 0), bin.b + (quadrant.y ? 1 : 0)),
239
+ far:(a:Int, b:Int) = (bin.a + (quadrant.x ? 0 : 1), bin.b + (quadrant.y ? 0 : 1))
240
+
241
+ let divider_distance:(x:Double, y:Double) = ((offset.x - 0.5) * (offset.x - 0.5), (offset.y - 0.5) * (offset.y - 0.5))
242
+
243
+ var r2_min:Double = self.distance(from: sample, generating_point: near)
244
+
245
+ @inline(__always)
246
+ func test(generating_point:(a:Int, b:Int))
247
+ {
248
+ let r2:Double = self.distance(from: sample, generating_point: generating_point)
249
+
250
+ if r2 < r2_min
251
+ {
252
+ r2_min = r2
253
+ }
254
+ }
255
+
256
+ if divider_distance.x < r2_min
257
+ {
258
+ test(generating_point: (far.a, near.b)) // near point horizontal
259
+ }
260
+
261
+ if divider_distance.y < r2_min
262
+ {
263
+ test(generating_point: (near.a, far.b)) // near point vertical
264
+ }
265
+
266
+ if divider_distance.x < r2_min && divider_distance.y < r2_min
267
+ {
268
+ test(generating_point: far)
269
+ }
270
+
271
+ return self.amplitude * r2_min
272
+ */
273
+ return 0
274
+ }
275
+
276
+ public
277
+ func evaluate( _ x: Double , _ y: Double , _: Double ) -> Double
278
+ {
279
+ return self . evaluate ( x, y)
280
+ }
281
+
282
+ public
283
+ func evaluate( _ x: Double , _ y: Double , _: Double , _: Double ) -> Double
284
+ {
285
+ return self . evaluate ( x, y)
286
+ }
287
+ }
0 commit comments