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