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(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
14#[cfg_attr(
15 all(feature = "zerocopy-08", not(feature = "core-simd")),
16 derive(FromBytes, Immutable, IntoBytes, KnownLayout)
17)]
18#[repr(C)]
19pub struct Affine3A {
20 pub matrix3: Mat3A,
21 pub translation: Vec3A,
22}
23
24impl Affine3A {
25 pub const ZERO: Self = Self {
30 matrix3: Mat3A::ZERO,
31 translation: Vec3A::ZERO,
32 };
33
34 pub const IDENTITY: Self = Self {
38 matrix3: Mat3A::IDENTITY,
39 translation: Vec3A::ZERO,
40 };
41
42 pub const NAN: Self = Self {
44 matrix3: Mat3A::NAN,
45 translation: Vec3A::NAN,
46 };
47
48 #[inline(always)]
50 #[must_use]
51 pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A, w_axis: Vec3A) -> Self {
52 Self {
53 matrix3: Mat3A::from_cols(x_axis, y_axis, z_axis),
54 translation: w_axis,
55 }
56 }
57
58 #[inline]
60 #[must_use]
61 pub fn from_cols_array(m: &[f32; 12]) -> Self {
62 Self {
63 matrix3: Mat3A::from_cols_array(&[
64 m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8],
65 ]),
66 translation: Vec3A::from_array([m[9], m[10], m[11]]),
67 }
68 }
69
70 #[inline]
72 #[must_use]
73 pub fn to_cols_array(&self) -> [f32; 12] {
74 let x = &self.matrix3.x_axis;
75 let y = &self.matrix3.y_axis;
76 let z = &self.matrix3.z_axis;
77 let w = &self.translation;
78 [x.x, x.y, x.z, y.x, y.y, y.z, z.x, z.y, z.z, w.x, w.y, w.z]
79 }
80
81 #[inline]
86 #[must_use]
87 pub fn from_cols_array_2d(m: &[[f32; 3]; 4]) -> Self {
88 Self {
89 matrix3: Mat3A::from_cols(m[0].into(), m[1].into(), m[2].into()),
90 translation: m[3].into(),
91 }
92 }
93
94 #[inline]
98 #[must_use]
99 pub fn to_cols_array_2d(&self) -> [[f32; 3]; 4] {
100 [
101 self.matrix3.x_axis.into(),
102 self.matrix3.y_axis.into(),
103 self.matrix3.z_axis.into(),
104 self.translation.into(),
105 ]
106 }
107
108 #[inline]
114 #[must_use]
115 pub fn from_cols_slice(slice: &[f32]) -> Self {
116 Self {
117 matrix3: Mat3A::from_cols_slice(&slice[0..9]),
118 translation: Vec3A::from_slice(&slice[9..12]),
119 }
120 }
121
122 #[inline]
128 pub fn write_cols_to_slice(&self, slice: &mut [f32]) {
129 self.matrix3.write_cols_to_slice(&mut slice[0..9]);
130 self.translation.write_to_slice(&mut slice[9..12]);
131 }
132
133 #[inline]
136 #[must_use]
137 pub fn from_scale(scale: Vec3) -> Self {
138 Self {
139 matrix3: Mat3A::from_diagonal(scale),
140 translation: Vec3A::ZERO,
141 }
142 }
143 #[inline]
149 #[must_use]
150 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
151 pub fn from_quat(rotation: Quat) -> Self {
152 Self {
153 matrix3: Mat3A::from_quat(rotation),
154 translation: Vec3A::ZERO,
155 }
156 }
157
158 #[inline]
165 #[must_use]
166 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
167 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
168 Self {
169 matrix3: Mat3A::from_axis_angle(axis, angle),
170 translation: Vec3A::ZERO,
171 }
172 }
173
174 #[inline]
177 #[must_use]
178 pub fn from_rotation_x(angle: f32) -> Self {
179 Self {
180 matrix3: Mat3A::from_rotation_x(angle),
181 translation: Vec3A::ZERO,
182 }
183 }
184
185 #[inline]
188 #[must_use]
189 pub fn from_rotation_y(angle: f32) -> Self {
190 Self {
191 matrix3: Mat3A::from_rotation_y(angle),
192 translation: Vec3A::ZERO,
193 }
194 }
195
196 #[inline]
199 #[must_use]
200 pub fn from_rotation_z(angle: f32) -> Self {
201 Self {
202 matrix3: Mat3A::from_rotation_z(angle),
203 translation: Vec3A::ZERO,
204 }
205 }
206
207 #[inline]
209 #[must_use]
210 pub fn from_translation(translation: Vec3) -> Self {
211 #[allow(clippy::useless_conversion)]
212 Self {
213 matrix3: Mat3A::IDENTITY,
214 translation: translation.into(),
215 }
216 }
217
218 #[inline]
221 #[must_use]
222 pub fn from_mat3(mat3: Mat3) -> Self {
223 #[allow(clippy::useless_conversion)]
224 Self {
225 matrix3: mat3.into(),
226 translation: Vec3A::ZERO,
227 }
228 }
229
230 #[inline]
235 #[must_use]
236 pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
237 #[allow(clippy::useless_conversion)]
238 Self {
239 matrix3: mat3.into(),
240 translation: translation.into(),
241 }
242 }
243
244 #[inline]
254 #[must_use]
255 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
256 pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
257 let rotation = Mat3A::from_quat(rotation);
258 #[allow(clippy::useless_conversion)]
259 Self {
260 matrix3: Mat3A::from_cols(
261 rotation.x_axis * scale.x,
262 rotation.y_axis * scale.y,
263 rotation.z_axis * scale.z,
264 ),
265 translation: translation.into(),
266 }
267 }
268
269 #[inline]
277 #[must_use]
278 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
279 pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
280 #[allow(clippy::useless_conversion)]
281 Self {
282 matrix3: Mat3A::from_quat(rotation),
283 translation: translation.into(),
284 }
285 }
286
287 #[inline]
290 #[must_use]
291 pub fn from_mat4(m: Mat4) -> Self {
292 Self {
293 matrix3: Mat3A::from_cols(
294 Vec3A::from_vec4(m.x_axis),
295 Vec3A::from_vec4(m.y_axis),
296 Vec3A::from_vec4(m.z_axis),
297 ),
298 translation: Vec3A::from_vec4(m.w_axis),
299 }
300 }
301
302 #[inline]
312 #[must_use]
313 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
314 pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
315 let det = self.matrix3.determinant();
316 glam_assert!(det != 0.0);
317
318 let scale = Vec3::new(
319 self.matrix3.x_axis.length() * det.signum(),
320 self.matrix3.y_axis.length(),
321 self.matrix3.z_axis.length(),
322 );
323
324 glam_assert!(scale.cmpne(Vec3::ZERO).all());
325
326 let inv_scale = scale.recip();
327
328 #[allow(clippy::useless_conversion)]
329 let rotation = Quat::from_mat3(&Mat3::from_cols(
330 (self.matrix3.x_axis * inv_scale.x).into(),
331 (self.matrix3.y_axis * inv_scale.y).into(),
332 (self.matrix3.z_axis * inv_scale.z).into(),
333 ));
334
335 #[allow(clippy::useless_conversion)]
336 (scale, rotation, self.translation.into())
337 }
338
339 #[inline]
341 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
342 #[allow(clippy::useless_conversion)]
343 ((self.matrix3.x_axis * rhs.x)
344 + (self.matrix3.y_axis * rhs.y)
345 + (self.matrix3.z_axis * rhs.z)
346 + self.translation)
347 .into()
348 }
349
350 #[inline]
355 #[must_use]
356 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
357 #[allow(clippy::useless_conversion)]
358 ((self.matrix3.x_axis * rhs.x)
359 + (self.matrix3.y_axis * rhs.y)
360 + (self.matrix3.z_axis * rhs.z))
361 .into()
362 }
363
364 #[inline]
366 #[must_use]
367 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
368 self.matrix3 * rhs + self.translation
369 }
370
371 #[inline]
376 #[must_use]
377 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
378 self.matrix3 * rhs
379 }
380
381 #[inline]
386 #[must_use]
387 pub fn is_finite(&self) -> bool {
388 self.matrix3.is_finite() && self.translation.is_finite()
389 }
390
391 #[inline]
393 #[must_use]
394 pub fn is_nan(&self) -> bool {
395 self.matrix3.is_nan() || self.translation.is_nan()
396 }
397
398 #[inline]
408 #[must_use]
409 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
410 self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff)
411 && self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
412 }
413
414 #[inline]
422 #[must_use]
423 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
424 pub fn inverse(&self) -> Self {
425 let matrix3 = self.matrix3.inverse();
426 let translation = -(matrix3 * self.translation);
428
429 Self {
430 matrix3,
431 translation,
432 }
433 }
434
435 #[cfg(feature = "f64")]
437 #[inline]
438 #[must_use]
439 pub fn as_daffine3(&self) -> crate::DAffine3 {
440 crate::DAffine3::from_mat3_translation(self.matrix3.as_dmat3(), self.translation.as_dvec3())
441 }
442}
443
444impl Default for Affine3A {
445 #[inline(always)]
446 fn default() -> Self {
447 Self::IDENTITY
448 }
449}
450
451impl Deref for Affine3A {
452 type Target = crate::deref::Cols4<Vec3A>;
453 #[inline(always)]
454 fn deref(&self) -> &Self::Target {
455 unsafe { &*(self as *const Self as *const Self::Target) }
456 }
457}
458
459impl DerefMut for Affine3A {
460 #[inline(always)]
461 fn deref_mut(&mut self) -> &mut Self::Target {
462 unsafe { &mut *(self as *mut Self as *mut Self::Target) }
463 }
464}
465
466impl PartialEq for Affine3A {
467 #[inline]
468 fn eq(&self, rhs: &Self) -> bool {
469 self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation)
470 }
471}
472
473impl core::fmt::Debug for Affine3A {
474 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
475 fmt.debug_struct(stringify!(Affine3A))
476 .field("matrix3", &self.matrix3)
477 .field("translation", &self.translation)
478 .finish()
479 }
480}
481
482impl core::fmt::Display for Affine3A {
483 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
484 if let Some(p) = f.precision() {
485 write!(
486 f,
487 "[{:.*}, {:.*}, {:.*}, {:.*}]",
488 p,
489 self.matrix3.x_axis,
490 p,
491 self.matrix3.y_axis,
492 p,
493 self.matrix3.z_axis,
494 p,
495 self.translation
496 )
497 } else {
498 write!(
499 f,
500 "[{}, {}, {}, {}]",
501 self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation
502 )
503 }
504 }
505}
506
507impl<'a> core::iter::Product<&'a Self> for Affine3A {
508 fn product<I>(iter: I) -> Self
509 where
510 I: Iterator<Item = &'a Self>,
511 {
512 iter.fold(Self::IDENTITY, |a, &b| a * b)
513 }
514}
515
516impl Mul for Affine3A {
517 type Output = Self;
518
519 #[inline]
520 fn mul(self, rhs: Self) -> Self {
521 Self {
522 matrix3: self.matrix3 * rhs.matrix3,
523 translation: self.matrix3 * rhs.translation + self.translation,
524 }
525 }
526}
527
528impl Mul<&Self> for Affine3A {
529 type Output = Self;
530 #[inline]
531 fn mul(self, rhs: &Self) -> Self {
532 self.mul(*rhs)
533 }
534}
535
536impl Mul<&Affine3A> for &Affine3A {
537 type Output = Affine3A;
538 #[inline]
539 fn mul(self, rhs: &Affine3A) -> Affine3A {
540 (*self).mul(*rhs)
541 }
542}
543
544impl Mul<Affine3A> for &Affine3A {
545 type Output = Affine3A;
546 #[inline]
547 fn mul(self, rhs: Affine3A) -> Affine3A {
548 (*self).mul(rhs)
549 }
550}
551
552impl MulAssign for Affine3A {
553 #[inline]
554 fn mul_assign(&mut self, rhs: Self) {
555 *self = self.mul(rhs);
556 }
557}
558
559impl MulAssign<&Self> for Affine3A {
560 #[inline]
561 fn mul_assign(&mut self, rhs: &Self) {
562 self.mul_assign(*rhs);
563 }
564}
565
566impl Mul<Mat4> for Affine3A {
567 type Output = Mat4;
568
569 #[inline]
570 fn mul(self, rhs: Mat4) -> Self::Output {
571 Mat4::from(self) * rhs
572 }
573}
574
575impl Mul<&Mat4> for Affine3A {
576 type Output = Mat4;
577 #[inline]
578 fn mul(self, rhs: &Mat4) -> Mat4 {
579 self.mul(*rhs)
580 }
581}
582
583impl Mul<&Mat4> for &Affine3A {
584 type Output = Mat4;
585 #[inline]
586 fn mul(self, rhs: &Mat4) -> Mat4 {
587 (*self).mul(*rhs)
588 }
589}
590
591impl Mul<Mat4> for &Affine3A {
592 type Output = Mat4;
593 #[inline]
594 fn mul(self, rhs: Mat4) -> Mat4 {
595 (*self).mul(rhs)
596 }
597}
598
599impl Mul<Affine3A> for Mat4 {
600 type Output = Self;
601
602 #[inline]
603 fn mul(self, rhs: Affine3A) -> Self {
604 self * Self::from(rhs)
605 }
606}
607
608impl Mul<&Affine3A> for Mat4 {
609 type Output = Self;
610 #[inline]
611 fn mul(self, rhs: &Affine3A) -> Self {
612 self.mul(*rhs)
613 }
614}
615
616impl Mul<&Affine3A> for &Mat4 {
617 type Output = Mat4;
618 #[inline]
619 fn mul(self, rhs: &Affine3A) -> Mat4 {
620 (*self).mul(*rhs)
621 }
622}
623
624impl Mul<Affine3A> for &Mat4 {
625 type Output = Mat4;
626 #[inline]
627 fn mul(self, rhs: Affine3A) -> Mat4 {
628 (*self).mul(rhs)
629 }
630}
631
632impl MulAssign<Affine3A> for Mat4 {
633 #[inline]
634 fn mul_assign(&mut self, rhs: Affine3A) {
635 *self = self.mul(rhs);
636 }
637}
638
639impl MulAssign<&Affine3A> for Mat4 {
640 #[inline]
641 fn mul_assign(&mut self, rhs: &Affine3A) {
642 self.mul_assign(*rhs);
643 }
644}
645
646impl From<Affine3A> for Mat4 {
647 #[inline]
648 fn from(m: Affine3A) -> Self {
649 Self::from_cols(
650 m.matrix3.x_axis.extend(0.0),
651 m.matrix3.y_axis.extend(0.0),
652 m.matrix3.z_axis.extend(0.0),
653 m.translation.extend(1.0),
654 )
655 }
656}
657
658impl From<Affine3> for Affine3A {
659 #[inline]
660 fn from(a: Affine3) -> Self {
661 Self::from_cols(
662 a.matrix3.x_axis.into(),
663 a.matrix3.y_axis.into(),
664 a.matrix3.z_axis.into(),
665 a.translation.into(),
666 )
667 }
668}