parry3d/transformation/to_trimesh/
ball_to_trimesh.rs

1use crate::math::{ComplexField, Real, RealField, Vector, Vector3, DIM};
2use crate::shape::Ball;
3use crate::transformation::utils;
4use alloc::vec::Vec;
5
6impl Ball {
7    /// Discretize the boundary of this ball as a triangle-mesh.
8    pub fn to_trimesh(
9        &self,
10        ntheta_subdiv: u32,
11        nphi_subdiv: u32,
12    ) -> (Vec<Vector3>, Vec<[u32; 3]>) {
13        let diameter = self.radius * 2.0;
14        let (vtx, idx) = unit_sphere(ntheta_subdiv, nphi_subdiv);
15        (utils::scaled(vtx, Vector::splat(diameter)), idx)
16    }
17}
18
19fn unit_sphere(ntheta_subdiv: u32, nphi_subdiv: u32) -> (Vec<Vector3>, Vec<[u32; 3]>) {
20    let dtheta = Real::two_pi() / (ntheta_subdiv as Real);
21    let dphi = Real::pi() / (nphi_subdiv as Real);
22
23    let mut coords = Vec::new();
24    let mut curr_phi: Real = -Real::frac_pi_2() + dphi;
25
26    coords.push(Vector::new(0.0, -1.0, 0.0));
27
28    for _ in 1..nphi_subdiv {
29        utils::push_circle(
30            <Real as ComplexField>::cos(curr_phi),
31            ntheta_subdiv,
32            dtheta,
33            <Real as ComplexField>::sin(curr_phi),
34            &mut coords,
35        );
36        curr_phi += dphi;
37    }
38
39    coords.push(Vector::new(0.0, 1.0, 0.0));
40
41    let mut idx = Vec::new();
42
43    utils::push_degenerate_top_ring_indices(1, 0, ntheta_subdiv, &mut idx);
44    utils::reverse_clockwising(&mut idx);
45
46    for i in 0..nphi_subdiv - 2 {
47        utils::push_ring_indices(
48            1 + i * ntheta_subdiv,
49            1 + (i + 1) * ntheta_subdiv,
50            ntheta_subdiv,
51            &mut idx,
52        );
53    }
54
55    utils::push_degenerate_top_ring_indices(
56        coords.len() as u32 - 1 - ntheta_subdiv,
57        coords.len() as u32 - 1,
58        ntheta_subdiv,
59        &mut idx,
60    );
61
62    (utils::scaled(coords, Vector::splat(0.5)), idx)
63}
64
65/// Creates an hemisphere with a diameter of 1.
66pub(crate) fn unit_hemisphere(
67    ntheta_subdiv: u32,
68    nphi_subdiv: u32,
69) -> (Vec<Vector>, Vec<[u32; DIM]>) {
70    let two_pi = Real::two_pi();
71    let pi_two = Real::frac_pi_2();
72    let dtheta = two_pi / (ntheta_subdiv as Real);
73    let dphi = pi_two / (nphi_subdiv as Real);
74
75    let mut coords = Vec::new();
76    let mut curr_phi: Real = 0.0;
77
78    for _ in 0..nphi_subdiv {
79        utils::push_circle(
80            <Real as ComplexField>::cos(curr_phi),
81            ntheta_subdiv,
82            dtheta,
83            <Real as ComplexField>::sin(curr_phi),
84            &mut coords,
85        );
86        curr_phi += dphi;
87    }
88
89    coords.push(Vector::new(0.0, 1.0, 0.0));
90
91    let mut idx = Vec::new();
92
93    for i in 0..nphi_subdiv - 1 {
94        utils::push_ring_indices(
95            i * ntheta_subdiv,
96            (i + 1) * ntheta_subdiv,
97            ntheta_subdiv,
98            &mut idx,
99        );
100    }
101
102    utils::push_degenerate_top_ring_indices(
103        (nphi_subdiv - 1) * ntheta_subdiv,
104        coords.len() as u32 - 1,
105        ntheta_subdiv,
106        &mut idx,
107    );
108
109    (utils::scaled(coords, Vector::splat(0.5)), idx)
110}