Skip to main content

glam/f32/
affine3.rs

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