Skip to main content

glam/f32/
affine3a.rs

1// Generated from affine.rs.tera template. Edit the template, not the generated file.
2
3use 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/// A 3D affine transform, which can represent translation, rotation, scaling and shear.
10///
11/// This type is 16 byte aligned.
12#[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    /// The degenerate zero transform.
26    ///
27    /// This transforms any finite vector and point to zero.
28    /// The zero transform is non-invertible.
29    pub const ZERO: Self = Self {
30        matrix3: Mat3A::ZERO,
31        translation: Vec3A::ZERO,
32    };
33
34    /// The identity transform.
35    ///
36    /// Multiplying a vector with this returns the same vector.
37    pub const IDENTITY: Self = Self {
38        matrix3: Mat3A::IDENTITY,
39        translation: Vec3A::ZERO,
40    };
41
42    /// All NAN:s.
43    pub const NAN: Self = Self {
44        matrix3: Mat3A::NAN,
45        translation: Vec3A::NAN,
46    };
47
48    /// Creates an affine transform from three column vectors.
49    #[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    /// Creates an affine transform from a `[f32; 12]` array stored in column major order.
59    #[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    /// Creates a `[f32; 12]` array storing data in column major order.
71    #[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    /// Creates an affine transform from a `[[f32; 3]; 4]`
82    /// 3D array stored in column major order.
83    /// If your data is in row major order you will need to `transpose` the returned
84    /// matrix.
85    #[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    /// Creates a `[[f32; 3]; 4]` 3D array storing data in
95    /// column major order.
96    /// If you require data in row major order `transpose` the matrix first.
97    #[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    /// Creates an affine transform from the first 12 values in `slice`.
109    ///
110    /// # Panics
111    ///
112    /// Panics if `slice` is less than 12 elements long.
113    #[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    /// Writes the columns of `self` to the first 12 elements in `slice`.
123    ///
124    /// # Panics
125    ///
126    /// Panics if `slice` is less than 12 elements long.
127    #[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    /// Creates an affine transform that changes scale.
134    /// Note that if any scale is zero the transform will be non-invertible.
135    #[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    /// Creates an affine transform from the given `rotation` quaternion.
144    ///
145    /// # Panics
146    ///
147    /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
148    #[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    /// Creates an affine transform containing a 3D rotation around a normalized
159    /// rotation `axis` of `angle` (in radians).
160    ///
161    /// # Panics
162    ///
163    /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
164    #[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    /// Creates an affine transform containing a 3D rotation around the x axis of
175    /// `angle` (in radians).
176    #[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    /// Creates an affine transform containing a 3D rotation around the y axis of
186    /// `angle` (in radians).
187    #[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    /// Creates an affine transform containing a 3D rotation around the z axis of
197    /// `angle` (in radians).
198    #[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    /// Creates an affine transformation from the given 3D `translation`.
208    #[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    /// Creates an affine transform from a 3x3 matrix (expressing scale, shear and
219    /// rotation)
220    #[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    /// Creates an affine transform from a 3x3 matrix (expressing scale, shear and rotation)
231    /// and a translation vector.
232    ///
233    /// Equivalent to `Affine3A::from_translation(translation) * Affine3A::from_mat3(mat3)`
234    #[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    /// Creates an affine transform from the given 3D `scale`, `rotation` and
245    /// `translation`.
246    ///
247    /// Equivalent to `Affine3A::from_translation(translation) *
248    /// Affine3A::from_quat(rotation) * Affine3A::from_scale(scale)`
249    ///
250    /// # Panics
251    ///
252    /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
253    #[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    /// Creates an affine transform from the given 3D `rotation` and `translation`.
270    ///
271    /// Equivalent to `Affine3A::from_translation(translation) * Affine3A::from_quat(rotation)`
272    ///
273    /// # Panics
274    ///
275    /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
276    #[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    /// The given `Mat4` must be an affine transform,
288    /// i.e. contain no perspective transform.
289    #[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    /// Extracts `scale`, `rotation` and `translation` from `self`.
303    ///
304    /// The transform is expected to be non-degenerate and without shearing, or the output
305    /// will be invalid.
306    ///
307    /// # Panics
308    ///
309    /// Will panic if the determinant `self.matrix3` is zero or if the resulting scale
310    /// vector contains any zero elements when `glam_assert` is enabled.
311    #[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    /// Transforms the given 3D points, applying shear, scale, rotation and translation.
340    #[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    /// Transforms the given 3D vector, applying shear, scale and rotation (but NOT
351    /// translation).
352    ///
353    /// To also apply translation, use [`Self::transform_point3()`] instead.
354    #[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    /// Transforms the given [`Vec3A`], applying shear, scale, rotation and translation.
365    #[inline]
366    #[must_use]
367    pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
368        self.matrix3 * rhs + self.translation
369    }
370
371    /// Transforms the given [`Vec3A`], applying shear, scale and rotation (but NOT
372    /// translation).
373    ///
374    /// To also apply translation, use [`Self::transform_point3a()`] instead.
375    #[inline]
376    #[must_use]
377    pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
378        self.matrix3 * rhs
379    }
380
381    /// Returns `true` if, and only if, all elements are finite.
382    ///
383    /// If any element is either `NaN`, positive or negative infinity, this will return
384    /// `false`.
385    #[inline]
386    #[must_use]
387    pub fn is_finite(&self) -> bool {
388        self.matrix3.is_finite() && self.translation.is_finite()
389    }
390
391    /// Returns `true` if any elements are `NaN`.
392    #[inline]
393    #[must_use]
394    pub fn is_nan(&self) -> bool {
395        self.matrix3.is_nan() || self.translation.is_nan()
396    }
397
398    /// Returns true if the absolute difference of all elements between `self` and `rhs`
399    /// is less than or equal to `max_abs_diff`.
400    ///
401    /// This can be used to compare if two 3x4 matrices contain similar elements. It works
402    /// best when comparing with a known value. The `max_abs_diff` that should be used used
403    /// depends on the values being compared against.
404    ///
405    /// For more see
406    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
407    #[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    /// Return the inverse of this transform.
415    ///
416    /// Note that if the transform is not invertible the result will be invalid.
417    ///
418    /// # Panics
419    ///
420    /// Will panic if the resulting inverted matrix is not finite when `glam_assert` is enabled.
421    #[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        // transform negative translation by the matrix inverse:
427        let translation = -(matrix3 * self.translation);
428
429        Self {
430            matrix3,
431            translation,
432        }
433    }
434
435    /// Casts all elements of `self` to `f64`.
436    #[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}