simplex_23d/lib.rs
1#[cfg(test)]
2mod tests;
3
4// Rust implementation of:
5//
6// Simplex noise demystified
7// Stefan Gustavson, Linköping University, Sweden (stegu@itn.liu.se), 2005-03-22
8//
9// https://github.com/stegu/perlin-noise/blob/master/simplexnoise.pdf
10//
11// https://web.archive.org/web/20210506195658/http://weber.itn.liu.se/~stegu/simplexnoise/SimplexNoise.java
12//
13
14const SQRT3: f32 = 1.732_050_8; // f32::sqrt(3.0);
15const F2: f32 = 0.5 * (SQRT3 - 1.0);
16const G2: f32 = (3.0 - SQRT3) / 6.0;
17const F3: f32 = 1.0 / 3.0;
18const G3: f32 = 1.0 / 6.0; // Very nice and simple unskew factor, too
19
20const GRAD3: [[f32; 3]; 12] = [
21 [1.0, 1.0, 0.0],
22 [-1.0, 1.0, 0.0],
23 [1.0, -1.0, 0.0],
24 [-1.0, -1.0, 0.0],
25 [1.0, 0.0, 1.0],
26 [-1.0, 0.0, 1.0],
27 [1.0, 0.0, -1.0],
28 [-1.0, 0.0, -1.0],
29 [0.0, 1.0, 1.0],
30 [0.0, -1.0, 1.0],
31 [0.0, 1.0, -1.0],
32 [0.0, -1.0, -1.0],
33];
34
35// uses a seed value to generate a permutation table and the same table with values mod 12
36fn generate_perm_mod12(seed: u64) -> ([usize; 512], [usize; 512]) {
37 use rand::{seq::SliceRandom, SeedableRng};
38 // random number generator with seed:
39 let mut rng: rand::rngs::StdRng = SeedableRng::seed_from_u64(seed);
40 let mut seq: Vec<_> = (0usize..256).collect();
41 seq.shuffle(&mut rng);
42 let mut perm = [0; 512];
43 let mut perm_mod12 = [0; 512];
44 // To remove the need for index wrapping, double the permutation table length
45 // mod 12 to lookup the gradients of the simplex corners
46 for i in 0..512 {
47 let value = seq[i & 255];
48 perm[i] = value;
49 perm_mod12[i] = value % 12;
50 }
51 (perm, perm_mod12)
52}
53
54#[inline(always)]
55fn fastfloor(x: f32) -> i32 {
56 if x > 0.0 {
57 x as i32
58 } else {
59 (x as i32) - 1
60 }
61}
62
63#[inline(always)]
64fn dot2(x0: f32, y0: f32, x1: f32, y1: f32) -> f32 {
65 x0 * x1 + y0 * y1
66}
67
68#[inline(always)]
69fn dot3(x0: f32, y0: f32, z0: f32, x1: f32, y1: f32, z1: f32) -> f32 {
70 x0 * x1 + y0 * y1 + z0 * z1
71}
72
73/// Simplex noise generator instance that keeps a permutation table internally.
74pub struct Simplex {
75 seed: u64,
76 perm: [usize; 512],
77 perm_mod12: [usize; 512],
78}
79
80impl Simplex {
81 /// Create a new simplex noise generator for the given seed value.
82 ///
83 /// Creates a pre-computed permutation table using the seed value.
84 pub fn new(seed: u64) -> Self {
85 let (perm, perm_mod12) = generate_perm_mod12(seed);
86 Self {
87 seed,
88 perm,
89 perm_mod12
90 }
91 }
92
93 /// Sample the noise function in 2D at the given coordinates.
94 ///
95 /// For frequency, multiply the coordinates by the desired frequency.
96 pub fn sample2d(&self, x: f32, y: f32) -> f32 {
97 // Skew the input space to determine which simplex cell we're in
98
99 let s = (x + y) * F2; // Hairy factor for 2D
100 let i = fastfloor(x + s);
101 let j = fastfloor(y + s);
102 let t = ((i + j) as f32) * G2;
103 let x0 = (i as f32) - t; // Unskew the cell origin back to (x,y) space
104 let y0 = (j as f32) - t;
105 let x0 = x - x0; // The x,y distances from the cell origin
106 let y0 = y - y0;
107
108 // For the 2D case, the simplex shape is an equilateral triangle.
109 // Determine which simplex we are in.
110 // Offsets for second (middle) corner of simplex in (i,j) coords
111 let (i1, j1) = if x0 > y0 {
112 (1, 0) // lower triangle, XY order: (0,0)->(1,0)->(1,1)
113 } else {
114 (0, 1) // upper triangle, YX order: (0,0)->(0,1)->(1,1)
115 };
116
117 // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
118 // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
119 // c = (3-sqrt(3))/6
120 let x1 = x0 - (i1 as f32) + G2; // Offsets for middle corner in (x,y) unskewed coords
121 let y1 = y0 - (j1 as f32) + G2;
122 let x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords
123 let y2 = y0 - 1.0 + 2.0 * G2;
124
125 // Work out the hashed gradient indices of the three simplex corners
126 let ii: usize = (i & 255) as usize;
127 let jj: usize = (j & 255) as usize;
128 let gi0 = self.perm_mod12[ii + self.perm[jj]];
129 let gi1 = self.perm_mod12[ii + i1 + self.perm[jj + j1]];
130 let gi2 = self.perm_mod12[ii + 1 + self.perm[jj + 1]];
131
132 // Calculate the contribution from the three corners
133 // double n0, n1, n2; // Noise contributions from the three corners
134 let mut t0 = 0.5 - x0 * x0 - y0 * y0;
135 let n0 = if t0 < 0.0 {
136 0.0
137 } else {
138 t0 *= t0;
139 t0 * t0 * dot2(GRAD3[gi0][0], GRAD3[gi0][1], x0, y0) // (x,y) of grad3 used for 2D gradient
140 };
141
142 let mut t1 = 0.5 - x1 * x1 - y1 * y1;
143 let n1 = if t1 < 0.0 {
144 0.0
145 } else {
146 t1 *= t1;
147 t1 * t1 * dot2(GRAD3[gi1][0], GRAD3[gi1][1], x1, y1)
148 };
149
150 let mut t2 = 0.5 - x2 * x2 - y2 * y2;
151 let n2 = if t2 < 0.0 {
152 0.0
153 } else {
154 t2 *= t2;
155 t2 * t2 * dot2(GRAD3[gi2][0], GRAD3[gi2][1], x2, y2)
156 };
157
158 // Add contributions from each corner to get the final noise value.
159 // The result is scaled to return values in the interval [-1,1].
160 n0 + n1 + n2
161 }
162
163 /// Sample the noise function in 3D at the given coordinates.
164 ///
165 /// For frequency, multiply the coordinates by the desired frequency.
166 pub fn sample3d(&self, x: f32, y: f32, z: f32) -> f32 {
167 // Skew the input space to determine which simplex cell we're in
168 let s = (x + y + z) * F3; // Very nice and simple skew factor for 3D
169 let i = fastfloor(x + s);
170 let j = fastfloor(y + s);
171 let k = fastfloor(z + s);
172 let t = (i + j + k) as f32 * G3;
173 let x0 = i as f32 - t; // Unskew the cell origin back to (x,y,z) space
174 let y0 = j as f32 - t;
175 let z0 = k as f32 - t;
176 let x0 = x - x0; // The x,y,z distances from the cell origin
177 let y0 = y - y0;
178 let z0 = z - z0;
179 // For the 3D case, the simplex shape is a slightly irregular tetrahedron.
180 // Determine which simplex we are in.
181
182 // Offsets for second corner of simplex in (i,j,k) coords
183 let i1;
184 let j1;
185 let k1;
186
187 // Offsets for third corner of simplex in (i,j,k) coords
188 let i2;
189 let j2;
190 let k2;
191
192 if x0 >= y0 {
193 if y0 >= z0 {
194 i1 = 1;
195 j1 = 0;
196 k1 = 0;
197 i2 = 1;
198 j2 = 1;
199 k2 = 0;
200 }
201 // X Y Z order
202 else if x0 >= z0 {
203 i1 = 1;
204 j1 = 0;
205 k1 = 0;
206 i2 = 1;
207 j2 = 0;
208 k2 = 1;
209 }
210 // X Z Y order
211 else {
212 i1 = 0;
213 j1 = 0;
214 k1 = 1;
215 i2 = 1;
216 j2 = 0;
217 k2 = 1;
218 } // Z X Y order
219 } else {
220 // x0<y0
221 if y0 < z0 {
222 i1 = 0;
223 j1 = 0;
224 k1 = 1;
225 i2 = 0;
226 j2 = 1;
227 k2 = 1;
228 }
229 // Z Y X order
230 else if x0 < z0 {
231 i1 = 0;
232 j1 = 1;
233 k1 = 0;
234 i2 = 0;
235 j2 = 1;
236 k2 = 1;
237 }
238 // Y Z X order
239 else {
240 i1 = 0;
241 j1 = 1;
242 k1 = 0;
243 i2 = 1;
244 j2 = 1;
245 k2 = 0;
246 } // Y X Z order
247 }
248 // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
249 // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
250 // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
251 // c = 1/6.
252 let x1 = x0 - i1 as f32 + G3; // Offsets for second corner in (x,y,z) coords
253 let y1 = y0 - j1 as f32 + G3;
254 let z1 = z0 - k1 as f32 + G3;
255 let x2 = x0 - i2 as f32 + 2.0 * G3; // Offsets for third corner in (x,y,z) coords
256 let y2 = y0 - j2 as f32 + 2.0 * G3;
257 let z2 = z0 - k2 as f32 + 2.0 * G3;
258 let x3 = x0 - 1.0 + 3.0 * G3; // Offsets for last corner in (x,y,z) coords
259 let y3 = y0 - 1.0 + 3.0 * G3;
260 let z3 = z0 - 1.0 + 3.0 * G3;
261 // Work out the hashed gradient indices of the four simplex corners
262 let ii = (i & 255) as usize;
263 let jj = (j & 255) as usize;
264 let kk = (k & 255) as usize;
265 let gi0 = self.perm_mod12[ii + self.perm[jj + self.perm[kk]]];
266 let gi1 = self.perm_mod12[ii + i1 + self.perm[jj + j1 + self.perm[kk + k1]]];
267 let gi2 = self.perm_mod12[ii + i2 + self.perm[jj + j2 + self.perm[kk + k2]]];
268 let gi3 = self.perm_mod12[ii + 1 + self.perm[jj + 1 + self.perm[kk + 1]]];
269 // Calculate the contribution from the four corners
270 // let n0, n1, n2, n3;
271 // Noise contributions from the four corners
272 let mut t0 = 0.5 - x0 * x0 - y0 * y0 - z0 * z0;
273 let n0 = if t0 < 0.0 {
274 0.0
275 } else {
276 t0 *= t0;
277 t0 * t0 * dot3(GRAD3[gi0][0], GRAD3[gi0][1], GRAD3[gi0][2], x0, y0, z0)
278 };
279
280 let mut t1 = 0.5 - x1 * x1 - y1 * y1 - z1 * z1;
281 let n1 = if t1 < 0.0 {
282 0.0
283 } else {
284 t1 *= t1;
285 t1 * t1 * dot3(GRAD3[gi1][0], GRAD3[gi1][1], GRAD3[gi1][2], x1, y1, z1)
286 };
287
288 let mut t2 = 0.5 - x2 * x2 - y2 * y2 - z2 * z2;
289 let n2 = if t2 < 0.0 {
290 0.0
291 } else {
292 t2 *= t2;
293 t2 * t2 * dot3(GRAD3[gi2][0], GRAD3[gi2][1], GRAD3[gi2][2], x2, y2, z2)
294 };
295
296 let mut t3 = 0.5 - x3 * x3 - y3 * y3 - z3 * z3;
297 let n3 = if t3 < 0.0 {
298 0.0
299 } else {
300 t3 *= t3;
301 t3 * t3 * dot3(GRAD3[gi3][0], GRAD3[gi3][1], GRAD3[gi3][2], x3, y3, z3)
302 };
303
304 // Add contributions from each corner to get the final noise value.
305 // The result is scaled to stay just inside [-1,1]
306 n0 + n1 + n2 + n3
307 }
308
309 /// Returns the seed value that was used to generate the permutation table.
310 pub fn seed(&self) -> u64 {
311 self.seed
312 }
313}