1use crate::{Affine3, Mat3, Mat3A, Mat4, Quat, Vec3, Vec3A};
4use core::ops::{Deref, DerefMut, Mul, MulAssign};
5
6#[cfg(all(feature = "zerocopy-08", not(feature = "core-simd")))]
7use zerocopy_derive_08::*;
8
9#[derive(Copy, Clone)]
13#[cfg_attr(
14 all(feature = "bytemuck", not(target_arch = "spirv")),
15 derive(bytemuck::Pod, bytemuck::Zeroable)
16)]
17#[cfg_attr(
18 all(feature = "bytemuck", target_arch = "spirv"),
19 derive(bytemuck::AnyBitPattern)
20)]
21#[cfg_attr(
22 all(
23 feature = "zerocopy-08",
24 not(feature = "core-simd"),
25 not(target_arch = "spirv")
26 ),
27 derive(FromBytes, Immutable, IntoBytes, KnownLayout)
28)]
29#[cfg_attr(
30 all(
31 feature = "zerocopy-08",
32 not(feature = "core-simd"),
33 target_arch = "spirv"
34 ),
35 derive(FromBytes, Immutable, KnownLayout)
36)]
37#[repr(C)]
38pub struct Affine3A {
39 pub matrix3: Mat3A,
40 pub translation: Vec3A,
41}
42
43impl Affine3A {
44 pub const ZERO: Self = Self {
49 matrix3: Mat3A::ZERO,
50 translation: Vec3A::ZERO,
51 };
52
53 pub const IDENTITY: Self = Self {
57 matrix3: Mat3A::IDENTITY,
58 translation: Vec3A::ZERO,
59 };
60
61 pub const NAN: Self = Self {
63 matrix3: Mat3A::NAN,
64 translation: Vec3A::NAN,
65 };
66
67 #[inline(always)]
69 #[must_use]
70 pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A, w_axis: Vec3A) -> Self {
71 Self {
72 matrix3: Mat3A::from_cols(x_axis, y_axis, z_axis),
73 translation: w_axis,
74 }
75 }
76
77 #[inline]
79 #[must_use]
80 pub fn from_cols_array(m: &[f32; 12]) -> Self {
81 Self {
82 matrix3: Mat3A::from_cols_array(&[
83 m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8],
84 ]),
85 translation: Vec3A::from_array([m[9], m[10], m[11]]),
86 }
87 }
88
89 #[inline]
91 #[must_use]
92 pub fn to_cols_array(&self) -> [f32; 12] {
93 let x = &self.matrix3.x_axis;
94 let y = &self.matrix3.y_axis;
95 let z = &self.matrix3.z_axis;
96 let w = &self.translation;
97 [x.x, x.y, x.z, y.x, y.y, y.z, z.x, z.y, z.z, w.x, w.y, w.z]
98 }
99
100 #[inline]
105 #[must_use]
106 pub fn from_cols_array_2d(m: &[[f32; 3]; 4]) -> Self {
107 Self {
108 matrix3: Mat3A::from_cols(m[0].into(), m[1].into(), m[2].into()),
109 translation: m[3].into(),
110 }
111 }
112
113 #[inline]
117 #[must_use]
118 pub fn to_cols_array_2d(&self) -> [[f32; 3]; 4] {
119 [
120 self.matrix3.x_axis.into(),
121 self.matrix3.y_axis.into(),
122 self.matrix3.z_axis.into(),
123 self.translation.into(),
124 ]
125 }
126
127 #[inline]
133 #[must_use]
134 pub fn from_cols_slice(slice: &[f32]) -> Self {
135 Self {
136 matrix3: Mat3A::from_cols_slice(&slice[0..9]),
137 translation: Vec3A::from_slice(&slice[9..12]),
138 }
139 }
140
141 #[inline]
147 pub fn write_cols_to_slice(&self, slice: &mut [f32]) {
148 self.matrix3.write_cols_to_slice(&mut slice[0..9]);
149 self.translation.write_to_slice(&mut slice[9..12]);
150 }
151
152 #[inline]
155 #[must_use]
156 pub fn from_scale(scale: Vec3) -> Self {
157 Self {
158 matrix3: Mat3A::from_diagonal(scale),
159 translation: Vec3A::ZERO,
160 }
161 }
162 #[inline]
164 #[must_use]
165 pub fn from_quat(rotation: Quat) -> Self {
166 Self {
167 matrix3: Mat3A::from_quat(rotation),
168 translation: Vec3A::ZERO,
169 }
170 }
171
172 #[inline]
175 #[must_use]
176 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
177 Self {
178 matrix3: Mat3A::from_axis_angle(axis, angle),
179 translation: Vec3A::ZERO,
180 }
181 }
182
183 #[inline]
186 #[must_use]
187 pub fn from_rotation_x(angle: f32) -> Self {
188 Self {
189 matrix3: Mat3A::from_rotation_x(angle),
190 translation: Vec3A::ZERO,
191 }
192 }
193
194 #[inline]
197 #[must_use]
198 pub fn from_rotation_y(angle: f32) -> Self {
199 Self {
200 matrix3: Mat3A::from_rotation_y(angle),
201 translation: Vec3A::ZERO,
202 }
203 }
204
205 #[inline]
208 #[must_use]
209 pub fn from_rotation_z(angle: f32) -> Self {
210 Self {
211 matrix3: Mat3A::from_rotation_z(angle),
212 translation: Vec3A::ZERO,
213 }
214 }
215
216 #[inline]
218 #[must_use]
219 pub fn from_translation(translation: Vec3) -> Self {
220 #[allow(clippy::useless_conversion)]
221 Self {
222 matrix3: Mat3A::IDENTITY,
223 translation: translation.into(),
224 }
225 }
226
227 #[inline]
230 #[must_use]
231 pub fn from_mat3(mat3: Mat3) -> Self {
232 #[allow(clippy::useless_conversion)]
233 Self {
234 matrix3: mat3.into(),
235 translation: Vec3A::ZERO,
236 }
237 }
238
239 #[inline]
244 #[must_use]
245 pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
246 #[allow(clippy::useless_conversion)]
247 Self {
248 matrix3: mat3.into(),
249 translation: translation.into(),
250 }
251 }
252
253 #[inline]
259 #[must_use]
260 pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
261 let rotation = Mat3A::from_quat(rotation);
262 #[allow(clippy::useless_conversion)]
263 Self {
264 matrix3: Mat3A::from_cols(
265 rotation.x_axis * scale.x,
266 rotation.y_axis * scale.y,
267 rotation.z_axis * scale.z,
268 ),
269 translation: translation.into(),
270 }
271 }
272
273 #[inline]
277 #[must_use]
278 pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
279 #[allow(clippy::useless_conversion)]
280 Self {
281 matrix3: Mat3A::from_quat(rotation),
282 translation: translation.into(),
283 }
284 }
285
286 #[inline]
289 #[must_use]
290 pub fn from_mat4(m: Mat4) -> Self {
291 Self {
292 matrix3: Mat3A::from_cols(
293 Vec3A::from_vec4(m.x_axis),
294 Vec3A::from_vec4(m.y_axis),
295 Vec3A::from_vec4(m.z_axis),
296 ),
297 translation: Vec3A::from_vec4(m.w_axis),
298 }
299 }
300
301 #[inline]
311 #[must_use]
312 pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
313 use crate::f32::math;
314 let det = self.matrix3.determinant();
315 glam_assert!(det != 0.0);
316
317 let scale = Vec3::new(
318 self.matrix3.x_axis.length() * math::signum(det),
319 self.matrix3.y_axis.length(),
320 self.matrix3.z_axis.length(),
321 );
322
323 glam_assert!(scale.cmpne(Vec3::ZERO).all());
324
325 let inv_scale = scale.recip();
326
327 #[allow(clippy::useless_conversion)]
328 let rotation = Quat::from_mat3(&Mat3::from_cols(
329 (self.matrix3.x_axis * inv_scale.x).into(),
330 (self.matrix3.y_axis * inv_scale.y).into(),
331 (self.matrix3.z_axis * inv_scale.z).into(),
332 ));
333
334 #[allow(clippy::useless_conversion)]
335 (scale, rotation, self.translation.into())
336 }
337
338 #[deprecated(
343 since = "0.33.1",
344 note = "use the `glam::camera::lh::view::look_to_affine3` function instead"
345 )]
346 #[inline]
347 #[must_use]
348 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
349 #[allow(deprecated)]
350 Self::look_to_rh(eye, -dir, up)
351 }
352
353 #[deprecated(
358 since = "0.33.1",
359 note = "use the `glam::camera::rh::view::look_to_affine3` function instead"
360 )]
361 #[inline]
362 #[must_use]
363 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
364 let f = dir.normalize();
365 let s = f.cross(up).normalize();
366 let u = s.cross(f);
367
368 Self {
369 matrix3: Mat3A::from_cols(
370 Vec3A::new(s.x, u.x, -f.x),
371 Vec3A::new(s.y, u.y, -f.y),
372 Vec3A::new(s.z, u.z, -f.z),
373 ),
374 translation: Vec3A::new(-eye.dot(s), -eye.dot(u), eye.dot(f)),
375 }
376 }
377
378 #[deprecated(
386 since = "0.33.1",
387 note = "use the `glam::camera::lh::view::look_at_affine3` function instead"
388 )]
389 #[inline]
390 #[must_use]
391 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
392 glam_assert!(up.is_normalized());
393 #[allow(deprecated)]
394 Self::look_to_lh(eye, center - eye, up)
395 }
396
397 #[deprecated(
405 since = "0.33.1",
406 note = "use the `glam::camera::rh::view::look_at_affine3` function instead"
407 )]
408 #[inline]
409 #[must_use]
410 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
411 glam_assert!(up.is_normalized());
412 #[allow(deprecated)]
413 Self::look_to_rh(eye, center - eye, up)
414 }
415
416 #[inline]
418 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
419 #[allow(clippy::useless_conversion)]
420 ((self.matrix3.x_axis * rhs.x)
421 + (self.matrix3.y_axis * rhs.y)
422 + (self.matrix3.z_axis * rhs.z)
423 + self.translation)
424 .into()
425 }
426
427 #[inline]
432 #[must_use]
433 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
434 #[allow(clippy::useless_conversion)]
435 ((self.matrix3.x_axis * rhs.x)
436 + (self.matrix3.y_axis * rhs.y)
437 + (self.matrix3.z_axis * rhs.z))
438 .into()
439 }
440
441 #[inline]
443 #[must_use]
444 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
445 self.matrix3 * rhs + self.translation
446 }
447
448 #[inline]
453 #[must_use]
454 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
455 self.matrix3 * rhs
456 }
457
458 #[inline]
463 #[must_use]
464 pub fn is_finite(&self) -> bool {
465 self.matrix3.is_finite() && self.translation.is_finite()
466 }
467
468 #[inline]
470 #[must_use]
471 pub fn is_nan(&self) -> bool {
472 self.matrix3.is_nan() || self.translation.is_nan()
473 }
474
475 #[inline]
485 #[must_use]
486 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
487 self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff)
488 && self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
489 }
490
491 #[inline]
495 #[must_use]
496 pub fn inverse(&self) -> Self {
497 let matrix3 = self.matrix3.inverse();
498 let translation = -(matrix3 * self.translation);
500
501 Self {
502 matrix3,
503 translation,
504 }
505 }
506
507 #[cfg(feature = "f64")]
509 #[inline]
510 #[must_use]
511 pub fn as_daffine3(&self) -> crate::DAffine3 {
512 crate::DAffine3::from_mat3_translation(self.matrix3.as_dmat3(), self.translation.as_dvec3())
513 }
514}
515
516impl Default for Affine3A {
517 #[inline(always)]
518 fn default() -> Self {
519 Self::IDENTITY
520 }
521}
522
523impl Deref for Affine3A {
524 type Target = crate::deref::Cols4<Vec3A>;
525 #[inline(always)]
526 fn deref(&self) -> &Self::Target {
527 unsafe { &*(self as *const Self as *const Self::Target) }
528 }
529}
530
531impl DerefMut for Affine3A {
532 #[inline(always)]
533 fn deref_mut(&mut self) -> &mut Self::Target {
534 unsafe { &mut *(self as *mut Self as *mut Self::Target) }
535 }
536}
537
538impl PartialEq for Affine3A {
539 #[inline]
540 fn eq(&self, rhs: &Self) -> bool {
541 self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation)
542 }
543}
544
545impl core::fmt::Debug for Affine3A {
546 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
547 fmt.debug_struct(stringify!(Affine3A))
548 .field("matrix3", &self.matrix3)
549 .field("translation", &self.translation)
550 .finish()
551 }
552}
553
554impl core::fmt::Display for Affine3A {
555 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
556 if let Some(p) = f.precision() {
557 write!(
558 f,
559 "[{:.*}, {:.*}, {:.*}, {:.*}]",
560 p,
561 self.matrix3.x_axis,
562 p,
563 self.matrix3.y_axis,
564 p,
565 self.matrix3.z_axis,
566 p,
567 self.translation
568 )
569 } else {
570 write!(
571 f,
572 "[{}, {}, {}, {}]",
573 self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation
574 )
575 }
576 }
577}
578
579impl<'a> core::iter::Product<&'a Self> for Affine3A {
580 fn product<I>(iter: I) -> Self
581 where
582 I: Iterator<Item = &'a Self>,
583 {
584 iter.fold(Self::IDENTITY, |a, &b| a * b)
585 }
586}
587
588impl Mul for Affine3A {
589 type Output = Self;
590
591 #[inline]
592 fn mul(self, rhs: Self) -> Self {
593 Self {
594 matrix3: self.matrix3 * rhs.matrix3,
595 translation: self.matrix3 * rhs.translation + self.translation,
596 }
597 }
598}
599
600impl Mul<&Self> for Affine3A {
601 type Output = Self;
602 #[inline]
603 fn mul(self, rhs: &Self) -> Self {
604 self.mul(*rhs)
605 }
606}
607
608impl Mul<&Affine3A> for &Affine3A {
609 type Output = Affine3A;
610 #[inline]
611 fn mul(self, rhs: &Affine3A) -> Affine3A {
612 (*self).mul(*rhs)
613 }
614}
615
616impl Mul<Affine3A> for &Affine3A {
617 type Output = Affine3A;
618 #[inline]
619 fn mul(self, rhs: Affine3A) -> Affine3A {
620 (*self).mul(rhs)
621 }
622}
623
624impl MulAssign for Affine3A {
625 #[inline]
626 fn mul_assign(&mut self, rhs: Self) {
627 *self = self.mul(rhs);
628 }
629}
630
631impl MulAssign<&Self> for Affine3A {
632 #[inline]
633 fn mul_assign(&mut self, rhs: &Self) {
634 self.mul_assign(*rhs);
635 }
636}
637
638impl Mul<Mat4> for Affine3A {
639 type Output = Mat4;
640
641 #[inline]
642 fn mul(self, rhs: Mat4) -> Self::Output {
643 Mat4::from(self) * rhs
644 }
645}
646
647impl Mul<&Mat4> for Affine3A {
648 type Output = Mat4;
649 #[inline]
650 fn mul(self, rhs: &Mat4) -> Mat4 {
651 self.mul(*rhs)
652 }
653}
654
655impl Mul<&Mat4> for &Affine3A {
656 type Output = Mat4;
657 #[inline]
658 fn mul(self, rhs: &Mat4) -> Mat4 {
659 (*self).mul(*rhs)
660 }
661}
662
663impl Mul<Mat4> for &Affine3A {
664 type Output = Mat4;
665 #[inline]
666 fn mul(self, rhs: Mat4) -> Mat4 {
667 (*self).mul(rhs)
668 }
669}
670
671impl Mul<Affine3A> for Mat4 {
672 type Output = Self;
673
674 #[inline]
675 fn mul(self, rhs: Affine3A) -> Self {
676 self * Self::from(rhs)
677 }
678}
679
680impl Mul<&Affine3A> for Mat4 {
681 type Output = Self;
682 #[inline]
683 fn mul(self, rhs: &Affine3A) -> Self {
684 self.mul(*rhs)
685 }
686}
687
688impl Mul<&Affine3A> for &Mat4 {
689 type Output = Mat4;
690 #[inline]
691 fn mul(self, rhs: &Affine3A) -> Mat4 {
692 (*self).mul(*rhs)
693 }
694}
695
696impl Mul<Affine3A> for &Mat4 {
697 type Output = Mat4;
698 #[inline]
699 fn mul(self, rhs: Affine3A) -> Mat4 {
700 (*self).mul(rhs)
701 }
702}
703
704impl MulAssign<Affine3A> for Mat4 {
705 #[inline]
706 fn mul_assign(&mut self, rhs: Affine3A) {
707 *self = self.mul(rhs);
708 }
709}
710
711impl MulAssign<&Affine3A> for Mat4 {
712 #[inline]
713 fn mul_assign(&mut self, rhs: &Affine3A) {
714 self.mul_assign(*rhs);
715 }
716}
717
718impl From<Affine3A> for Mat4 {
719 #[inline]
720 fn from(m: Affine3A) -> Self {
721 Self::from_cols(
722 m.matrix3.x_axis.extend(0.0),
723 m.matrix3.y_axis.extend(0.0),
724 m.matrix3.z_axis.extend(0.0),
725 m.translation.extend(1.0),
726 )
727 }
728}
729
730impl From<Affine3> for Affine3A {
731 #[inline]
732 fn from(a: Affine3) -> Self {
733 Self::from_cols(
734 a.matrix3.x_axis.into(),
735 a.matrix3.y_axis.into(),
736 a.matrix3.z_axis.into(),
737 a.translation.into(),
738 )
739 }
740}