Skip to content

Commit 189fbbf

Browse files
committed
Permutation table struct
1 parent 94792c7 commit 189fbbf

File tree

7 files changed

+41
-56
lines changed

7 files changed

+41
-56
lines changed

simplex.png

210 Bytes
Loading

sources/noise/cell.swift

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
11
public
2-
struct Cell2D:HashedNoise
2+
struct Cell2D
33
{
4-
let perm1024:[Int],
5-
hashes:[Int]
6-
7-
static
8-
var n_hashes:Int = 1024
94

105
public
116
init(amplitude:Double, frequency:Double, seed:Int = 0)
127
{
13-
(self.perm1024, self.hashes) = SuperSimplex2D.table(seed: seed)
148
}
159

1610
public

sources/noise/noise.swift

Lines changed: 31 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -52,24 +52,17 @@ extension Noise
5252
}
5353
}
5454

55-
protocol HashedNoise:Noise
55+
struct PermutationTable
5656
{
57-
var perm1024:[Int] { get }
58-
var hashes:[Int] { get }
59-
60-
static
61-
var n_hashes:Int { get }
62-
}
57+
private
58+
let permut:[UInt8], // keep these small to minimize cache misses
59+
hashes:[UInt8]
6360

64-
extension HashedNoise
65-
{
66-
static
67-
func table(seed:Int) -> ([Int], [Int])
61+
init(range:Int, seed:Int)
6862
{
69-
let range:Int = Self.n_hashes
70-
var perm1024:[Int] = [Int](0 ..< 1024),
71-
state128:(UInt32, UInt32, UInt32, UInt32) = (1, 0, 0, UInt32(extendingOrTruncating: seed))
72-
for i in 0 ..< 1024 - 1
63+
var permutations:[UInt8] = [UInt8](0 ... 255),
64+
state128:(UInt32, UInt32, UInt32, UInt32) = (1, 0, UInt32(extendingOrTruncating: seed >> 32), UInt32(extendingOrTruncating: seed))
65+
for i in 0 ..< 255 - 1
7366
{
7467
var t:UInt32 = state128.3
7568
t ^= t &<< 11
@@ -80,34 +73,40 @@ extension HashedNoise
8073
t ^= state128.0
8174
t ^= state128.0 &>> 19
8275
state128.0 = t
83-
perm1024.swapAt(i, Int(t) & 1023)
76+
permutations.swapAt(i, Int(t) & 255)
8477
}
8578

86-
return (perm1024, perm1024.map{ $0 % range })
79+
self.permut = permutations
80+
self.hashes = permutations.map{ $0 % UInt8(range) }
81+
}
82+
83+
func hash(_ n1:Int, _ n2:Int) -> Int
84+
{
85+
return Int(self.hashes[Int(self.permut[n1 & 255]) ^ (n2 & 255)])
86+
}
87+
88+
func hash(_ n1:Int, _ n2:Int, _ n3:Int) -> Int
89+
{
90+
return Int(self.hashes[Int(self.permut[Int(self.permut[n1 & 255]) ^ (n2 & 255)]) ^ (n3 & 255)])
8791
}
8892
}
8993

90-
protocol Hashed2DGradientNoise:HashedNoise
94+
protocol GradientNoise2D:Noise
9195
{
96+
var permutation_table:PermutationTable { get }
97+
9298
static var gradient_table:[(Double, Double)] { get }
9399
static var radius:Double { get }
94100
}
95101

96-
extension Hashed2DGradientNoise
102+
extension GradientNoise2D
97103
{
98-
static
99-
var n_hashes:Int
100-
{
101-
return Self.gradient_table.count
102-
}
103-
104104
func gradient(u:Int, v:Int, dx:Double, dy:Double) -> Double
105105
{
106106
let dr:Double = Self.radius - dx*dx - dy*dy
107107
if dr > 0
108108
{
109-
let hash:Int = self.hashes[self.perm1024[u & 1023] ^ (v & 1023)],
110-
gradient:(Double, Double) = Self.gradient_table[hash],
109+
let gradient:(Double, Double) = Self.gradient_table[self.permutation_table.hash(u, v)],
111110
drdr:Double = dr * dr
112111
return drdr * drdr * (gradient.0 * dx + gradient.1 * dy)
113112
}
@@ -118,26 +117,21 @@ extension Hashed2DGradientNoise
118117
}
119118
}
120119

