graphics/
meshes.rs

1//! This module generates meshes
2
3use std::{
4    collections::HashMap,
5    f32::consts::TAU,
6    fs::File,
7    io::{BufReader, Read},
8};
9
10use lin_alg::f32::Vec3;
11
12use crate::{
13    graphics::UP_VEC,
14    types::{Mesh, Vertex},
15};
16
17/// Rotate a 2d vector counter-clockwise a given angle.
18fn rotate_vec_2d(vec: [f32; 2], θ: f32) -> [f32; 2] {
19    // Self-contained 2d rotation matrix (col-maj)
20    let (sin_θ, cos_θ) = θ.sin_cos();
21    let mat = [cos_θ, sin_θ, -sin_θ, cos_θ];
22
23    [
24        vec[0] * mat[0] + vec[1] * mat[2],
25        vec[0] * mat[1] + vec[1] * mat[3],
26    ]
27}
28
29impl Mesh {
30    // /// Create a triangular face, with no volume. Only visible from one side.
31    // /// Useful for building a grid surface like terrain, or a surface plot.
32    // pub fn new_tri_face(a: [f32; 3], b: [f32; 3], c: [f32; 3]) -> Self {
33    //     let norm = Vec3::new(0., 0., -1.);
34
35    //     let vertices = vec![
36    //         Vertex::new(a, norm),
37    //         Vertex::new(b, norm),
38    //         Vertex::new(c, norm),
39    //     ];
40
41    //     let indices = vec![0, 1, 2];
42
43    //     Self {
44    //         vertices,
45    //         indices,
46    //         material: 0,
47    //     }
48    // }
49
50    /// Create a grid surface of triangles.
51    /// Useful for building a grid surface like terrain, or a surface plot.
52    /// `grid`'s outer vec is rows; inner vec is col-associated values within that
53    /// row. The grid is evenly-spaced.
54    /// todo:  You should draw both sides.
55
56    /// Create a sided surface. Useful as terrain, or as a 2-sided plot.
57    /// Note that the grid is viewed here as x, z, with values in y direction, to be compatible
58    /// with the convention of Z-up used elsewhere.
59    ///
60    /// Points are (x, y, z), with Z being the vertical component. Their indices correspond to how they're
61    /// tied together in a mesh.
62    // pub fn new_surface(grid: &Vec<Vec<f32>>, start: f32, step: f32, two_sided: bool) -> Self {
63    pub fn new_surface(points: &Vec<Vec<Vec3>>, two_sided: bool) -> Self {
64        let mut vertices = Vec::new();
65        let mut indices = Vec::new();
66
67        // let mut x = start;
68        let mut this_vert_i = 0;
69
70        // Note: Y is
71        for (i, rows) in points.into_iter().enumerate() {
72            for (j, point) in rows.into_iter().enumerate() {
73                let x = point.x;
74                let y = point.z; // Swap y and z coords.
75                let z = point.y;
76
77                // for (i, row) in posits.iter().enumerate() {
78                //     let mut z = start;
79                //     for (j, y_posit) in row.into_iter().enumerate() {
80                vertices.push(Vertex::new([x, y, z], Vec3::new_zero()));
81
82                // To understand how we set up the triangles (index buffer),
83                // it's best to draw it out.
84
85                // Upper triangle: This exists for every vertex except
86                // the bottom and right edges.
87                // (grid.length is num_rows)
88                if i != points.len() - 1 && j != rows.len() - 1 {
89                    indices.append(&mut vec![
90                        this_vert_i,
91                        this_vert_i + points.len(),
92                        this_vert_i + 1,
93                    ]);
94                }
95
96                // Lower triangle: This exists for every vertex except
97                // the top and left edges.
98                if i != 0 && j != 0 {
99                    indices.append(&mut vec![
100                        this_vert_i,
101                        this_vert_i - points.len(),
102                        this_vert_i - 1,
103                    ]);
104                }
105
106                // z += step;
107                this_vert_i += 1;
108                // }
109            }
110            // x += step;
111        }
112
113        // Now that we've populated our vertices, update their normals.
114        for i in 0..indices.len() / 3 {
115            let tri_start_i = i * 3;
116            // Find the vertices that make up each triangle.
117            let vert0 = vertices[indices[tri_start_i]];
118            let vert1 = vertices[indices[tri_start_i + 1]];
119            let vert2 = vertices[indices[tri_start_i + 2]];
120
121            // Convert from arrays to Vec3.
122            let v0 = Vec3::new(vert0.position[0], vert0.position[1], vert0.position[2]);
123            let v1 = Vec3::new(vert1.position[0], vert1.position[1], vert1.position[2]);
124            let v2 = Vec3::new(vert2.position[0], vert2.position[1], vert2.position[2]);
125
126            let norm = (v2 - v0).to_normalized().cross((v1 - v0).to_normalized());
127
128            // todo: DRY on this indexing.
129            vertices[indices[tri_start_i]].normal = norm;
130            vertices[indices[tri_start_i + 1]].normal = norm;
131            vertices[indices[tri_start_i + 1]].normal = norm;
132        }
133
134        // If dual-sided, We need to replicate vertices, since the normal will be opposite.
135        // Then, update the index buffer with these new vertices, using the opposite triangle order.
136        if two_sided {
137            let orig_vert_len = vertices.len();
138            let mut vertices_other_side = Vec::new();
139            for vertex in &vertices {
140                let mut new_vertex = vertex.clone();
141                new_vertex.normal *= -1.;
142                vertices_other_side.push(new_vertex);
143            }
144            vertices.append(&mut vertices_other_side);
145
146            let mut new_indices = Vec::new();
147            for i in 0..indices.len() / 3 {
148                let tri_start_i = i * 3;
149                // Opposite direction of first-side indices.
150                new_indices.push(indices[tri_start_i] + orig_vert_len);
151                new_indices.push(indices[tri_start_i + 2] + orig_vert_len);
152                new_indices.push(indices[tri_start_i + 1] + orig_vert_len);
153            }
154            indices.append(&mut new_indices);
155        }
156
157        Self {
158            vertices,
159            indices,
160            material: 0,
161        }
162    }
163
164    /// Creates an isosphere, from subdividing an icosahedron. 2-3 subdivisions works well for most uses.
165    pub fn new_sphere(radius: f32, mut subdivisions: u32) -> Self {
166        if subdivisions > 4 {
167            println!(
168                "Warning: Sphere subdivisions > 4 is not allowed due to extreme performance cost. Setting to 4."
169            );
170            subdivisions = 4;
171        }
172        let mut vertices = Vec::new();
173        let mut indices = Vec::new();
174
175        // Create the initial icosahedron.
176        // 't' is the golden ratio.
177        let t = (1.0 + 5.0_f32.sqrt()) / 2.0;
178
179        let mut initial_points = vec![
180            Vec3::new(-1.0, t, 0.0),
181            Vec3::new(1.0, t, 0.0),
182            Vec3::new(-1.0, -t, 0.0),
183            Vec3::new(1.0, -t, 0.0),
184            Vec3::new(0.0, -1.0, t),
185            Vec3::new(0.0, 1.0, t),
186            Vec3::new(0.0, -1.0, -t),
187            Vec3::new(0.0, 1.0, -t),
188            Vec3::new(t, 0.0, -1.0),
189            Vec3::new(t, 0.0, 1.0),
190            Vec3::new(-t, 0.0, -1.0),
191            Vec3::new(-t, 0.0, 1.0),
192        ];
193
194        // Normalize each vertex to lie on the sphere and scale by the radius.
195        for point in &mut initial_points {
196            *point = point.to_normalized() * radius;
197            vertices.push(Vertex::new(point.to_arr(), point.to_normalized()));
198        }
199
200        // The 20 faces of the icosahedron defined as triangles (each index refers to a vertex).
201        let mut faces = vec![
202            [0, 11, 5],
203            [0, 5, 1],
204            [0, 1, 7],
205            [0, 7, 10],
206            [0, 10, 11],
207            [1, 5, 9],
208            [5, 11, 4],
209            [11, 10, 2],
210            [10, 7, 6],
211            [7, 1, 8],
212            [3, 9, 4],
213            [3, 4, 2],
214            [3, 2, 6],
215            [3, 6, 8],
216            [3, 8, 9],
217            [4, 9, 5],
218            [2, 4, 11],
219            [6, 2, 10],
220            [8, 6, 7],
221            [9, 8, 1],
222        ];
223
224        // Cache to avoid duplicating vertices at the midpoints.
225        let mut middle_point_cache = HashMap::<(usize, usize), usize>::new();
226
227        // Helper closure to get the midpoint between two vertices.
228        // The midpoint is computed, normalized to the sphere and added to the vertex list.
229        let mut get_middle_point = |a: usize, b: usize| -> usize {
230            let key = if a < b { (a, b) } else { (b, a) };
231            if let Some(&index) = middle_point_cache.get(&key) {
232                return index;
233            }
234            let point_a = Vec3::from_slice(&vertices[a].position).unwrap();
235            let point_b = Vec3::from_slice(&vertices[b].position).unwrap();
236            let middle = (point_a + point_b) * 0.5;
237            let normalized = middle.to_normalized() * radius;
238            let index = vertices.len();
239            vertices.push(Vertex::new(normalized.to_arr(), normalized.to_normalized()));
240            middle_point_cache.insert(key, index);
241            index
242        };
243
244        // Subdivide each triangular face.
245        // For each subdivision iteration, every triangle is split into 4 smaller ones.
246        for _ in 0..subdivisions {
247            let mut new_faces = Vec::new();
248            for tri in &faces {
249                let a = tri[0];
250                let b = tri[1];
251                let c = tri[2];
252
253                let ab = get_middle_point(a, b);
254                let bc = get_middle_point(b, c);
255                let ca = get_middle_point(c, a);
256
257                new_faces.push([a, ca, ab]);
258                new_faces.push([b, ab, bc]);
259                new_faces.push([c, bc, ca]);
260                new_faces.push([ab, ca, bc]);
261            }
262            faces = new_faces;
263        }
264
265        // Flatten the faces into the indices vector.
266        for face in &mut faces {
267            if subdivisions % 2 == 0 {
268                let first = face[0];
269                face[0] = face[1];
270                face[1] = first;
271            }
272            indices.extend_from_slice(face);
273        }
274
275        Self {
276            vertices,
277            indices,
278            material: 0,
279        }
280    }
281
282    /// Create a UV sphere mesh. A higher number of latitudes and longitudes results in a
283    /// a smoother sphere.
284    pub fn new_sphere_uv(radius: f32, num_lats: usize, num_lons: usize) -> Self {
285        let mut vertices = Vec::new();
286        // We use faces to construct indices (triangles)
287        let mut faces = Vec::new();
288        let mut indices = Vec::new();
289
290        // In radians
291        let lat_size = TAU / (2. * num_lats as f32);
292        let lon_size = TAU / num_lons as f32;
293
294        let mut current_i = 0;
295
296        // Bottom vertex and faces
297        vertices.push(Vertex::new([0., -radius, 0.], Vec3::new(0., -1., 0.)));
298        current_i += 1;
299
300        // Faces connected to the bottom vertex.
301        for k in 0..num_lons {
302            if k == num_lons - 1 {
303                indices.append(&mut vec![0, k + 2 - num_lons, k + 1]);
304            } else {
305                indices.append(&mut vec![0, k + 2, k + 1]);
306            }
307        }
308
309        // Don't include the top or bottom (0, TAU/2) angles in lats.
310        for i in 1..num_lats {
311            let θ = i as f32 * lat_size;
312
313            for j in 0..num_lons {
314                let φ = j as f32 * lon_size;
315
316                // https://en.wikipedia.org/wiki/Spherical_coordinate_system
317                let x = radius * φ.cos() * θ.sin();
318                let y = radius * φ.sin() * θ.sin();
319                let z = radius * θ.cos();
320
321                vertices.push(Vertex::new([x, y, z], Vec3::new(x, y, z).to_normalized()));
322
323                if i < num_lats - 1 {
324                    // In CCW order
325                    if j == num_lons - 1 {
326                        faces.push([
327                            current_i,
328                            current_i + 1 - num_lons,
329                            current_i + 1,
330                            current_i + num_lons,
331                        ]);
332                    } else {
333                        faces.push([
334                            current_i,
335                            current_i + 1,
336                            current_i + num_lons + 1,
337                            current_i + num_lons,
338                        ]);
339                    }
340                }
341                current_i += 1;
342            }
343        }
344
345        // Top vertex and faces
346        vertices.push(Vertex::new([0., radius, 0.], Vec3::new(0., 1., 0.)));
347
348        // Faces connected to the bottom vertex.
349        let top_ring_start_i = current_i - num_lons;
350
351        // todo: There's a rougue internal triangle on both the top and bottom caps, but it
352        // todo does'nt appear to be visible from the outside. Possibly related: The caps look wrong.
353
354        for k in 0..num_lons {
355            if k == num_lons - 1 {
356                indices.append(&mut vec![current_i, top_ring_start_i + k, top_ring_start_i]);
357            } else {
358                indices.append(&mut vec![
359                    current_i,
360                    top_ring_start_i + k,
361                    top_ring_start_i + k + 1,
362                ]);
363            }
364        }
365
366        for f in faces {
367            indices.append(&mut vec![f[0], f[1], f[2], f[0], f[2], f[3]]);
368        }
369
370        Self {
371            vertices,
372            indices,
373            material: 0,
374        }
375    }
376
377    // todo: Fill this in.
378    // todo: DRY with cylinder
379    pub fn new_ring(len: f32, radius_inner: f32, radius_outer: f32, num_sides: usize) -> Self {
380        let angle_between_vertices = TAU / num_sides as f32;
381
382        let mut circle_vertices_inner = Vec::new();
383        for i in 0..num_sides {
384            circle_vertices_inner.push(rotate_vec_2d(
385                [radius_inner, 0.],
386                i as f32 * angle_between_vertices,
387            ));
388        }
389
390        // todo DRY
391        let mut circle_vertices_outer = Vec::new();
392        for i in 0..num_sides {
393            circle_vertices_outer.push(rotate_vec_2d(
394                [radius_outer, 0.],
395                i as f32 * angle_between_vertices,
396            ));
397        }
398
399        let half_len = len * 0.5;
400        let mod_ = 2 * num_sides;
401
402        let mut vertices = Vec::new();
403        let mut indices = Vec::new();
404
405        let mut i_vertex = 0;
406
407        // Set up the sides
408        for vert in &circle_vertices_inner {
409            // The number of faces is the number of angles - 1.
410            // Triangle 1: This top, this bottom, next top.
411            indices.append(&mut vec![i_vertex, i_vertex + 1, (i_vertex + 2) % mod_]);
412            // Triangle 2: This bottom, next bottom, next top.
413            indices.append(&mut vec![
414                // Note: Order swapped from outer.
415                i_vertex + 1,
416                (i_vertex + 2) % mod_,
417                (i_vertex + 3) % mod_,
418            ]);
419
420            // On edge face, top
421            vertices.push(Vertex::new(
422                [vert[0], half_len, vert[1]],
423                Vec3::new(vert[0], 0., vert[1]).to_normalized(),
424            ));
425            i_vertex += 1;
426
427            // On edge face, bottom
428            vertices.push(Vertex::new(
429                [vert[0], -half_len, vert[1]],
430                Vec3::new(vert[0], 0., vert[1]).to_normalized(),
431            ));
432            i_vertex += 1;
433        }
434
435        // todo DRY!
436        for vert in &circle_vertices_outer {
437            // The number of faces is the number of angles - 1.
438            // Triangle 1: This top, this bottom, next top.
439            indices.append(&mut vec![i_vertex, i_vertex + 1, (i_vertex + 2) % mod_]);
440            // Triangle 2: This bottom, next bottom, next top.
441            indices.append(&mut vec![
442                i_vertex + 1,
443                (i_vertex + 3) % mod_,
444                (i_vertex + 2) % mod_,
445            ]);
446
447            // On edge face, top
448            vertices.push(Vertex::new(
449                [vert[0], half_len, vert[1]],
450                Vec3::new(vert[0], 0., vert[1]).to_normalized(),
451            ));
452            i_vertex += 1;
453
454            // On edge face, bottom
455            vertices.push(Vertex::new(
456                [vert[0], -half_len, vert[1]],
457                Vec3::new(vert[0], 0., vert[1]).to_normalized(),
458            ));
459            i_vertex += 1;
460        }
461
462        let top_anchor = i_vertex;
463        let bottom_anchor = i_vertex + 1;
464
465        // for (j, vert) in circle_vertices_inner.iter().enumerate() {
466        //     // We need num_sides - 2 triangles using this anchor-vertex algorithm.
467        //     if j != 0 && j != num_sides - 1 {
468        //         indices.append(&mut vec![top_anchor, i_vertex, i_vertex + 2]);
469        //         // We need CCW triangles for both, so reverse order on the bottom face.
470        //         indices.append(&mut vec![bottom_anchor, i_vertex + 3, i_vertex + 1]);
471        //     }
472        //
473        //     // Top face
474        //     vertices.push(Vertex::new([vert[0], half_len, vert[1]], UP_VEC));
475        //     i_vertex += 1;
476        //
477        //     // Bottom face
478        //     vertices.push(Vertex::new([vert[0], -half_len, vert[1]], -UP_VEC));
479        //     i_vertex += 1;
480        // }
481
482        Self {
483            vertices,
484            indices,
485            material: 0,
486        }
487    }
488
489    /// Create a box (rectangular prism) mesh.
490    pub fn new_box(len_x: f32, len_y: f32, len_z: f32) -> Self {
491        let x = len_x / 2.;
492        let y = len_y / 2.;
493        let z = len_z / 2.;
494
495        // Aft face
496        let abl = [-x, -y, -z];
497        let abr = [x, -y, -z];
498        let atr = [x, y, -z];
499        let atl = [-x, y, -z];
500
501        // Forward face
502        let fbl = [-x, -y, z];
503        let fbr = [x, -y, z];
504        let ftr = [x, y, z];
505        let ftl = [-x, y, z];
506
507        // Normal vectors
508        let aft = Vec3::new(0., 0., -1.);
509        let fwd = Vec3::new(0., 0., 1.);
510        let l = Vec3::new(-1., 0., 0.);
511        let r = Vec3::new(1., 0., 0.);
512        let t = Vec3::new(0., 1., 0.);
513        let b = Vec3::new(0., -1., 0.);
514
515        let vertices = vec![
516            // Aft
517            Vertex::new(abl, aft),
518            Vertex::new(abr, aft),
519            Vertex::new(atr, aft),
520            Vertex::new(atl, aft),
521            // Fwd
522            Vertex::new(fbl, fwd),
523            Vertex::new(ftl, fwd),
524            Vertex::new(ftr, fwd),
525            Vertex::new(fbr, fwd),
526            // Left
527            Vertex::new(fbl, l),
528            Vertex::new(abl, l),
529            Vertex::new(atl, l),
530            Vertex::new(ftl, l),
531            // Right
532            Vertex::new(abr, r),
533            Vertex::new(fbr, r),
534            Vertex::new(ftr, r),
535            Vertex::new(atr, r),
536            // Top
537            Vertex::new(atl, t),
538            Vertex::new(atr, t),
539            Vertex::new(ftr, t),
540            Vertex::new(ftl, t),
541            // Bottom
542            Vertex::new(abl, b),
543            Vertex::new(fbl, b),
544            Vertex::new(fbr, b),
545            Vertex::new(abr, b),
546        ];
547
548        let faces = [
549            [0, 1, 2, 3],
550            [4, 5, 6, 7],
551            [8, 9, 10, 11],
552            [12, 13, 14, 15],
553            [16, 17, 18, 19],
554            [20, 21, 22, 23],
555        ];
556
557        let mut indices = Vec::new();
558        for face in &faces {
559            indices.append(&mut vec![
560                face[0], face[1], face[2], face[0], face[2], face[3],
561            ]);
562        }
563
564        Self {
565            vertices,
566            indices,
567            material: 0,
568        }
569    }
570
571    /// Create a tetrahedron mesh
572    pub fn new_tetrahedron(side_len: f32) -> Self {
573        let c = side_len / 2.;
574
575        let v_0 = [c, c, c];
576        let v_1 = [c, -c, -c];
577        let v_2 = [-c, c, -c];
578        let v_3 = [-c, -c, c];
579
580        // Note: For tetrahedrons, the normals are the corners of the cube we
581        // didn't use for vertices.
582        let n_0 = Vec3::new(1., 1., -1.).to_normalized();
583        let n_1 = Vec3::new(1., -1., 1.).to_normalized();
584        let n_2 = Vec3::new(-1., 1., 1.).to_normalized();
585        let n_3 = Vec3::new(-1., -1., -1.).to_normalized();
586
587        let vertices = vec![
588            // Face 0
589            Vertex::new(v_0, n_0),
590            Vertex::new(v_2, n_0),
591            Vertex::new(v_1, n_0),
592            // Face 1
593            Vertex::new(v_0, n_1),
594            Vertex::new(v_1, n_1),
595            Vertex::new(v_3, n_1),
596            // Face 2
597            Vertex::new(v_0, n_2),
598            Vertex::new(v_3, n_2),
599            Vertex::new(v_2, n_2),
600            // Face 3
601            Vertex::new(v_1, n_3),
602            Vertex::new(v_2, n_3),
603            Vertex::new(v_3, n_3),
604        ];
605
606        // These indices define faces by triangles. (each 3 represent a triangle, starting at index 0.
607        // Indices are arranged CCW, from front of face
608        // Note that because we're using "hard" lighting on faces, we can't repeat any vertices, since
609        // they each have a different normal.
610        #[rustfmt::skip]
611            // let indices: &[u32] = &[
612            let indices = vec![
613            0, 1, 2,
614            3, 4, 5,
615            6, 7, 8,
616            9, 10, 11,
617        ];
618
619        Self {
620            vertices,
621            indices,
622            // vertex_buffer: Vec<usize>,
623            // index_buffer: Vec<usize>,
624            // num_elements: u32,
625            material: 0,
626        }
627    }
628
629    /// Create a cylinder
630    pub fn new_cylinder(len: f32, radius: f32, num_sides: usize) -> Self {
631        let angle_between_vertices = TAU / num_sides as f32;
632
633        let mut circle_vertices = Vec::new();
634        for i in 0..num_sides {
635            circle_vertices.push(rotate_vec_2d(
636                [radius, 0.],
637                i as f32 * angle_between_vertices,
638            ));
639        }
640
641        let half_len = len * 0.5;
642        let mod_ = 2 * num_sides;
643
644        let mut vertices = Vec::new();
645        let mut indices = Vec::new();
646
647        let mut i_vertex = 0;
648
649        // Set up the sides
650        for vert in &circle_vertices {
651            // The number of faces is the number of angles - 1.
652            // Triangle 1: This top, this bottom, next top.
653            indices.append(&mut vec![i_vertex, i_vertex + 1, (i_vertex + 2) % mod_]);
654            // Triangle 2: This bottom, next bottom, next top.
655            indices.append(&mut vec![
656                i_vertex + 1,
657                (i_vertex + 3) % mod_,
658                (i_vertex + 2) % mod_,
659            ]);
660
661            // On edge face, top
662            vertices.push(Vertex::new(
663                [vert[0], half_len, vert[1]],
664                Vec3::new(vert[0], 0., vert[1]).to_normalized(),
665            ));
666            i_vertex += 1;
667
668            // On edge face, bottom
669            vertices.push(Vertex::new(
670                [vert[0], -half_len, vert[1]],
671                Vec3::new(vert[0], 0., vert[1]).to_normalized(),
672            ));
673            i_vertex += 1;
674        }
675
676        let top_anchor = i_vertex;
677        let bottom_anchor = i_vertex + 1;
678
679        for (j, vert) in circle_vertices.iter().enumerate() {
680            // We need num_sides - 2 triangles using this anchor-vertex algorithm.
681            if j != 0 && j != num_sides - 1 {
682                indices.append(&mut vec![top_anchor, i_vertex, i_vertex + 2]);
683                // We need CCW triangles for both, so reverse order on the bottom face.
684                indices.append(&mut vec![bottom_anchor, i_vertex + 3, i_vertex + 1]);
685            }
686
687            // Top face
688            vertices.push(Vertex::new([vert[0], half_len, vert[1]], UP_VEC));
689            i_vertex += 1;
690
691            // Bottom face
692            vertices.push(Vertex::new([vert[0], -half_len, vert[1]], -UP_VEC));
693            i_vertex += 1;
694        }
695
696        Self {
697            vertices,
698            indices,
699            material: 0,
700        }
701    }
702
703    pub fn new_pyramid(len: f32, radius: f32, num_sides: usize) -> Self {
704        // Note: DRY with cylinder; this is similar, but one of the faces consists of a single, central point.
705        let angle_between_vertices = TAU / num_sides as f32;
706
707        let mut circle_vertices = Vec::new();
708        for i in 0..num_sides {
709            circle_vertices.push(rotate_vec_2d(
710                [radius, 0.],
711                i as f32 * angle_between_vertices,
712            ));
713        }
714
715        let half_len = len * 0.5;
716
717        let mut vertices = Vec::new();
718        let mut indices = Vec::new();
719
720        let tip = 0;
721
722        let mut i_vertex = 0;
723
724        // A central point; the tip of the arrow.
725        vertices.push(Vertex::new([0., half_len, 0.], UP_VEC));
726        i_vertex += 1;
727
728        indices.push(tip);
729
730        // Set up the sides.
731        for (j, vert) in circle_vertices.iter().enumerate() {
732            // The number of faces is the number of angles - 1.
733
734            let next = if j == num_sides - 1 {
735                i_vertex + 1 - num_sides // Wrap to the first.
736            } else {
737                i_vertex + 1
738            };
739            // Triangle: This edge, next edge, central;
740            indices.append(&mut vec![i_vertex, next, tip]);
741
742            vertices.push(Vertex::new(
743                [vert[0], -half_len, vert[1]],
744                Vec3::new(vert[0], len, vert[1]).to_normalized(),
745            ));
746            i_vertex += 1;
747        }
748
749        let bottom_anchor = i_vertex; // An arbitrary point shared by all bottom triangles.
750
751        // Set up the bottom face.
752        for (j, vert) in circle_vertices.iter().enumerate() {
753            // We need num_sides - 2 triangles using this anchor-vertex algorithm.
754            if j != 0 && j != num_sides - 1 {
755                indices.append(&mut vec![bottom_anchor, i_vertex + 1, i_vertex]);
756            }
757
758            vertices.push(Vertex::new([vert[0], -half_len, vert[1]], -UP_VEC));
759            i_vertex += 1;
760        }
761
762        Self {
763            vertices,
764            indices,
765            material: 0,
766        }
767    }
768
769    /// Create an arrow, oriented up.
770    pub fn new_arrow(len: f32, radius: f32, num_sides: usize) -> Self {
771        let tip_offset = len / 2.;
772        let cylinder = Self::new_cylinder(len, radius, num_sides);
773
774        let tip = Self::new_pyramid(len * 0.5, radius * 3., num_sides);
775
776        let mut vertices = cylinder.vertices.clone();
777        let mut indices = cylinder.indices.clone();
778
779        for vertex in tip.vertices {
780            vertices.push(Vertex {
781                position: [
782                    vertex.position[0],
783                    vertex.position[1] + tip_offset,
784                    vertex.position[2],
785                ],
786                ..vertex
787            });
788        }
789
790        let ci2 = cylinder.indices.clone();
791        let tip_start_index = ci2.iter().max().unwrap() + 1;
792
793        for index in tip.indices {
794            indices.push(index + tip_start_index);
795        }
796
797        Self {
798            vertices,
799            indices,
800            material: 0,
801        }
802    }
803
804    /// Load a mesh from obj data.
805    /// [File type description](https://en.wikipedia.org/wiki/Wavefront_.obj_file)
806    /// [Example](https://github.com/gfx-rs/wgpu/blob/master/wgpu/examples/skybox/main.rs)
807    pub fn from_obj(obj_data: &[u8]) -> Self {
808        let data = obj::ObjData::load_buf(&obj_data[..]).unwrap();
809        let mut vertices = Vec::new();
810
811        for object in data.objects {
812            for group in object.groups {
813                vertices.clear();
814
815                for poly in group.polys {
816                    for end_index in 2..poly.0.len() {
817                        for &index in &[0, end_index - 1, end_index] {
818                            let obj::IndexTuple(position_id, _texture_id, normal_id) =
819                                poly.0[index];
820
821                            let n = data.normal[normal_id.unwrap()];
822
823                            vertices.push(Vertex::new(
824                                data.position[position_id],
825                                Vec3::new(n[0], n[1], n[2]),
826                            ));
827                        }
828                    }
829                }
830            }
831        }
832
833        // todo: Is this right?
834        let indices = (0..vertices.len()).collect();
835
836        Self {
837            vertices,
838            indices,
839            material: 0,
840        }
841    }
842
843    /// Load a mesh from a obj file.
844    /// [File type description](https://en.wikipedia.org/wiki/Wavefront_.obj_file)
845    /// [Example](https://github.com/gfx-rs/wgpu/blob/master/wgpu/examples/skybox/main.rs)
846    pub fn from_obj_file(filename: &str) -> Self {
847        // todo: Add a way to load from an obj bytestream etc instead of just file API.
848        let f = File::open(filename).unwrap();
849        let mut reader = BufReader::new(f);
850        let mut file_buf = Vec::new();
851
852        reader.read_to_end(&mut file_buf).unwrap();
853
854        Self::from_obj(&file_buf)
855    }
856}