1use crate::{Mat3, Mat3A, Mat4, Quat, Vec3, Vec3A};
4use core::ops::{Deref, DerefMut, Mul, MulAssign};
5
6#[derive(Copy, Clone)]
10#[cfg_attr(feature = "bytemuck", derive(bytemuck::AnyBitPattern))]
11#[repr(C)]
12pub struct Affine3A {
13 pub matrix3: Mat3A,
14 pub translation: Vec3A,
15}
16
17impl Affine3A {
18 pub const ZERO: Self = Self {
23 matrix3: Mat3A::ZERO,
24 translation: Vec3A::ZERO,
25 };
26
27 pub const IDENTITY: Self = Self {
31 matrix3: Mat3A::IDENTITY,
32 translation: Vec3A::ZERO,
33 };
34
35 pub const NAN: Self = Self {
37 matrix3: Mat3A::NAN,
38 translation: Vec3A::NAN,
39 };
40
41 #[inline(always)]
43 #[must_use]
44 pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A, w_axis: Vec3A) -> Self {
45 Self {
46 matrix3: Mat3A::from_cols(x_axis, y_axis, z_axis),
47 translation: w_axis,
48 }
49 }
50
51 #[inline]
53 #[must_use]
54 pub fn from_cols_array(m: &[f32; 12]) -> Self {
55 Self {
56 matrix3: Mat3A::from_cols_array(&[
57 m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8],
58 ]),
59 translation: Vec3A::from_array([m[9], m[10], m[11]]),
60 }
61 }
62
63 #[inline]
65 #[must_use]
66 pub fn to_cols_array(&self) -> [f32; 12] {
67 let x = &self.matrix3.x_axis;
68 let y = &self.matrix3.y_axis;
69 let z = &self.matrix3.z_axis;
70 let w = &self.translation;
71 [x.x, x.y, x.z, y.x, y.y, y.z, z.x, z.y, z.z, w.x, w.y, w.z]
72 }
73
74 #[inline]
79 #[must_use]
80 pub fn from_cols_array_2d(m: &[[f32; 3]; 4]) -> Self {
81 Self {
82 matrix3: Mat3A::from_cols(m[0].into(), m[1].into(), m[2].into()),
83 translation: m[3].into(),
84 }
85 }
86
87 #[inline]
91 #[must_use]
92 pub fn to_cols_array_2d(&self) -> [[f32; 3]; 4] {
93 [
94 self.matrix3.x_axis.into(),
95 self.matrix3.y_axis.into(),
96 self.matrix3.z_axis.into(),
97 self.translation.into(),
98 ]
99 }
100
101 #[inline]
107 #[must_use]
108 pub fn from_cols_slice(slice: &[f32]) -> Self {
109 Self {
110 matrix3: Mat3A::from_cols_slice(&slice[0..9]),
111 translation: Vec3A::from_slice(&slice[9..12]),
112 }
113 }
114
115 #[inline]
121 pub fn write_cols_to_slice(self, slice: &mut [f32]) {
122 self.matrix3.write_cols_to_slice(&mut slice[0..9]);
123 self.translation.write_to_slice(&mut slice[9..12]);
124 }
125
126 #[inline]
129 #[must_use]
130 pub fn from_scale(scale: Vec3) -> Self {
131 Self {
132 matrix3: Mat3A::from_diagonal(scale),
133 translation: Vec3A::ZERO,
134 }
135 }
136 #[inline]
138 #[must_use]
139 pub fn from_quat(rotation: Quat) -> Self {
140 Self {
141 matrix3: Mat3A::from_quat(rotation),
142 translation: Vec3A::ZERO,
143 }
144 }
145
146 #[inline]
149 #[must_use]
150 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
151 Self {
152 matrix3: Mat3A::from_axis_angle(axis, angle),
153 translation: Vec3A::ZERO,
154 }
155 }
156
157 #[inline]
160 #[must_use]
161 pub fn from_rotation_x(angle: f32) -> Self {
162 Self {
163 matrix3: Mat3A::from_rotation_x(angle),
164 translation: Vec3A::ZERO,
165 }
166 }
167
168 #[inline]
171 #[must_use]
172 pub fn from_rotation_y(angle: f32) -> Self {
173 Self {
174 matrix3: Mat3A::from_rotation_y(angle),
175 translation: Vec3A::ZERO,
176 }
177 }
178
179 #[inline]
182 #[must_use]
183 pub fn from_rotation_z(angle: f32) -> Self {
184 Self {
185 matrix3: Mat3A::from_rotation_z(angle),
186 translation: Vec3A::ZERO,
187 }
188 }
189
190 #[inline]
192 #[must_use]
193 pub fn from_translation(translation: Vec3) -> Self {
194 #[allow(clippy::useless_conversion)]
195 Self {
196 matrix3: Mat3A::IDENTITY,
197 translation: translation.into(),
198 }
199 }
200
201 #[inline]
204 #[must_use]
205 pub fn from_mat3(mat3: Mat3) -> Self {
206 #[allow(clippy::useless_conversion)]
207 Self {
208 matrix3: mat3.into(),
209 translation: Vec3A::ZERO,
210 }
211 }
212
213 #[inline]
218 #[must_use]
219 pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
220 #[allow(clippy::useless_conversion)]
221 Self {
222 matrix3: mat3.into(),
223 translation: translation.into(),
224 }
225 }
226
227 #[inline]
233 #[must_use]
234 pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
235 let rotation = Mat3A::from_quat(rotation);
236 #[allow(clippy::useless_conversion)]
237 Self {
238 matrix3: Mat3A::from_cols(
239 rotation.x_axis * scale.x,
240 rotation.y_axis * scale.y,
241 rotation.z_axis * scale.z,
242 ),
243 translation: translation.into(),
244 }
245 }
246
247 #[inline]
251 #[must_use]
252 pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
253 #[allow(clippy::useless_conversion)]
254 Self {
255 matrix3: Mat3A::from_quat(rotation),
256 translation: translation.into(),
257 }
258 }
259
260 #[inline]
263 #[must_use]
264 pub fn from_mat4(m: Mat4) -> Self {
265 Self {
266 matrix3: Mat3A::from_cols(
267 Vec3A::from_vec4(m.x_axis),
268 Vec3A::from_vec4(m.y_axis),
269 Vec3A::from_vec4(m.z_axis),
270 ),
271 translation: Vec3A::from_vec4(m.w_axis),
272 }
273 }
274
275 #[inline]
285 #[must_use]
286 pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
287 use crate::f32::math;
288 let det = self.matrix3.determinant();
289 glam_assert!(det != 0.0);
290
291 let scale = Vec3::new(
292 self.matrix3.x_axis.length() * math::signum(det),
293 self.matrix3.y_axis.length(),
294 self.matrix3.z_axis.length(),
295 );
296
297 glam_assert!(scale.cmpne(Vec3::ZERO).all());
298
299 let inv_scale = scale.recip();
300
301 #[allow(clippy::useless_conversion)]
302 let rotation = Quat::from_mat3(&Mat3::from_cols(
303 (self.matrix3.x_axis * inv_scale.x).into(),
304 (self.matrix3.y_axis * inv_scale.y).into(),
305 (self.matrix3.z_axis * inv_scale.z).into(),
306 ));
307
308 #[allow(clippy::useless_conversion)]
309 (scale, rotation, self.translation.into())
310 }
311
312 #[inline]
317 #[must_use]
318 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
319 Self::look_to_rh(eye, -dir, up)
320 }
321
322 #[inline]
327 #[must_use]
328 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
329 let f = dir.normalize();
330 let s = f.cross(up).normalize();
331 let u = s.cross(f);
332
333 Self {
334 matrix3: Mat3A::from_cols(
335 Vec3A::new(s.x, u.x, -f.x),
336 Vec3A::new(s.y, u.y, -f.y),
337 Vec3A::new(s.z, u.z, -f.z),
338 ),
339 translation: Vec3A::new(-eye.dot(s), -eye.dot(u), eye.dot(f)),
340 }
341 }
342
343 #[inline]
351 #[must_use]
352 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
353 glam_assert!(up.is_normalized());
354 Self::look_to_lh(eye, center - eye, up)
355 }
356
357 #[inline]
365 #[must_use]
366 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
367 glam_assert!(up.is_normalized());
368 Self::look_to_rh(eye, center - eye, up)
369 }
370
371 #[inline]
373 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
374 #[allow(clippy::useless_conversion)]
375 ((self.matrix3.x_axis * rhs.x)
376 + (self.matrix3.y_axis * rhs.y)
377 + (self.matrix3.z_axis * rhs.z)
378 + self.translation)
379 .into()
380 }
381
382 #[inline]
387 #[must_use]
388 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
389 #[allow(clippy::useless_conversion)]
390 ((self.matrix3.x_axis * rhs.x)
391 + (self.matrix3.y_axis * rhs.y)
392 + (self.matrix3.z_axis * rhs.z))
393 .into()
394 }
395
396 #[inline]
398 #[must_use]
399 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
400 self.matrix3 * rhs + self.translation
401 }
402
403 #[inline]
408 #[must_use]
409 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
410 self.matrix3 * rhs
411 }
412
413 #[inline]
418 #[must_use]
419 pub fn is_finite(&self) -> bool {
420 self.matrix3.is_finite() && self.translation.is_finite()
421 }
422
423 #[inline]
425 #[must_use]
426 pub fn is_nan(&self) -> bool {
427 self.matrix3.is_nan() || self.translation.is_nan()
428 }
429
430 #[inline]
440 #[must_use]
441 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
442 self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff)
443 && self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
444 }
445
446 #[inline]
450 #[must_use]
451 pub fn inverse(&self) -> Self {
452 let matrix3 = self.matrix3.inverse();
453 let translation = -(matrix3 * self.translation);
455
456 Self {
457 matrix3,
458 translation,
459 }
460 }
461
462 #[inline]
464 #[must_use]
465 pub fn as_daffine3(&self) -> crate::DAffine3 {
466 crate::DAffine3::from_mat3_translation(self.matrix3.as_dmat3(), self.translation.as_dvec3())
467 }
468}
469
470impl Default for Affine3A {
471 #[inline(always)]
472 fn default() -> Self {
473 Self::IDENTITY
474 }
475}
476
477impl Deref for Affine3A {
478 type Target = crate::deref::Cols4<Vec3A>;
479 #[inline(always)]
480 fn deref(&self) -> &Self::Target {
481 unsafe { &*(self as *const Self as *const Self::Target) }
482 }
483}
484
485impl DerefMut for Affine3A {
486 #[inline(always)]
487 fn deref_mut(&mut self) -> &mut Self::Target {
488 unsafe { &mut *(self as *mut Self as *mut Self::Target) }
489 }
490}
491
492impl PartialEq for Affine3A {
493 #[inline]
494 fn eq(&self, rhs: &Self) -> bool {
495 self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation)
496 }
497}
498
499impl core::fmt::Debug for Affine3A {
500 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
501 fmt.debug_struct(stringify!(Affine3A))
502 .field("matrix3", &self.matrix3)
503 .field("translation", &self.translation)
504 .finish()
505 }
506}
507
508impl core::fmt::Display for Affine3A {
509 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
510 if let Some(p) = f.precision() {
511 write!(
512 f,
513 "[{:.*}, {:.*}, {:.*}, {:.*}]",
514 p,
515 self.matrix3.x_axis,
516 p,
517 self.matrix3.y_axis,
518 p,
519 self.matrix3.z_axis,
520 p,
521 self.translation
522 )
523 } else {
524 write!(
525 f,
526 "[{}, {}, {}, {}]",
527 self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation
528 )
529 }
530 }
531}
532
533impl<'a> core::iter::Product<&'a Self> for Affine3A {
534 fn product<I>(iter: I) -> Self
535 where
536 I: Iterator<Item = &'a Self>,
537 {
538 iter.fold(Self::IDENTITY, |a, &b| a * b)
539 }
540}
541
542impl Mul for Affine3A {
543 type Output = Self;
544
545 #[inline]
546 fn mul(self, rhs: Self) -> Self {
547 Self {
548 matrix3: self.matrix3 * rhs.matrix3,
549 translation: self.matrix3 * rhs.translation + self.translation,
550 }
551 }
552}
553
554impl Mul<&Self> for Affine3A {
555 type Output = Self;
556 #[inline]
557 fn mul(self, rhs: &Self) -> Self {
558 self.mul(*rhs)
559 }
560}
561
562impl Mul<&Affine3A> for &Affine3A {
563 type Output = Affine3A;
564 #[inline]
565 fn mul(self, rhs: &Affine3A) -> Affine3A {
566 (*self).mul(*rhs)
567 }
568}
569
570impl Mul<Affine3A> for &Affine3A {
571 type Output = Affine3A;
572 #[inline]
573 fn mul(self, rhs: Affine3A) -> Affine3A {
574 (*self).mul(rhs)
575 }
576}
577
578impl MulAssign for Affine3A {
579 #[inline]
580 fn mul_assign(&mut self, rhs: Self) {
581 *self = self.mul(rhs);
582 }
583}
584
585impl MulAssign<&Self> for Affine3A {
586 #[inline]
587 fn mul_assign(&mut self, rhs: &Self) {
588 self.mul_assign(*rhs);
589 }
590}
591
592impl Mul<Mat4> for Affine3A {
593 type Output = Mat4;
594
595 #[inline]
596 fn mul(self, rhs: Mat4) -> Self::Output {
597 Mat4::from(self) * rhs
598 }
599}
600
601impl Mul<&Mat4> for Affine3A {
602 type Output = Mat4;
603 #[inline]
604 fn mul(self, rhs: &Mat4) -> Mat4 {
605 self.mul(*rhs)
606 }
607}
608
609impl Mul<&Mat4> for &Affine3A {
610 type Output = Mat4;
611 #[inline]
612 fn mul(self, rhs: &Mat4) -> Mat4 {
613 (*self).mul(*rhs)
614 }
615}
616
617impl Mul<Mat4> for &Affine3A {
618 type Output = Mat4;
619 #[inline]
620 fn mul(self, rhs: Mat4) -> Mat4 {
621 (*self).mul(rhs)
622 }
623}
624
625impl Mul<Affine3A> for Mat4 {
626 type Output = Self;
627
628 #[inline]
629 fn mul(self, rhs: Affine3A) -> Self {
630 self * Self::from(rhs)
631 }
632}
633
634impl Mul<&Affine3A> for Mat4 {
635 type Output = Self;
636 #[inline]
637 fn mul(self, rhs: &Affine3A) -> Self {
638 self.mul(*rhs)
639 }
640}
641
642impl Mul<&Affine3A> for &Mat4 {
643 type Output = Mat4;
644 #[inline]
645 fn mul(self, rhs: &Affine3A) -> Mat4 {
646 (*self).mul(*rhs)
647 }
648}
649
650impl Mul<Affine3A> for &Mat4 {
651 type Output = Mat4;
652 #[inline]
653 fn mul(self, rhs: Affine3A) -> Mat4 {
654 (*self).mul(rhs)
655 }
656}
657
658impl MulAssign<Affine3A> for Mat4 {
659 #[inline]
660 fn mul_assign(&mut self, rhs: Affine3A) {
661 *self = self.mul(rhs);
662 }
663}
664
665impl MulAssign<&Affine3A> for Mat4 {
666 #[inline]
667 fn mul_assign(&mut self, rhs: &Affine3A) {
668 self.mul_assign(*rhs);
669 }
670}
671
672impl From<Affine3A> for Mat4 {
673 #[inline]
674 fn from(m: Affine3A) -> Self {
675 Self::from_cols(
676 m.matrix3.x_axis.extend(0.0),
677 m.matrix3.y_axis.extend(0.0),
678 m.matrix3.z_axis.extend(0.0),
679 m.translation.extend(1.0),
680 )
681 }
682}