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) -> [i32; 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    pub fn opposite(&self) -> Self {
86        match self {
87            Self::Up => Self::Down,
88            Self::Down => Self::Up,
89            Self::Right => Self::Left,
90            Self::Left => Self::Right,
91            Self::Front => Self::Back,
92            Self::Back => Self::Front,
93        }
94    }
95
96    /// Takes a quad as outputted by binary greedy meshing, and outputs 4 vertices encoded as:
97    /// (v << 24) | (u << 18) | (z << 12) | (y << 6) | x
98    pub fn vertices_packed(&self, quad: Quad) -> [Vertex; 4] {
99        let w = quad.width() as u32;
100        let h = quad.height() as u32;
101        let xyz = (MASK_XYZ & quad.0) as u32;
102        match self {
103            Face::Left => [
104                Vertex::pack(xyz, h, w),
105                Vertex::pack(xyz + packed_xyz(0, 0, h), 0, w),
106                Vertex::pack(xyz + packed_xyz(0, w, 0), h, 0),
107                Vertex::pack(xyz + packed_xyz(0, w, h), 0, 0),
108            ],
109            Face::Down => [
110                Vertex::pack(xyz - packed_xyz(w, 0, 0) + packed_xyz(0, 0, h), w, h),
111                Vertex::pack(xyz - packed_xyz(w, 0, 0), w, 0),
112                Vertex::pack(xyz + packed_xyz(0, 0, h), 0, h),
113                Vertex::pack(xyz, 0, 0),
114            ],
115            Face::Back => [
116                Vertex::pack(xyz, w, h),
117                Vertex::pack(xyz + packed_xyz(0, h, 0), w, 0),
118                Vertex::pack(xyz + packed_xyz(w, 0, 0), 0, h),
119                Vertex::pack(xyz + packed_xyz(w, h, 0), 0, 0),
120            ],
121            Face::Right => [
122                Vertex::pack(xyz, 0, 0),
123                Vertex::pack(xyz + packed_xyz(0, 0, h), h, 0),
124                Vertex::pack(xyz - packed_xyz(0, w, 0), 0, w),
125                Vertex::pack(xyz + packed_xyz(0, 0, h) - packed_xyz(0, w, 0), h, w),
126            ],
127            Face::Up => [
128                Vertex::pack(xyz + packed_xyz(w, 0, h), w, h),
129                Vertex::pack(xyz + packed_xyz(w, 0, 0), w, 0),
130                Vertex::pack(xyz + packed_xyz(0, 0, h), 0, h),
131                Vertex::pack(xyz, 0, 0),
132            ],
133            Face::Front => [
134                Vertex::pack(xyz - packed_xyz(w, 0, 0) + packed_xyz(0, h, 0), 0, 0),
135                Vertex::pack(xyz - packed_xyz(w, 0, 0), 0, h),
136                Vertex::pack(xyz + packed_xyz(0, h, 0), w, 0),
137                Vertex::pack(xyz, w, h),
138            ],
139        }
140    }
141}