glam/f64/
daffine3.rs

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