binary_greedy_meshing/
face.rs

1use crate::Quad;
2
3const MASK_XYZ: u64 = 0b111111_111111_111111;
4
5#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
6pub enum Face {
7    Up,
8    Down,
9    Right,
10    Left,
11    Front,
12    Back,
13}
14
15impl From<u8> for Face {
16    fn from(value: u8) -> Self {
17        assert!(value < 6);
18        match value {
19            0 => Self::Up,
20            1 => Self::Down,
21            2 => Self::Right,
22            3 => Self::Left,
23            4 => Self::Front,
24            5 => Self::Back,
25            _ => unreachable!(),
26        }
27    }
28}
29
30#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
31pub struct Vertex(pub u32);
32
33impl Vertex {
34    const MASK_6: u32 = 0b111111;
35
36    pub fn new() -> Self {
37        Self(0u32)
38    }
39
40    pub fn pack(xyz: u32, u: u32, v: u32) -> Self {
41        Self((v << 24) | (u << 18) | xyz)
42    }
43
44    pub fn x(&self) -> u32 {
45        self.0 & Vertex::MASK_6
46    }
47
48    pub fn y(&self) -> u32 {
49        (self.0 >> 6) & Vertex::MASK_6
50    }
51
52    pub fn z(&self) -> u32 {
53        (self.0 >> 12) & Vertex::MASK_6
54    }
55
56    pub fn u(&self) -> u32 {
57        (self.0 >> 18) & Vertex::MASK_6
58    }
59
60    pub fn v(&self) -> u32 {
61        (self.0 >> 24) & Vertex::MASK_6
62    }
63
64    pub fn xyz(&self) -> [u32; 3] {
65        [self.x(), self.y(), self.z()]
66    }
67}
68
69fn packed_xyz(x: u32, y: u32, z: u32) -> u32 {
70    (z << 12) | (y << 6) | x
71}
72
73impl Face {
74    pub fn n(&self) -> [f32; 3] {
75        match self {
76            Self::Up => [0., 1., 0.],
77            Self::Down => [0., -1., 0.],
78            Self::Right => [1., 0., 0.],
79            Self::Left => [-1., 0., 0.],
80            Self::Front => [0., 0., 1.],
81            Self::Back => [0., 0., -1.],
82        }
83    }
84
85    /// Takes a quad as outputted by binary greedy meshing, and outputs 4 vertices encoded as:
86    /// (v << 24) | (u << 18) | (z << 12) | (y << 6) | x
87    pub fn vertices_packed(&self, quad: Quad) -> [Vertex; 4] {
88        let w = quad.width() as u32;
89        let h = quad.height() as u32;
90        let xyz = (MASK_XYZ & quad.0) as u32;
91        match self {
92            Face::Left => [
93                Vertex::pack(xyz, h, w),
94                Vertex::pack(xyz + packed_xyz(0, 0, h), 0, w),
95                Vertex::pack(xyz + packed_xyz(0, w, 0), h, 0),
96                Vertex::pack(xyz + packed_xyz(0, w, h), 0, 0),
97            ],
98            Face::Down => [
99                Vertex::pack(xyz - packed_xyz(w, 0, 0) + packed_xyz(0, 0, h), w, h),
100                Vertex::pack(xyz - packed_xyz(w, 0, 0), w, 0),
101                Vertex::pack(xyz + packed_xyz(0, 0, h), 0, h),
102                Vertex::pack(xyz, 0, 0),
103            ],
104            Face::Back => [
105                Vertex::pack(xyz, w, h),
106                Vertex::pack(xyz + packed_xyz(0, h, 0), w, 0),
107                Vertex::pack(xyz + packed_xyz(w, 0, 0), 0, h),
108                Vertex::pack(xyz + packed_xyz(w, h, 0), 0, 0),
109            ],
110            Face::Right => [
111                Vertex::pack(xyz, 0, 0),
112                Vertex::pack(xyz + packed_xyz(0, 0, h), h, 0),
113                Vertex::pack(xyz - packed_xyz(0, w, 0), 0, w),
114                Vertex::pack(xyz + packed_xyz(0, 0, h) - packed_xyz(0, w, 0), h, w),
115            ],
116            Face::Up => [
117                Vertex::pack(xyz + packed_xyz(w, 0, h), w, h),
118                Vertex::pack(xyz + packed_xyz(w, 0, 0), w, 0),
119                Vertex::pack(xyz + packed_xyz(0, 0, h), 0, h),
120                Vertex::pack(xyz, 0, 0),
121            ],
122            Face::Front => [
123                Vertex::pack(xyz - packed_xyz(w, 0, 0) + packed_xyz(0, h, 0), 0, 0),
124                Vertex::pack(xyz - packed_xyz(w, 0, 0), 0, h),
125                Vertex::pack(xyz + packed_xyz(0, h, 0), w, 0),
126                Vertex::pack(xyz, w, h),
127            ],
128        }
129    }
130}