Skip to main content

randscape/generators/
mod.rs

1pub mod auto_tile;
2
3use crate::grid::Grid;
4use noise::NoiseFn;
5use std::ops::{Add, Div, Mul, Range, Sub};
6use vek::{Mat4, Vec2};
7
8pub trait GridGenetator<T: Copy> {
9    fn generate(
10        &mut self,
11        location: Vec2<usize>,
12        size: Vec2<usize>,
13        current: T,
14        grid: &Grid<T>,
15    ) -> T;
16}
17
18impl<T: Copy, F: FnMut(Vec2<usize>, Vec2<usize>, T) -> T> GridGenetator<T> for F {
19    fn generate(&mut self, location: Vec2<usize>, size: Vec2<usize>, current: T, _: &Grid<T>) -> T {
20        self(location, size, current)
21    }
22}
23
24pub struct ConstGenerator<T: Copy>(pub T);
25
26impl<T: Copy> GridGenetator<T> for ConstGenerator<T> {
27    fn generate(&mut self, _: Vec2<usize>, _: Vec2<usize>, _: T, _: &Grid<T>) -> T {
28        self.0
29    }
30}
31
32pub struct OffsetLocationGenerator<'a, T: Copy> {
33    pub generator: &'a mut dyn GridGenetator<T>,
34    pub offsets: &'a Grid<Vec2<isize>>,
35}
36
37impl<T: Copy> GridGenetator<T> for OffsetLocationGenerator<'_, T> {
38    fn generate(
39        &mut self,
40        mut location: Vec2<usize>,
41        size: Vec2<usize>,
42        current: T,
43        grid: &Grid<T>,
44    ) -> T {
45        let offset = self.offsets.get(location).unwrap_or_default();
46        if offset.x >= 0 {
47            location.x = (location.x + offset.x as usize) % size.x;
48        } else {
49            location.x = (location.x + size.x - offset.x.unsigned_abs() % size.x) % size.x;
50        }
51        if offset.y >= 0 {
52            location.y = (location.y + offset.y as usize) % size.y;
53        } else {
54            location.y = (location.y + size.y - offset.y.unsigned_abs() % size.y) % size.y;
55        }
56        self.generator.generate(location, size, current, grid)
57    }
58}
59
60pub struct NoiseGenerator<T: NoiseFn<f64, 2>> {
61    pub noise: T,
62    pub transform: Mat4<f64>,
63}
64
65impl<T: NoiseFn<f64, 2>> NoiseGenerator<T> {
66    pub fn new(noise: T) -> Self {
67        Self {
68            noise,
69            transform: Mat4::identity(),
70        }
71    }
72
73    pub fn transform(mut self, transform: Mat4<f64>) -> Self {
74        self.transform = transform;
75        self
76    }
77}
78
79impl<T: NoiseFn<f64, 2>> GridGenetator<f64> for NoiseGenerator<T> {
80    fn generate(&mut self, location: Vec2<usize>, _: Vec2<usize>, _: f64, _: &Grid<f64>) -> f64 {
81        let point = self.transform.mul_point(Vec2 {
82            x: location.x as f64,
83            y: location.y as f64,
84        });
85        self.noise.get(point.into_array())
86    }
87}
88
89pub struct CopyGenerator<'a, T: Copy> {
90    pub other: &'a Grid<T>,
91}
92
93impl<T: Copy + Add<Output = T> + Default> GridGenetator<T> for CopyGenerator<'_, T> {
94    fn generate(&mut self, location: Vec2<usize>, _: Vec2<usize>, _: T, _: &Grid<T>) -> T {
95        self.other.get(location).unwrap_or_default()
96    }
97}
98
99pub struct AddGenerator<'a, T: Copy> {
100    pub other: &'a Grid<T>,
101}
102
103impl<T: Copy + Add<Output = T> + Default> GridGenetator<T> for AddGenerator<'_, T> {
104    fn generate(&mut self, location: Vec2<usize>, _: Vec2<usize>, current: T, _: &Grid<T>) -> T {
105        current + self.other.get(location).unwrap_or_default()
106    }
107}
108
109pub struct SubGenerator<'a, T: Copy> {
110    pub other: &'a Grid<T>,
111}
112
113impl<T: Copy + Sub<Output = T> + Default> GridGenetator<T> for SubGenerator<'_, T> {
114    fn generate(&mut self, location: Vec2<usize>, _: Vec2<usize>, current: T, _: &Grid<T>) -> T {
115        current - self.other.get(location).unwrap_or_default()
116    }
117}
118
119pub struct MulGenerator<'a, T: Copy> {
120    pub other: &'a Grid<T>,
121}
122
123impl<T: Copy + Mul<Output = T> + Default> GridGenetator<T> for MulGenerator<'_, T> {
124    fn generate(&mut self, location: Vec2<usize>, _: Vec2<usize>, current: T, _: &Grid<T>) -> T {
125        current * self.other.get(location).unwrap_or_default()
126    }
127}
128
129pub struct DivGenerator<'a, T: Copy> {
130    pub other: &'a Grid<T>,
131}
132
133impl<T: Copy + Div<Output = T> + Default> GridGenetator<T> for DivGenerator<'_, T> {
134    fn generate(&mut self, location: Vec2<usize>, _: Vec2<usize>, current: T, _: &Grid<T>) -> T {
135        current / self.other.get(location).unwrap_or_default()
136    }
137}
138
139pub struct MinGenerator<'a, T: Copy> {
140    pub other: &'a Grid<T>,
141}
142
143impl<T: Copy + Div<Output = T> + Ord + Default> GridGenetator<T> for MinGenerator<'_, T> {
144    fn generate(&mut self, location: Vec2<usize>, _: Vec2<usize>, current: T, _: &Grid<T>) -> T {
145        current.min(self.other.get(location).unwrap_or_default())
146    }
147}
148
149pub struct MaxGenerator<'a, T: Copy> {
150    pub other: &'a Grid<T>,
151}
152
153impl<T: Copy + Div<Output = T> + Ord + Default> GridGenetator<T> for MaxGenerator<'_, T> {
154    fn generate(&mut self, location: Vec2<usize>, _: Vec2<usize>, current: T, _: &Grid<T>) -> T {
155        current.max(self.other.get(location).unwrap_or_default())
156    }
157}
158
159pub struct ClampGenerator<T: Copy> {
160    pub min: T,
161    pub max: T,
162}
163
164impl<T: Copy + Ord + Default> GridGenetator<T> for ClampGenerator<T> {
165    fn generate(&mut self, _: Vec2<usize>, _: Vec2<usize>, current: T, _: &Grid<T>) -> T {
166        current.clamp(self.min, self.max)
167    }
168}
169
170pub struct RemapGenerator<T: Copy> {
171    pub from: Range<T>,
172    pub to: Range<T>,
173}
174
175impl<T: Copy + Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>>
176    GridGenetator<T> for RemapGenerator<T>
177{
178    fn generate(&mut self, _: Vec2<usize>, _: Vec2<usize>, current: T, _: &Grid<T>) -> T {
179        let factor = (current - self.from.start) / (self.from.end - self.from.start);
180        (self.to.end - self.to.start) * factor + self.to.start
181    }
182}
183
184pub enum ThresholdGenerator<'a, T: Copy> {
185    Constant {
186        threshold: T,
187        value_upper: T,
188        value_lower: T,
189    },
190    Samples {
191        thresholds: &'a Grid<T>,
192        value_upper: T,
193        value_lower: T,
194    },
195}
196
197impl<T: Copy + PartialOrd + Default> GridGenetator<T> for ThresholdGenerator<'_, T> {
198    fn generate(&mut self, location: Vec2<usize>, _: Vec2<usize>, current: T, _: &Grid<T>) -> T {
199        match self {
200            Self::Constant {
201                threshold,
202                value_upper,
203                value_lower,
204            } => {
205                if current > *threshold {
206                    *value_upper
207                } else {
208                    *value_lower
209                }
210            }
211            Self::Samples {
212                thresholds,
213                value_upper,
214                value_lower,
215            } => {
216                if current > thresholds.get(location).unwrap_or_default() {
217                    *value_upper
218                } else {
219                    *value_lower
220                }
221            }
222        }
223    }
224}
225
226pub struct Kernel33Generator<'a, T: Copy> {
227    pub other: &'a Grid<T>,
228    pub kernel: [T; 9],
229}
230
231impl<'a> Kernel33Generator<'a, f64> {
232    pub fn identity(other: &'a Grid<f64>) -> Self {
233        Self {
234            other,
235            kernel: [0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
236        }
237    }
238
239    pub fn ridge(other: &'a Grid<f64>) -> Self {
240        Self {
241            other,
242            kernel: [0.0, -1.0, 0.0, -1.0, 4.0, -1.0, 0.0, -1.0, 0.0],
243        }
244    }
245
246    pub fn edge_detection(other: &'a Grid<f64>) -> Self {
247        Self {
248            other,
249            kernel: [-1.0, -1.0, -1.0, -1.0, 8.0, -1.0, -1.0, -1.0, -1.0],
250        }
251    }
252
253    pub fn sharpen(other: &'a Grid<f64>) -> Self {
254        Self {
255            other,
256            kernel: [0.0, -1.0, 0.0, -1.0, 5.0, -1.0, 0.0, -1.0, 0.0],
257        }
258    }
259
260    pub fn emboss(other: &'a Grid<f64>) -> Self {
261        Self {
262            other,
263            kernel: [-2.0, -1.0, 0.0, -1.0, 1.0, 1.0, 0.0, 1.0, 2.0],
264        }
265    }
266
267    pub fn box_blur(other: &'a Grid<f64>) -> Self {
268        Self {
269            other,
270            kernel: [
271                1.0 / 9.0,
272                1.0 / 9.0,
273                1.0 / 9.0,
274                1.0 / 9.0,
275                1.0 / 9.0,
276                1.0 / 9.0,
277                1.0 / 9.0,
278                1.0 / 9.0,
279                1.0 / 9.0,
280            ],
281        }
282    }
283
284    pub fn gaussian_blur(other: &'a Grid<f64>) -> Self {
285        Self {
286            other,
287            kernel: [
288                1.0 / 16.0,
289                2.0 / 16.0,
290                1.0 / 16.0,
291                2.0 / 16.0,
292                4.0 / 16.0,
293                2.0 / 16.0,
294                1.0 / 16.0,
295                2.0 / 16.0,
296                1.0 / 16.0,
297            ],
298        }
299    }
300}
301
302impl<T: Copy + Add<Output = T> + Mul<Output = T> + Default> GridGenetator<T>
303    for Kernel33Generator<'_, T>
304{
305    fn generate(&mut self, location: Vec2<usize>, size: Vec2<usize>, _: T, _: &Grid<T>) -> T {
306        let region = [
307            self.other
308                .get(location + Vec2::new(size.x - 1, size.y - 1))
309                .unwrap_or_default(),
310            self.other
311                .get(location + Vec2::new(0, size.y - 1))
312                .unwrap_or_default(),
313            self.other
314                .get(location + Vec2::new(1, size.y - 1))
315                .unwrap_or_default(),
316            self.other
317                .get(location + Vec2::new(size.x - 1, 0))
318                .unwrap_or_default(),
319            self.other.get(location).unwrap_or_default(),
320            self.other
321                .get(location + Vec2::new(1, 0))
322                .unwrap_or_default(),
323            self.other
324                .get(location + Vec2::new(size.x - 1, 1))
325                .unwrap_or_default(),
326            self.other
327                .get(location + Vec2::new(0, 1))
328                .unwrap_or_default(),
329            self.other
330                .get(location + Vec2::new(1, 1))
331                .unwrap_or_default(),
332        ];
333        region
334            .into_iter()
335            .zip(self.kernel)
336            .fold(Default::default(), |accumulator, (value, kernel)| {
337                value * kernel + accumulator
338            })
339    }
340}