glam/f32/
affine3a.rs

1// Generated from affine.rs.tera template. Edit the template, not the generated file.
2
3use crate::{Mat3, Mat3A, Mat4, Quat, Vec3, Vec3A};
4use core::ops::{Deref, DerefMut, Mul, MulAssign};
5
6/// A 3D affine transform, which can represent translation, rotation, scaling and shear.
7///
8/// This type is 16 byte aligned.
9#[derive(Copy, Clone)]
10#[repr(C)]
11pub struct Affine3A {
12    pub matrix3: Mat3A,
13    pub translation: Vec3A,
14}
15
16impl Affine3A {
17    /// The degenerate zero transform.
18    ///
19    /// This transforms any finite vector and point to zero.
20    /// The zero transform is non-invertible.
21    pub const ZERO: Self = Self {
22        matrix3: Mat3A::ZERO,
23        translation: Vec3A::ZERO,
24    };
25
26    /// The identity transform.
27    ///
28    /// Multiplying a vector with this returns the same vector.
29    pub const IDENTITY: Self = Self {
30        matrix3: Mat3A::IDENTITY,
31        translation: Vec3A::ZERO,
32    };
33
34    /// All NAN:s.
35    pub const NAN: Self = Self {
36        matrix3: Mat3A::NAN,
37        translation: Vec3A::NAN,
38    };
39
40    /// Creates an affine transform from three column vectors.
41    #[inline(always)]
42    #[must_use]
43    pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A, w_axis: Vec3A) -> Self {
44        Self {
45            matrix3: Mat3A::from_cols(x_axis, y_axis, z_axis),
46            translation: w_axis,
47        }
48    }
49
50    /// Creates an affine transform from a `[f32; 12]` array stored in column major order.
51    #[inline]
52    #[must_use]
53    pub fn from_cols_array(m: &[f32; 12]) -> Self {
54        Self {
55            matrix3: Mat3A::from_cols_array(&[
56                m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8],
57            ]),
58            translation: Vec3A::from_array([m[9], m[10], m[11]]),
59        }
60    }
61
62    /// Creates a `[f32; 12]` array storing data in column major order.
63    #[inline]
64    #[must_use]
65    pub fn to_cols_array(&self) -> [f32; 12] {
66        let x = &self.matrix3.x_axis;
67        let y = &self.matrix3.y_axis;
68        let z = &self.matrix3.z_axis;
69        let w = &self.translation;
70        [x.x, x.y, x.z, y.x, y.y, y.z, z.x, z.y, z.z, w.x, w.y, w.z]
71    }
72
73    /// Creates an affine transform from a `[[f32; 3]; 4]`
74    /// 3D array stored in column major order.
75    /// If your data is in row major order you will need to `transpose` the returned
76    /// matrix.
77    #[inline]
78    #[must_use]
79    pub fn from_cols_array_2d(m: &[[f32; 3]; 4]) -> Self {
80        Self {
81            matrix3: Mat3A::from_cols(m[0].into(), m[1].into(), m[2].into()),
82            translation: m[3].into(),
83        }
84    }
85
86    /// Creates a `[[f32; 3]; 4]` 3D array storing data in
87    /// column major order.
88    /// If you require data in row major order `transpose` the matrix first.
89    #[inline]
90    #[must_use]
91    pub fn to_cols_array_2d(&self) -> [[f32; 3]; 4] {
92        [
93            self.matrix3.x_axis.into(),
94            self.matrix3.y_axis.into(),
95            self.matrix3.z_axis.into(),
96            self.translation.into(),
97        ]
98    }
99
100    /// Creates an affine transform from the first 12 values in `slice`.
101    ///
102    /// # Panics
103    ///
104    /// Panics if `slice` is less than 12 elements long.
105    #[inline]
106    #[must_use]
107    pub fn from_cols_slice(slice: &[f32]) -> Self {
108        Self {
109            matrix3: Mat3A::from_cols_slice(&slice[0..9]),
110            translation: Vec3A::from_slice(&slice[9..12]),
111        }
112    }
113
114    /// Writes the columns of `self` to the first 12 elements in `slice`.
115    ///
116    /// # Panics
117    ///
118    /// Panics if `slice` is less than 12 elements long.
119    #[inline]
120    pub fn write_cols_to_slice(self, slice: &mut [f32]) {
121        self.matrix3.write_cols_to_slice(&mut slice[0..9]);
122        self.translation.write_to_slice(&mut slice[9..12]);
123    }
124
125    /// Creates an affine transform that changes scale.
126    /// Note that if any scale is zero the transform will be non-invertible.
127    #[inline]
128    #[must_use]
129    pub fn from_scale(scale: Vec3) -> Self {
130        Self {
131            matrix3: Mat3A::from_diagonal(scale),
132            translation: Vec3A::ZERO,
133        }
134    }
135    /// Creates an affine transform from the given `rotation` quaternion.
136    #[inline]
137    #[must_use]
138    pub fn from_quat(rotation: Quat) -> Self {
139        Self {
140            matrix3: Mat3A::from_quat(rotation),
141            translation: Vec3A::ZERO,
142        }
143    }
144
145    /// Creates an affine transform containing a 3D rotation around a normalized
146    /// rotation `axis` of `angle` (in radians).
147    #[inline]
148    #[must_use]
149    pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
150        Self {
151            matrix3: Mat3A::from_axis_angle(axis, angle),
152            translation: Vec3A::ZERO,
153        }
154    }
155
156    /// Creates an affine transform containing a 3D rotation around the x axis of
157    /// `angle` (in radians).
158    #[inline]
159    #[must_use]
160    pub fn from_rotation_x(angle: f32) -> Self {
161        Self {
162            matrix3: Mat3A::from_rotation_x(angle),
163            translation: Vec3A::ZERO,
164        }
165    }
166
167    /// Creates an affine transform containing a 3D rotation around the y axis of
168    /// `angle` (in radians).
169    #[inline]
170    #[must_use]
171    pub fn from_rotation_y(angle: f32) -> Self {
172        Self {
173            matrix3: Mat3A::from_rotation_y(angle),
174            translation: Vec3A::ZERO,
175        }
176    }
177
178    /// Creates an affine transform containing a 3D rotation around the z axis of
179    /// `angle` (in radians).
180    #[inline]
181    #[must_use]
182    pub fn from_rotation_z(angle: f32) -> Self {
183        Self {
184            matrix3: Mat3A::from_rotation_z(angle),
185            translation: Vec3A::ZERO,
186        }
187    }
188
189    /// Creates an affine transformation from the given 3D `translation`.
190    #[inline]
191    #[must_use]
192    pub fn from_translation(translation: Vec3) -> Self {
193        #[allow(clippy::useless_conversion)]
194        Self {
195            matrix3: Mat3A::IDENTITY,
196            translation: translation.into(),
197        }
198    }
199
200    /// Creates an affine transform from a 3x3 matrix (expressing scale, shear and
201    /// rotation)
202    #[inline]
203    #[must_use]
204    pub fn from_mat3(mat3: Mat3) -> Self {
205        #[allow(clippy::useless_conversion)]
206        Self {
207            matrix3: mat3.into(),
208            translation: Vec3A::ZERO,
209        }
210    }
211
212    /// Creates an affine transform from a 3x3 matrix (expressing scale, shear and rotation)
213    /// and a translation vector.
214    ///
215    /// Equivalent to `Affine3A::from_translation(translation) * Affine3A::from_mat3(mat3)`
216    #[inline]
217    #[must_use]
218    pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
219        #[allow(clippy::useless_conversion)]
220        Self {
221            matrix3: mat3.into(),
222            translation: translation.into(),
223        }
224    }
225
226    /// Creates an affine transform from the given 3D `scale`, `rotation` and
227    /// `translation`.
228    ///
229    /// Equivalent to `Affine3A::from_translation(translation) *
230    /// Affine3A::from_quat(rotation) * Affine3A::from_scale(scale)`
231    #[inline]
232    #[must_use]
233    pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
234        let rotation = Mat3A::from_quat(rotation);
235        #[allow(clippy::useless_conversion)]
236        Self {
237            matrix3: Mat3A::from_cols(
238                rotation.x_axis * scale.x,
239                rotation.y_axis * scale.y,
240                rotation.z_axis * scale.z,
241            ),
242            translation: translation.into(),
243        }
244    }
245
246    /// Creates an affine transform from the given 3D `rotation` and `translation`.
247    ///
248    /// Equivalent to `Affine3A::from_translation(translation) * Affine3A::from_quat(rotation)`
249    #[inline]
250    #[must_use]
251    pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
252        #[allow(clippy::useless_conversion)]
253        Self {
254            matrix3: Mat3A::from_quat(rotation),
255            translation: translation.into(),
256        }
257    }
258
259    /// The given `Mat4` must be an affine transform,
260    /// i.e. contain no perspective transform.
261    #[inline]
262    #[must_use]
263    pub fn from_mat4(m: Mat4) -> Self {
264        Self {
265            matrix3: Mat3A::from_cols(
266                Vec3A::from_vec4(m.x_axis),
267                Vec3A::from_vec4(m.y_axis),
268                Vec3A::from_vec4(m.z_axis),
269            ),
270            translation: Vec3A::from_vec4(m.w_axis),
271        }
272    }
273
274    /// Extracts `scale`, `rotation` and `translation` from `self`.
275    ///
276    /// The transform is expected to be non-degenerate and without shearing, or the output
277    /// will be invalid.
278    ///
279    /// # Panics
280    ///
281    /// Will panic if the determinant `self.matrix3` is zero or if the resulting scale
282    /// vector contains any zero elements when `glam_assert` is enabled.
283    #[inline]
284    #[must_use]
285    pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
286        use crate::f32::math;
287        let det = self.matrix3.determinant();
288        glam_assert!(det != 0.0);
289
290        let scale = Vec3::new(
291            self.matrix3.x_axis.length() * math::signum(det),
292            self.matrix3.y_axis.length(),
293            self.matrix3.z_axis.length(),
294        );
295
296        glam_assert!(scale.cmpne(Vec3::ZERO).all());
297
298        let inv_scale = scale.recip();
299
300        #[allow(clippy::useless_conversion)]
301        let rotation = Quat::from_mat3(&Mat3::from_cols(
302            (self.matrix3.x_axis * inv_scale.x).into(),
303            (self.matrix3.y_axis * inv_scale.y).into(),
304            (self.matrix3.z_axis * inv_scale.z).into(),
305        ));
306
307        #[allow(clippy::useless_conversion)]
308        (scale, rotation, self.translation.into())
309    }
310
311    /// Creates a left-handed view transform using a camera position, an up direction, and a facing
312    /// direction.
313    ///
314    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
315    #[inline]
316    #[must_use]
317    pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
318        Self::look_to_rh(eye, -dir, up)
319    }
320
321    /// Creates a right-handed view transform using a camera position, an up direction, and a facing
322    /// direction.
323    ///
324    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
325    #[inline]
326    #[must_use]
327    pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
328        let f = dir.normalize();
329        let s = f.cross(up).normalize();
330        let u = s.cross(f);
331
332        Self {
333            matrix3: Mat3A::from_cols(
334                Vec3A::new(s.x, u.x, -f.x),
335                Vec3A::new(s.y, u.y, -f.y),
336                Vec3A::new(s.z, u.z, -f.z),
337            ),
338            translation: Vec3A::new(-eye.dot(s), -eye.dot(u), eye.dot(f)),
339        }
340    }
341
342    /// Creates a left-handed view transform using a camera position, an up direction, and a focal
343    /// point.
344    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
345    ///
346    /// # Panics
347    ///
348    /// Will panic if `up` is not normalized when `glam_assert` is enabled.
349    #[inline]
350    #[must_use]
351    pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
352        glam_assert!(up.is_normalized());
353        Self::look_to_lh(eye, center - eye, up)
354    }
355
356    /// Creates a right-handed view transform using a camera position, an up direction, and a focal
357    /// point.
358    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
359    ///
360    /// # Panics
361    ///
362    /// Will panic if `up` is not normalized when `glam_assert` is enabled.
363    #[inline]
364    #[must_use]
365    pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
366        glam_assert!(up.is_normalized());
367        Self::look_to_rh(eye, center - eye, up)
368    }
369
370    /// Transforms the given 3D points, applying shear, scale, rotation and translation.
371    #[inline]
372    pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
373        #[allow(clippy::useless_conversion)]
374        ((self.matrix3.x_axis * rhs.x)
375            + (self.matrix3.y_axis * rhs.y)
376            + (self.matrix3.z_axis * rhs.z)
377            + self.translation)
378            .into()
379    }
380
381    /// Transforms the given 3D vector, applying shear, scale and rotation (but NOT
382    /// translation).
383    ///
384    /// To also apply translation, use [`Self::transform_point3()`] instead.
385    #[inline]
386    #[must_use]
387    pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
388        #[allow(clippy::useless_conversion)]
389        ((self.matrix3.x_axis * rhs.x)
390            + (self.matrix3.y_axis * rhs.y)
391            + (self.matrix3.z_axis * rhs.z))
392            .into()
393    }
394
395    /// Transforms the given [`Vec3A`], applying shear, scale, rotation and translation.
396    #[inline]
397    #[must_use]
398    pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
399        self.matrix3 * rhs + self.translation
400    }
401
402    /// Transforms the given [`Vec3A`], applying shear, scale and rotation (but NOT
403    /// translation).
404    ///
405    /// To also apply translation, use [`Self::transform_point3a()`] instead.
406    #[inline]
407    #[must_use]
408    pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
409        self.matrix3 * rhs
410    }
411
412    /// Returns `true` if, and only if, all elements are finite.
413    ///
414    /// If any element is either `NaN`, positive or negative infinity, this will return
415    /// `false`.
416    #[inline]
417    #[must_use]
418    pub fn is_finite(&self) -> bool {
419        self.matrix3.is_finite() && self.translation.is_finite()
420    }
421
422    /// Returns `true` if any elements are `NaN`.
423    #[inline]
424    #[must_use]
425    pub fn is_nan(&self) -> bool {
426        self.matrix3.is_nan() || self.translation.is_nan()
427    }
428
429    /// Returns true if the absolute difference of all elements between `self` and `rhs`
430    /// is less than or equal to `max_abs_diff`.
431    ///
432    /// This can be used to compare if two 3x4 matrices contain similar elements. It works
433    /// best when comparing with a known value. The `max_abs_diff` that should be used used
434    /// depends on the values being compared against.
435    ///
436    /// For more see
437    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
438    #[inline]
439    #[must_use]
440    pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
441        self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff)
442            && self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
443    }
444
445    /// Return the inverse of this transform.
446    ///
447    /// Note that if the transform is not invertible the result will be invalid.
448    #[inline]
449    #[must_use]
450    pub fn inverse(&self) -> Self {
451        let matrix3 = self.matrix3.inverse();
452        // transform negative translation by the matrix inverse:
453        let translation = -(matrix3 * self.translation);
454
455        Self {
456            matrix3,
457            translation,
458        }
459    }
460}
461
462impl Default for Affine3A {
463    #[inline(always)]
464    fn default() -> Self {
465        Self::IDENTITY
466    }
467}
468
469impl Deref for Affine3A {
470    type Target = crate::deref::Cols4<Vec3A>;
471    #[inline(always)]
472    fn deref(&self) -> &Self::Target {
473        unsafe { &*(self as *const Self as *const Self::Target) }
474    }
475}
476
477impl DerefMut for Affine3A {
478    #[inline(always)]
479    fn deref_mut(&mut self) -> &mut Self::Target {
480        unsafe { &mut *(self as *mut Self as *mut Self::Target) }
481    }
482}
483
484impl PartialEq for Affine3A {
485    #[inline]
486    fn eq(&self, rhs: &Self) -> bool {
487        self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation)
488    }
489}
490
491impl core::fmt::Debug for Affine3A {
492    fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
493        fmt.debug_struct(stringify!(Affine3A))
494            .field("matrix3", &self.matrix3)
495            .field("translation", &self.translation)
496            .finish()
497    }
498}
499
500impl core::fmt::Display for Affine3A {
501    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
502        if let Some(p) = f.precision() {
503            write!(
504                f,
505                "[{:.*}, {:.*}, {:.*}, {:.*}]",
506                p,
507                self.matrix3.x_axis,
508                p,
509                self.matrix3.y_axis,
510                p,
511                self.matrix3.z_axis,
512                p,
513                self.translation
514            )
515        } else {
516            write!(
517                f,
518                "[{}, {}, {}, {}]",
519                self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation
520            )
521        }
522    }
523}
524
525impl<'a> core::iter::Product<&'a Self> for Affine3A {
526    fn product<I>(iter: I) -> Self
527    where
528        I: Iterator<Item = &'a Self>,
529    {
530        iter.fold(Self::IDENTITY, |a, &b| a * b)
531    }
532}
533
534impl Mul for Affine3A {
535    type Output = Affine3A;
536
537    #[inline]
538    fn mul(self, rhs: Affine3A) -> Self::Output {
539        Self {
540            matrix3: self.matrix3 * rhs.matrix3,
541            translation: self.matrix3 * rhs.translation + self.translation,
542        }
543    }
544}
545
546impl MulAssign for Affine3A {
547    #[inline]
548    fn mul_assign(&mut self, rhs: Affine3A) {
549        *self = self.mul(rhs);
550    }
551}
552
553impl From<Affine3A> for Mat4 {
554    #[inline]
555    fn from(m: Affine3A) -> Mat4 {
556        Mat4::from_cols(
557            m.matrix3.x_axis.extend(0.0),
558            m.matrix3.y_axis.extend(0.0),
559            m.matrix3.z_axis.extend(0.0),
560            m.translation.extend(1.0),
561        )
562    }
563}
564
565impl Mul<Mat4> for Affine3A {
566    type Output = Mat4;
567
568    #[inline]
569    fn mul(self, rhs: Mat4) -> Self::Output {
570        Mat4::from(self) * rhs
571    }
572}
573
574impl Mul<Affine3A> for Mat4 {
575    type Output = Mat4;
576
577    #[inline]
578    fn mul(self, rhs: Affine3A) -> Self::Output {
579        self * Mat4::from(rhs)
580    }
581}