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 #[deprecated(
326 since = "0.33.1",
327 note = "use the `glam::dcamera::lh::view::look_to_affine3` function instead"
328 )]
329 #[inline]
330 #[must_use]
331 pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
332 #[allow(deprecated)]
333 Self::look_to_rh(eye, -dir, up)
334 }
335
336 #[deprecated(
341 since = "0.33.1",
342 note = "use the `glam::dcamera::rh::view::look_to_affine3` function instead"
343 )]
344 #[inline]
345 #[must_use]
346 pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
347 let f = dir.normalize();
348 let s = f.cross(up).normalize();
349 let u = s.cross(f);
350
351 Self {
352 matrix3: DMat3::from_cols(
353 DVec3::new(s.x, u.x, -f.x),
354 DVec3::new(s.y, u.y, -f.y),
355 DVec3::new(s.z, u.z, -f.z),
356 ),
357 translation: DVec3::new(-eye.dot(s), -eye.dot(u), eye.dot(f)),
358 }
359 }
360
361 #[deprecated(
369 since = "0.33.1",
370 note = "use the `glam::dcamera::lh::view::look_at_affine3` function instead"
371 )]
372 #[inline]
373 #[must_use]
374 pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
375 glam_assert!(up.is_normalized());
376 #[allow(deprecated)]
377 Self::look_to_lh(eye, center - eye, up)
378 }
379
380 #[deprecated(
388 since = "0.33.1",
389 note = "use the `glam::dcamera::rh::view::look_at_affine3` function instead"
390 )]
391 #[inline]
392 #[must_use]
393 pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
394 glam_assert!(up.is_normalized());
395 #[allow(deprecated)]
396 Self::look_to_rh(eye, center - eye, up)
397 }
398
399 #[inline]
401 pub fn transform_point3(&self, rhs: DVec3) -> DVec3 {
402 #[allow(clippy::useless_conversion)]
403 ((self.matrix3.x_axis * rhs.x)
404 + (self.matrix3.y_axis * rhs.y)
405 + (self.matrix3.z_axis * rhs.z)
406 + self.translation)
407 .into()
408 }
409
410 #[inline]
415 #[must_use]
416 pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 {
417 #[allow(clippy::useless_conversion)]
418 ((self.matrix3.x_axis * rhs.x)
419 + (self.matrix3.y_axis * rhs.y)
420 + (self.matrix3.z_axis * rhs.z))
421 .into()
422 }
423
424 #[inline]
429 #[must_use]
430 pub fn is_finite(&self) -> bool {
431 self.matrix3.is_finite() && self.translation.is_finite()
432 }
433
434 #[inline]
436 #[must_use]
437 pub fn is_nan(&self) -> bool {
438 self.matrix3.is_nan() || self.translation.is_nan()
439 }
440
441 #[inline]
451 #[must_use]
452 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
453 self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff)
454 && self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
455 }
456
457 #[inline]
461 #[must_use]
462 pub fn inverse(&self) -> Self {
463 let matrix3 = self.matrix3.inverse();
464 let translation = -(matrix3 * self.translation);
466
467 Self {
468 matrix3,
469 translation,
470 }
471 }
472
473 #[inline]
475 #[must_use]
476 pub fn as_affine3(&self) -> crate::Affine3 {
477 crate::Affine3::from_mat3_translation(self.matrix3.as_mat3(), self.translation.as_vec3())
478 }
479
480 #[inline]
482 #[must_use]
483 pub fn as_affine3a(&self) -> crate::Affine3A {
484 crate::Affine3A::from_mat3_translation(self.matrix3.as_mat3(), self.translation.as_vec3())
485 }
486}
487
488impl Default for DAffine3 {
489 #[inline(always)]
490 fn default() -> Self {
491 Self::IDENTITY
492 }
493}
494
495impl Deref for DAffine3 {
496 type Target = crate::deref::Cols4<DVec3>;
497 #[inline(always)]
498 fn deref(&self) -> &Self::Target {
499 unsafe { &*(self as *const Self as *const Self::Target) }
500 }
501}
502
503impl DerefMut for DAffine3 {
504 #[inline(always)]
505 fn deref_mut(&mut self) -> &mut Self::Target {
506 unsafe { &mut *(self as *mut Self as *mut Self::Target) }
507 }
508}
509
510impl PartialEq for DAffine3 {
511 #[inline]
512 fn eq(&self, rhs: &Self) -> bool {
513 self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation)
514 }
515}
516
517impl core::fmt::Debug for DAffine3 {
518 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
519 fmt.debug_struct(stringify!(DAffine3))
520 .field("matrix3", &self.matrix3)
521 .field("translation", &self.translation)
522 .finish()
523 }
524}
525
526impl core::fmt::Display for DAffine3 {
527 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
528 if let Some(p) = f.precision() {
529 write!(
530 f,
531 "[{:.*}, {:.*}, {:.*}, {:.*}]",
532 p,
533 self.matrix3.x_axis,
534 p,
535 self.matrix3.y_axis,
536 p,
537 self.matrix3.z_axis,
538 p,
539 self.translation
540 )
541 } else {
542 write!(
543 f,
544 "[{}, {}, {}, {}]",
545 self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation
546 )
547 }
548 }
549}
550
551impl<'a> core::iter::Product<&'a Self> for DAffine3 {
552 fn product<I>(iter: I) -> Self
553 where
554 I: Iterator<Item = &'a Self>,
555 {
556 iter.fold(Self::IDENTITY, |a, &b| a * b)
557 }
558}
559
560impl Mul for DAffine3 {
561 type Output = Self;
562
563 #[inline]
564 fn mul(self, rhs: Self) -> Self {
565 Self {
566 matrix3: self.matrix3 * rhs.matrix3,
567 translation: self.matrix3 * rhs.translation + self.translation,
568 }
569 }
570}
571
572impl Mul<&Self> for DAffine3 {
573 type Output = Self;
574 #[inline]
575 fn mul(self, rhs: &Self) -> Self {
576 self.mul(*rhs)
577 }
578}
579
580impl Mul<&DAffine3> for &DAffine3 {
581 type Output = DAffine3;
582 #[inline]
583 fn mul(self, rhs: &DAffine3) -> DAffine3 {
584 (*self).mul(*rhs)
585 }
586}
587
588impl Mul<DAffine3> for &DAffine3 {
589 type Output = DAffine3;
590 #[inline]
591 fn mul(self, rhs: DAffine3) -> DAffine3 {
592 (*self).mul(rhs)
593 }
594}
595
596impl MulAssign for DAffine3 {
597 #[inline]
598 fn mul_assign(&mut self, rhs: Self) {
599 *self = self.mul(rhs);
600 }
601}
602
603impl MulAssign<&Self> for DAffine3 {
604 #[inline]
605 fn mul_assign(&mut self, rhs: &Self) {
606 self.mul_assign(*rhs);
607 }
608}
609
610impl Mul<DMat4> for DAffine3 {
611 type Output = DMat4;
612
613 #[inline]
614 fn mul(self, rhs: DMat4) -> Self::Output {
615 DMat4::from(self) * rhs
616 }
617}
618
619impl Mul<&DMat4> for DAffine3 {
620 type Output = DMat4;
621 #[inline]
622 fn mul(self, rhs: &DMat4) -> DMat4 {
623 self.mul(*rhs)
624 }
625}
626
627impl Mul<&DMat4> for &DAffine3 {
628 type Output = DMat4;
629 #[inline]
630 fn mul(self, rhs: &DMat4) -> DMat4 {
631 (*self).mul(*rhs)
632 }
633}
634
635impl Mul<DMat4> for &DAffine3 {
636 type Output = DMat4;
637 #[inline]
638 fn mul(self, rhs: DMat4) -> DMat4 {
639 (*self).mul(rhs)
640 }
641}
642
643impl Mul<DAffine3> for DMat4 {
644 type Output = Self;
645
646 #[inline]
647 fn mul(self, rhs: DAffine3) -> Self {
648 self * Self::from(rhs)
649 }
650}
651
652impl Mul<&DAffine3> for DMat4 {
653 type Output = Self;
654 #[inline]
655 fn mul(self, rhs: &DAffine3) -> Self {
656 self.mul(*rhs)
657 }
658}
659
660impl Mul<&DAffine3> for &DMat4 {
661 type Output = DMat4;
662 #[inline]
663 fn mul(self, rhs: &DAffine3) -> DMat4 {
664 (*self).mul(*rhs)
665 }
666}
667
668impl Mul<DAffine3> for &DMat4 {
669 type Output = DMat4;
670 #[inline]
671 fn mul(self, rhs: DAffine3) -> DMat4 {
672 (*self).mul(rhs)
673 }
674}
675
676impl MulAssign<DAffine3> for DMat4 {
677 #[inline]
678 fn mul_assign(&mut self, rhs: DAffine3) {
679 *self = self.mul(rhs);
680 }
681}
682
683impl MulAssign<&DAffine3> for DMat4 {
684 #[inline]
685 fn mul_assign(&mut self, rhs: &DAffine3) {
686 self.mul_assign(*rhs);
687 }
688}
689
690impl From<DAffine3> for DMat4 {
691 #[inline]
692 fn from(m: DAffine3) -> Self {
693 Self::from_cols(
694 m.matrix3.x_axis.extend(0.0),
695 m.matrix3.y_axis.extend(0.0),
696 m.matrix3.z_axis.extend(0.0),
697 m.translation.extend(1.0),
698 )
699 }
700}