Skip to content

Commit 57436df

Browse files
committed
make 2D voronoi noise code more compact and consistent with the 3D implementation
1 parent a13d4c8 commit 57436df

File tree

1 file changed

+39
-72
lines changed

1 file changed

+39
-72
lines changed

sources/noise/cell.swift

Lines changed: 39 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,12 @@ struct CellNoise2D:Noise
6666
// as “near” and “far” points. We call these points the *generating points*.
6767
// The sample point (example) has been marked with an ‘*’.
6868

69-
// A ------ far
69+
// A —————— far
7070
// | | |
7171
// |----+----|
7272
// | * | |
73-
// near ------ A
73+
// near —————— A ← quadrant
74+
// ↓
7475

7576
// The actual feature points never spawn outside of the unit square surrounding
7677
// their generating points. Therefore, the boundaries of the generating
@@ -79,48 +80,36 @@ struct CellNoise2D:Noise
7980
// square since it cannot produce a feature point closer than we have already
8081
// found.
8182

82-
let quadrant:(x:Bool, y:Bool) = (offset.x > 0.5, offset.y > 0.5),
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))
83+
let quadrant:IntV2 = (offset.x > 0.5 ? 1 : -1, offset.y > 0.5 ? 1 : -1),
84+
near:IntV2 = (bin.a + (quadrant.a + 1) >> 1, bin.b + (quadrant.b + 1) >> 1),
85+
far:IntV2 = (near.a - quadrant.a, near.b - quadrant.b)
8586

86-
let nearpoint_disp:DoubleV2 = (abs(offset.x - (quadrant.x ? 1 : 0)),
87-
abs(offset.y - (quadrant.y ? 1 : 0)))
87+
let nearpoint_disp:DoubleV2 = (abs(offset.x - Double((quadrant.a + 1) >> 1)),
88+
abs(offset.y - Double((quadrant.b + 1) >> 1)))
8889

89-
var r2_min:Double = self.distance(from: sample, generating_point: near)
90+
var r2:Double = self.distance(from: sample, generating_point: near)
9091

9192
@inline(__always)
92-
func test(generating_point:IntV2)
93+
func test(generating_point:IntV2, dx:Double = 0, dy:Double = 0)
9394
{
94-
let r2:Double = self.distance(from: sample, generating_point: generating_point)
95-
96-
if r2 < r2_min
95+
if dx*dx + dy*dy < r2
9796
{
98-
r2_min = r2
97+
r2 = min(r2, self.distance(from: sample, generating_point: generating_point))
9998
}
10099
}
101100

102101
// A points
103-
if (0.5 - nearpoint_disp.y) * (0.5 - nearpoint_disp.y) < r2_min
104-
{
105-
test(generating_point: (near.a, far.b))
106-
}
107-
108-
if (0.5 - nearpoint_disp.x) * (0.5 - nearpoint_disp.x) < r2_min
109-
{
110-
test(generating_point: (far.a, near.b))
111-
}
102+
test(generating_point: (near.a, far.b), dy: nearpoint_disp.y - 0.5)
103+
test(generating_point: (far.a, near.b), dx: nearpoint_disp.x - 0.5)
112104

113105
// far point
114-
if (0.5 - nearpoint_disp.x) * (0.5 - nearpoint_disp.x) + (0.5 - nearpoint_disp.y) * (0.5 - nearpoint_disp.y) < r2_min
115-
{
116-
test(generating_point: far)
117-
}
106+
test(generating_point: far, dx: nearpoint_disp.x - 0.5, dy: nearpoint_disp.y - 0.5)
118107

119108
// EARLY EXIT: if we have a point within 0.5 units, we don’t have to check
120109
// the outer kernel
121-
if r2_min < 0.5*0.5
110+
if r2 < 0.25
122111
{
123-
return self.amplitude * r2_min
112+
return self.amplitude * r2
124113
}
125114

126115
// This is the part where shit hits the fan. (`inner` and `outer` are never
@@ -139,59 +128,37 @@ struct CellNoise2D:Noise
139128
// | | | | | | |
140129
// |----+----|----+----|----+----|
141130
// | | | | | | |
142-
// inner ----- B ------- C --------+
131+
// inner ----- B ------- C --------+ ← quadrant
132+
// ↓
143133

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))
134+
let inner:IntV2 = (near.a + quadrant.a, near.b + quadrant.b)
146135

147136
// B points
148-
if (nearpoint_disp.x + 0.5) * (nearpoint_disp.x + 0.5) < r2_min
149-
{
150-
test(generating_point: (inner.a, near.b))
151-
}
152-
if (nearpoint_disp.y + 0.5) * (nearpoint_disp.y + 0.5) < r2_min
153-
{
154-
test(generating_point: (near.a, inner.b))
155-
}
137+
test(generating_point: (inner.a, near.b), dx: nearpoint_disp.x + 0.5)
138+
test(generating_point: (near.a, inner.b), dy: nearpoint_disp.y + 0.5)
156139

