noise_functions/modifiers/
tileable.rs

1use crate::{
2    math::{cos, sin},
3    Noise, Sample,
4};
5
6use core::f32::consts::{PI, TAU};
7
8#[cfg(feature = "nightly-simd")]
9use core::simd::{f32x2, f32x4};
10
11/// Creates a tileable 2D noise from a 4D noise.
12///
13/// The parameters `width` and `height` describe the size of the repeating tile.
14#[derive(Debug, Clone, Copy, PartialEq)]
15pub struct Tileable<Noise> {
16    pub noise: Noise,
17    width_div_pi: f32,
18    height_div_pi: f32,
19    tau_div_width: f32,
20    tau_div_height: f32,
21}
22
23impl<Noise> Tileable<Noise> {
24    pub const fn new(noise: Noise, width: f32, height: f32) -> Self {
25        Self {
26            noise,
27            width_div_pi: width / PI,
28            height_div_pi: height / PI,
29            tau_div_width: TAU / width,
30            tau_div_height: TAU / height,
31        }
32    }
33
34    fn map_point(&self, [x, y]: [f32; 2]) -> [f32; 4] {
35        let nx = cos(x * self.tau_div_width) * self.width_div_pi;
36        let ny = cos(y * self.tau_div_height) * self.height_div_pi;
37        let nz = sin(x * self.tau_div_width) * self.width_div_pi;
38        let nw = sin(y * self.tau_div_height) * self.height_div_pi;
39        [nx, ny, nz, nw]
40    }
41}
42
43impl<N> Noise for Tileable<N> {}
44
45impl<Noise> Sample<2> for Tileable<Noise>
46where
47    Noise: Sample<4>,
48{
49    fn sample_with_seed(&self, point: [f32; 2], seed: i32) -> f32 {
50        self.noise.sample_with_seed(self.map_point(point), seed)
51    }
52}
53
54#[cfg(feature = "nightly-simd")]
55impl<Noise> Sample<2, f32x2> for Tileable<Noise>
56where
57    Noise: Sample<4, f32x4>,
58{
59    fn sample_with_seed(&self, point: f32x2, seed: i32) -> f32 {
60        self.noise.sample_with_seed(self.map_point(point.into()).into(), seed)
61    }
62}