noise_functions/base/
value.rs

1use crate::{
2    base::impl_noise,
3    math::{floor, lerp},
4};
5
6#[cfg(feature = "nightly-simd")]
7use core::simd::{f32x2, f32x4};
8
9/// 2/3/4 dimensional Value noise.
10#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
11pub struct Value;
12
13impl_noise!(234 Value);
14
15impl Value {
16    #[inline]
17    fn gen2(self, [x, y]: [f32; 2], seed: i32) -> f32 {
18        // implementation from FastNoiseLite
19        use crate::from_fast_noise_lite::{floor_to_int, interp_hermite, value2, PRIME_X, PRIME_Y};
20
21        let mut x0 = floor_to_int(x);
22        let mut y0 = floor_to_int(y);
23
24        let xs = interp_hermite(x - x0 as f32);
25        let ys = interp_hermite(y - y0 as f32);
26
27        x0 = x0.wrapping_mul(PRIME_X);
28        y0 = y0.wrapping_mul(PRIME_Y);
29
30        let x1 = x0.wrapping_add(PRIME_X);
31        let y1 = y0.wrapping_add(PRIME_Y);
32
33        let xf0 = lerp(value2(seed, x0, y0), value2(seed, x1, y0), xs);
34        let xf1 = lerp(value2(seed, x0, y1), value2(seed, x1, y1), xs);
35
36        lerp(xf0, xf1, ys)
37    }
38
39    #[inline]
40    fn gen3(self, [x, y, z]: [f32; 3], seed: i32) -> f32 {
41        // implementation from FastNoiseLite
42        use crate::from_fast_noise_lite::{floor_to_int, interp_hermite, value3, PRIME_X, PRIME_Y, PRIME_Z};
43
44        let mut x0 = floor_to_int(x);
45        let mut y0 = floor_to_int(y);
46        let mut z0 = floor_to_int(z);
47
48        let xs = interp_hermite(x - x0 as f32);
49        let ys = interp_hermite(y - y0 as f32);
50        let zs = interp_hermite(z - z0 as f32);
51
52        x0 = x0.wrapping_mul(PRIME_X);
53        y0 = y0.wrapping_mul(PRIME_Y);
54        z0 = z0.wrapping_mul(PRIME_Z);
55
56        let x1 = x0.wrapping_add(PRIME_X);
57        let y1 = y0.wrapping_add(PRIME_Y);
58        let z1 = z0.wrapping_add(PRIME_Z);
59
60        let xf00 = lerp(value3(seed, x0, y0, z0), value3(seed, x1, y0, z0), xs);
61        let xf10 = lerp(value3(seed, x0, y1, z0), value3(seed, x1, y1, z0), xs);
62        let xf01 = lerp(value3(seed, x0, y0, z1), value3(seed, x1, y0, z1), xs);
63        let xf11 = lerp(value3(seed, x0, y1, z1), value3(seed, x1, y1, z1), xs);
64
65        let yf0 = lerp(xf00, xf10, ys);
66        let yf1 = lerp(xf01, xf11, ys);
67
68        lerp(yf0, yf1, zs)
69    }
70
71    #[inline]
72    fn gen4(self, [x, y, z, w]: [f32; 4], seed: i32) -> f32 {
73        // implementation from FastNoise2
74        use crate::from_fast_noise_2::{interp_hermite, primes, value_coord4};
75
76        let xs = floor(x);
77        let ys = floor(y);
78        let zs = floor(z);
79        let ws = floor(w);
80
81        let x0 = (xs as i32).wrapping_mul(primes::X);
82        let y0 = (ys as i32).wrapping_mul(primes::Y);
83        let z0 = (zs as i32).wrapping_mul(primes::Z);
84        let w0 = (ws as i32).wrapping_mul(primes::W);
85
86        let x1 = x0.wrapping_add(primes::X);
87        let y1 = y0.wrapping_add(primes::Y);
88        let z1 = z0.wrapping_add(primes::Z);
89        let w1 = w0.wrapping_add(primes::W);
90
91        let xs = interp_hermite(x - xs);
92        let ys = interp_hermite(y - ys);
93        let zs = interp_hermite(z - zs);
94        let ws = interp_hermite(w - ws);
95
96        lerp(
97            lerp(
98                lerp(
99                    lerp(value_coord4(seed, x0, y0, z0, w0), value_coord4(seed, x1, y0, z0, w0), xs),
100                    lerp(value_coord4(seed, x0, y1, z0, w0), value_coord4(seed, x1, y1, z0, w0), xs),
101                    ys,
102                ),
103                lerp(
104                    lerp(value_coord4(seed, x0, y0, z1, w0), value_coord4(seed, x1, y0, z1, w0), xs),
105                    lerp(value_coord4(seed, x0, y1, z1, w0), value_coord4(seed, x1, y1, z1, w0), xs),
106                    ys,
107                ),
108                zs,
109            ),
110            lerp(
111                lerp(
112                    lerp(value_coord4(seed, x0, y0, z0, w1), value_coord4(seed, x1, y0, z0, w1), xs),
113                    lerp(value_coord4(seed, x0, y1, z0, w1), value_coord4(seed, x1, y1, z0, w1), xs),
114                    ys,
115                ),
116                lerp(
117                    lerp(value_coord4(seed, x0, y0, z1, w1), value_coord4(seed, x1, y0, z1, w1), xs),
118                    lerp(value_coord4(seed, x0, y1, z1, w1), value_coord4(seed, x1, y1, z1, w1), xs),
119                    ys,
120                ),
121                zs,
122            ),
123            ws,
124        )
125    }
126
127    #[inline]
128    #[cfg(feature = "nightly-simd")]
129    fn gen2a(self, point: f32x2, seed: i32) -> f32 {
130        // based on the implementation from FastNoiseLite
131        use crate::from_fast_noise_lite::{floor_to_int, interp_hermite, value2, PRIME_XY};
132
133        use core::simd::num::SimdInt;
134
135        let v0 = floor_to_int(point);
136        let s = interp_hermite(point - v0.cast::<f32>());
137        let v0 = v0 * PRIME_XY;
138        let v1 = v0 + PRIME_XY;
139        let xf0 = lerp(value2(seed, v0[0], v0[1]), value2(seed, v1[0], v0[1]), s[0]);
140        let xf1 = lerp(value2(seed, v0[0], v1[1]), value2(seed, v1[0], v1[1]), s[0]);
141        lerp(xf0, xf1, s[1])
142    }
143
144    #[inline]
145    #[cfg(feature = "nightly-simd")]
146    fn gen3a(self, point: f32x4, seed: i32) -> f32 {
147        // based on the implementation from FastNoiseLite
148        use core::simd::num::SimdInt;
149
150        use crate::from_fast_noise_lite::{floor_to_int, interp_hermite, value3, PRIME_XYZ};
151
152        let v0 = floor_to_int(point);
153        let s = interp_hermite(point - v0.cast());
154        let v0 = v0 * PRIME_XYZ;
155        let v1 = v0 + PRIME_XYZ;
156
157        let xf00 = lerp(value3(seed, v0[0], v0[1], v0[2]), value3(seed, v1[0], v0[1], v0[2]), s[0]);
158        let xf10 = lerp(value3(seed, v0[0], v1[1], v0[2]), value3(seed, v1[0], v1[1], v0[2]), s[0]);
159        let xf01 = lerp(value3(seed, v0[0], v0[1], v1[2]), value3(seed, v1[0], v0[1], v1[2]), s[0]);
160        let xf11 = lerp(value3(seed, v0[0], v1[1], v1[2]), value3(seed, v1[0], v1[1], v1[2]), s[0]);
161
162        let yf0 = lerp(xf00, xf10, s[1]);
163        let yf1 = lerp(xf01, xf11, s[1]);
164
165        lerp(yf0, yf1, s[2])
166    }
167
168    #[inline]
169    #[cfg(feature = "nightly-simd")]
170    fn gen4a(self, point: f32x4, seed: i32) -> f32 {
171        self.gen4(point.into(), seed)
172    }
173}