1use crate::components::Mesh;
2use crate::renderer::Vertex;
3use gizmo_math::Vec3;
4use std::sync::Arc;
5use wgpu::util::DeviceExt;
6
7impl super::AssetManager {
8 pub fn create_tetrahedron(device: &wgpu::Device, size: f32) -> Mesh {
9 let s = size;
10 let p0 = [s, s, s];
11 let p1 = [-s, -s, s];
12 let p2 = [-s, s, -s];
13 let p3 = [s, -s, -s];
14
15 let mut vertices = Vec::new();
16 let faces = [
17 (p0, p1, p2),
18 (p0, p2, p3),
19 (p0, p3, p1),
20 (p1, p3, p2),
21 ];
22
23 let def_j = [0; 4];
24 let def_w = [0.0; 4];
25
26 for (a, b, c) in faces {
27 let va = Vec3::from_array(a);
28 let vb = Vec3::from_array(b);
29 let vc = Vec3::from_array(c);
30 let n = (vc - va).cross(vb - va).normalize();
31 let normal = [n.x, n.y, n.z];
32
33 vertices.push(Vertex { position: a, color: [1.0; 3], normal, tex_coords: [0.0, 0.0], joint_indices: def_j, joint_weights: def_w, ..Default::default() });
34 vertices.push(Vertex { position: b, color: [1.0; 3], normal, tex_coords: [1.0, 0.0], joint_indices: def_j, joint_weights: def_w, ..Default::default() });
35 vertices.push(Vertex { position: c, color: [1.0; 3], normal, tex_coords: [0.5, 1.0], joint_indices: def_j, joint_weights: def_w, ..Default::default() });
36 }
37
38 let vbuf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
39 label: Some("Tetrahedron VBuf"),
40 contents: bytemuck::cast_slice(&vertices),
41 usage: wgpu::BufferUsages::VERTEX,
42 });
43
44 Mesh::new(device, Arc::new(vbuf), &vertices, Vec3::ZERO, "tetrahedron".to_string())
45 }
46
47 pub fn create_conical_frustum(device: &wgpu::Device, radius_bottom: f32, radius_top: f32, height: f32, radial_segments: u32) -> Mesh {
48 let radial_segments = radial_segments.max(3);
49 let mut vertices = Vec::new();
50 let pi = std::f32::consts::PI;
51 let half_h = height / 2.0;
52
53 let def_j = [0; 4]; let def_w = [0.0; 4];
54 let col = [1.0; 3];
55
56 let y_normal = (radius_bottom - radius_top) / height;
57
58 for i in 0..radial_segments {
59 let t1 = (i as f32 / radial_segments as f32) * 2.0 * pi;
60 let t2 = ((i + 1) as f32 / radial_segments as f32) * 2.0 * pi;
61
62 let u1 = i as f32 / radial_segments as f32;
63 let u2 = (i + 1) as f32 / radial_segments as f32;
64
65 let p1_top = [radius_top * t1.cos(), half_h, radius_top * t1.sin()];
66 let p1_bot = [radius_bottom * t1.cos(), -half_h, radius_bottom * t1.sin()];
67 let p2_top = [radius_top * t2.cos(), half_h, radius_top * t2.sin()];
68 let p2_bot = [radius_bottom * t2.cos(), -half_h, radius_bottom * t2.sin()];
69
70 let n1 = Vec3::new(t1.cos(), y_normal, t1.sin()).normalize();
71 let n2 = Vec3::new(t2.cos(), y_normal, t2.sin()).normalize();
72 let n1_arr = [n1.x, n1.y, n1.z];
73 let n2_arr = [n2.x, n2.y, n2.z];
74
75 vertices.push(Vertex { position: p1_top, normal: n1_arr, tex_coords: [u1, 0.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
77 vertices.push(Vertex { position: p1_bot, normal: n1_arr, tex_coords: [u1, 1.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
78 vertices.push(Vertex { position: p2_bot, normal: n2_arr, tex_coords: [u2, 1.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
79
80 vertices.push(Vertex { position: p1_top, normal: n1_arr, tex_coords: [u1, 0.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
81 vertices.push(Vertex { position: p2_bot, normal: n2_arr, tex_coords: [u2, 1.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
82 vertices.push(Vertex { position: p2_top, normal: n2_arr, tex_coords: [u2, 0.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
83
84 vertices.push(Vertex { position: [0.0, half_h, 0.0], normal: [0.0, 1.0, 0.0], tex_coords: [0.5, 0.5], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
86 vertices.push(Vertex { position: p1_top, normal: [0.0, 1.0, 0.0], tex_coords: [0.5 + 0.5 * t1.cos(), 0.5 + 0.5 * t1.sin()], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
87 vertices.push(Vertex { position: p2_top, normal: [0.0, 1.0, 0.0], tex_coords: [0.5 + 0.5 * t2.cos(), 0.5 + 0.5 * t2.sin()], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
88
89 vertices.push(Vertex { position: [0.0, -half_h, 0.0], normal: [0.0, -1.0, 0.0], tex_coords: [0.5, 0.5], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
91 vertices.push(Vertex { position: p2_bot, normal: [0.0, -1.0, 0.0], tex_coords: [0.5 + 0.5 * t2.cos(), 0.5 + 0.5 * t2.sin()], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
92 vertices.push(Vertex { position: p1_bot, normal: [0.0, -1.0, 0.0], tex_coords: [0.5 + 0.5 * t1.cos(), 0.5 + 0.5 * t1.sin()], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
93 }
94
95 let vbuf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
96 label: Some("Conical Frustum VBuf"),
97 contents: bytemuck::cast_slice(&vertices),
98 usage: wgpu::BufferUsages::VERTEX,
99 });
100
101 Mesh::new(device, Arc::new(vbuf), &vertices, Vec3::ZERO, "conical_frustum".to_string())
102 }
103
104 pub fn create_convex_extrusion(device: &wgpu::Device, points_2d: &[[f32; 2]], depth: f32) -> Mesh {
105 let mut vertices = Vec::new();
106 let half_d = depth / 2.0;
107 let def_j = [0; 4]; let def_w = [0.0; 4];
108 let col = [1.0; 3];
109
110 let count = points_2d.len();
111
112 let mut cx = 0.0;
113 let mut cy = 0.0;
114 for p in points_2d {
115 cx += p[0];
116 cy += p[1];
117 }
118 cx /= count as f32;
119 cy /= count as f32;
120
121 for i in 0..count {
122 let p1 = points_2d[i];
123 let p2 = points_2d[(i + 1) % count];
124
125 let dx = p2[0] - p1[0];
126 let dy = p2[1] - p1[1];
127 let len = (dx*dx + dy*dy).sqrt();
128 let nx = dy / len;
129 let ny = -dx / len;
130 let normal = [nx, 0.0, ny];
131
132 let v1_top = [p1[0], half_d, p1[1]];
133 let v1_bot = [p1[0], -half_d, p1[1]];
134 let v2_top = [p2[0], half_d, p2[1]];
135 let v2_bot = [p2[0], -half_d, p2[1]];
136
137 vertices.push(Vertex { position: v1_top, normal, tex_coords: [0.0, 0.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
139 vertices.push(Vertex { position: v1_bot, normal, tex_coords: [0.0, 1.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
140 vertices.push(Vertex { position: v2_bot, normal, tex_coords: [1.0, 1.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
141
142 vertices.push(Vertex { position: v1_top, normal, tex_coords: [0.0, 0.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
143 vertices.push(Vertex { position: v2_bot, normal, tex_coords: [1.0, 1.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
144 vertices.push(Vertex { position: v2_top, normal, tex_coords: [1.0, 0.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
145
146 vertices.push(Vertex { position: [cx, half_d, cy], normal: [0.0, 1.0, 0.0], tex_coords: [0.5, 0.5], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
148 vertices.push(Vertex { position: v1_top, normal: [0.0, 1.0, 0.0], tex_coords: [0.5 + p1[0], 0.5 + p1[1]], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
149 vertices.push(Vertex { position: v2_top, normal: [0.0, 1.0, 0.0], tex_coords: [0.5 + p2[0], 0.5 + p2[1]], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
150
151 vertices.push(Vertex { position: [cx, -half_d, cy], normal: [0.0, -1.0, 0.0], tex_coords: [0.5, 0.5], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
153 vertices.push(Vertex { position: v2_bot, normal: [0.0, -1.0, 0.0], tex_coords: [0.5 + p2[0], 0.5 + p2[1]], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
154 vertices.push(Vertex { position: v1_bot, normal: [0.0, -1.0, 0.0], tex_coords: [0.5 + p1[0], 0.5 + p1[1]], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
155 }
156
157 let vbuf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
158 label: Some("Extrusion VBuf"),
159 contents: bytemuck::cast_slice(&vertices),
160 usage: wgpu::BufferUsages::VERTEX,
161 });
162
163 Mesh::new(device, Arc::new(vbuf), &vertices, Vec3::ZERO, "extrusion".to_string())
164 }
165
166 pub fn create_ring_extrusion(device: &wgpu::Device, inner_points: &[[f32; 2]], outer_points: &[[f32; 2]], depth: f32) -> Mesh {
167 let mut vertices = Vec::new();
168 let half_d = depth / 2.0;
169 let def_j = [0; 4]; let def_w = [0.0; 4];
170 let col = [1.0; 3];
171
172 let count = outer_points.len();
173
174 for i in 0..count {
175 let o1 = outer_points[i];
176 let o2 = outer_points[(i + 1) % count];
177 let i1 = inner_points[i];
178 let i2 = inner_points[(i + 1) % count];
179
180 let dx_o = o2[0] - o1[0]; let dy_o = o2[1] - o1[1];
182 let len_o = (dx_o*dx_o + dy_o*dy_o).sqrt();
183 let nx_o = dy_o / len_o; let ny_o = -dx_o / len_o;
184 let normal_o = [nx_o, 0.0, ny_o];
185
186 let dx_i = i2[0] - i1[0]; let dy_i = i2[1] - i1[1];
188 let len_i = (dx_i*dx_i + dy_i*dy_i).sqrt();
189 let nx_i = -dy_i / len_i; let ny_i = dx_i / len_i;
190 let normal_i = [nx_i, 0.0, ny_i];
191
192 let v_o1_t = [o1[0], half_d, o1[1]]; let v_o1_b = [o1[0], -half_d, o1[1]];
193 let v_o2_t = [o2[0], half_d, o2[1]]; let v_o2_b = [o2[0], -half_d, o2[1]];
194
195 let v_i1_t = [i1[0], half_d, i1[1]]; let v_i1_b = [i1[0], -half_d, i1[1]];
196 let v_i2_t = [i2[0], half_d, i2[1]]; let v_i2_b = [i2[0], -half_d, i2[1]];
197
198 vertices.push(Vertex { position: v_o1_t, normal: normal_o, tex_coords: [0.0, 0.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
200 vertices.push(Vertex { position: v_o1_b, normal: normal_o, tex_coords: [0.0, 1.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
201 vertices.push(Vertex { position: v_o2_b, normal: normal_o, tex_coords: [1.0, 1.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
202
203 vertices.push(Vertex { position: v_o1_t, normal: normal_o, tex_coords: [0.0, 0.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
204 vertices.push(Vertex { position: v_o2_b, normal: normal_o, tex_coords: [1.0, 1.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
205 vertices.push(Vertex { position: v_o2_t, normal: normal_o, tex_coords: [1.0, 0.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
206
207 vertices.push(Vertex { position: v_i2_t, normal: normal_i, tex_coords: [0.0, 0.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
209 vertices.push(Vertex { position: v_i2_b, normal: normal_i, tex_coords: [0.0, 1.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
210 vertices.push(Vertex { position: v_i1_b, normal: normal_i, tex_coords: [1.0, 1.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
211
212 vertices.push(Vertex { position: v_i2_t, normal: normal_i, tex_coords: [0.0, 0.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
213 vertices.push(Vertex { position: v_i1_b, normal: normal_i, tex_coords: [1.0, 1.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
214 vertices.push(Vertex { position: v_i1_t, normal: normal_i, tex_coords: [1.0, 0.0], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
215
216 let n_top = [0.0, 1.0, 0.0];
218 vertices.push(Vertex { position: v_o1_t, normal: n_top, tex_coords: [o1[0], o1[1]], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
219 vertices.push(Vertex { position: v_i1_t, normal: n_top, tex_coords: [i1[0], i1[1]], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
220 vertices.push(Vertex { position: v_o2_t, normal: n_top, tex_coords: [o2[0], o2[1]], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
221
222 vertices.push(Vertex { position: v_o2_t, normal: n_top, tex_coords: [o2[0], o2[1]], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
223 vertices.push(Vertex { position: v_i1_t, normal: n_top, tex_coords: [i1[0], i1[1]], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
224 vertices.push(Vertex { position: v_i2_t, normal: n_top, tex_coords: [i2[0], i2[1]], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
225
226 let n_bot = [0.0, -1.0, 0.0];
228 vertices.push(Vertex { position: v_o1_b, normal: n_bot, tex_coords: [o1[0], o1[1]], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
229 vertices.push(Vertex { position: v_o2_b, normal: n_bot, tex_coords: [o2[0], o2[1]], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
230 vertices.push(Vertex { position: v_i1_b, normal: n_bot, tex_coords: [i1[0], i1[1]], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
231
232 vertices.push(Vertex { position: v_o2_b, normal: n_bot, tex_coords: [o2[0], o2[1]], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
233 vertices.push(Vertex { position: v_i2_b, normal: n_bot, tex_coords: [i2[0], i2[1]], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
234 vertices.push(Vertex { position: v_i1_b, normal: n_bot, tex_coords: [i1[0], i1[1]], color: col, joint_indices: def_j, joint_weights: def_w, ..Default::default() });
235 }
236
237 let vbuf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
238 label: Some("Ring Extrusion VBuf"),
239 contents: bytemuck::cast_slice(&vertices),
240 usage: wgpu::BufferUsages::VERTEX,
241 });
242
243 Mesh::new(device, Arc::new(vbuf), &vertices, Vec3::ZERO, "ring_extrusion".to_string())
244 }
245}