ncollide3d/procedural/
capsule.rs

1use super::{sphere, utils};
2use super::{IndexBuffer, TriMesh};
3use na;
4use simba::scalar::RealField;
5
6/// Generates a capsule.
7pub 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    // shift the top
41    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    // flip + shift the bottom
48    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    // flip the bottom normals
55    for normal in bottom_normals.iter_mut() {
56        normal.y = -normal.y;
57    }
58
59    // shift the top index buffer
60    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    // merge all buffers
69    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    // attach the two caps
74    utils::push_ring_indices(0, base_top_coords, ntheta_subdiv, &mut bottom_indices);
75
76    // FIXME: uvs
77    TriMesh::new(
78        bottom_coords,
79        Some(bottom_normals),
80        None,
81        Some(IndexBuffer::Unified(bottom_indices)),
82    )
83}