gioser

tawasuyu/llimphi

Sovereign retained-mode GPU UI framework in Rust (wgpu+vello+taffy+parley), Elm loop, 40+ widgets.

Rust 484Markdown 258TOML 131RON 38118 Definitions

⎇ main llimphi-voxel/examples/jardin_demo.rs Rust · 112 lines · 4.4 KB History Who touched what raw

chore: refresco desde el monorepo (pin tawasuyu.git v0.3.0) b575c63f1 · Sergio ·

1//! **El jardín SDF**: las 30 formas de vegetación ([`Forma`](llimphi_voxel::Forma))
2//! armadas con primitivas analíticas ([`flora_sdf`](llimphi_voxel::flora_sdf)) — el
3//! ficus con sus raíces aéreas, la palmera con la fronda arqueada, el jacarandá en
4//! flor, la rosa por capas.
5//!
6//! ```text
7//! cargo run -p llimphi-voxel --example jardin_demo --release
8//! ```
9//! Salida: `/tmp/jardin_1.png` …, `/tmp/jardin_semillas.png` (la misma especie con
10//! cinco semillas: si salen iguales, el bosque es papel pintado) y
11//! `/tmp/jardin_viento.png`.
12
13use llimphi_voxel::{alto_flora, flora_sdf, Forma};
14
15#[path = "comun/mod.rs"]
16mod comun;
17
18const TW: u32 = 320;
19const TH: u32 = 300;
20const COLS: usize = 6;
21const POR_HOJA: usize = 24;
22
23fn main() {
24    let mut toma = comun::Toma::nueva();
25    let piso = toma.piso([116, 124, 106], [100, 110, 94]);
26    let dir = comun::dir();
27    let yaw: f32 = std::env::var("YAW").ok().and_then(|s| s.parse().ok()).unwrap_or(28.0);
28
29    println!("jardin_demo — {} formas", Forma::ALL.len());
30    let vacia = toma.casilla(&piso, Vec::new(), 12.0, comun::RADIO, yaw, TW, TH);
31    let mut casillas: Vec<(String, Vec<u8>)> = Vec::new();
32    let mut flacos = Vec::new();
33    for (i, f) in Forma::ALL.into_iter().enumerate() {
34        let unidad = flora_sdf(f, 1.0, 11, 0.0);
35        let (_, r1) = unidad.bound();
36        let alto = comun::RADIO / r1.max(1e-3);
37        let ser = flora_sdf(f, alto, 11, 0.15);
38        let (c, r) = ser.bound();
39        let n = ser.prims.len();
40        let posado = ser.posado(
41            [comun::DIM as f32 * 0.5, comun::PISO as f32, comun::DIM as f32 * 0.5],
42            0.0,
43        );
44        let px = toma.casilla(&piso, vec![posado], c[1], r, yaw, TW, TH);
45        let cov = comun::ocupacion(&px, &vacia);
46        if cov < 900 {
47            flacos.push(format!("{} ({cov} px)", f.label()));
48        }
49        println!("  {:<12} {:>3} prims  {:>6} px  {:.1} m", f.label(), n, cov, alto_flora(f));
50        casillas.push((format!("{}. {}", i + 1, f.label()), px));
51    }
52    for (h, grupo) in casillas.chunks(POR_HOJA).enumerate() {
53        let (px, w, hh) = toma.hoja(
54            &format!("jardín SDF — hoja {} de {}", h + 1, casillas.len().div_ceil(POR_HOJA)),
55            grupo,
56            COLS,
57            TW,
58            TH,
59        );
60        let out = format!("{dir}/jardin_{}.png", h + 1);
61        comun::png(&px, w, hh, &out);
62        println!("→ {out}");
63    }
64
65    // La semilla: cinco ficus y cinco palmeras que no son la misma planta.
66    let mut casillas = Vec::new();
67    for f in [Forma::Ficus, Forma::Palmera, Forma::Arbol] {
68        for s in 0..5u32 {
69            let unidad = flora_sdf(f, 1.0, s * 13 + 1, 0.0);
70            let (_, r1) = unidad.bound();
71            let ser = flora_sdf(f, comun::RADIO / r1.max(1e-3), s * 13 + 1, 0.0);
72            let (c, r) = ser.bound();
73            let posado = ser.posado(
74                [comun::DIM as f32 * 0.5, comun::PISO as f32, comun::DIM as f32 * 0.5],
75                0.0,
76            );
77            let px = toma.casilla(&piso, vec![posado], c[1], r, yaw, TW, TH);
78            casillas.push((format!("{} · semilla {s}", f.label()), px));
79        }
80    }
81    let (px, w, hh) = toma.hoja("jardín SDF — la semilla varía la planta", &casillas, 5, TW, TH);
82    let out = format!("{dir}/jardin_semillas.png");
83    comun::png(&px, w, hh, &out);
84    println!("→ {out}");
85
86    // El viento.
87    let mut casillas = Vec::new();
88    for f in [Forma::Palmera, Forma::Trigo, Forma::Cipres] {
89        for v in [0.0f32, 0.5, 1.0, 1.6] {
90            let unidad = flora_sdf(f, 1.0, 7, 0.0);
91            let (_, r1) = unidad.bound();
92            let ser = flora_sdf(f, comun::RADIO / r1.max(1e-3), 7, v);
93            let (c, r) = ser.bound();
94            let posado = ser.posado(
95                [comun::DIM as f32 * 0.5, comun::PISO as f32, comun::DIM as f32 * 0.5],
96                0.0,
97            );
98            let px = toma.casilla(&piso, vec![posado], c[1], r, 0.0, TW, TH);
99            casillas.push((format!("{} · viento {v:.1}", f.label()), px));
100        }
101    }
102    let (px, w, hh) = toma.hoja("jardín SDF — el viento dobla la copa", &casillas, 4, TW, TH);
103    let out = format!("{dir}/jardin_viento.png");
104    comun::png(&px, w, hh, &out);
105    println!("→ {out}");
106
107    if flacos.is_empty() {
108        println!("✓ las {} formas dibujaron píxeles de sobra", Forma::ALL.len());
109    } else {
110        println!("⚠ casi no se ven: {}", flacos.join(", "));
111    }
112}