Skip to main content

terrain_forge/effects/
blend.rs

1//! Blending effects
2
3use crate::{Grid, Tile};
4
5pub fn threshold(values: &[Vec<f64>], grid: &mut Grid<Tile>, thresh: f64) {
6    let h = values.len().min(grid.height());
7    let w = values
8        .first()
9        .map(|r| r.len())
10        .unwrap_or(0)
11        .min(grid.width());
12
13    for (y, row) in values.iter().enumerate().take(h) {
14        for (x, &val) in row.iter().enumerate().take(w) {
15            grid.set(
16                x as i32,
17                y as i32,
18                if val > thresh {
19                    Tile::Floor
20                } else {
21                    Tile::Wall
22                },
23            );
24        }
25    }
26}
27
28pub fn gradient_blend(
29    base: &Grid<Tile>,
30    overlay: &Grid<Tile>,
31    output: &mut Grid<Tile>,
32    horizontal: bool,
33) {
34    let w = base.width().min(overlay.width()).min(output.width());
35    let h = base.height().min(overlay.height()).min(output.height());
36
37    for y in 0..h {
38        for x in 0..w {
39            let t = if horizontal {
40                x as f64 / w as f64
41            } else {
42                y as f64 / h as f64
43            };
44            let cell = if t > 0.5 {
45                overlay[(x, y)]
46            } else {
47                base[(x, y)]
48            };
49            output.set(x as i32, y as i32, cell);
50        }
51    }
52}
53
54pub fn radial_blend(
55    base: &Grid<Tile>,
56    overlay: &Grid<Tile>,
57    output: &mut Grid<Tile>,
58    inner_r: f64,
59    outer_r: f64,
60) {
61    let w = base.width().min(overlay.width()).min(output.width());
62    let h = base.height().min(overlay.height()).min(output.height());
63    let (cx, cy) = (w as f64 / 2.0, h as f64 / 2.0);
64
65    for y in 0..h {
66        for x in 0..w {
67            let dist = ((x as f64 - cx).powi(2) + (y as f64 - cy).powi(2)).sqrt();
68            let cell = if dist < inner_r {
69                base[(x, y)]
70            } else if dist > outer_r {
71                overlay[(x, y)]
72            } else if base[(x, y)].is_floor() || overlay[(x, y)].is_floor() {
73                Tile::Floor
74            } else {
75                Tile::Wall
76            };
77            output.set(x as i32, y as i32, cell);
78        }
79    }
80}