1use crate::{DMat3, DMat4, DQuat, DVec3};
4use core::ops::{Deref, DerefMut, Mul, MulAssign};
5
6#[cfg(feature = "zerocopy")]
7use zerocopy_derive::*;
8
9#[derive(Copy, Clone)]
11#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
12#[cfg_attr(
13 feature = "zerocopy",
14 derive(FromBytes, Immutable, IntoBytes, KnownLayout)
15)]
16#[repr(C)]
17pub struct DAffine3 {
18 pub matrix3: DMat3,
19 pub translation: DVec3,
20}
21
22impl DAffine3 {
23 pub const ZERO: Self = Self {
28 matrix3: DMat3::ZERO,
29 translation: DVec3::ZERO,
30 };
31
32 pub const IDENTITY: Self = Self {
36 matrix3: DMat3::IDENTITY,
37 translation: DVec3::ZERO,
38 };
39
40 pub const NAN: Self = Self {
42 matrix3: DMat3::NAN,
43 translation: DVec3::NAN,
44 };
45
46 #[inline(always)]
48 #[must_use]
49 pub const fn from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3, w_axis: DVec3) -> Self {
50 Self {
51 matrix3: DMat3::from_cols(x_axis, y_axis, z_axis),
52 translation: w_axis,
53 }
54 }
55
56 #[inline]
58 #[must_use]
59 pub fn from_cols_array(m: &[f64; 12]) -> Self {
60 Self {
61 matrix3: DMat3::from_cols_array(&[
62 m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8],
63 ]),
64 translation: DVec3::from_array([m[9], m[10], m[11]]),
65 }
66 }
67
68 #[inline]
70 #[must_use]
71 pub fn to_cols_array(&self) -> [f64; 12] {
72 let x = &self.matrix3.x_axis;
73 let y = &self.matrix3.y_axis;
74 let z = &self.matrix3.z_axis;
75 let w = &self.translation;
76 [x.x, x.y, x.z, y.x, y.y, y.z, z.x, z.y, z.z, w.x, w.y, w.z]
77 }
78
79 #[inline]
84 #[must_use]
85 pub fn from_cols_array_2d(m: &[[f64; 3]; 4]) -> Self {
86 Self {
87 matrix3: DMat3::from_cols(m[0].into(), m[1].into(), m[2].into()),
88 translation: m[3].into(),
89 }
90 }
91
92 #[inline]
96 #[must_use]
97 pub fn to_cols_array_2d(&self) -> [[f64; 3]; 4] {
98 [
99 self.matrix3.x_axis.into(),
100 self.matrix3.y_axis.into(),
101 self.matrix3.z_axis.into(),
102 self.translation.into(),
103 ]
104 }
105
106 #[inline]
112 #[must_use]
113 pub fn from_cols_slice(slice: &[f64]) -> Self {
114 Self {
115 matrix3: DMat3::from_cols_slice(&slice[0..9]),
116 translation: DVec3::from_slice(&slice[9..12]),
117 }
118 }
119
120 #[inline]
126 pub fn write_cols_to_slice(&self, slice: &mut [f64]) {
127 self.matrix3.write_cols_to_slice(&mut slice[0..9]);
128 self.translation.write_to_slice(&mut slice[9..12]);
129 }
130
131 #[inline]
134 #[must_use]
135 pub fn from_scale(scale: DVec3) -> Self {
136 Self {
137 matrix3: DMat3::from_diagonal(scale),
138 translation: DVec3::ZERO,
139 }
140 }
141 #[inline]
143 #[must_use]
144 pub fn from_quat(rotation: DQuat) -> Self {
145 Self {
146 matrix3: DMat3::from_quat(rotation),
147 translation: DVec3::ZERO,
148 }
149 }
150
151 #[inline]
154 #[must_use]
155 pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
156 Self {
157 matrix3: DMat3::from_axis_angle(axis, angle),
158 translation: DVec3::ZERO,
159 }
160 }
161
162 #[inline]
165 #[must_use]
166 pub fn from_rotation_x(angle: f64) -> Self {
167 Self {
168 matrix3: DMat3::from_rotation_x(angle),
169 translation: DVec3::ZERO,
170 }
171 }
172
173 #[inline]
176 #[must_use]
177 pub fn from_rotation_y(angle: f64) -> Self {
178 Self {
179 matrix3: DMat3::from_rotation_y(angle),
180 translation: DVec3::ZERO,
181 }
182 }
183
184 #[inline]
187 #[must_use]
188 pub fn from_rotation_z(angle: f64) -> Self {
189 Self {
190 matrix3: DMat3::from_rotation_z(angle),
191 translation: DVec3::ZERO,
192 }
193 }
194
195 #[inline]
197 #[must_use]
198 pub fn from_translation(translation: DVec3) -> Self {
199 #[allow(clippy::useless_conversion)]
200 Self {
201 matrix3: DMat3::IDENTITY,
202 translation: translation.into(),
203 }
204 }
205
206 #[inline]
209 #[must_use]
210 pub fn from_mat3(mat3: DMat3) -> Self {
211 #[allow(clippy::useless_conversion)]
212 Self {
213 matrix3: mat3.into(),
214 translation: DVec3::ZERO,
215 }
216 }
217
218 #[inline]
223 #[must_use]
224 pub fn from_mat3_translation(mat3: DMat3, translation: DVec3) -> Self {
225 #[allow(clippy::useless_conversion)]
226 Self {
227 matrix3: mat3.into(),
228 translation: translation.into(),
229 }
230 }
231
232 #[inline]
238 #[must_use]
239 pub fn from_scale_rotation_translation(
240 scale: DVec3,
241 rotation: DQuat,
242 translation: DVec3,
243 ) -> Self {
244 let rotation = DMat3::from_quat(rotation);
245 #[allow(clippy::useless_conversion)]
246 Self {
247 matrix3: DMat3::from_cols(
248 rotation.x_axis * scale.x,
249 rotation.y_axis * scale.y,
250 rotation.z_axis * scale.z,
251 ),
252 translation: translation.into(),
253 }
254 }
255
256 #[inline]
260 #[must_use]
261 pub fn from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self {
262 #[allow(clippy::useless_conversion)]
263 Self {
264 matrix3: DMat3::from_quat(rotation),
265 translation: translation.into(),
266 }
267 }
268
269 #[inline]
272 #[must_use]
273 pub fn from_mat4(m: DMat4) -> Self {
274 Self {
275 matrix3: DMat3::from_cols(
276 DVec3::from_vec4(m.x_axis),
277 DVec3::from_vec4(m.y_axis),
278 DVec3::from_vec4(m.z_axis),
279 ),
280 translation: DVec3::from_vec4(m.w_axis),
281 }
282 }
283
284 #[inline]
294 #[must_use]
295 pub fn to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3) {
296 use crate::f64::math;
297 let det = self.matrix3.determinant();
298 glam_assert!(det != 0.0);
299
300 let scale = DVec3::new(
301 self.matrix3.x_axis.length() * math::signum(det),
302 self.matrix3.y_axis.length(),
303 self.matrix3.z_axis.length(),
304 );
305
306 glam_assert!(scale.cmpne(DVec3::ZERO).all());
307
308 let inv_scale = scale.recip();
309
310 #[allow(clippy::useless_conversion)]
311 let rotation = DQuat::from_mat3(&DMat3::from_cols(
312 (self.matrix3.x_axis * inv_scale.x).into(),
313 (self.matrix3.y_axis * inv_scale.y).into(),
314 (self.matrix3.z_axis * inv_scale.z).into(),
315 ));
316
317 #[allow(clippy::useless_conversion)]
318 (scale, rotation, self.translation.into())
319 }
320
321 #[inline]
326 #[must_use]
327 pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
328 Self::look_to_rh(eye, -dir, up)
329 }
330
331 #[inline]
336 #[must_use]
337 pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
338 let f = dir.normalize();
339 let s = f.cross(up).normalize();
340 let u = s.cross(f);
341
342 Self {
343 matrix3: DMat3::from_cols(
344 DVec3::new(s.x, u.x, -f.x),
345 DVec3::new(s.y, u.y, -f.y),
346 DVec3::new(s.z, u.z, -f.z),
347 ),
348 translation: DVec3::new(-eye.dot(s), -eye.dot(u), eye.dot(f)),
349 }
350 }
351
352 #[inline]
360 #[must_use]
361 pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
362 glam_assert!(up.is_normalized());
363 Self::look_to_lh(eye, center - eye, up)
364 }
365
366 #[inline]
374 #[must_use]
375 pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
376 glam_assert!(up.is_normalized());
377 Self::look_to_rh(eye, center - eye, up)
378 }
379
380 #[inline]
382 pub fn transform_point3(&self, rhs: DVec3) -> DVec3 {
383 #[allow(clippy::useless_conversion)]
384 ((self.matrix3.x_axis * rhs.x)
385 + (self.matrix3.y_axis * rhs.y)
386 + (self.matrix3.z_axis * rhs.z)
387 + self.translation)
388 .into()
389 }
390
391 #[inline]
396 #[must_use]
397 pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 {
398 #[allow(clippy::useless_conversion)]
399 ((self.matrix3.x_axis * rhs.x)
400 + (self.matrix3.y_axis * rhs.y)
401 + (self.matrix3.z_axis * rhs.z))
402 .into()
403 }
404
405 #[inline]
410 #[must_use]
411 pub fn is_finite(&self) -> bool {
412 self.matrix3.is_finite() && self.translation.is_finite()
413 }
414
415 #[inline]
417 #[must_use]
418 pub fn is_nan(&self) -> bool {
419 self.matrix3.is_nan() || self.translation.is_nan()
420 }
421
422 #[inline]
432 #[must_use]
433 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
434 self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff)
435 && self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
436 }
437
438 #[inline]
442 #[must_use]
443 pub fn inverse(&self) -> Self {
444 let matrix3 = self.matrix3.inverse();
445 let translation = -(matrix3 * self.translation);
447
448 Self {
449 matrix3,
450 translation,
451 }
452 }
453
454 #[inline]
456 #[must_use]
457 pub fn as_affine3(&self) -> crate::Affine3 {
458 crate::Affine3::from_mat3_translation(self.matrix3.as_mat3(), self.translation.as_vec3())
459 }
460
461 #[inline]
463 #[must_use]
464 pub fn as_affine3a(&self) -> crate::Affine3A {
465 crate::Affine3A::from_mat3_translation(self.matrix3.as_mat3(), self.translation.as_vec3())
466 }
467}
468
469impl Default for DAffine3 {
470 #[inline(always)]
471 fn default() -> Self {
472 Self::IDENTITY
473 }
474}
475
476impl Deref for DAffine3 {
477 type Target = crate::deref::Cols4<DVec3>;
478 #[inline(always)]
479 fn deref(&self) -> &Self::Target {
480 unsafe { &*(self as *const Self as *const Self::Target) }
481 }
482}
483
484impl DerefMut for DAffine3 {
485 #[inline(always)]
486 fn deref_mut(&mut self) -> &mut Self::Target {
487 unsafe { &mut *(self as *mut Self as *mut Self::Target) }
488 }
489}
490
491impl PartialEq for DAffine3 {
492 #[inline]
493 fn eq(&self, rhs: &Self) -> bool {
494 self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation)
495 }
496}
497
498impl core::fmt::Debug for DAffine3 {
499 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
500 fmt.debug_struct(stringify!(DAffine3))
501 .field("matrix3", &self.matrix3)
502 .field("translation", &self.translation)
503 .finish()
504 }
505}
506
507impl core::fmt::Display for DAffine3 {
508 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
509 if let Some(p) = f.precision() {
510 write!(
511 f,
512 "[{:.*}, {:.*}, {:.*}, {:.*}]",
513 p,
514 self.matrix3.x_axis,
515 p,
516 self.matrix3.y_axis,
517 p,
518 self.matrix3.z_axis,
519 p,
520 self.translation
521 )
522 } else {
523 write!(
524 f,
525 "[{}, {}, {}, {}]",
526 self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation
527 )
528 }
529 }
530}
531
532impl<'a> core::iter::Product<&'a Self> for DAffine3 {
533 fn product<I>(iter: I) -> Self
534 where
535 I: Iterator<Item = &'a Self>,
536 {
537 iter.fold(Self::IDENTITY, |a, &b| a * b)
538 }
539}
540
541impl Mul for DAffine3 {
542 type Output = Self;
543
544 #[inline]
545 fn mul(self, rhs: Self) -> Self {
546 Self {
547 matrix3: self.matrix3 * rhs.matrix3,
548 translation: self.matrix3 * rhs.translation + self.translation,
549 }
550 }
551}
552
553impl Mul<&Self> for DAffine3 {
554 type Output = Self;
555 #[inline]
556 fn mul(self, rhs: &Self) -> Self {
557 self.mul(*rhs)
558 }
559}
560
561impl Mul<&DAffine3> for &DAffine3 {
562 type Output = DAffine3;
563 #[inline]
564 fn mul(self, rhs: &DAffine3) -> DAffine3 {
565 (*self).mul(*rhs)
566 }
567}
568
569impl Mul<DAffine3> for &DAffine3 {
570 type Output = DAffine3;
571 #[inline]
572 fn mul(self, rhs: DAffine3) -> DAffine3 {
573 (*self).mul(rhs)
574 }
575}
576
577impl MulAssign for DAffine3 {
578 #[inline]
579 fn mul_assign(&mut self, rhs: Self) {
580 *self = self.mul(rhs);
581 }
582}
583
584impl MulAssign<&Self> for DAffine3 {
585 #[inline]
586 fn mul_assign(&mut self, rhs: &Self) {
587 self.mul_assign(*rhs);
588 }
589}
590
591impl Mul<DMat4> for DAffine3 {
592 type Output = DMat4;
593
594 #[inline]
595 fn mul(self, rhs: DMat4) -> Self::Output {
596 DMat4::from(self) * rhs
597 }
598}
599
600impl Mul<&DMat4> for DAffine3 {
601 type Output = DMat4;
602 #[inline]
603 fn mul(self, rhs: &DMat4) -> DMat4 {
604 self.mul(*rhs)
605 }
606}
607
608impl Mul<&DMat4> for &DAffine3 {
609 type Output = DMat4;
610 #[inline]
611 fn mul(self, rhs: &DMat4) -> DMat4 {
612 (*self).mul(*rhs)
613 }
614}
615
616impl Mul<DMat4> for &DAffine3 {
617 type Output = DMat4;
618 #[inline]
619 fn mul(self, rhs: DMat4) -> DMat4 {
620 (*self).mul(rhs)
621 }
622}
623
624impl Mul<DAffine3> for DMat4 {
625 type Output = Self;
626
627 #[inline]
628 fn mul(self, rhs: DAffine3) -> Self {
629 self * Self::from(rhs)
630 }
631}
632
633impl Mul<&DAffine3> for DMat4 {
634 type Output = Self;
635 #[inline]
636 fn mul(self, rhs: &DAffine3) -> Self {
637 self.mul(*rhs)
638 }
639}
640
641impl Mul<&DAffine3> for &DMat4 {
642 type Output = DMat4;
643 #[inline]
644 fn mul(self, rhs: &DAffine3) -> DMat4 {
645 (*self).mul(*rhs)
646 }
647}
648
649impl Mul<DAffine3> for &DMat4 {
650 type Output = DMat4;
651 #[inline]
652 fn mul(self, rhs: DAffine3) -> DMat4 {
653 (*self).mul(rhs)
654 }
655}
656
657impl MulAssign<DAffine3> for DMat4 {
658 #[inline]
659 fn mul_assign(&mut self, rhs: DAffine3) {
660 *self = self.mul(rhs);
661 }
662}
663
664impl MulAssign<&DAffine3> for DMat4 {
665 #[inline]
666 fn mul_assign(&mut self, rhs: &DAffine3) {
667 self.mul_assign(*rhs);
668 }
669}
670
671impl From<DAffine3> for DMat4 {
672 #[inline]
673 fn from(m: DAffine3) -> Self {
674 Self::from_cols(
675 m.matrix3.x_axis.extend(0.0),
676 m.matrix3.y_axis.extend(0.0),
677 m.matrix3.z_axis.extend(0.0),
678 m.translation.extend(1.0),
679 )
680 }
681}