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_affine3a(&self) -> crate::Affine3A {
458        crate::Affine3A::from_mat3_translation(self.matrix3.as_mat3(), self.translation.as_vec3())
459    }
460}
461
462impl Default for DAffine3 {
463    #[inline(always)]
464    fn default() -> Self {
465        Self::IDENTITY
466    }
467}
468
469impl Deref for DAffine3 {
470    type Target = crate::deref::Cols4<DVec3>;
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 DAffine3 {
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 DAffine3 {
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 DAffine3 {
492    fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
493        fmt.debug_struct(stringify!(DAffine3))
494            .field("matrix3", &self.matrix3)
495            .field("translation", &self.translation)
496            .finish()
497    }
498}
499
500impl core::fmt::Display for DAffine3 {
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 DAffine3 {
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 DAffine3 {
535    type Output = Self;
536
537    #[inline]
538    fn mul(self, rhs: Self) -> Self {
539        Self {
540            matrix3: self.matrix3 * rhs.matrix3,
541            translation: self.matrix3 * rhs.translation + self.translation,
542        }
543    }
544}
545
546impl Mul<&Self> for DAffine3 {
547    type Output = Self;
548    #[inline]
549    fn mul(self, rhs: &Self) -> Self {
550        self.mul(*rhs)
551    }
552}
553
554impl Mul<&DAffine3> for &DAffine3 {
555    type Output = DAffine3;
556    #[inline]
557    fn mul(self, rhs: &DAffine3) -> DAffine3 {
558        (*self).mul(*rhs)
559    }
560}
561
562impl Mul<DAffine3> for &DAffine3 {
563    type Output = DAffine3;
564    #[inline]
565    fn mul(self, rhs: DAffine3) -> DAffine3 {
566        (*self).mul(rhs)
567    }
568}
569
570impl MulAssign for DAffine3 {
571    #[inline]
572    fn mul_assign(&mut self, rhs: Self) {
573        *self = self.mul(rhs);
574    }
575}
576
577impl MulAssign<&Self> for DAffine3 {
578    #[inline]
579    fn mul_assign(&mut self, rhs: &Self) {
580        self.mul_assign(*rhs);
581    }
582}
583
584impl Mul<DMat4> for DAffine3 {
585    type Output = DMat4;
586
587    #[inline]
588    fn mul(self, rhs: DMat4) -> Self::Output {
589        DMat4::from(self) * rhs
590    }
591}
592
593impl Mul<&DMat4> for DAffine3 {
594    type Output = DMat4;
595    #[inline]
596    fn mul(self, rhs: &DMat4) -> DMat4 {
597        self.mul(*rhs)
598    }
599}
600
601impl Mul<&DMat4> for &DAffine3 {
602    type Output = DMat4;
603    #[inline]
604    fn mul(self, rhs: &DMat4) -> DMat4 {
605        (*self).mul(*rhs)
606    }
607}
608
609impl Mul<DMat4> for &DAffine3 {
610    type Output = DMat4;
611    #[inline]
612    fn mul(self, rhs: DMat4) -> DMat4 {
613        (*self).mul(rhs)
614    }
615}
616
617impl Mul<DAffine3> for DMat4 {
618    type Output = Self;
619
620    #[inline]
621    fn mul(self, rhs: DAffine3) -> Self {
622        self * Self::from(rhs)
623    }
624}
625
626impl Mul<&DAffine3> for DMat4 {
627    type Output = Self;
628    #[inline]
629    fn mul(self, rhs: &DAffine3) -> Self {
630        self.mul(*rhs)
631    }
632}
633
634impl Mul<&DAffine3> for &DMat4 {
635    type Output = DMat4;
636    #[inline]
637    fn mul(self, rhs: &DAffine3) -> DMat4 {
638        (*self).mul(*rhs)
639    }
640}
641
642impl Mul<DAffine3> for &DMat4 {
643    type Output = DMat4;
644    #[inline]
645    fn mul(self, rhs: DAffine3) -> DMat4 {
646        (*self).mul(rhs)
647    }
648}
649
650impl MulAssign<DAffine3> for DMat4 {
651    #[inline]
652    fn mul_assign(&mut self, rhs: DAffine3) {
653        *self = self.mul(rhs);
654    }
655}
656
657impl MulAssign<&DAffine3> for DMat4 {
658    #[inline]
659    fn mul_assign(&mut self, rhs: &DAffine3) {
660        self.mul_assign(*rhs);
661    }
662}
663
664impl From<DAffine3> for DMat4 {
665    #[inline]
666    fn from(m: DAffine3) -> Self {
667        Self::from_cols(
668            m.matrix3.x_axis.extend(0.0),
669            m.matrix3.y_axis.extend(0.0),
670            m.matrix3.z_axis.extend(0.0),
671            m.translation.extend(1.0),
672        )
673    }
674}