glam_matrix_extras/
mat_ext.rs1use core::ops::Mul;
2
3#[cfg(feature = "f64")]
4use glam::{DMat2, DMat3, DMat4, DVec2, DVec3, DVec4};
5use glam::{Mat2, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4};
6
7pub trait SquareMatExt {
11 type Vector;
13
14 #[must_use]
16 fn from_outer_product(a: Self::Vector, b: Self::Vector) -> Self;
17
18 #[must_use]
20 fn diagonal(&self) -> Self::Vector;
21
22 #[must_use]
24 fn inverse_or_zero(&self) -> Self;
25
26 #[must_use]
28 fn is_symmetric(&self) -> bool;
29}
30
31impl SquareMatExt for Mat2 {
32 type Vector = Vec2;
33
34 #[inline]
35 fn from_outer_product(a: Vec2, b: Vec2) -> Self {
36 Mat2::from_cols(a * b.x, a * b.y)
37 }
38
39 #[inline]
40 fn inverse_or_zero(&self) -> Self {
41 let inverse = self.inverse();
42 if inverse.is_finite() {
43 inverse
44 } else {
45 Mat2::ZERO
46 }
47 }
48
49 #[inline]
50 fn diagonal(&self) -> Vec2 {
51 Vec2::new(self.x_axis.x, self.y_axis.y)
52 }
53
54 #[inline]
55 fn is_symmetric(&self) -> bool {
56 self.x_axis.y == self.y_axis.x
57 }
58}
59
60#[cfg(feature = "f64")]
61impl SquareMatExt for DMat2 {
62 type Vector = DVec2;
63
64 #[inline]
65 fn from_outer_product(a: DVec2, b: DVec2) -> Self {
66 DMat2::from_cols(a * b.x, a * b.y)
67 }
68
69 #[inline]
70 fn inverse_or_zero(&self) -> Self {
71 let inverse = self.inverse();
72 if inverse.is_finite() {
73 inverse
74 } else {
75 DMat2::ZERO
76 }
77 }
78
79 #[inline]
80 fn diagonal(&self) -> DVec2 {
81 DVec2::new(self.x_axis.x, self.y_axis.y)
82 }
83
84 #[inline]
85 fn is_symmetric(&self) -> bool {
86 self.x_axis.y == self.y_axis.x
87 }
88}
89
90impl SquareMatExt for Mat3 {
91 type Vector = Vec3;
92
93 #[inline]
94 fn from_outer_product(a: Vec3, b: Vec3) -> Self {
95 Mat3::from_cols(a * b.x, a * b.y, a * b.z)
96 }
97
98 #[inline]
99 fn inverse_or_zero(&self) -> Self {
100 let tmp0 = self.y_axis.cross(self.z_axis);
101 let tmp1 = self.z_axis.cross(self.x_axis);
102 let tmp2 = self.x_axis.cross(self.y_axis);
103 let det = self.z_axis.dot(tmp2);
104 if det != 0.0 {
105 let inv_det = Vec3::splat(det.recip());
106 Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose()
107 } else {
108 Mat3::ZERO
109 }
110 }
111
112 #[inline]
113 fn diagonal(&self) -> Vec3 {
114 Vec3::new(self.x_axis.x, self.y_axis.y, self.z_axis.z)
115 }
116
117 #[inline]
118 fn is_symmetric(&self) -> bool {
119 self.x_axis.y == self.y_axis.x
120 && self.x_axis.z == self.z_axis.x
121 && self.y_axis.z == self.z_axis.y
122 }
123}
124
125#[cfg(feature = "f64")]
126impl SquareMatExt for DMat3 {
127 type Vector = DVec3;
128
129 #[inline]
130 fn from_outer_product(a: DVec3, b: DVec3) -> Self {
131 DMat3::from_cols(a * b.x, a * b.y, a * b.z)
132 }
133
134 #[inline]
135 fn inverse_or_zero(&self) -> Self {
136 let tmp0 = self.y_axis.cross(self.z_axis);
137 let tmp1 = self.z_axis.cross(self.x_axis);
138 let tmp2 = self.x_axis.cross(self.y_axis);
139 let det = self.z_axis.dot(tmp2);
140 if det != 0.0 {
141 let inv_det = DVec3::splat(det.recip());
142 Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose()
143 } else {
144 DMat3::ZERO
145 }
146 }
147
148 #[inline]
149 fn diagonal(&self) -> DVec3 {
150 DVec3::new(self.x_axis.x, self.y_axis.y, self.z_axis.z)
151 }
152
153 #[inline]
154 fn is_symmetric(&self) -> bool {
155 self.x_axis.y == self.y_axis.x
156 && self.x_axis.z == self.z_axis.x
157 && self.y_axis.z == self.z_axis.y
158 }
159}
160
161impl SquareMatExt for Mat3A {
162 type Vector = Vec3A;
163
164 #[inline]
165 fn from_outer_product(a: Vec3A, b: Vec3A) -> Self {
166 Mat3A::from_cols(a * b.x, a * b.y, a * b.z)
167 }
168
169 #[inline]
170 fn inverse_or_zero(&self) -> Self {
171 let tmp0 = self.y_axis.cross(self.z_axis);
172 let tmp1 = self.z_axis.cross(self.x_axis);
173 let tmp2 = self.x_axis.cross(self.y_axis);
174 let det = self.z_axis.dot(tmp2);
175 if det != 0.0 {
176 let inv_det = Vec3A::splat(det.recip());
177 Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose()
178 } else {
179 Mat3A::ZERO
180 }
181 }
182
183 #[inline]
184 fn diagonal(&self) -> Vec3A {
185 Vec3A::new(self.x_axis.x, self.y_axis.y, self.z_axis.z)
186 }
187
188 #[inline]
189 fn is_symmetric(&self) -> bool {
190 self.x_axis.y == self.y_axis.x
191 && self.x_axis.z == self.z_axis.x
192 && self.y_axis.z == self.z_axis.y
193 }
194}
195
196impl SquareMatExt for Mat4 {
197 type Vector = Vec4;
198
199 #[inline]
200 fn from_outer_product(a: Vec4, b: Vec4) -> Self {
201 Mat4::from_cols(a * b.x, a * b.y, a * b.z, a * b.w)
202 }
203
204 #[inline]
205 fn inverse_or_zero(&self) -> Self {
206 let inverse = self.inverse();
207 if inverse.is_finite() {
208 inverse
209 } else {
210 Mat4::ZERO
211 }
212 }
213
214 #[inline]
215 fn is_symmetric(&self) -> bool {
216 self.x_axis.y == self.y_axis.x
217 && self.x_axis.z == self.z_axis.x
218 && self.x_axis.w == self.w_axis.x
219 && self.y_axis.z == self.z_axis.y
220 && self.y_axis.w == self.w_axis.y
221 && self.z_axis.w == self.w_axis.z
222 }
223
224 #[inline]
225 fn diagonal(&self) -> Vec4 {
226 Vec4::new(self.x_axis.x, self.y_axis.y, self.z_axis.z, self.w_axis.w)
227 }
228}
229
230#[cfg(feature = "f64")]
231impl SquareMatExt for DMat4 {
232 type Vector = DVec4;
233
234 #[inline]
235 fn from_outer_product(a: DVec4, b: DVec4) -> Self {
236 DMat4::from_cols(a * b.x, a * b.y, a * b.z, a * b.w)
237 }
238
239 #[inline]
240 fn inverse_or_zero(&self) -> Self {
241 let inverse = self.inverse();
242 if inverse.is_finite() {
243 inverse
244 } else {
245 DMat4::ZERO
246 }
247 }
248
249 #[inline]
250 fn is_symmetric(&self) -> bool {
251 self.x_axis.y == self.y_axis.x
252 && self.x_axis.z == self.z_axis.x
253 && self.x_axis.w == self.w_axis.x
254 && self.y_axis.z == self.z_axis.y
255 && self.y_axis.w == self.w_axis.y
256 && self.z_axis.w == self.w_axis.z
257 }
258
259 #[inline]
260 fn diagonal(&self) -> DVec4 {
261 DVec4::new(self.x_axis.x, self.y_axis.y, self.z_axis.z, self.w_axis.w)
262 }
263}