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_affine3a(&self) -> crate::Affine3A {
458 crate::Affine3A::from_mat3_translation(self.matrix3.as_mat3(), self.translation.as_vec3())
459 }
460}
461
462impl Default for DAffine3 {
463 #[inline(always)]
464 fn default() -> Self {
465 Self::IDENTITY
466 }
467}
468
469impl Deref for DAffine3 {
470 type Target = crate::deref::Cols4<DVec3>;
471 #[inline(always)]
472 fn deref(&self) -> &Self::Target {
473 unsafe { &*(self as *const Self as *const Self::Target) }
474 }
475}
476
477impl DerefMut for DAffine3 {
478 #[inline(always)]
479 fn deref_mut(&mut self) -> &mut Self::Target {
480 unsafe { &mut *(self as *mut Self as *mut Self::Target) }
481 }
482}
483
484impl PartialEq for DAffine3 {
485 #[inline]
486 fn eq(&self, rhs: &Self) -> bool {
487 self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation)
488 }
489}
490
491impl core::fmt::Debug for DAffine3 {
492 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
493 fmt.debug_struct(stringify!(DAffine3))
494 .field("matrix3", &self.matrix3)
495 .field("translation", &self.translation)
496 .finish()
497 }
498}
499
500impl core::fmt::Display for DAffine3 {
501 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
502 if let Some(p) = f.precision() {
503 write!(
504 f,
505 "[{:.*}, {:.*}, {:.*}, {:.*}]",
506 p,
507 self.matrix3.x_axis,
508 p,
509 self.matrix3.y_axis,
510 p,
511 self.matrix3.z_axis,
512 p,
513 self.translation
514 )
515 } else {
516 write!(
517 f,
518 "[{}, {}, {}, {}]",
519 self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation
520 )
521 }
522 }
523}
524
525impl<'a> core::iter::Product<&'a Self> for DAffine3 {
526 fn product<I>(iter: I) -> Self
527 where
528 I: Iterator<Item = &'a Self>,
529 {
530 iter.fold(Self::IDENTITY, |a, &b| a * b)
531 }
532}
533
534impl Mul for DAffine3 {
535 type Output = Self;
536
537 #[inline]
538 fn mul(self, rhs: Self) -> Self {
539 Self {
540 matrix3: self.matrix3 * rhs.matrix3,
541 translation: self.matrix3 * rhs.translation + self.translation,
542 }
543 }
544}
545
546impl Mul<&Self> for DAffine3 {
547 type Output = Self;
548 #[inline]
549 fn mul(self, rhs: &Self) -> Self {
550 self.mul(*rhs)
551 }
552}
553
554impl Mul<&DAffine3> for &DAffine3 {
555 type Output = DAffine3;
556 #[inline]
557 fn mul(self, rhs: &DAffine3) -> DAffine3 {
558 (*self).mul(*rhs)
559 }
560}
561
562impl Mul<DAffine3> for &DAffine3 {
563 type Output = DAffine3;
564 #[inline]
565 fn mul(self, rhs: DAffine3) -> DAffine3 {
566 (*self).mul(rhs)
567 }
568}
569
570impl MulAssign for DAffine3 {
571 #[inline]
572 fn mul_assign(&mut self, rhs: Self) {
573 *self = self.mul(rhs);
574 }
575}
576
577impl MulAssign<&Self> for DAffine3 {
578 #[inline]
579 fn mul_assign(&mut self, rhs: &Self) {
580 self.mul_assign(*rhs);
581 }
582}
583
584impl Mul<DMat4> for DAffine3 {
585 type Output = DMat4;
586
587 #[inline]
588 fn mul(self, rhs: DMat4) -> Self::Output {
589 DMat4::from(self) * rhs
590 }
591}
592
593impl Mul<&DMat4> for DAffine3 {
594 type Output = DMat4;
595 #[inline]
596 fn mul(self, rhs: &DMat4) -> DMat4 {
597 self.mul(*rhs)
598 }
599}
600
601impl Mul<&DMat4> for &DAffine3 {
602 type Output = DMat4;
603 #[inline]
604 fn mul(self, rhs: &DMat4) -> DMat4 {
605 (*self).mul(*rhs)
606 }
607}
608
609impl Mul<DMat4> for &DAffine3 {
610 type Output = DMat4;
611 #[inline]
612 fn mul(self, rhs: DMat4) -> DMat4 {
613 (*self).mul(rhs)
614 }
615}
616
617impl Mul<DAffine3> for DMat4 {
618 type Output = Self;
619
620 #[inline]
621 fn mul(self, rhs: DAffine3) -> Self {
622 self * Self::from(rhs)
623 }
624}
625
626impl Mul<&DAffine3> for DMat4 {
627 type Output = Self;
628 #[inline]
629 fn mul(self, rhs: &DAffine3) -> Self {
630 self.mul(*rhs)
631 }
632}
633
634impl Mul<&DAffine3> for &DMat4 {
635 type Output = DMat4;
636 #[inline]
637 fn mul(self, rhs: &DAffine3) -> DMat4 {
638 (*self).mul(*rhs)
639 }
640}
641
642impl Mul<DAffine3> for &DMat4 {
643 type Output = DMat4;
644 #[inline]
645 fn mul(self, rhs: DAffine3) -> DMat4 {
646 (*self).mul(rhs)
647 }
648}
649
650impl MulAssign<DAffine3> for DMat4 {
651 #[inline]
652 fn mul_assign(&mut self, rhs: DAffine3) {
653 *self = self.mul(rhs);
654 }
655}
656
657impl MulAssign<&DAffine3> for DMat4 {
658 #[inline]
659 fn mul_assign(&mut self, rhs: &DAffine3) {
660 self.mul_assign(*rhs);
661 }
662}
663
664impl From<DAffine3> for DMat4 {
665 #[inline]
666 fn from(m: DAffine3) -> Self {
667 Self::from_cols(
668 m.matrix3.x_axis.extend(0.0),
669 m.matrix3.y_axis.extend(0.0),
670 m.matrix3.z_axis.extend(0.0),
671 m.translation.extend(1.0),
672 )
673 }
674}