1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
use crate::prelude::*;

pub use dot_vox;

use building_blocks_core::prelude::*;

use dot_vox::*;

#[derive(Copy, Clone, Eq, PartialEq)]
pub enum VoxColor {
    Color(u8),
    Empty,
}

impl IsEmpty for VoxColor {
    fn is_empty(&self) -> bool {
        matches!(self, VoxColor::Empty)
    }
}

pub fn encode_vox<Map>(map: &Map, map_extent: Extent3i) -> DotVoxData
where
    Map: Get<Point3i, Item = VoxColor>,
{
    let shape = map_extent.shape;
    let vox_extent = map_extent - map_extent.minimum;

    // VOX coordinates are limited to u8.
    assert!(shape <= Point3i::fill(std::u8::MAX as i32));

    let size = dot_vox::Size {
        x: shape.x() as u32,
        y: shape.y() as u32,
        z: shape.z() as u32,
    };

    let mut voxels = Vec::new();
    for (vox_p, map_p) in vox_extent.iter_points().zip(map_extent.iter_points()) {
        if let VoxColor::Color(i) = map.get(map_p) {
            voxels.push(dot_vox::Voxel {
                x: vox_p.x() as u8,
                y: vox_p.y() as u8,
                z: vox_p.z() as u8,
                i,
            });
        }
    }

    let model = dot_vox::Model { size, voxels };

    DotVoxData {
        version: 150,
        models: vec![model],
        palette: Vec::new(),
        materials: Vec::new(),
    }
}