1use bevy::prelude::{IVec3, Vec2, Vec3};
5
6use crate::mesh::block_model::{BlockModelGenerator, BlockOcclusion};
7use crate::vertex_data::TempMesh;
8
9#[rustfmt::skip]
21const CUBE_VERTICES: [(Vec3, Vec3, Vec2); 24] = [
22 (Vec3::new(0.0, 0.0, 0.0), Vec3::new(-1., 0.0, 0.0), Vec2::new(0.0, 0.0)),
24 (Vec3::new(0.0, 0.0, 1.0), Vec3::new(-1., 0.0, 0.0), Vec2::new(0.0, 1.0)),
25 (Vec3::new(0.0, 1.0, 1.0), Vec3::new(-1., 0.0, 0.0), Vec2::new(1.0, 1.0)),
26 (Vec3::new(0.0, 1.0, 0.0), Vec3::new(-1., 0.0, 0.0), Vec2::new(1.0, 0.0)),
27 (Vec3::new(1.0, 0.0, 0.0), Vec3::new(1.0, 0.0, 0.0), Vec2::new(0.0, 0.0)),
29 (Vec3::new(1.0, 1.0, 0.0), Vec3::new(1.0, 0.0, 0.0), Vec2::new(0.0, 1.0)),
30 (Vec3::new(1.0, 1.0, 1.0), Vec3::new(1.0, 0.0, 0.0), Vec2::new(1.0, 1.0)),
31 (Vec3::new(1.0, 0.0, 1.0), Vec3::new(1.0, 0.0, 0.0), Vec2::new(1.0, 0.0)),
32 (Vec3::new(0.0, 0.0, 0.0), Vec3::new(0.0, -1., 0.0), Vec2::new(0.0, 0.0)),
34 (Vec3::new(1.0, 0.0, 0.0), Vec3::new(0.0, -1., 0.0), Vec2::new(0.0, 1.0)),
35 (Vec3::new(1.0, 0.0, 1.0), Vec3::new(0.0, -1., 0.0), Vec2::new(1.0, 1.0)),
36 (Vec3::new(0.0, 0.0, 1.0), Vec3::new(0.0, -1., 0.0), Vec2::new(1.0, 0.0)),
37 (Vec3::new(0.0, 1.0, 0.0), Vec3::new(0.0, 1.0, 0.0), Vec2::new(0.0, 0.0)),
39 (Vec3::new(0.0, 1.0, 1.0), Vec3::new(0.0, 1.0, 0.0), Vec2::new(0.0, 1.0)),
40 (Vec3::new(1.0, 1.0, 1.0), Vec3::new(0.0, 1.0, 0.0), Vec2::new(1.0, 1.0)),
41 (Vec3::new(1.0, 1.0, 0.0), Vec3::new(0.0, 1.0, 0.0), Vec2::new(1.0, 0.0)),
42 (Vec3::new(0.0, 0.0, 0.0), Vec3::new(0.0, 0.0, -1.), Vec2::new(0.0, 0.0)),
44 (Vec3::new(0.0, 1.0, 0.0), Vec3::new(0.0, 0.0, -1.), Vec2::new(0.0, 1.0)),
45 (Vec3::new(1.0, 1.0, 0.0), Vec3::new(0.0, 0.0, -1.), Vec2::new(1.0, 1.0)),
46 (Vec3::new(1.0, 0.0, 0.0), Vec3::new(0.0, 0.0, -1.), Vec2::new(1.0, 0.0)),
47 (Vec3::new(0.0, 0.0, 1.0), Vec3::new(0.0, 0.0, 1.0), Vec2::new(0.0, 0.0)),
49 (Vec3::new(1.0, 0.0, 1.0), Vec3::new(0.0, 0.0, 1.0), Vec2::new(0.0, 1.0)),
50 (Vec3::new(1.0, 1.0, 1.0), Vec3::new(0.0, 0.0, 1.0), Vec2::new(1.0, 1.0)),
51 (Vec3::new(0.0, 1.0, 1.0), Vec3::new(0.0, 0.0, 1.0), Vec2::new(1.0, 0.0)),
52];
53
54const QUAD_INDICES: [u16; 6] = [0, 1, 2, 0, 2, 3];
57
58pub struct CubeModelBuilder {
63 local_pos: Vec3,
65
66 size: Vec3,
68
69 occlusion: BlockOcclusion,
71}
72
73impl CubeModelBuilder {
74 pub fn new() -> Self {
79 Self {
81 local_pos: Vec3::ZERO,
82 size: Vec3::ONE,
83 occlusion: BlockOcclusion::empty(),
84 }
85 }
86
87 pub fn set_pos(mut self, pos: Vec3) -> Self {
91 self.local_pos = pos;
92 self
93 }
94
95 pub fn set_size(mut self, size: Vec3) -> Self {
97 self.size = size;
98 self
99 }
100
101 pub fn set_occlusion(mut self, occlusion: BlockOcclusion) -> Self {
103 self.occlusion = occlusion;
104 self
105 }
106}
107
108impl Default for CubeModelBuilder {
109 fn default() -> Self {
110 Self::new()
111 }
112}
113
114impl BlockModelGenerator for CubeModelBuilder {
115 fn write_to_mesh(&self, mesh: &mut TempMesh, block_pos: IVec3) {
116 let pos = block_pos.as_vec3() + self.local_pos;
117 let size = self.size;
118 let occlusion = self.occlusion;
119
120 let mut quad = |offset: usize| {
121 let vertex_count = mesh.vertices.len() as u16;
122 mesh.indices
123 .extend_from_slice(&QUAD_INDICES.map(|i| i + vertex_count));
124
125 for vert_data in CUBE_VERTICES.iter().skip(offset).take(4) {
126 let (vertex, normal, uv) = *vert_data;
127 mesh.vertices.push(vertex * size + pos);
128 mesh.normals.push(normal);
129 mesh.uvs.push(uv);
130 }
131 };
132
133 if !occlusion.contains(BlockOcclusion::NEG_X) {
134 quad(0);
135 }
136
137 if !occlusion.contains(BlockOcclusion::POS_X) {
138 quad(4);
139 }
140
141 if !occlusion.contains(BlockOcclusion::NEG_Y) {
142 quad(8);
143 }
144
145 if !occlusion.contains(BlockOcclusion::POS_Y) {
146 quad(12);
147 }
148
149 if !occlusion.contains(BlockOcclusion::NEG_Z) {
150 quad(16);
151 }
152
153 if !occlusion.contains(BlockOcclusion::POS_Z) {
154 quad(20);
155 }
156 }
157}
158
159#[cfg(test)]
160mod test {
161 use pretty_assertions::assert_eq;
162
163 use super::*;
164
165 #[test]
166 fn half_slab() {
167 let mut mesh = TempMesh::default();
168 let cube = CubeModelBuilder::new()
169 .set_size(Vec3::new(1.0, 0.5, 1.0))
170 .set_occlusion(BlockOcclusion::NEG_Y);
171
172 cube.write_to_mesh(&mut mesh, IVec3::new(3, 7, 2));
173
174 #[rustfmt::skip]
175 assert_eq!(mesh.vertices, vec![
176 Vec3::new(3.0, 7.0, 2.0), Vec3::new(3.0, 7.0, 3.0),
178 Vec3::new(3.0, 7.5, 3.0), Vec3::new(3.0, 7.5, 2.0),
179 Vec3::new(4.0, 7.0, 2.0), Vec3::new(4.0, 7.5, 2.0),
181 Vec3::new(4.0, 7.5, 3.0), Vec3::new(4.0, 7.0, 3.0),
182 Vec3::new(3.0, 7.5, 2.0), Vec3::new(3.0, 7.5, 3.0),
184 Vec3::new(4.0, 7.5, 3.0), Vec3::new(4.0, 7.5, 2.0),
185 Vec3::new(3.0, 7.0, 2.0), Vec3::new(3.0, 7.5, 2.0),
187 Vec3::new(4.0, 7.5, 2.0), Vec3::new(4.0, 7.0, 2.0),
188 Vec3::new(3.0, 7.0, 3.0), Vec3::new(4.0, 7.0, 3.0),
190 Vec3::new(4.0, 7.5, 3.0), Vec3::new(3.0, 7.5, 3.0),
191 ]);
192
193 #[rustfmt::skip]
194 assert_eq!(mesh.normals, vec![
195 Vec3::new(-1., 0.0, 0.0), Vec3::new(-1., 0.0, 0.0),
197 Vec3::new(-1., 0.0, 0.0), Vec3::new(-1., 0.0, 0.0),
198 Vec3::new(1.0, 0.0, 0.0), Vec3::new(1.0, 0.0, 0.0),
200 Vec3::new(1.0, 0.0, 0.0), Vec3::new(1.0, 0.0, 0.0),
201 Vec3::new(0.0, 1.0, 0.0), Vec3::new(0.0, 1.0, 0.0),
203 Vec3::new(0.0, 1.0, 0.0), Vec3::new(0.0, 1.0, 0.0),
204 Vec3::new(0.0, 0.0, -1.), Vec3::new(0.0, 0.0, -1.),
206 Vec3::new(0.0, 0.0, -1.), Vec3::new(0.0, 0.0, -1.),
207 Vec3::new(0.0, 0.0, 1.0), Vec3::new(0.0, 0.0, 1.0),
209 Vec3::new(0.0, 0.0, 1.0), Vec3::new(0.0, 0.0, 1.0),
210 ]);
211
212 #[rustfmt::skip]
213 assert_eq!(mesh.uvs, vec![
214 Vec2::new(0.0, 0.0), Vec2::new(0.0, 1.0),
216 Vec2::new(1.0, 1.0), Vec2::new(1.0, 0.0),
217 Vec2::new(0.0, 0.0), Vec2::new(0.0, 1.0),
219 Vec2::new(1.0, 1.0), Vec2::new(1.0, 0.0),
220 Vec2::new(0.0, 0.0), Vec2::new(0.0, 1.0),
222 Vec2::new(1.0, 1.0), Vec2::new(1.0, 0.0),
223 Vec2::new(0.0, 0.0), Vec2::new(0.0, 1.0),
225 Vec2::new(1.0, 1.0), Vec2::new(1.0, 0.0),
226 Vec2::new(0.0, 0.0), Vec2::new(0.0, 1.0),
228 Vec2::new(1.0, 1.0), Vec2::new(1.0, 0.0),
229 ]);
230
231 #[rustfmt::skip]
232 assert_eq!(mesh.indices, vec![
233 0, 1, 2, 0, 2, 3,
235 4, 5, 6, 4, 6, 7,
237 8, 9, 10, 8, 10, 11,
239 12, 13, 14, 12, 14, 15,
241 16, 17, 18, 16, 18, 19,
243 ]);
244 }
245}