157140
// C points
158-
if (nearpoint_disp.x + 0.5) * (nearpoint_disp.x + 0.5) + (0.5 - nearpoint_disp.y) * (0.5 - nearpoint_disp.y) < r2_min
159-
{
160-
test(generating_point: (inner.a, far.b))
161-
}
162-
if (nearpoint_disp.y + 0.5) * (nearpoint_disp.y + 0.5) + (0.5 - nearpoint_disp.x) * (0.5 - nearpoint_disp.x) < r2_min
163-
{
164-
test(generating_point: (far.a, inner.b))
165-
}
141+
test(generating_point: (inner.a, far.b), dx: nearpoint_disp.x + 0.5, dy: nearpoint_disp.y - 0.5)
142+
test(generating_point: (far.a, inner.b), dx: nearpoint_disp.x - 0.5, dy: nearpoint_disp.y + 0.5)
166143

167144
// EARLY EXIT: if we have a point within 1 unit, we don’t have to check
168145
// the D points or the E points
169-
if r2_min < 1*1
146+
if r2 < 1
170147
{
171-
return self.amplitude * r2_min
148+
return self.amplitude * r2
172149
}
173150

151+
let outer:IntV2 = (far.a - quadrant.a, far.b - quadrant.b)
152+
174153
// D points
175-
if (1.5 - nearpoint_disp.y) * (1.5 - nearpoint_disp.y) < r2_min
176-
{
177-
test(generating_point: (near.a, outer.b))
178-
}
179-
if (1.5 - nearpoint_disp.x) * (1.5 - nearpoint_disp.x) < r2_min
180-
{
181-
test(generating_point: (outer.a, near.b))
182-
}
154+
test(generating_point: (near.a, outer.b), dy: nearpoint_disp.y - 1.5)
155+
test(generating_point: (outer.a, near.b), dx: nearpoint_disp.x - 1.5)
183156

184157
// E points
185-
if (0.5 - nearpoint_disp.x) * (0.5 - nearpoint_disp.x) + (1.5 - nearpoint_disp.y) * (1.5 - nearpoint_disp.y) < r2_min
186-
{
187-
test(generating_point: (far.a, outer.b))
188-
}
189-
if (0.5 - nearpoint_disp.y) * (0.5 - nearpoint_disp.y) + (1.5 - nearpoint_disp.x) * (1.5 - nearpoint_disp.x) < r2_min
190-
{
191-
test(generating_point: (outer.a, far.b))
192-
}
158+
test(generating_point: (far.a, outer.b), dx: nearpoint_disp.x - 0.5, dy: nearpoint_disp.y - 1.5)
159+
test(generating_point: (outer.a, far.b), dx: nearpoint_disp.x - 1.5, dy: nearpoint_disp.y - 0.5)
193160

194-
return self.amplitude * r2_min
161+
return self.amplitude * r2
195162
}
196163

197164
public
@@ -323,20 +290,20 @@ struct CellNoise3D:Noise
323290
cell_distance2 = 0
324291
}
325292
else
326-
{ // move by 0.5 towards zero
327-
let dx:Double = Double(cell_offset.a) + (cell_offset.a > 0 ? -0.5 : 0.5) + nearpoint_disp.x
293+
{ // move by 0.5 towards zero
294+
let dx:Double = nearpoint_disp.x + Double(cell_offset.a) + (cell_offset.a > 0 ? -0.5 : 0.5)
328295
cell_distance2 = dx*dx
329296
}
330297

331298
if cell_offset.b != 0
332-
{ // move by 0.5 towards zero
333-
let dy:Double = Double(cell_offset.b) + (cell_offset.b > 0 ? -0.5 : 0.5) + nearpoint_disp.y
299+
{ // move by 0.5 towards zero
300+
let dy:Double = nearpoint_disp.y + Double(cell_offset.b) + (cell_offset.b > 0 ? -0.5 : 0.5)
334301
cell_distance2 += dy*dy
335302
}
336303

337304
if cell_offset.c != 0
338-
{ // move by 0.5 towards zero
339-
let dz:Double = Double(cell_offset.c) + (cell_offset.c > 0 ? -0.5 : 0.5) + nearpoint_disp.z
305+
{ // move by 0.5 towards zero
306+
let dz:Double = nearpoint_disp.z + Double(cell_offset.c) + (cell_offset.c > 0 ? -0.5 : 0.5)
340307
cell_distance2 += dz*dz
341308
}
342309

0 commit comments

Comments
 (0)