nphysics3d/volumetric/
volumetric_compound.rs1use num::Zero;
2
3use crate::math::{AngularInertia, Point};
4use crate::volumetric::{InertiaTensor, Volumetric};
5use na::{self, RealField};
6use ncollide::shape::Compound;
7
8impl<N: RealField + Copy> Volumetric<N> for Compound<N> {
9 fn area(&self) -> N {
10 let mut stot: N = na::zero();
11
12 for &(_, ref s) in self.shapes().iter() {
13 stot += s.area()
14 }
15
16 stot
17 }
18
19 fn volume(&self) -> N {
20 let mut vtot: N = na::zero();
21
22 for &(_, ref s) in self.shapes().iter() {
23 vtot += s.volume()
24 }
25
26 vtot
27 }
28
29 fn center_of_mass(&self) -> Point<N> {
30 let mut mtot = N::zero();
31 let mut ctot = Point::origin();
32 let mut gtot = Point::origin(); let shapes = self.shapes();
35
36 for &(ref m, ref s) in shapes.iter() {
37 let (mpart, cpart, _) = s.mass_properties(na::one());
38
39 mtot += mpart;
40 ctot += (*m * cpart * mpart).coords;
41 gtot += (*m * cpart).coords;
42 }
43
44 if mtot.is_zero() {
45 gtot
46 } else {
47 ctot / mtot
48 }
49 }
50
51 fn unit_angular_inertia(&self) -> AngularInertia<N> {
52 let mut itot = AngularInertia::zero();
53
54 let com = self.center_of_mass();
55 let shapes = self.shapes();
56
57 for &(ref m, ref s) in shapes.iter() {
58 let (mpart, cpart, ipart) = s.mass_properties(na::one());
59
60 itot += ipart
61 .to_world_space(m)
62 .to_relative_wrt_point(mpart, &(*m * cpart + (-com.coords)));
63 }
64
65 itot
66 }
67
68 fn mass_properties(&self, density: N) -> (N, Point<N>, AngularInertia<N>) {
73 let mut itot = AngularInertia::zero();
74 let mut ctot = Point::origin();
75 let mut gtot = Point::origin(); let mut mtot = N::zero();
77
78 let shapes = self.shapes();
79 let props: Vec<_> = shapes
80 .iter()
81 .map(|&(_, ref s)| s.mass_properties(na::one()))
82 .collect();
83
84 for (&(ref m, _), &(ref mpart, ref cpart, _)) in shapes.iter().zip(props.iter()) {
85 mtot += *mpart;
86 ctot += (*m * *cpart * *mpart).coords;
87 gtot += (*m * *cpart).coords;
88 }
89
90 if mtot.is_zero() {
91 ctot = gtot;
92 } else {
93 ctot /= mtot;
94 }
95
96 for (&(ref m, _), &(ref mpart, ref cpart, ref ipart)) in shapes.iter().zip(props.iter()) {
97 itot += ipart
98 .to_world_space(m)
99 .to_relative_wrt_point(*mpart, &(*m * *cpart + (-ctot.coords)));
100 }
101
102 (mtot * density, ctot, itot * density)
103 }
104}