ncollide3d/procedural/
capsule.rs
1use super::{sphere, utils};
2use super::{IndexBuffer, TriMesh};
3use na;
4use simba::scalar::RealField;
5
6pub fn capsule<N>(
8 caps_diameter: &N,
9 cylinder_height: &N,
10 ntheta_subdiv: u32,
11 nphi_subdiv: u32,
12) -> TriMesh<N>
13where
14 N: RealField + Copy,
15{
16 let top = sphere::unit_hemisphere::<N>(ntheta_subdiv, nphi_subdiv);
17 let TriMesh {
18 coords,
19 normals,
20 indices,
21 ..
22 } = top.clone();
23 let mut bottom_coords = coords;
24 let mut bottom_normals = normals.unwrap();
25 let mut bottom_indices = indices.unwrap_unified();
26 utils::reverse_clockwising(&mut bottom_indices[..]);
27
28 let TriMesh {
29 coords,
30 normals,
31 indices,
32 ..
33 } = top;
34 let mut top_coords = coords;
35 let top_normals = normals.unwrap();
36 let mut top_indices = indices.unwrap_unified();
37
38 let half_height = *cylinder_height * na::convert(0.5);
39
40 for coord in top_coords.iter_mut() {
42 coord.x = coord.x * *caps_diameter;
43 coord.y = coord.y * *caps_diameter + half_height;
44 coord.z = coord.z * *caps_diameter;
45 }
46
47 for coord in bottom_coords.iter_mut() {
49 coord.x = coord.x * *caps_diameter;
50 coord.y = -(coord.y * *caps_diameter) - half_height;
51 coord.z = coord.z * *caps_diameter;
52 }
53
54 for normal in bottom_normals.iter_mut() {
56 normal.y = -normal.y;
57 }
58
59 let base_top_coords = bottom_coords.len() as u32;
61
62 for idx in top_indices.iter_mut() {
63 idx.x = idx.x + base_top_coords;
64 idx.y = idx.y + base_top_coords;
65 idx.z = idx.z + base_top_coords;
66 }
67
68 bottom_coords.extend(top_coords.into_iter());
70 bottom_normals.extend(top_normals.into_iter());
71 bottom_indices.extend(top_indices.into_iter());
72
73 utils::push_ring_indices(0, base_top_coords, ntheta_subdiv, &mut bottom_indices);
75
76 TriMesh::new(
78 bottom_coords,
79 Some(bottom_normals),
80 None,
81 Some(IndexBuffer::Unified(bottom_indices)),
82 )
83}