1use crate::{Mat3, Mat3A, Mat4, Quat, Vec3, Vec3A};
4use core::ops::{Deref, DerefMut, Mul, MulAssign};
5
6#[cfg(all(feature = "zerocopy", not(feature = "core-simd")))]
7use zerocopy_derive::*;
8
9#[derive(Copy, Clone)]
13#[cfg_attr(feature = "bytemuck", derive(bytemuck::AnyBitPattern))]
14#[cfg_attr(
15 all(feature = "zerocopy", not(feature = "core-simd")),
16 derive(FromBytes, Immutable, KnownLayout)
17)]
18#[cfg_attr(
19 all(
20 feature = "zerocopy",
21 any(
22 target_arch = "aarch64",
23 target_feature = "sse2",
24 target_feature = "simd128"
25 ),
26 not(any(feature = "core-simd", feature = "scalar-math"))
27 ),
28 derive(IntoBytes)
29)]
30#[repr(C)]
31pub struct Affine3A {
32 pub matrix3: Mat3A,
33 pub translation: Vec3A,
34}
35
36impl Affine3A {
37 pub const ZERO: Self = Self {
42 matrix3: Mat3A::ZERO,
43 translation: Vec3A::ZERO,
44 };
45
46 pub const IDENTITY: Self = Self {
50 matrix3: Mat3A::IDENTITY,
51 translation: Vec3A::ZERO,
52 };
53
54 pub const NAN: Self = Self {
56 matrix3: Mat3A::NAN,
57 translation: Vec3A::NAN,
58 };
59
60 #[inline(always)]
62 #[must_use]
63 pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A, w_axis: Vec3A) -> Self {
64 Self {
65 matrix3: Mat3A::from_cols(x_axis, y_axis, z_axis),
66 translation: w_axis,
67 }
68 }
69
70 #[inline]
72 #[must_use]
73 pub fn from_cols_array(m: &[f32; 12]) -> Self {
74 Self {
75 matrix3: Mat3A::from_cols_array(&[
76 m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8],
77 ]),
78 translation: Vec3A::from_array([m[9], m[10], m[11]]),
79 }
80 }
81
82 #[inline]
84 #[must_use]
85 pub fn to_cols_array(&self) -> [f32; 12] {
86 let x = &self.matrix3.x_axis;
87 let y = &self.matrix3.y_axis;
88 let z = &self.matrix3.z_axis;
89 let w = &self.translation;
90 [x.x, x.y, x.z, y.x, y.y, y.z, z.x, z.y, z.z, w.x, w.y, w.z]
91 }
92
93 #[inline]
98 #[must_use]
99 pub fn from_cols_array_2d(m: &[[f32; 3]; 4]) -> Self {
100 Self {
101 matrix3: Mat3A::from_cols(m[0].into(), m[1].into(), m[2].into()),
102 translation: m[3].into(),
103 }
104 }
105
106 #[inline]
110 #[must_use]
111 pub fn to_cols_array_2d(&self) -> [[f32; 3]; 4] {
112 [
113 self.matrix3.x_axis.into(),
114 self.matrix3.y_axis.into(),
115 self.matrix3.z_axis.into(),
116 self.translation.into(),
117 ]
118 }
119
120 #[inline]
126 #[must_use]
127 pub fn from_cols_slice(slice: &[f32]) -> Self {
128 Self {
129 matrix3: Mat3A::from_cols_slice(&slice[0..9]),
130 translation: Vec3A::from_slice(&slice[9..12]),
131 }
132 }
133
134 #[inline]
140 pub fn write_cols_to_slice(self, slice: &mut [f32]) {
141 self.matrix3.write_cols_to_slice(&mut slice[0..9]);
142 self.translation.write_to_slice(&mut slice[9..12]);
143 }
144
145 #[inline]
148 #[must_use]
149 pub fn from_scale(scale: Vec3) -> Self {
150 Self {
151 matrix3: Mat3A::from_diagonal(scale),
152 translation: Vec3A::ZERO,
153 }
154 }
155 #[inline]
157 #[must_use]
158 pub fn from_quat(rotation: Quat) -> Self {
159 Self {
160 matrix3: Mat3A::from_quat(rotation),
161 translation: Vec3A::ZERO,
162 }
163 }
164
165 #[inline]
168 #[must_use]
169 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
170 Self {
171 matrix3: Mat3A::from_axis_angle(axis, angle),
172 translation: Vec3A::ZERO,
173 }
174 }
175
176 #[inline]
179 #[must_use]
180 pub fn from_rotation_x(angle: f32) -> Self {
181 Self {
182 matrix3: Mat3A::from_rotation_x(angle),
183 translation: Vec3A::ZERO,
184 }
185 }
186
187 #[inline]
190 #[must_use]
191 pub fn from_rotation_y(angle: f32) -> Self {
192 Self {
193 matrix3: Mat3A::from_rotation_y(angle),
194 translation: Vec3A::ZERO,
195 }
196 }
197
198 #[inline]
201 #[must_use]
202 pub fn from_rotation_z(angle: f32) -> Self {
203 Self {
204 matrix3: Mat3A::from_rotation_z(angle),
205 translation: Vec3A::ZERO,
206 }
207 }
208
209 #[inline]
211 #[must_use]
212 pub fn from_translation(translation: Vec3) -> Self {
213 #[allow(clippy::useless_conversion)]
214 Self {
215 matrix3: Mat3A::IDENTITY,
216 translation: translation.into(),
217 }
218 }
219
220 #[inline]
223 #[must_use]
224 pub fn from_mat3(mat3: Mat3) -> Self {
225 #[allow(clippy::useless_conversion)]
226 Self {
227 matrix3: mat3.into(),
228 translation: Vec3A::ZERO,
229 }
230 }
231
232 #[inline]
237 #[must_use]
238 pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
239 #[allow(clippy::useless_conversion)]
240 Self {
241 matrix3: mat3.into(),
242 translation: translation.into(),
243 }
244 }
245
246 #[inline]
252 #[must_use]
253 pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
254 let rotation = Mat3A::from_quat(rotation);
255 #[allow(clippy::useless_conversion)]
256 Self {
257 matrix3: Mat3A::from_cols(
258 rotation.x_axis * scale.x,
259 rotation.y_axis * scale.y,
260 rotation.z_axis * scale.z,
261 ),
262 translation: translation.into(),
263 }
264 }
265
266 #[inline]
270 #[must_use]
271 pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
272 #[allow(clippy::useless_conversion)]
273 Self {
274 matrix3: Mat3A::from_quat(rotation),
275 translation: translation.into(),
276 }
277 }
278
279 #[inline]
282 #[must_use]
283 pub fn from_mat4(m: Mat4) -> Self {
284 Self {
285 matrix3: Mat3A::from_cols(
286 Vec3A::from_vec4(m.x_axis),
287 Vec3A::from_vec4(m.y_axis),
288 Vec3A::from_vec4(m.z_axis),
289 ),
290 translation: Vec3A::from_vec4(m.w_axis),
291 }
292 }
293
294 #[inline]
304 #[must_use]
305 pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
306 use crate::f32::math;
307 let det = self.matrix3.determinant();
308 glam_assert!(det != 0.0);
309
310 let scale = Vec3::new(
311 self.matrix3.x_axis.length() * math::signum(det),
312 self.matrix3.y_axis.length(),
313 self.matrix3.z_axis.length(),
314 );
315
316 glam_assert!(scale.cmpne(Vec3::ZERO).all());
317
318 let inv_scale = scale.recip();
319
320 #[allow(clippy::useless_conversion)]
321 let rotation = Quat::from_mat3(&Mat3::from_cols(
322 (self.matrix3.x_axis * inv_scale.x).into(),
323 (self.matrix3.y_axis * inv_scale.y).into(),
324 (self.matrix3.z_axis * inv_scale.z).into(),
325 ));
326
327 #[allow(clippy::useless_conversion)]
328 (scale, rotation, self.translation.into())
329 }
330
331 #[inline]
336 #[must_use]
337 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
338 Self::look_to_rh(eye, -dir, up)
339 }
340
341 #[inline]
346 #[must_use]
347 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
348 let f = dir.normalize();
349 let s = f.cross(up).normalize();
350 let u = s.cross(f);
351
352 Self {
353 matrix3: Mat3A::from_cols(
354 Vec3A::new(s.x, u.x, -f.x),
355 Vec3A::new(s.y, u.y, -f.y),
356 Vec3A::new(s.z, u.z, -f.z),
357 ),
358 translation: Vec3A::new(-eye.dot(s), -eye.dot(u), eye.dot(f)),
359 }
360 }
361
362 #[inline]
370 #[must_use]
371 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
372 glam_assert!(up.is_normalized());
373 Self::look_to_lh(eye, center - eye, up)
374 }
375
376 #[inline]
384 #[must_use]
385 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
386 glam_assert!(up.is_normalized());
387 Self::look_to_rh(eye, center - eye, up)
388 }
389
390 #[inline]
392 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
393 #[allow(clippy::useless_conversion)]
394 ((self.matrix3.x_axis * rhs.x)
395 + (self.matrix3.y_axis * rhs.y)
396 + (self.matrix3.z_axis * rhs.z)
397 + self.translation)
398 .into()
399 }
400
401 #[inline]
406 #[must_use]
407 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
408 #[allow(clippy::useless_conversion)]
409 ((self.matrix3.x_axis * rhs.x)
410 + (self.matrix3.y_axis * rhs.y)
411 + (self.matrix3.z_axis * rhs.z))
412 .into()
413 }
414
415 #[inline]
417 #[must_use]
418 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
419 self.matrix3 * rhs + self.translation
420 }
421
422 #[inline]
427 #[must_use]
428 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
429 self.matrix3 * rhs
430 }
431
432 #[inline]
437 #[must_use]
438 pub fn is_finite(&self) -> bool {
439 self.matrix3.is_finite() && self.translation.is_finite()
440 }
441
442 #[inline]
444 #[must_use]
445 pub fn is_nan(&self) -> bool {
446 self.matrix3.is_nan() || self.translation.is_nan()
447 }
448
449 #[inline]
459 #[must_use]
460 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
461 self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff)
462 && self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
463 }
464
465 #[inline]
469 #[must_use]
470 pub fn inverse(&self) -> Self {
471 let matrix3 = self.matrix3.inverse();
472 let translation = -(matrix3 * self.translation);
474
475 Self {
476 matrix3,
477 translation,
478 }
479 }
480
481 #[inline]
483 #[must_use]
484 pub fn as_daffine3(&self) -> crate::DAffine3 {
485 crate::DAffine3::from_mat3_translation(self.matrix3.as_dmat3(), self.translation.as_dvec3())
486 }
487}
488
489impl Default for Affine3A {
490 #[inline(always)]
491 fn default() -> Self {
492 Self::IDENTITY
493 }
494}
495
496impl Deref for Affine3A {
497 type Target = crate::deref::Cols4<Vec3A>;
498 #[inline(always)]
499 fn deref(&self) -> &Self::Target {
500 unsafe { &*(self as *const Self as *const Self::Target) }
501 }
502}
503
504impl DerefMut for Affine3A {
505 #[inline(always)]
506 fn deref_mut(&mut self) -> &mut Self::Target {
507 unsafe { &mut *(self as *mut Self as *mut Self::Target) }
508 }
509}
510
511impl PartialEq for Affine3A {
512 #[inline]
513 fn eq(&self, rhs: &Self) -> bool {
514 self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation)
515 }
516}
517
518impl core::fmt::Debug for Affine3A {
519 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
520 fmt.debug_struct(stringify!(Affine3A))
521 .field("matrix3", &self.matrix3)
522 .field("translation", &self.translation)
523 .finish()
524 }
525}
526
527impl core::fmt::Display for Affine3A {
528 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
529 if let Some(p) = f.precision() {
530 write!(
531 f,
532 "[{:.*}, {:.*}, {:.*}, {:.*}]",
533 p,
534 self.matrix3.x_axis,
535 p,
536 self.matrix3.y_axis,
537 p,
538 self.matrix3.z_axis,
539 p,
540 self.translation
541 )
542 } else {
543 write!(
544 f,
545 "[{}, {}, {}, {}]",
546 self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation
547 )
548 }
549 }
550}
551
552impl<'a> core::iter::Product<&'a Self> for Affine3A {
553 fn product<I>(iter: I) -> Self
554 where
555 I: Iterator<Item = &'a Self>,
556 {
557 iter.fold(Self::IDENTITY, |a, &b| a * b)
558 }
559}
560
561impl Mul for Affine3A {
562 type Output = Self;
563
564 #[inline]
565 fn mul(self, rhs: Self) -> Self {
566 Self {
567 matrix3: self.matrix3 * rhs.matrix3,
568 translation: self.matrix3 * rhs.translation + self.translation,
569 }
570 }
571}
572
573impl Mul<&Self> for Affine3A {
574 type Output = Self;
575 #[inline]
576 fn mul(self, rhs: &Self) -> Self {
577 self.mul(*rhs)
578 }
579}
580
581impl Mul<&Affine3A> for &Affine3A {
582 type Output = Affine3A;
583 #[inline]
584 fn mul(self, rhs: &Affine3A) -> Affine3A {
585 (*self).mul(*rhs)
586 }
587}
588
589impl Mul<Affine3A> for &Affine3A {
590 type Output = Affine3A;
591 #[inline]
592 fn mul(self, rhs: Affine3A) -> Affine3A {
593 (*self).mul(rhs)
594 }
595}
596
597impl MulAssign for Affine3A {
598 #[inline]
599 fn mul_assign(&mut self, rhs: Self) {
600 *self = self.mul(rhs);
601 }
602}
603
604impl MulAssign<&Self> for Affine3A {
605 #[inline]
606 fn mul_assign(&mut self, rhs: &Self) {
607 self.mul_assign(*rhs);
608 }
609}
610
611impl Mul<Mat4> for Affine3A {
612 type Output = Mat4;
613
614 #[inline]
615 fn mul(self, rhs: Mat4) -> Self::Output {
616 Mat4::from(self) * rhs
617 }
618}
619
620impl Mul<&Mat4> for Affine3A {
621 type Output = Mat4;
622 #[inline]
623 fn mul(self, rhs: &Mat4) -> Mat4 {
624 self.mul(*rhs)
625 }
626}
627
628impl Mul<&Mat4> for &Affine3A {
629 type Output = Mat4;
630 #[inline]
631 fn mul(self, rhs: &Mat4) -> Mat4 {
632 (*self).mul(*rhs)
633 }
634}
635
636impl Mul<Mat4> for &Affine3A {
637 type Output = Mat4;
638 #[inline]
639 fn mul(self, rhs: Mat4) -> Mat4 {
640 (*self).mul(rhs)
641 }
642}
643
644impl Mul<Affine3A> for Mat4 {
645 type Output = Self;
646
647 #[inline]
648 fn mul(self, rhs: Affine3A) -> Self {
649 self * Self::from(rhs)
650 }
651}
652
653impl Mul<&Affine3A> for Mat4 {
654 type Output = Self;
655 #[inline]
656 fn mul(self, rhs: &Affine3A) -> Self {
657 self.mul(*rhs)
658 }
659}
660
661impl Mul<&Affine3A> for &Mat4 {
662 type Output = Mat4;
663 #[inline]
664 fn mul(self, rhs: &Affine3A) -> Mat4 {
665 (*self).mul(*rhs)
666 }
667}
668
669impl Mul<Affine3A> for &Mat4 {
670 type Output = Mat4;
671 #[inline]
672 fn mul(self, rhs: Affine3A) -> Mat4 {
673 (*self).mul(rhs)
674 }
675}
676
677impl MulAssign<Affine3A> for Mat4 {
678 #[inline]
679 fn mul_assign(&mut self, rhs: Affine3A) {
680 *self = self.mul(rhs);
681 }
682}
683
684impl MulAssign<&Affine3A> for Mat4 {
685 #[inline]
686 fn mul_assign(&mut self, rhs: &Affine3A) {
687 self.mul_assign(*rhs);
688 }
689}
690
691impl From<Affine3A> for Mat4 {
692 #[inline]
693 fn from(m: Affine3A) -> Self {
694 Self::from_cols(
695 m.matrix3.x_axis.extend(0.0),
696 m.matrix3.y_axis.extend(0.0),
697 m.matrix3.z_axis.extend(0.0),
698 m.translation.extend(1.0),
699 )
700 }
701}