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