121-
protocol Hashed3DGradientNoise:HashedNoise
120+
protocol GradientNoise3D:Noise
122121
{
122+
var permutation_table:PermutationTable { get }
123+
123124
static var gradient_table:[(Double, Double, Double)] { get }
124125
}
125126

126-
extension Hashed3DGradientNoise
127+
extension GradientNoise3D
127128
{
128-
static
129-
var n_hashes:Int
130-
{
131-
return Self.gradient_table.count
132-
}
133-
134129
func gradient(u:Int, v:Int, w:Int, dx:Double, dy:Double, dz:Double) -> Double
135130
{
136131
let dr:Double = 0.75 - dx*dx - dy*dy - dz*dz
137132
if dr > 0
138133
{
139-
let hash:Int = self.hashes[self.perm1024[self.perm1024[u & 1023] ^ (v & 1023)] ^ (w & 1023)],
140-
gradient:(Double, Double, Double) = Self.gradient_table[hash],
134+
let gradient:(Double, Double, Double) = Self.gradient_table[self.permutation_table.hash(u, v, w)],
141135
drdr:Double = dr * dr
142136
return drdr * drdr * (gradient.0 * dx + gradient.1 * dy + gradient.2 * dz)
143137
}

sources/noise/opensimplex.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
public
2-
struct Simplex2D:Hashed2DGradientNoise
2+
struct Simplex2D:GradientNoise2D
33
{
44
static
55
let gradient_table:[(Double, Double)] =
@@ -11,8 +11,7 @@ struct Simplex2D:Hashed2DGradientNoise
1111
static
1212
let radius:Double = 2
1313

14-
let perm1024:[Int],
15-
hashes:[Int]
14+
let permutation_table:PermutationTable
1615

1716
private
1817
let amplitude:Double, // this is not necissaryly the same amplitude passed into the initializer
@@ -23,7 +22,7 @@ struct Simplex2D:Hashed2DGradientNoise
2322
{
2423
self.amplitude = 0.096 * amplitude
2524
self.frequency = frequency
26-
(self.perm1024, self.hashes) = Simplex2D.table(seed: seed)
25+
self.permutation_table = PermutationTable(range: Simplex2D.gradient_table.count, seed: seed)
2726
}
2827

2928
public

sources/noise/supersimplex.swift

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import func Glibc.sin
22
import func Glibc.cos
33

44
public
5-
struct SuperSimplex2D:Hashed2DGradientNoise
5+
struct SuperSimplex2D:GradientNoise2D
66
{
77
private
88
struct LatticePoint
@@ -102,8 +102,7 @@ struct SuperSimplex2D:Hashed2DGradientNoise
102102
static
103103
let radius:Double = 2/3
104104

105-
let perm1024:[Int],
106-
hashes:[Int]
105+
let permutation_table:PermutationTable
107106

108107
private
109108
let amplitude:Double,
@@ -114,7 +113,7 @@ struct SuperSimplex2D:Hashed2DGradientNoise
114113
{
115114
self.amplitude = 18 * amplitude
116115
self.frequency = frequency
117-
(self.perm1024, self.hashes) = SuperSimplex2D.table(seed: seed)
116+
self.permutation_table = PermutationTable(range: SuperSimplex2D.gradient_table.count, seed: seed)
118117
}
119118

120119
public
@@ -266,7 +265,7 @@ struct SuperSimplex2D:Hashed2DGradientNoise
266265
}
267266

268267
public
269-
struct SuperSimplex3D:Hashed3DGradientNoise
268+
struct SuperSimplex3D:GradientNoise3D
270269
{
271270
private
272271
struct LatticePoint
@@ -356,8 +355,7 @@ struct SuperSimplex3D:Hashed3DGradientNoise
356355
(1, 1, 0), (-1, 1, 0), (0, -1, 1), (0, -1, -1)
357356
]
358357

359-
let perm1024:[Int],
360-
hashes:[Int]
358+
let permutation_table:PermutationTable
361359

362360
private
363361
let amplitude:Double,
@@ -368,7 +366,7 @@ struct SuperSimplex3D:Hashed3DGradientNoise
368366
{
369367
self.amplitude = 9 * amplitude
370368
self.frequency = frequency
371-
(self.perm1024, self.hashes) = SuperSimplex3D.table(seed: seed)
369+
self.permutation_table = PermutationTable(range: SuperSimplex3D.gradient_table.count, seed: seed)
372370
}
373371

374372
public

super_simplex.png

8.46 KB
Loading

super_simplex3D.png

34.6 KB
Loading

0 commit comments

Comments
 (0)