Skip to main content

gl_utils/mesh/
capsule.rs

1use crate::vertex;
2use super::*;
3
4/// (vertex count, index count)
5pub const 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 to
21  /// achieve the correct capsule height.
22  ///
23  /// Can also be used to render a hemisphere or a sphere by slicing the corresponding
24  /// number of indices. Note that the sphere is slightly degenerate since there are
25  /// duplicate vertices on the equator, and so the last `2 * longitude_divisions`
26  /// indices will differ but the total index count will be the same.
27  ///
28  /// # Panics
29  ///
30  /// Panics of `hemisphere_latitude_divisions` is zero or if `longitude_divisions` is
31  /// less than two.
32  pub fn capsule (
33    index_offset                  : u32,
34    hemisphere_latitude_divisions : u16,
35    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    { // generate lower hemisphere and flip Z axis
58      let Lines3d { vertices: mut lower_vertices, indices: mut lower_indices } =
59        Lines3d::hemisphere (
60          index_offset + hemisphere_vertex_count,
61          hemisphere_latitude_divisions,
62          longitude_divisions);
63      for vertex in lower_vertices.as_mut_slice() {
64        vertex.inst_position[2] *= -1.0;
65      }
66      vertices.append (&mut lower_vertices);
67      indices.append  (&mut lower_indices);
68    }
69    let double_hemisphere_vertex_count = 2 * hemisphere_vertex_count;
70    // add lines connecting equators of each hemisphere
71    for i in 0..longitude_divisions as u32 {
72      indices.push (index_offset + double_hemisphere_vertex_count - 1 - i);
73      indices.push (index_offset + hemisphere_vertex_count - 1 - i);
74    }
75    debug_assert_eq!(vertices.len(), num_vertices as usize);
76    debug_assert_eq!(indices.len(),  num_indices as usize);
77
78    Lines3d { vertices, indices }
79  }
80}