nphysics3d/algebra/
inertia3.rs1use std::ops::{Add, AddAssign, Mul, Neg};
2
3use crate::algebra::{Force3, Velocity3};
4use na::{self, Isometry3, Matrix3, Matrix6, RealField, U3};
5
6#[derive(Clone, Copy, Debug)]
8pub struct Inertia3<N: RealField + Copy> {
9 pub linear: N,
11 pub angular: Matrix3<N>,
13}
14
15impl<N: RealField + Copy> Inertia3<N> {
16 pub fn new(linear: N, angular: Matrix3<N>) -> Self {
18 Inertia3 { linear, angular }
19 }
20
21 pub fn new_with_angular_matrix(linear: N, angular: Matrix3<N>) -> Self {
23 Self::new(linear, angular)
24 }
25
26 pub fn mass(&self) -> N {
28 self.linear
29 }
30
31 pub fn inv_mass(&self) -> N {
35 if self.linear.is_zero() {
36 N::zero()
37 } else {
38 self.linear
39 }
40 }
41
42 pub fn zero() -> Self {
44 Inertia3::new(na::zero(), na::zero())
45 }
46
47 #[inline]
49 pub fn angular_matrix(&self) -> &Matrix3<N> {
50 &self.angular
51 }
52
53 pub fn to_matrix(&self) -> Matrix6<N> {
57 let mut res = Matrix6::zeros();
58 res.fixed_slice_mut::<3, 3>(3, 3).copy_from(&self.angular);
59
60 res.m11 = self.linear;
61 res.m22 = self.linear;
62 res.m33 = self.linear;
63
64 res
65 }
66
67 pub fn transformed(&self, i: &Isometry3<N>) -> Self {
69 let rot = i.rotation.to_rotation_matrix();
70 Inertia3::new(self.linear, rot * self.angular * rot.inverse())
71 }
72
73 #[cfg(not(feature = "improved_fixed_point_support"))]
77 pub fn inverse(&self) -> Self {
78 let inv_mass = if self.linear.is_zero() {
79 N::zero()
80 } else {
81 N::one() / self.linear
82 };
83
84 let inv_angular = self.angular.try_inverse().unwrap_or_else(na::zero);
85 Inertia3::new(inv_mass, inv_angular)
86 }
87
88 #[cfg(feature = "improved_fixed_point_support")]
89 pub fn inverse(&self) -> Self {
93 let inv_mass = if self.linear.is_zero() {
94 N::zero()
95 } else {
96 N::one() / self.linear
97 };
98
99 let diag = self.angular.diagonal();
102 let mut preconditioned = self.angular;
103
104 for i in 0..3 {
107 if !diag[i].is_zero() {
108 let mut row_i = preconditioned.row_mut(i);
109 row_i /= diag[i];
110 }
111 }
112
113 let mut inv_angular = preconditioned.try_inverse().unwrap_or_else(na::zero);
118
119 for i in 0..3 {
120 if !diag[i].is_zero() {
121 let mut col_i = inv_angular.column_mut(i);
122 col_i /= diag[i];
123 }
124 }
125
126 Inertia3::new(inv_mass, inv_angular)
127 }
128}
129
130impl<N: RealField + Copy> Neg for Inertia3<N> {
131 type Output = Self;
132
133 #[inline]
134 fn neg(self) -> Self {
135 Self::new(-self.linear, -self.angular)
136 }
137}
138
139impl<N: RealField + Copy> Add<Inertia3<N>> for Inertia3<N> {
140 type Output = Inertia3<N>;
141
142 #[inline]
143 fn add(self, rhs: Inertia3<N>) -> Inertia3<N> {
144 Inertia3::new(self.linear + rhs.linear, self.angular + rhs.angular)
145 }
146}
147
148impl<N: RealField + Copy> AddAssign<Inertia3<N>> for Inertia3<N> {
149 #[inline]
150 fn add_assign(&mut self, rhs: Inertia3<N>) {
151 self.linear += rhs.linear;
152 self.angular += rhs.angular;
153 }
154}
155
156impl<N: RealField + Copy> Mul<Velocity3<N>> for Inertia3<N> {
157 type Output = Force3<N>;
158
159 #[inline]
160 fn mul(self, rhs: Velocity3<N>) -> Force3<N> {
161 Force3::new(rhs.linear * self.linear, self.angular * rhs.angular)
162 }
163}
164
165impl<N: RealField + Copy> Mul<Force3<N>> for Inertia3<N> {
167 type Output = Velocity3<N>;
168
169 #[inline]
170 fn mul(self, rhs: Force3<N>) -> Velocity3<N> {
171 Velocity3::new(rhs.linear * self.linear, self.angular * rhs.angular)
172 }
173}