tawasuyu

tawasuyu/llimphi

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

Rust 660Markdown 302TOML 157RON 312382 Sutichaykuna

⎇ main llimphi-voxel/examples/exportar_vox.rs Rust · 86 siq'ikuna · 3.3 KB Ñawpa willay Pi imata llamkarqan ch'uya

chore: refresco desde el monorepo — 128 miembros, los 76 widgets y los 11 módulos b3f12e136 · Sergio ·

1//! **El camino de vuelta**: lo que se compone acá sale al editor ajeno.
2//!
3//! Arma un par de casas procedurales (cada una con su semilla) y las escribe como
4//! escena `.vox` — modelos + grafo de colocación, que es lo que MagicaVoxel abre con
5//! las piezas separadas y ubicadas, no fundidas en un bloque. Después la vuelve a
6//! leer y **compara**, que es la única forma de saber que el archivo sirve sin
7//! abrirlo.
8//!
9//! ```bash
10//! cargo run -p llimphi-voxel --example exportar_vox --release
11//! ```
12//!
13//! Deja `/tmp/tawasuyu_barrio.vox` (escena de dos casas) y `/tmp/tawasuyu_casa.vox`
14//! (una sola, `.vox` clásico).
15
16use foreign_vox::{Placement, Rot};
17use llimphi_3d::VoxelGrid;
18use llimphi_voxel::{grid_to_model, save_grid, scene_to_grid, CasaTipo};
19
20fn solidos(g: &VoxelGrid) -> usize {
21    let d = g.dim();
22    let mut n = 0;
23    for x in 0..d[0] {
24        for y in 0..d[1] {
25            for z in 0..d[2] {
26                if g.is_solid(x as i32, y as i32, z as i32) {
27                    n += 1;
28                }
29            }
30        }
31    }
32    n
33}
34
35fn casa(tipo: CasaTipo, seed: u32) -> VoxelGrid {
36    let mut g = VoxelGrid::new([24, 24, 24]);
37    llimphi_voxel::stamp_casa(&mut g, tipo, 12, 0, 12, seed);
38    g
39}
40
41fn main() {
42    // --- Una casa sola: el `.vox` clásico de un modelo.
43    let cabana = casa(CasaTipo::Cabana, 7);
44    save_grid("/tmp/tawasuyu_casa.vox", &cabana).expect("escribir la casa");
45    let leida = llimphi_voxel::load_grid("/tmp/tawasuyu_casa.vox").expect("releer la casa");
46    println!(
47        "casa sola      : {} voxels → /tmp/tawasuyu_casa.vox → releída {} voxels  {}",
48        solidos(&cabana),
49        solidos(&leida),
50        if solidos(&cabana) == solidos(&leida) { "✓" } else { "✗" }
51    );
52
53    // --- Dos casas como ESCENA: cada una es un modelo con su lugar (y una girada).
54    let moderna = casa(CasaTipo::Moderna, 3);
55    let hobbit = casa(CasaTipo::Hobbit, 11);
56    let modelos = vec![
57        grid_to_model(&moderna).expect("exportar moderna"),
58        grid_to_model(&hobbit).expect("exportar hobbit"),
59    ];
60    let colocaciones = vec![
61        Placement { model: 0, translation: [0, 0, 0], rotation: Rot::IDENTITY },
62        // La segunda, corrida 30 voxels y girada un cuarto de vuelta.
63        Placement { model: 1, translation: [30, 0, 0], rotation: Rot::from_byte(17) },
64    ];
65    let bytes = foreign_vox::write_scene(&modelos, &colocaciones);
66    std::fs::write("/tmp/tawasuyu_barrio.vox", &bytes).expect("escribir el barrio");
67    println!("barrio         : {} bytes → /tmp/tawasuyu_barrio.vox", bytes.len());
68
69    // --- Y se relee: los dos modelos, sus lugares y su rotación.
70    let escena = foreign_vox::parse_scene(&bytes).expect("releer el barrio");
71    println!(
72        "               : {} modelos, {} colocaciones, rotación de la 2ª = {}",
73        escena.models.len(),
74        escena.placements.len(),
75        escena.placements.iter().find(|p| p.model == 1).map(|p| p.rotation.to_byte()).unwrap_or(0)
76    );
77    let compuesto = scene_to_grid(&escena);
78    let esperado = solidos(&moderna) + solidos(&hobbit);
79    println!(
80        "compuesto      : {:?} = {} voxels (las dos casas juntas: {})  {}",
81        compuesto.dim(),
82        solidos(&compuesto),
83        esperado,
84        if solidos(&compuesto) == esperado { "✓" } else { "✗ se pisan o se pierden" }
85    );
86}