1use crate::d3::Vertex3D;
2
3#[derive(Debug, Copy, Clone, PartialEq)]
4pub struct Box {
5 pub width: f32,
6 pub height: f32,
7 pub depth: f32,
8 pub width_segments: u32,
9 pub height_segments: u32,
10 pub depth_segments: u32,
11}
12
13impl Box {
14 pub fn new(
15 width: f32,
16 height: f32,
17 depth: f32,
18 width_segments: u32,
19 height_segments: u32,
20 depth_segments: u32,
21 ) -> Self {
22 Self {
23 width,
24 height,
25 depth,
26 width_segments,
27 height_segments,
28 depth_segments,
29 }
30 }
31
32 fn vertices(&self) -> Vec<Vertex3D> {
33 let mut vertices = Vec::new();
34
35 build_plane(
36 &mut vertices,
37 2,
38 1,
39 0,
40 -1.,
41 -1.,
42 self.depth,
43 self.height,
44 self.width,
45 self.depth_segments,
46 self.height_segments,
47 );
48 build_plane(
49 &mut vertices,
50 2,
51 1,
52 0,
53 1.,
54 -1.,
55 self.depth,
56 self.height,
57 -self.width,
58 self.depth_segments,
59 self.height_segments,
60 );
61 build_plane(
62 &mut vertices,
63 0,
64 2,
65 1,
66 1.,
67 1.,
68 self.width,
69 self.depth,
70 self.height,
71 self.width_segments,
72 self.depth_segments,
73 );
74 build_plane(
75 &mut vertices,
76 0,
77 2,
78 1,
79 1.,
80 -1.,
81 self.width,
82 self.depth,
83 -self.height,
84 self.width_segments,
85 self.depth_segments,
86 );
87 build_plane(
88 &mut vertices,
89 0,
90 1,
91 2,
92 1.,
93 -1.,
94 self.width,
95 self.height,
96 self.depth,
97 self.width_segments,
98 self.height_segments,
99 );
100 build_plane(
101 &mut vertices,
102 0,
103 1,
104 2,
105 -1.,
106 -1.,
107 self.width,
108 self.height,
109 -self.depth,
110 self.width_segments,
111 self.height_segments,
112 );
113
114 vertices
115 }
116
117 fn indices(&self) -> Vec<u32> {
118 let faces = [
119 (self.depth_segments, self.height_segments),
120 (self.depth_segments, self.height_segments),
121 (self.width_segments, self.depth_segments),
122 (self.width_segments, self.depth_segments),
123 (self.width_segments, self.height_segments),
124 (self.width_segments, self.height_segments),
125 ];
126
127 let mut index_start = 0;
128 let mut indices = Vec::new();
129 for (grid_x, grid_y) in faces.iter().copied() {
130 let grid_x1 = grid_x + 1;
131 for iy in 0..grid_y {
132 for ix in 0..grid_x {
133 let a = ix + grid_x1 * iy;
134 let b = ix + grid_x1 * (iy + 1);
135 let c = (ix + 1) + grid_x1 * (iy + 1);
136 let d = (ix + 1) + grid_x1 * iy;
137
138 indices.push(index_start + a);
139 indices.push(index_start + b);
140 indices.push(index_start + d);
141
142 indices.push(index_start + b);
143 indices.push(index_start + c);
144 indices.push(index_start + d);
145 }
146 }
147 index_start += grid_x * grid_y * 4;
148 }
149
150 indices
151 }
152}
153
154impl Default for Box {
155 fn default() -> Self {
156 Self {
157 width: 1.,
158 height: 1.,
159 depth: 1.,
160 width_segments: 1,
161 height_segments: 1,
162 depth_segments: 1,
163 }
164 }
165}
166
167impl From<&Box> for crate::Geometry<'_, Vertex3D> {
168 fn from(b: &Box) -> Self {
169 Self::new(b.vertices(), Some(b.indices()))
170 }
171}
172
173impl From<Box> for crate::Geometry<'_, Vertex3D> {
174 fn from(b: Box) -> Self {
175 Self::new(b.vertices(), Some(b.indices()))
176 }
177}
178
179fn build_plane(
180 vertices: &mut Vec<Vertex3D>,
181 u: usize,
182 v: usize,
183 w: usize,
184 u_dir: f32,
185 v_dir: f32,
186 width: f32,
187 height: f32,
188 depth: f32,
189 grid_x: u32,
190 grid_y: u32,
191) {
192 let segment_width = width / grid_x as f32;
193 let segment_height = height / grid_y as f32;
194
195 let width_half = width / 2.;
196 let height_half = height / 2.;
197 let depth_half = depth / 2.;
198
199 let grid_x1 = grid_x + 1;
200 let grid_y1 = grid_y + 1;
201
202 for iy in 0..grid_y1 {
203 let iy = iy as f32;
204 let y = iy * segment_height - height_half;
205 for ix in 0..grid_x1 {
206 let ix = ix as f32;
207 let x = ix * segment_width - width_half;
208
209 let mut position = [0f32; 3];
210 position[u] = x * u_dir;
211 position[v] = y * v_dir;
212 position[w] = depth_half;
213
214 let mut normal = [0f32; 3];
215 normal[u] = 0.;
216 normal[v] = 0.;
217 normal[w] = if depth > 0. { 1. } else { -1. };
218
219 vertices.push(Vertex3D {
220 position,
221 normal,
222 uv: [ix / grid_x as f32, iy / grid_y as f32],
223 color: [1., 1., 1., 1.],
224 })
225 }
226 }
227}