noise_functions/base/
simplex.rs

1use crate::{
2    base::impl_noise,
3    from_fast_noise_2::{masked_add, nmasked_add},
4    math::floor,
5};
6
7#[cfg(feature = "nightly-simd")]
8use core::simd::{f32x2, f32x4};
9
10/// 2/3/4 dimensional Simplex noise.
11#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
12pub struct Simplex;
13
14impl_noise!(234 Simplex);
15
16impl Simplex {
17    #[inline]
18    fn gen2(self, [x, y]: [f32; 2], seed: i32) -> f32 {
19        // implementation from FastNoise2
20        use crate::from_fast_noise_2::{gradient_dot2, hash_primes2, max, mul_add, primes};
21
22        const SQRT3: f32 = 1.7320508075688772935274463415059;
23        const F2: f32 = 0.5 * (SQRT3 - 1.0);
24        const G2: f32 = (3.0 - SQRT3) / 6.0;
25
26        let f = F2 * (x + y);
27        let mut x0 = floor(x + f);
28        let mut y0 = floor(y + f);
29
30        let i = (x0 as i32).wrapping_mul(primes::X);
31        let j = (y0 as i32).wrapping_mul(primes::Y);
32
33        let g = G2 * (x0 + y0);
34        x0 = x - (x0 - g);
35        y0 = y - (y0 - g);
36
37        let i1 = x0 > y0;
38
39        let x1 = if i1 { x0 - 1.0 } else { x0 } + G2;
40        let y1 = if i1 { y0 } else { y0 - 1.0 } + G2;
41
42        let x2 = x0 + (G2 * 2.0 - 1.0);
43        let y2 = y0 + (G2 * 2.0 - 1.0);
44
45        let mut t0 = 0.5 - (x0 * x0) - (y0 * y0);
46        let mut t1 = 0.5 - (x1 * x1) - (y1 * y1);
47        let mut t2 = 0.5 - (x2 * x2) - (y2 * y2);
48
49        t0 = max(t0, 0.0);
50        t1 = max(t1, 0.0);
51        t2 = max(t2, 0.0);
52
53        t0 *= t0;
54        t0 *= t0;
55
56        t1 *= t1;
57        t1 *= t1;
58
59        t2 *= t2;
60        t2 *= t2;
61
62        let n0 = gradient_dot2(hash_primes2(seed, i, j), x0, y0);
63        let n1 = gradient_dot2(hash_primes2(seed, masked_add(i, primes::X, i1), nmasked_add(j, primes::Y, i1)), x1, y1);
64        let n2 = gradient_dot2(hash_primes2(seed, i.wrapping_add(primes::X), j.wrapping_add(primes::Y)), x2, y2);
65
66        38.283687591552734375 * mul_add(n0, t0, mul_add(n1, t1, n2 * t2))
67    }
68
69    #[inline]
70    fn gen3(self, [mut x, mut y, mut z]: [f32; 3], seed: i32) -> f32 {
71        // implementation from FastNoise2
72        use crate::from_fast_noise_2::{gradient_dot3, hash_primes3, masked_add, masked_sub, max, mul_add, nmasked_add, nmasked_sub, nmul_add, primes};
73
74        const F3: f32 = 1.0 / 3.0;
75        const G3: f32 = 1.0 / 2.0;
76
77        let s = F3 * (x + y + z);
78        x += s;
79        y += s;
80        z += s;
81
82        let mut x0 = floor(x);
83        let mut y0 = floor(y);
84        let mut z0 = floor(z);
85        let xi = x - x0;
86        let yi = y - y0;
87        let zi = z - z0;
88
89        let i = (x0 as i32).wrapping_mul(primes::X);
90        let j = (y0 as i32).wrapping_mul(primes::Y);
91        let k = (z0 as i32).wrapping_mul(primes::Z);
92
93        let x_ge_y = xi >= yi;
94        let y_ge_z = yi >= zi;
95        let x_ge_z = xi >= zi;
96
97        let g = G3 * (xi + yi + zi);
98        x0 = xi - g;
99        y0 = yi - g;
100        z0 = zi - g;
101
102        let i1 = x_ge_y & x_ge_z;
103        let j1 = y_ge_z & !x_ge_y;
104        let k1 = !x_ge_z & !y_ge_z;
105
106        let i2 = x_ge_y | x_ge_z;
107        let j2 = !x_ge_y | y_ge_z;
108        let k2 = x_ge_z & y_ge_z; //NMasked
109
110        let x1 = masked_sub(x0, 1.0, i1) + G3;
111        let y1 = masked_sub(y0, 1.0, j1) + G3;
112        let z1 = masked_sub(z0, 1.0, k1) + G3;
113        let x2 = masked_sub(x0, 1.0, i2) + G3 * 2.0;
114        let y2 = masked_sub(y0, 1.0, j2) + G3 * 2.0;
115        let z2 = nmasked_sub(z0, 1.0, k2) + G3 * 2.0;
116        let x3 = x0 + (G3 * 3.0 - 1.0);
117        let y3 = y0 + (G3 * 3.0 - 1.0);
118        let z3 = z0 + (G3 * 3.0 - 1.0);
119
120        let mut t0 = nmul_add(x0, x0, nmul_add(y0, y0, nmul_add(z0, z0, 0.6)));
121        let mut t1 = nmul_add(x1, x1, nmul_add(y1, y1, nmul_add(z1, z1, 0.6)));
122        let mut t2 = nmul_add(x2, x2, nmul_add(y2, y2, nmul_add(z2, z2, 0.6)));
123        let mut t3 = nmul_add(x3, x3, nmul_add(y3, y3, nmul_add(z3, z3, 0.6)));
124
125        t0 = max(t0, 0.0);
126        t1 = max(t1, 0.0);
127        t2 = max(t2, 0.0);
128        t3 = max(t3, 0.0);
129
130        t0 *= t0;
131        t0 *= t0;
132        t1 *= t1;
133        t1 *= t1;
134        t2 *= t2;
135        t2 *= t2;
136        t3 *= t3;
137        t3 *= t3;
138
139        let n0 = gradient_dot3(hash_primes3(seed, i, j, k), x0, y0, z0);
140        let n1 = gradient_dot3(hash_primes3(seed, masked_add(i, primes::X, i1), masked_add(j, primes::Y, j1), masked_add(k, primes::Z, k1)), x1, y1, z1);
141        let n2 = gradient_dot3(
142            hash_primes3(seed, masked_add(i, primes::X, i2), masked_add(j, primes::Y, j2), nmasked_add(k, primes::Z, k2)),
143            x2,
144            y2,
145            z2,
146        );
147        let n3 = gradient_dot3(hash_primes3(seed, i.wrapping_add(primes::X), j.wrapping_add(primes::Y), k.wrapping_add(primes::Z)), x3, y3, z3);
148
149        32.69428253173828125 * mul_add(n0, t0, mul_add(n1, t1, mul_add(n2, t2, n3 * t3)))
150    }
151
152    #[inline]
153    fn gen4(self, [mut x, mut y, mut z, mut w]: [f32; 4], seed: i32) -> f32 {
154        // implementation from FastNoise2
155        use crate::from_fast_noise_2::{gradient_dot4, hash_primes4, masked_add, masked_inc, masked_sub, max, mul_add, nmul_add, primes};
156
157        const SQRT5: f32 = 2.236067977499;
158        const F4: f32 = (SQRT5 - 1.0) / 4.0;
159        const G4: f32 = (5.0 - SQRT5) / 20.0;
160
161        let s = F4 * (x + y + z + w);
162        x += s;
163        y += s;
164        z += s;
165        w += s;
166
167        let mut x0 = floor(x);
168        let mut y0 = floor(y);
169        let mut z0 = floor(z);
170        let mut w0 = floor(w);
171        let xi = x - x0;
172        let yi = y - y0;
173        let zi = z - z0;
174        let wi = w - w0;
175
176        let i = (x0 as i32).wrapping_mul(primes::X);
177        let j = (y0 as i32).wrapping_mul(primes::Y);
178        let k = (z0 as i32).wrapping_mul(primes::Z);
179        let l = (w0 as i32).wrapping_mul(primes::W);
180
181        let g = G4 * (xi + yi + zi + wi);
182        x0 = xi - g;
183        y0 = yi - g;
184        z0 = zi - g;
185        w0 = wi - g;
186
187        let mut rankx = 0;
188        let mut ranky = 0;
189        let mut rankz = 0;
190        let mut rankw = 0;
191
192        let x_ge_y = x0 >= y0;
193        rankx = masked_inc(rankx, x_ge_y);
194        ranky = masked_inc(ranky, !x_ge_y);
195
196        let x_ge_z = x0 >= z0;
197        rankx = masked_inc(rankx, x_ge_z);
198        rankz = masked_inc(rankz, !x_ge_z);
199
200        let x_ge_w = x0 >= w0;
201        rankx = masked_inc(rankx, x_ge_w);
202        rankw = masked_inc(rankw, !x_ge_w);
203
204        let y_ge_z = y0 >= z0;
205        ranky = masked_inc(ranky, y_ge_z);
206        rankz = masked_inc(rankz, !y_ge_z);
207
208        let y_ge_w = y0 >= w0;
209        ranky = masked_inc(ranky, y_ge_w);
210        rankw = masked_inc(rankw, !y_ge_w);
211
212        let z_ge_w = z0 >= w0;
213        rankz = masked_inc(rankz, z_ge_w);
214        rankw = masked_inc(rankw, !z_ge_w);
215
216        let i1 = rankx > 2;
217        let j1 = ranky > 2;
218        let k1 = rankz > 2;
219        let l1 = rankw > 2;
220
221        let i2 = rankx > 1;
222        let j2 = ranky > 1;
223        let k2 = rankz > 1;
224        let l2 = rankw > 1;
225
226        let i3 = rankx > 0;
227        let j3 = ranky > 0;
228        let k3 = rankz > 0;
229        let l3 = rankw > 0;
230
231        let x1 = masked_sub(x0, 1.0, i1) + G4;
232        let y1 = masked_sub(y0, 1.0, j1) + G4;
233        let z1 = masked_sub(z0, 1.0, k1) + G4;
234        let w1 = masked_sub(w0, 1.0, l1) + G4;
235        let x2 = masked_sub(x0, 1.0, i2) + G4 * 2.0;
236        let y2 = masked_sub(y0, 1.0, j2) + G4 * 2.0;
237        let z2 = masked_sub(z0, 1.0, k2) + G4 * 2.0;
238        let w2 = masked_sub(w0, 1.0, l2) + G4 * 2.0;
239        let x3 = masked_sub(x0, 1.0, i3) + G4 * 3.0;
240        let y3 = masked_sub(y0, 1.0, j3) + G4 * 3.0;
241        let z3 = masked_sub(z0, 1.0, k3) + G4 * 3.0;
242        let w3 = masked_sub(w0, 1.0, l3) + G4 * 3.0;
243        let x4 = x0 + (G4 * 4.0 - 1.0);
244        let y4 = y0 + (G4 * 4.0 - 1.0);
245        let z4 = z0 + (G4 * 4.0 - 1.0);
246        let w4 = w0 + (G4 * 4.0 - 1.0);
247
248        let mut t0 = nmul_add(x0, x0, nmul_add(y0, y0, nmul_add(z0, z0, nmul_add(w0, w0, 0.6))));
249        let mut t1 = nmul_add(x1, x1, nmul_add(y1, y1, nmul_add(z1, z1, nmul_add(w1, w1, 0.6))));
250        let mut t2 = nmul_add(x2, x2, nmul_add(y2, y2, nmul_add(z2, z2, nmul_add(w2, w2, 0.6))));
251        let mut t3 = nmul_add(x3, x3, nmul_add(y3, y3, nmul_add(z3, z3, nmul_add(w3, w3, 0.6))));
252        let mut t4 = nmul_add(x4, x4, nmul_add(y4, y4, nmul_add(z4, z4, nmul_add(w4, w4, 0.6))));
253
254        t0 = max(t0, 0.0);
255        t1 = max(t1, 0.0);
256        t2 = max(t2, 0.0);
257        t3 = max(t3, 0.0);
258        t4 = max(t4, 0.0);
259
260        t0 *= t0;
261        t0 *= t0;
262        t1 *= t1;
263        t1 *= t1;
264        t2 *= t2;
265        t2 *= t2;
266        t3 *= t3;
267        t3 *= t3;
268        t4 *= t4;
269        t4 *= t4;
270
271        let n0 = gradient_dot4(hash_primes4(seed, i, j, k, l), x0, y0, z0, w0);
272        let n1 = gradient_dot4(
273            hash_primes4(
274                seed,
275                masked_add(i, primes::X, i1),
276                masked_add(j, primes::Y, j1),
277                masked_add(k, primes::Z, k1),
278                masked_add(l, primes::W, l1),
279            ),
280            x1,
281            y1,
282            z1,
283            w1,
284        );
285        let n2 = gradient_dot4(
286            hash_primes4(
287                seed,
288                masked_add(i, primes::X, i2),
289                masked_add(j, primes::Y, j2),
290                masked_add(k, primes::Z, k2),
291                masked_add(l, primes::W, l2),
292            ),
293            x2,
294            y2,
295            z2,
296            w2,
297        );
298        let n3 = gradient_dot4(
299            hash_primes4(
300                seed,
301                masked_add(i, primes::X, i3),
302                masked_add(j, primes::Y, j3),
303                masked_add(k, primes::Z, k3),
304                masked_add(l, primes::W, l3),
305            ),
306            x3,
307            y3,
308            z3,
309            w3,
310        );
311        let n4 = gradient_dot4(
312            hash_primes4(seed, i.wrapping_add(primes::X), j.wrapping_add(primes::Y), k.wrapping_add(primes::Z), l.wrapping_add(primes::W)),
313            x4,
314            y4,
315            z4,
316            w4,
317        );
318
319        27.0 * mul_add(n0, t0, mul_add(n1, t1, mul_add(n2, t2, mul_add(n3, t3, n4 * t4))))
320    }
321
322    #[inline]
323    #[cfg(feature = "nightly-simd")]
324    fn gen2a(self, point: f32x2, seed: i32) -> f32 {
325        self.gen2(point.into(), seed)
326    }
327
328    #[inline]
329    #[cfg(feature = "nightly-simd")]
330    fn gen3a(self, point: f32x4, seed: i32) -> f32 {
331        self.gen3(*crate::array_4_take_3(point.as_array()), seed)
332    }
333
334    #[inline]
335    #[cfg(feature = "nightly-simd")]
336    fn gen4a(self, point: f32x4, seed: i32) -> f32 {
337        self.gen4(point.into(), seed)
338    }
339}