terrain_forge/algorithms/
noise_fill.rs1use crate::noise::{Perlin, Simplex, Value, Worley};
2use crate::{Algorithm, Grid, Tile};
3
4#[derive(Debug, Clone, Copy, Default)]
5pub enum NoiseType {
6 #[default]
7 Perlin,
8 Simplex,
9 Value,
10 Worley,
11}
12
13#[derive(Debug, Clone)]
14pub struct NoiseFillConfig {
15 pub noise: NoiseType,
16 pub frequency: f64,
17 pub threshold: f64,
18}
19
20impl Default for NoiseFillConfig {
21 fn default() -> Self {
22 Self {
23 noise: NoiseType::Perlin,
24 frequency: 0.08,
25 threshold: 0.0,
26 }
27 }
28}
29
30pub struct NoiseFill {
31 config: NoiseFillConfig,
32}
33
34impl NoiseFill {
35 pub fn new(config: NoiseFillConfig) -> Self {
36 Self { config }
37 }
38}
39
40impl Default for NoiseFill {
41 fn default() -> Self {
42 Self::new(NoiseFillConfig::default())
43 }
44}
45
46impl Algorithm<Tile> for NoiseFill {
47 fn generate(&self, grid: &mut Grid<Tile>, seed: u64) {
48 let (w, h) = (grid.width(), grid.height());
49
50 match self.config.noise {
51 NoiseType::Perlin => {
52 let noise = Perlin::new(seed).with_frequency(self.config.frequency);
53 fill_from_noise(grid, w, h, &noise, self.config.threshold);
54 }
55 NoiseType::Simplex => {
56 let noise = Simplex::new(seed).with_frequency(self.config.frequency);
57 fill_from_noise(grid, w, h, &noise, self.config.threshold);
58 }
59 NoiseType::Value => {
60 let noise = Value::new(seed).with_frequency(self.config.frequency);
61 fill_from_noise(grid, w, h, &noise, self.config.threshold);
62 }
63 NoiseType::Worley => {
64 let noise = Worley::new(seed).with_frequency(self.config.frequency);
65 fill_from_noise(grid, w, h, &noise, self.config.threshold);
66 }
67 }
68
69 if w > 0 && h > 0 {
71 for x in 0..w {
72 grid.set(x as i32, 0, Tile::Wall);
73 grid.set(x as i32, (h - 1) as i32, Tile::Wall);
74 }
75 for y in 0..h {
76 grid.set(0, y as i32, Tile::Wall);
77 grid.set((w - 1) as i32, y as i32, Tile::Wall);
78 }
79 }
80 }
81
82 fn name(&self) -> &'static str {
83 "NoiseFill"
84 }
85}
86
87fn fill_from_noise<N: crate::noise::NoiseSource>(
88 grid: &mut Grid<Tile>,
89 w: usize,
90 h: usize,
91 noise: &N,
92 threshold: f64,
93) {
94 for y in 0..h {
95 for x in 0..w {
96 let value = noise.sample(x as f64, y as f64);
97 let tile = if value >= threshold {
98 Tile::Floor
99 } else {
100 Tile::Wall
101 };
102 grid.set(x as i32, y as i32, tile);
103 }
104 }
105}