noise_functions/
open_simplex_2.rs

1#[cfg(feature = "nightly-simd")]
2use core::simd::{f32x2, f32x4};
3
4use crate::{Noise, Sample};
5
6pub(crate) trait Sealed {}
7
8macro_rules! r#if {
9    (if 2 == 2 { $($then:tt)* } else { $($else:tt)* }) => { $($then)* };
10    (if 2 == 3 { $($then:tt)* } else { $($else:tt)* }) => { $($else)* };
11    (if 2 == 4 { $($then:tt)* } else { $($else:tt)* }) => { $($else)* };
12    (if 3 == 2 { $($then:tt)* } else { $($else:tt)* }) => { $($else)* };
13    (if 3 == 3 { $($then:tt)* } else { $($else:tt)* }) => { $($then)* };
14    (if 3 == 4 { $($then:tt)* } else { $($else:tt)* }) => { $($else)* };
15    (if 4 == 2 { $($then:tt)* } else { $($else:tt)* }) => { $($else)* };
16    (if 4 == 3 { $($then:tt)* } else { $($else:tt)* }) => { $($else)* };
17    (if 4 == 4 { $($then:tt)* } else { $($else:tt)* }) => { $($then)* };
18}
19
20pub(crate) use r#if;
21
22macro_rules! impl_improves {
23    (
24        $(#[$trait_attrs:meta])*
25        trait $trait:ident {
26            $($trait_members:tt)*
27        }
28
29        $(
30            $(#[$improve_attrs:meta])*
31            $improve_struct:ident $improve_dim:tt $improve_fn:ident use $improve:ident $improve_a:ident;
32        )*
33    ) => {
34        $(#[$trait_attrs])*
35        #[expect(private_bounds)]
36        pub trait $trait: Sealed + Noise {
37            $(
38                $(#[$improve_attrs])*
39                fn $improve_fn(self) -> $improve_struct<Self>
40                where
41                    Self: Sized,
42                {
43                    $improve_struct(self)
44                }
45            )*
46
47            $($trait_members)*
48        }
49
50        $(
51            $(#[$improve_attrs])*
52            #[derive(Debug, Clone, Copy, PartialEq, Eq)]
53            pub struct $improve_struct<OpenSimplexNoise>(pub OpenSimplexNoise);
54
55            impl<N> Noise for $improve_struct<N> {}
56
57            impl<N: OpenSimplexNoise> Sealed for $improve_struct<N> {}
58
59            impl<N: OpenSimplexNoise> $trait for $improve_struct<N> {
60                #[inline(always)]
61                fn raw_sample2(&self, point: [f32; 2], seed: i32) -> f32 {
62                    self.0.raw_sample2(point, seed)
63                }
64
65                #[inline(always)]
66                #[cfg(feature = "nightly-simd")]
67                fn raw_sample2a(&self, point: f32x2, seed: i32) -> f32 {
68                    self.0.raw_sample2a(point, seed)
69                }
70
71                #[inline(always)]
72                fn raw_sample3(&self, point: [f32; 3], seed: i32) -> f32 {
73                    self.0.raw_sample3(point, seed)
74                }
75
76                #[inline(always)]
77                #[cfg(feature = "nightly-simd")]
78                fn raw_sample3a(&self, point: f32x4, seed: i32) -> f32 {
79                    self.0.raw_sample3a(point, seed)
80                }
81
82                #[inline(always)]
83                fn raw_sample4(&self, point: [f32; 4], seed: i32) -> f32 {
84                    self.0.raw_sample4(point, seed)
85                }
86
87                #[inline(always)]
88                #[cfg(feature = "nightly-simd")]
89                fn raw_sample4a(&self, point: f32x4, seed: i32) -> f32 {
90                    self.0.raw_sample4a(point, seed)
91                }
92
93                #[inline(always)]
94                fn raw_improve2_x(&self, point: [f32; 2]) -> [f32; 2] {
95                    self.0.raw_improve2_x(point)
96                }
97
98                #[inline(always)]
99                #[cfg(feature = "nightly-simd")]
100                fn raw_improve2a_x(&self, point: f32x2) -> f32x2 {
101                    self.0.raw_improve2a_x(point)
102                }
103
104                #[inline(always)]
105                fn raw_improve3_xy(&self, point: [f32; 3]) -> [f32; 3] {
106                    self.0.raw_improve3_xy(point)
107                }
108
109                #[inline(always)]
110                #[cfg(feature = "nightly-simd")]
111                fn raw_improve3a_xy(&self, point: f32x4) -> f32x4 {
112                    self.0.raw_improve3a_xy(point)
113                }
114
115                #[inline(always)]
116                fn raw_improve3_xz(&self, point: [f32; 3]) -> [f32; 3] {
117                    self.0.raw_improve3_xz(point)
118                }
119
120                #[inline(always)]
121                #[cfg(feature = "nightly-simd")]
122                fn raw_improve3a_xz(&self, point: f32x4) -> f32x4 {
123                    self.0.raw_improve3a_xz(point)
124                }
125
126                #[doc(hidden)]
127                fn raw_improve4_xyz_xy(&self, point: [f32; 4]) -> [f32; 4] {
128                    self.0.raw_improve4_xyz_xy(point)
129                }
130
131                #[doc(hidden)]
132                #[cfg(feature = "nightly-simd")]
133                fn raw_improve4a_xyz_xy(&self, point: f32x4) -> f32x4 {
134                    self.0.raw_improve4a_xyz_xy(point)
135                }
136
137                #[doc(hidden)]
138                fn raw_improve4_xyz_xz(&self, point: [f32; 4]) -> [f32; 4] {
139                    self.0.raw_improve4_xyz_xz(point)
140                }
141
142                #[doc(hidden)]
143                #[cfg(feature = "nightly-simd")]
144                fn raw_improve4a_xyz_xz(&self, point: f32x4) -> f32x4 {
145                    self.0.raw_improve4a_xyz_xz(point)
146                }
147
148                #[doc(hidden)]
149                fn raw_improve4_xyz(&self, point: [f32; 4]) -> [f32; 4] {
150                    self.0.raw_improve4_xyz(point)
151                }
152
153                #[doc(hidden)]
154                #[cfg(feature = "nightly-simd")]
155                fn raw_improve4a_xyz(&self, point: f32x4) -> f32x4 {
156                    self.0.raw_improve4a_xyz(point)
157                }
158
159                #[doc(hidden)]
160                fn raw_improve4_xy_zw(&self, point: [f32; 4]) -> [f32; 4] {
161                    self.0.raw_improve4_xy_zw(point)
162                }
163
164                #[doc(hidden)]
165                #[cfg(feature = "nightly-simd")]
166                fn raw_improve4a_xy_zw(&self, point: f32x4) -> f32x4 {
167                    self.0.raw_improve4a_xy_zw(point)
168                }
169            }
170
171            $crate::open_simplex_2::r#if! {
172                if $improve_dim == 2 {
173                    impl<N: OpenSimplexNoise> Sample<2> for $improve_struct<N> {
174                        #[inline(always)]
175                        fn sample_with_seed(&self, point: [f32; 2], seed: i32) -> f32 {
176                            self.0.raw_sample2(self.0.$improve(point), seed)
177                        }
178                    }
179
180                     #[cfg(feature = "nightly-simd")]
181                    impl<N: OpenSimplexNoise> Sample<2, core::simd::f32x2> for $improve_struct<N> {
182                        #[inline(always)]
183                        fn sample_with_seed(&self, point: f32x2, seed: i32) -> f32 {
184                            self.0.raw_sample2a(self.0.$improve_a(point), seed)
185                        }
186                    }
187                } else {
188                    impl<N: Sample<2>> Sample<2> for $improve_struct<N> {
189                        #[inline(always)]
190                        fn sample_with_seed(&self, point: [f32; 2], seed: i32) -> f32 {
191                            self.0.sample_with_seed(point, seed)
192                        }
193                    }
194
195                    #[cfg(feature = "nightly-simd")]
196                    impl<N: Sample<2, f32x2>> Sample<2, core::simd::f32x2> for $improve_struct<N> {
197                        #[inline(always)]
198                        fn sample_with_seed(&self, point: f32x2, seed: i32) -> f32 {
199                            self.0.sample_with_seed(point, seed)
200                        }
201                    }
202                }
203            }
204
205            $crate::open_simplex_2::r#if! {
206                if $improve_dim == 3 {
207                     impl<N: OpenSimplexNoise> Sample<3> for $improve_struct<N> {
208                        #[inline(always)]
209                        fn sample_with_seed(&self, point: [f32; 3], seed: i32) -> f32 {
210                            self.0.raw_sample3(self.0.$improve(point), seed)
211                        }
212                    }
213
214                    #[cfg(feature = "nightly-simd")]
215                    impl<N: OpenSimplexNoise> Sample<3, f32x4> for $improve_struct<N> {
216                        #[inline(always)]
217                        fn sample_with_seed(&self, point: f32x4, seed: i32) -> f32 {
218                            self.0.raw_sample3a(self.0.$improve_a(point), seed)
219                        }
220                    }
221                } else {
222                    impl<N: Sample<3>> Sample<3> for $improve_struct<N> {
223                        #[inline(always)]
224                        fn sample_with_seed(&self, point: [f32; 3], seed: i32) -> f32 {
225                            self.0.sample_with_seed(point, seed)
226                        }
227                    }
228
229                    #[cfg(feature = "nightly-simd")]
230                    impl<N: Sample<3, f32x4>> Sample<3, f32x4> for $improve_struct<N> {
231                        #[inline(always)]
232                        fn sample_with_seed(&self, point: f32x4, seed: i32) -> f32 {
233                            self.0.sample_with_seed(point, seed)
234                        }
235                    }
236                }
237            }
238
239            $crate::open_simplex_2::r#if! {
240                if $improve_dim == 4 {
241                    impl<N: OpenSimplexNoise> Sample<4> for $improve_struct<N> {
242                        #[inline(always)]
243                        fn sample_with_seed(&self, point: [f32; 4], seed: i32) -> f32 {
244                            self.0.raw_sample4(self.0.$improve(point), seed)
245                        }
246                    }
247
248                    #[cfg(feature = "nightly-simd")]
249                    impl<N: OpenSimplexNoise> Sample<4, f32x4> for $improve_struct<N> {
250                        #[inline(always)]
251                        fn sample_with_seed(&self, point: f32x4, seed: i32) -> f32 {
252                            self.0.raw_sample4a(self.0.$improve_a(point), seed)
253                        }
254                    }
255                } else {
256                    impl<N: Sample<4>> Sample<4> for $improve_struct<N> {
257                        #[inline(always)]
258                        fn sample_with_seed(&self, point: [f32; 4], seed: i32) -> f32 {
259                            self.0.sample_with_seed(point, seed)
260                        }
261                    }
262
263                    #[cfg(feature = "nightly-simd")]
264                    impl<N: Sample<4, f32x4>> Sample<4, f32x4> for $improve_struct<N> {
265                        #[inline(always)]
266                        fn sample_with_seed(&self, point: f32x4, seed: i32) -> f32 {
267                            self.0.sample_with_seed(point, seed)
268                        }
269                    }
270                }
271            }
272        )*
273    };
274}
275
276impl_improves! {
277    /// Provides utility methods for `OpenSimplex` noise types.
278    trait OpenSimplexNoise {
279        /// Sample this OpenSimplexNoise unskewed.
280        #[doc(hidden)]
281        fn raw_sample2(&self, point: [f32; 2], seed: i32) -> f32;
282
283        /// Sample this OpenSimplexNoise unskewed.
284        #[doc(hidden)]
285        #[cfg(feature = "nightly-simd")]
286        fn raw_sample2a(&self, point: f32x2, seed: i32) -> f32;
287
288        /// Sample this OpenSimplexNoise unrotated.
289        #[doc(hidden)]
290        fn raw_sample3(&self, point: [f32; 3], seed: i32) -> f32;
291
292        /// Sample this OpenSimplexNoise unrotated.
293        #[doc(hidden)]
294        #[cfg(feature = "nightly-simd")]
295        fn raw_sample3a(&self, point: f32x4, seed: i32) -> f32;
296
297        /// Sample this OpenSimplexNoise unskewed.
298        #[doc(hidden)]
299        fn raw_sample4(&self, point: [f32; 4], seed: i32) -> f32;
300
301        /// Sample this OpenSimplexNoise unskewed.
302        #[doc(hidden)]
303        #[cfg(feature = "nightly-simd")]
304        fn raw_sample4a(&self, point: f32x4, seed: i32) -> f32;
305
306        #[doc(hidden)]
307        fn raw_improve2_x(&self, point: [f32; 2]) -> [f32; 2];
308
309        #[doc(hidden)]
310        #[cfg(feature = "nightly-simd")]
311        fn raw_improve2a_x(&self, point: f32x2) -> f32x2;
312
313        #[doc(hidden)]
314        fn raw_improve3_xy(&self, point: [f32; 3]) -> [f32; 3];
315
316        #[doc(hidden)]
317        #[cfg(feature = "nightly-simd")]
318        fn raw_improve3a_xy(&self, point: f32x4) -> f32x4;
319
320        #[doc(hidden)]
321        fn raw_improve3_xz(&self, point: [f32; 3]) -> [f32; 3];
322
323        #[doc(hidden)]
324        #[cfg(feature = "nightly-simd")]
325        fn raw_improve3a_xz(&self, point: f32x4) -> f32x4;
326
327        #[doc(hidden)]
328        fn raw_improve4_xyz(&self, point: [f32; 4]) -> [f32; 4];
329
330        #[doc(hidden)]
331        #[cfg(feature = "nightly-simd")]
332        fn raw_improve4a_xyz(&self, point: f32x4) -> f32x4;
333
334        #[doc(hidden)]
335        fn raw_improve4_xyz_xy(&self, point: [f32; 4]) -> [f32; 4];
336
337        #[doc(hidden)]
338        #[cfg(feature = "nightly-simd")]
339        fn raw_improve4a_xyz_xy(&self, point: f32x4) -> f32x4;
340
341        #[doc(hidden)]
342        fn raw_improve4_xyz_xz(&self, point: [f32; 4]) -> [f32; 4];
343
344        #[doc(hidden)]
345        #[cfg(feature = "nightly-simd")]
346        fn raw_improve4a_xyz_xz(&self, point: f32x4) -> f32x4;
347
348        #[doc(hidden)]
349        fn raw_improve4_xy_zw(&self, point: [f32; 4]) -> [f32; 4];
350
351        #[doc(hidden)]
352        #[cfg(feature = "nightly-simd")]
353        fn raw_improve4a_xy_zw(&self, point: f32x4) -> f32x4;
354    }
355
356    /// Improves 2D orientation with Y pointing down the main diagonal.
357    ///
358    /// This might be better for a 2D sandbox style where Y is vertical.
359    /// Probably slightly less optimal for heightmaps or continent maps,
360    /// unless your map is centered around an equator. It's a subtle
361    /// difference, but the option is here to make it an easy choice.
362    Improve2X 2 improve2_x use raw_improve2_x raw_improve2a_x;
363
364    /// Improves 3D orientation for better visual isotropy in (X, Y).
365    ///
366    /// Recommended for 3D terrain and time-varied animations.
367    /// The Z coordinate should always be the "different" coordinate in
368    /// whatever your use case is.
369    Improve3Xy 3 improve3_xy use raw_improve3_xy raw_improve3a_xy;
370
371    /// Improves 3D orientation for better visual isotropy in (X, Z).
372    ///
373    /// Recommended for 3D terrain and time-varied animations.
374    /// The Y coordinate should always be the "different" coordinate in
375    /// whatever your use case is.
376    Improve3Xz 3 improve3_xz use raw_improve3_xz raw_improve3a_xz;
377
378    /// Improves 4D orientation so XYZ is oriented like the default 3D noise
379    /// and W for an extra degree of freedom. W repeats eventually.
380    ///
381    /// Recommended for time-varied animations which texture a 3D object with W as time
382    /// where there isn't a clear distinction between horizontal and vertical.
383    Improve4Xyz 4 improve4_xyz use raw_improve4_xyz raw_improve4a_xyz;
384
385    /// Improves 4D orientation so XYZ is oriented like the 3D `improve_xy` noise
386    /// and W for an extra degree of freedom. W repeats eventually.
387    ///
388    /// Recommended for time-varied animations which texture a 3D object with W as time
389    /// in a space where Z is vertical.
390    Improve4XyzXy 4 improve4_xyz_xy use raw_improve4_xyz_xy raw_improve4a_xyz_xy;
391
392    /// Improves 4D orientation so XYZ is oriented like the 3D `improve_xz` noise
393    /// and W for an extra degree of freedom. W repeats eventually.
394    ///
395    /// Recommended for time-varied animations which texture a 3D object with W as time
396    /// in a space where Y is vertical.
397    Improve4XyzXz 4 improve4_xyz_xz use raw_improve4_xyz_xz raw_improve4a_xyz_xz;
398
399    /// Improves 4D orientation so XY and ZW form orthogonal triangular-based planes.
400    ///
401    /// Recommended for 3D terrain, where X and Y or (Z and W) are horizontal.
402    ///
403    /// Recommended for the noise(x, y, sin(time), cos(time)) trick.
404    Improve4XyZw 4 improve4_xy_zw use raw_improve4_xy_zw raw_improve4a_xy_zw;
405}
406
407macro_rules! impl_open_simplex_noise {
408    (234 $struct:ident) => {
409        impl $crate::Noise for $struct {}
410
411        impl $crate::Sample<2> for $struct {
412            #[inline(always)]
413            fn sample_with_seed(&self, point: [f32; 2], seed: i32) -> f32 {
414                self.raw_sample2(improve2(point), seed)
415            }
416        }
417
418        #[cfg(feature = "nightly-simd")]
419        impl $crate::Sample<2, core::simd::f32x2> for $struct {
420            #[inline(always)]
421            fn sample_with_seed(&self, point: core::simd::f32x2, seed: i32) -> f32 {
422                self.raw_sample2a(improve2a(point), seed)
423            }
424        }
425
426        impl $crate::Sample<3> for $struct {
427            #[inline(always)]
428            fn sample_with_seed(&self, point: [f32; 3], seed: i32) -> f32 {
429                self.raw_sample3(improve3(point), seed)
430            }
431        }
432
433        #[cfg(feature = "nightly-simd")]
434        impl $crate::Sample<3, core::simd::f32x4> for $struct {
435            #[inline(always)]
436            fn sample_with_seed(&self, point: core::simd::f32x4, seed: i32) -> f32 {
437                self.raw_sample3a(improve3a(point), seed)
438            }
439        }
440
441        impl $crate::Sample<4> for $struct {
442            #[inline(always)]
443            fn sample_with_seed(&self, point: [f32; 4], seed: i32) -> f32 {
444                self.raw_sample4(improve4(point), seed)
445            }
446        }
447
448        #[cfg(feature = "nightly-simd")]
449        impl $crate::Sample<4, core::simd::f32x4> for $struct {
450            #[inline(always)]
451            fn sample_with_seed(&self, point: core::simd::f32x4, seed: i32) -> f32 {
452                self.raw_sample4a(improve4a(point), seed)
453            }
454        }
455
456        impl $crate::open_simplex_2::Sealed for $struct {}
457    };
458}
459
460pub(crate) use impl_open_simplex_noise;