noise/noise_fns/generators/fractals/
billow.rs1use crate::{
2 math::{scale_shift, vectors::*},
3 noise_fns::{MultiFractal, NoiseFn, Seedable},
4};
5use alloc::vec::Vec;
6
7#[derive(Clone, Debug)]
15pub struct Billow<T> {
16 pub octaves: usize,
22
23 pub frequency: f64,
25
26 pub lacunarity: f64,
35
36 pub persistence: f64,
43
44 seed: u32,
45 sources: Vec<T>,
46 scale_factor: f64,
47}
48
49impl<T> Billow<T>
50where
51 T: Default + Seedable,
52{
53 pub const DEFAULT_SEED: u32 = 0;
54 pub const DEFAULT_OCTAVE_COUNT: usize = 6;
55 pub const DEFAULT_FREQUENCY: f64 = 1.0;
56 pub const DEFAULT_LACUNARITY: f64 = core::f64::consts::PI * 2.0 / 3.0;
57 pub const DEFAULT_PERSISTENCE: f64 = 0.5;
58 pub const MAX_OCTAVES: usize = 32;
59
60 pub fn new(seed: u32) -> Self {
61 Self {
62 seed,
63 octaves: Self::DEFAULT_OCTAVE_COUNT,
64 frequency: Self::DEFAULT_FREQUENCY,
65 lacunarity: Self::DEFAULT_LACUNARITY,
66 persistence: Self::DEFAULT_PERSISTENCE,
67 sources: super::build_sources(seed, Self::DEFAULT_OCTAVE_COUNT),
68 scale_factor: Self::calc_scale_factor(
69 Self::DEFAULT_PERSISTENCE,
70 Self::DEFAULT_OCTAVE_COUNT,
71 ),
72 }
73 }
74
75 fn calc_scale_factor(persistence: f64, octaves: usize) -> f64 {
76 let denom = (1..=octaves).fold(0.0, |acc, x| acc + persistence.powi(x as i32));
77
78 1.0 / denom
79 }
80
81 pub fn set_sources(self, sources: Vec<T>) -> Self {
82 Self { sources, ..self }
83 }
84}
85
86impl<T> Default for Billow<T>
87where
88 T: Default + Seedable,
89{
90 fn default() -> Self {
91 Self::new(Self::DEFAULT_SEED)
92 }
93}
94
95impl<T> MultiFractal for Billow<T>
96where
97 T: Default + Seedable,
98{
99 fn set_octaves(self, mut octaves: usize) -> Self {
100 if self.octaves == octaves {
101 return self;
102 }
103
104 octaves = octaves.clamp(1, Self::MAX_OCTAVES);
105 Self {
106 octaves,
107 sources: super::build_sources(self.seed, octaves),
108 scale_factor: Self::calc_scale_factor(self.persistence, octaves),
109 ..self
110 }
111 }
112
113 fn set_frequency(self, frequency: f64) -> Self {
114 Self { frequency, ..self }
115 }
116
117 fn set_lacunarity(self, lacunarity: f64) -> Self {
118 Self { lacunarity, ..self }
119 }
120
121 fn set_persistence(self, persistence: f64) -> Self {
122 Self {
123 persistence,
124 scale_factor: Self::calc_scale_factor(persistence, self.octaves),
125 ..self
126 }
127 }
128}
129
130impl<T> Seedable for Billow<T>
131where
132 T: Default + Seedable,
133{
134 fn set_seed(self, seed: u32) -> Self {
135 if self.seed == seed {
136 return self;
137 }
138
139 Self {
140 seed,
141 sources: super::build_sources(seed, self.octaves),
142 ..self
143 }
144 }
145
146 fn seed(&self) -> u32 {
147 self.seed
148 }
149}
150
151impl<T> NoiseFn<f64, 2> for Billow<T>
153where
154 T: NoiseFn<f64, 2>,
155{
156 fn get(&self, point: [f64; 2]) -> f64 {
157 let mut point = Vector2::from(point);
158
159 let mut result = 0.0;
160
161 let mut attenuation = self.persistence;
162
163 point *= self.frequency;
164
165 for x in 0..self.octaves {
166 let mut signal = self.sources[x].get(point.into_array());
168
169 signal = scale_shift(signal, 2.0);
172
173 signal *= attenuation;
175
176 attenuation *= self.persistence;
178
179 result += signal;
181
182 point *= self.lacunarity;
184 }
185
186 result * self.scale_factor
188 }
189}
190
191impl<T> NoiseFn<f64, 3> for Billow<T>
193where
194 T: NoiseFn<f64, 3>,
195{
196 fn get(&self, point: [f64; 3]) -> f64 {
197 let mut point = Vector3::from(point);
198
199 let mut result = 0.0;
200
201 let mut attenuation = self.persistence;
202
203 point *= self.frequency;
204
205 for x in 0..self.octaves {
206 let mut signal = self.sources[x].get(point.into_array());
208
209 signal = scale_shift(signal, 2.0);
212
213 signal *= attenuation;
215
216 attenuation *= self.persistence;
218
219 result += signal;
221
222 point *= self.lacunarity;
224 }
225
226 result * self.scale_factor
228 }
229}
230
231impl<T> NoiseFn<f64, 4> for Billow<T>
233where
234 T: NoiseFn<f64, 4>,
235{
236 fn get(&self, point: [f64; 4]) -> f64 {
237 let mut point = Vector4::from(point);
238
239 let mut result = 0.0;
240
241 let mut attenuation = self.persistence;
242
243 point *= self.frequency;
244
245 for x in 0..self.octaves {
246 let mut signal = self.sources[x].get(point.into_array());
248
249 signal = scale_shift(signal, 2.0);
252
253 signal *= attenuation;
255
256 attenuation *= self.persistence;
258
259 result += signal;
261
262 point *= self.lacunarity;
264 }
265
266 result * self.scale_factor
268 }
269}