gl_utils/mesh/
capsule.rs

1use crate::vertex;
2use super::*;
3
4/// (vertex count, index count)
5pub fn lines3d_vertex_index_counts (
6  hemisphere_latitude_divisions : u16, longitude_divisions : u16
7) -> (u32, u32) {
8  let (hemisphere_vertex_count, hemisphere_index_count) =
9    hemisphere::lines3d_vertex_index_counts (
10      hemisphere_latitude_divisions, longitude_divisions);
11  (
12    2 * hemisphere_vertex_count,                               // vertex_count
13    2 * (hemisphere_index_count + longitude_divisions as u32)  // index count
14  )
15}
16
17impl Lines3d {
18  /// Two hemispherical "caps" connected at their equators.
19  ///
20  /// Intended to be scaled first and then each cap translated along the Z axis
21  /// to achieve the correct capsule height.
22  ///
23  /// Can also be used to render a hemisphere or a sphere by slicing the
24  /// corresponding number of indices. Note that the sphere is slightly
25  /// degenerate since there are duplicate vertices on the equator, and so the
26  /// last `2 * longitude_divisions` indices will differ but the total index
27  /// count will be the same.
28  ///
29  /// # Panics
30  ///
31  /// Panics of `hemisphere_latitude_divisions` is zero or if
32  /// `longitude_divisions` is less than two.
33  pub fn capsule (
34    index_offset : u32,
35    hemisphere_latitude_divisions : u16, longitude_divisions : u16
36  ) -> Self {
37    let (num_vertices, num_indices) = lines3d_vertex_index_counts (
38      hemisphere_latitude_divisions, longitude_divisions);
39    let mut vertices
40      = Vec::<vertex::Vert3dInstanced>::with_capacity (num_vertices as usize);
41    let mut indices = Vec::<u32>::with_capacity (num_indices as usize);
42    { // generate upper hemisphere
43      let Lines3d { vertices: mut upper_vertices, indices: mut upper_indices } =
44         Lines3d::hemisphere (
45          index_offset,
46          hemisphere_latitude_divisions,
47          longitude_divisions);
48      vertices.append (&mut upper_vertices);
49      indices.append  (&mut upper_indices);
50    }
51    let hemisphere_vertex_count = vertices.len() as u32;
52    let hemisphere_index_count  = indices.len()  as u32;
53    debug_assert_eq!(
54     (hemisphere_vertex_count, hemisphere_index_count),
55     hemisphere::lines3d_vertex_index_counts (
56      hemisphere_latitude_divisions, longitude_divisions)
57    );
58    { // generate lower hemisphere and flip Z axis
59      let Lines3d { vertices: mut lower_vertices, indices: mut lower_indices } =
60         Lines3d::hemisphere (
61          index_offset + hemisphere_vertex_count,
62          hemisphere_latitude_divisions,
63          longitude_divisions);
64      for vertex in lower_vertices.as_mut_slice() {
65        vertex.inst_position[2] *= -1.0;
66      }
67      vertices.append (&mut lower_vertices);
68      indices.append  (&mut lower_indices);
69    }
70    let double_hemisphere_vertex_count = 2 * hemisphere_vertex_count;
71    // add lines connecting equators of each hemisphere
72    for i in 0..longitude_divisions as u32 {
73      indices.push (index_offset + double_hemisphere_vertex_count - 1 - i);
74      indices.push (index_offset + hemisphere_vertex_count - 1 - i);
75    }
76    debug_assert_eq!(vertices.len(), num_vertices as usize);
77    debug_assert_eq!(indices.len(),  num_indices as usize);
78
79    Lines3d { vertices, indices }
80  }
81}