1use crate::{DMat3, DMat4, DQuat, DVec3};
4use core::ops::{Deref, DerefMut, Mul, MulAssign};
5
6#[derive(Copy, Clone)]
8#[repr(C)]
9pub struct DAffine3 {
10 pub matrix3: DMat3,
11 pub translation: DVec3,
12}
13
14impl DAffine3 {
15 pub const ZERO: Self = Self {
20 matrix3: DMat3::ZERO,
21 translation: DVec3::ZERO,
22 };
23
24 pub const IDENTITY: Self = Self {
28 matrix3: DMat3::IDENTITY,
29 translation: DVec3::ZERO,
30 };
31
32 pub const NAN: Self = Self {
34 matrix3: DMat3::NAN,
35 translation: DVec3::NAN,
36 };
37
38 #[inline(always)]
40 #[must_use]
41 pub const fn from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3, w_axis: DVec3) -> Self {
42 Self {
43 matrix3: DMat3::from_cols(x_axis, y_axis, z_axis),
44 translation: w_axis,
45 }
46 }
47
48 #[inline]
50 #[must_use]
51 pub fn from_cols_array(m: &[f64; 12]) -> Self {
52 Self {
53 matrix3: DMat3::from_cols_array(&[
54 m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8],
55 ]),
56 translation: DVec3::from_array([m[9], m[10], m[11]]),
57 }
58 }
59
60 #[inline]
62 #[must_use]
63 pub fn to_cols_array(&self) -> [f64; 12] {
64 let x = &self.matrix3.x_axis;
65 let y = &self.matrix3.y_axis;
66 let z = &self.matrix3.z_axis;
67 let w = &self.translation;
68 [x.x, x.y, x.z, y.x, y.y, y.z, z.x, z.y, z.z, w.x, w.y, w.z]
69 }
70
71 #[inline]
76 #[must_use]
77 pub fn from_cols_array_2d(m: &[[f64; 3]; 4]) -> Self {
78 Self {
79 matrix3: DMat3::from_cols(m[0].into(), m[1].into(), m[2].into()),
80 translation: m[3].into(),
81 }
82 }
83
84 #[inline]
88 #[must_use]
89 pub fn to_cols_array_2d(&self) -> [[f64; 3]; 4] {
90 [
91 self.matrix3.x_axis.into(),
92 self.matrix3.y_axis.into(),
93 self.matrix3.z_axis.into(),
94 self.translation.into(),
95 ]
96 }
97
98 #[inline]
104 #[must_use]
105 pub fn from_cols_slice(slice: &[f64]) -> Self {
106 Self {
107 matrix3: DMat3::from_cols_slice(&slice[0..9]),
108 translation: DVec3::from_slice(&slice[9..12]),
109 }
110 }
111
112 #[inline]
118 pub fn write_cols_to_slice(self, slice: &mut [f64]) {
119 self.matrix3.write_cols_to_slice(&mut slice[0..9]);
120 self.translation.write_to_slice(&mut slice[9..12]);
121 }
122
123 #[inline]
126 #[must_use]
127 pub fn from_scale(scale: DVec3) -> Self {
128 Self {
129 matrix3: DMat3::from_diagonal(scale),
130 translation: DVec3::ZERO,
131 }
132 }
133 #[inline]
135 #[must_use]
136 pub fn from_quat(rotation: DQuat) -> Self {
137 Self {
138 matrix3: DMat3::from_quat(rotation),
139 translation: DVec3::ZERO,
140 }
141 }
142
143 #[inline]
146 #[must_use]
147 pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
148 Self {
149 matrix3: DMat3::from_axis_angle(axis, angle),
150 translation: DVec3::ZERO,
151 }
152 }
153
154 #[inline]
157 #[must_use]
158 pub fn from_rotation_x(angle: f64) -> Self {
159 Self {
160 matrix3: DMat3::from_rotation_x(angle),
161 translation: DVec3::ZERO,
162 }
163 }
164
165 #[inline]
168 #[must_use]
169 pub fn from_rotation_y(angle: f64) -> Self {
170 Self {
171 matrix3: DMat3::from_rotation_y(angle),
172 translation: DVec3::ZERO,
173 }
174 }
175
176 #[inline]
179 #[must_use]
180 pub fn from_rotation_z(angle: f64) -> Self {
181 Self {
182 matrix3: DMat3::from_rotation_z(angle),
183 translation: DVec3::ZERO,
184 }
185 }
186
187 #[inline]
189 #[must_use]
190 pub fn from_translation(translation: DVec3) -> Self {
191 #[allow(clippy::useless_conversion)]
192 Self {
193 matrix3: DMat3::IDENTITY,
194 translation: translation.into(),
195 }
196 }
197
198 #[inline]
201 #[must_use]
202 pub fn from_mat3(mat3: DMat3) -> Self {
203 #[allow(clippy::useless_conversion)]
204 Self {
205 matrix3: mat3.into(),
206 translation: DVec3::ZERO,
207 }
208 }
209
210 #[inline]
215 #[must_use]
216 pub fn from_mat3_translation(mat3: DMat3, translation: DVec3) -> Self {
217 #[allow(clippy::useless_conversion)]
218 Self {
219 matrix3: mat3.into(),
220 translation: translation.into(),
221 }
222 }
223
224 #[inline]
230 #[must_use]
231 pub fn from_scale_rotation_translation(
232 scale: DVec3,
233 rotation: DQuat,
234 translation: DVec3,
235 ) -> Self {
236 let rotation = DMat3::from_quat(rotation);
237 #[allow(clippy::useless_conversion)]
238 Self {
239 matrix3: DMat3::from_cols(
240 rotation.x_axis * scale.x,
241 rotation.y_axis * scale.y,
242 rotation.z_axis * scale.z,
243 ),
244 translation: translation.into(),
245 }
246 }
247
248 #[inline]
252 #[must_use]
253 pub fn from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self {
254 #[allow(clippy::useless_conversion)]
255 Self {
256 matrix3: DMat3::from_quat(rotation),
257 translation: translation.into(),
258 }
259 }
260
261 #[inline]
264 #[must_use]
265 pub fn from_mat4(m: DMat4) -> Self {
266 Self {
267 matrix3: DMat3::from_cols(
268 DVec3::from_vec4(m.x_axis),
269 DVec3::from_vec4(m.y_axis),
270 DVec3::from_vec4(m.z_axis),
271 ),
272 translation: DVec3::from_vec4(m.w_axis),
273 }
274 }
275
276 #[inline]
286 #[must_use]
287 pub fn to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3) {
288 use crate::f64::math;
289 let det = self.matrix3.determinant();
290 glam_assert!(det != 0.0);
291
292 let scale = DVec3::new(
293 self.matrix3.x_axis.length() * math::signum(det),
294 self.matrix3.y_axis.length(),
295 self.matrix3.z_axis.length(),
296 );
297
298 glam_assert!(scale.cmpne(DVec3::ZERO).all());
299
300 let inv_scale = scale.recip();
301
302 #[allow(clippy::useless_conversion)]
303 let rotation = DQuat::from_mat3(&DMat3::from_cols(
304 (self.matrix3.x_axis * inv_scale.x).into(),
305 (self.matrix3.y_axis * inv_scale.y).into(),
306 (self.matrix3.z_axis * inv_scale.z).into(),
307 ));
308
309 #[allow(clippy::useless_conversion)]
310 (scale, rotation, self.translation.into())
311 }
312
313 #[inline]
318 #[must_use]
319 pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
320 Self::look_to_rh(eye, -dir, up)
321 }
322
323 #[inline]
328 #[must_use]
329 pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
330 let f = dir.normalize();
331 let s = f.cross(up).normalize();
332 let u = s.cross(f);
333
334 Self {
335 matrix3: DMat3::from_cols(
336 DVec3::new(s.x, u.x, -f.x),
337 DVec3::new(s.y, u.y, -f.y),
338 DVec3::new(s.z, u.z, -f.z),
339 ),
340 translation: DVec3::new(-eye.dot(s), -eye.dot(u), eye.dot(f)),
341 }
342 }
343
344 #[inline]
352 #[must_use]
353 pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
354 glam_assert!(up.is_normalized());
355 Self::look_to_lh(eye, center - eye, up)
356 }
357
358 #[inline]
366 #[must_use]
367 pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
368 glam_assert!(up.is_normalized());
369 Self::look_to_rh(eye, center - eye, up)
370 }
371
372 #[inline]
374 pub fn transform_point3(&self, rhs: DVec3) -> DVec3 {
375 #[allow(clippy::useless_conversion)]
376 ((self.matrix3.x_axis * rhs.x)
377 + (self.matrix3.y_axis * rhs.y)
378 + (self.matrix3.z_axis * rhs.z)
379 + self.translation)
380 .into()
381 }
382
383 #[inline]
388 #[must_use]
389 pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 {
390 #[allow(clippy::useless_conversion)]
391 ((self.matrix3.x_axis * rhs.x)
392 + (self.matrix3.y_axis * rhs.y)
393 + (self.matrix3.z_axis * rhs.z))
394 .into()
395 }
396
397 #[inline]
402 #[must_use]
403 pub fn is_finite(&self) -> bool {
404 self.matrix3.is_finite() && self.translation.is_finite()
405 }
406
407 #[inline]
409 #[must_use]
410 pub fn is_nan(&self) -> bool {
411 self.matrix3.is_nan() || self.translation.is_nan()
412 }
413
414 #[inline]
424 #[must_use]
425 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
426 self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff)
427 && self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
428 }
429
430 #[inline]
434 #[must_use]
435 pub fn inverse(&self) -> Self {
436 let matrix3 = self.matrix3.inverse();
437 let translation = -(matrix3 * self.translation);
439
440 Self {
441 matrix3,
442 translation,
443 }
444 }
445}
446
447impl Default for DAffine3 {
448 #[inline(always)]
449 fn default() -> Self {
450 Self::IDENTITY
451 }
452}
453
454impl Deref for DAffine3 {
455 type Target = crate::deref::Cols4<DVec3>;
456 #[inline(always)]
457 fn deref(&self) -> &Self::Target {
458 unsafe { &*(self as *const Self as *const Self::Target) }
459 }
460}
461
462impl DerefMut for DAffine3 {
463 #[inline(always)]
464 fn deref_mut(&mut self) -> &mut Self::Target {
465 unsafe { &mut *(self as *mut Self as *mut Self::Target) }
466 }
467}
468
469impl PartialEq for DAffine3 {
470 #[inline]
471 fn eq(&self, rhs: &Self) -> bool {
472 self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation)
473 }
474}
475
476impl core::fmt::Debug for DAffine3 {
477 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
478 fmt.debug_struct(stringify!(DAffine3))
479 .field("matrix3", &self.matrix3)
480 .field("translation", &self.translation)
481 .finish()
482 }
483}
484
485impl core::fmt::Display for DAffine3 {
486 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
487 if let Some(p) = f.precision() {
488 write!(
489 f,
490 "[{:.*}, {:.*}, {:.*}, {:.*}]",
491 p,
492 self.matrix3.x_axis,
493 p,
494 self.matrix3.y_axis,
495 p,
496 self.matrix3.z_axis,
497 p,
498 self.translation
499 )
500 } else {
501 write!(
502 f,
503 "[{}, {}, {}, {}]",
504 self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation
505 )
506 }
507 }
508}
509
510impl<'a> core::iter::Product<&'a Self> for DAffine3 {
511 fn product<I>(iter: I) -> Self
512 where
513 I: Iterator<Item = &'a Self>,
514 {
515 iter.fold(Self::IDENTITY, |a, &b| a * b)
516 }
517}
518
519impl Mul for DAffine3 {
520 type Output = DAffine3;
521
522 #[inline]
523 fn mul(self, rhs: DAffine3) -> Self::Output {
524 Self {
525 matrix3: self.matrix3 * rhs.matrix3,
526 translation: self.matrix3 * rhs.translation + self.translation,
527 }
528 }
529}
530
531impl MulAssign for DAffine3 {
532 #[inline]
533 fn mul_assign(&mut self, rhs: DAffine3) {
534 *self = self.mul(rhs);
535 }
536}
537
538impl From<DAffine3> for DMat4 {
539 #[inline]
540 fn from(m: DAffine3) -> DMat4 {
541 DMat4::from_cols(
542 m.matrix3.x_axis.extend(0.0),
543 m.matrix3.y_axis.extend(0.0),
544 m.matrix3.z_axis.extend(0.0),
545 m.translation.extend(1.0),
546 )
547 }
548}
549
550impl Mul<DMat4> for DAffine3 {
551 type Output = DMat4;
552
553 #[inline]
554 fn mul(self, rhs: DMat4) -> Self::Output {
555 DMat4::from(self) * rhs
556 }
557}
558
559impl Mul<DAffine3> for DMat4 {
560 type Output = DMat4;
561
562 #[inline]
563 fn mul(self, rhs: DAffine3) -> Self::Output {
564 self * DMat4::from(rhs)
565 }
566}