Skip to main content

glam/f64/
dmat4.rs

1// Generated from mat.rs.tera template. Edit the template, not the generated file.
2
3use crate::{
4    euler::{FromEuler, ToEuler},
5    f64::math,
6    swizzles::*,
7    DMat3, DQuat, DVec3, DVec4, EulerRot, Mat4,
8};
9use core::fmt;
10use core::iter::{Product, Sum};
11use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
12
13#[cfg(feature = "zerocopy")]
14use zerocopy_derive::*;
15
16/// Creates a 4x4 matrix from four column vectors.
17#[inline(always)]
18#[must_use]
19pub const fn dmat4(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> DMat4 {
20    DMat4::from_cols(x_axis, y_axis, z_axis, w_axis)
21}
22
23/// A 4x4 column major matrix.
24///
25/// If you are primarily dealing with 3D affine transformations
26/// considering using [`DAffine3`](crate::DAffine3) which is faster than a 4x4 matrix
27/// for some affine operations.
28///
29/// Affine transformations including 3D translation, rotation and scale can be created
30/// using methods such as [`Self::from_translation()`], [`Self::from_quat()`],
31/// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`].
32///
33/// The [`Self::transform_point3()`] and [`Self::transform_vector3()`] convenience methods
34/// are provided for performing affine transformations on 3D vectors and points. These
35/// multiply 3D inputs as 4D vectors with an implicit `w` value of `1` for points and `0`
36/// for vectors respectively. These methods assume that `Self` contains a valid affine
37/// transform.
38#[derive(Clone, Copy)]
39#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
40#[cfg_attr(
41    feature = "zerocopy",
42    derive(FromBytes, Immutable, IntoBytes, KnownLayout)
43)]
44#[cfg_attr(feature = "cuda", repr(align(16)))]
45#[repr(C)]
46pub struct DMat4 {
47    pub x_axis: DVec4,
48    pub y_axis: DVec4,
49    pub z_axis: DVec4,
50    pub w_axis: DVec4,
51}
52
53impl DMat4 {
54    /// A 4x4 matrix with all elements set to `0.0`.
55    pub const ZERO: Self = Self::from_cols(DVec4::ZERO, DVec4::ZERO, DVec4::ZERO, DVec4::ZERO);
56
57    /// A 4x4 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
58    pub const IDENTITY: Self = Self::from_cols(DVec4::X, DVec4::Y, DVec4::Z, DVec4::W);
59
60    /// All NAN:s.
61    pub const NAN: Self = Self::from_cols(DVec4::NAN, DVec4::NAN, DVec4::NAN, DVec4::NAN);
62
63    #[allow(clippy::too_many_arguments)]
64    #[inline(always)]
65    #[must_use]
66    const fn new(
67        m00: f64,
68        m01: f64,
69        m02: f64,
70        m03: f64,
71        m10: f64,
72        m11: f64,
73        m12: f64,
74        m13: f64,
75        m20: f64,
76        m21: f64,
77        m22: f64,
78        m23: f64,
79        m30: f64,
80        m31: f64,
81        m32: f64,
82        m33: f64,
83    ) -> Self {
84        Self {
85            x_axis: DVec4::new(m00, m01, m02, m03),
86            y_axis: DVec4::new(m10, m11, m12, m13),
87            z_axis: DVec4::new(m20, m21, m22, m23),
88            w_axis: DVec4::new(m30, m31, m32, m33),
89        }
90    }
91
92    /// Creates a 4x4 matrix from four column vectors.
93    #[inline(always)]
94    #[must_use]
95    pub const fn from_cols(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> Self {
96        Self {
97            x_axis,
98            y_axis,
99            z_axis,
100            w_axis,
101        }
102    }
103
104    /// Creates a 4x4 matrix from a `[f64; 16]` array stored in column major order.
105    /// If your data is stored in row major you will need to `transpose` the returned
106    /// matrix.
107    #[inline]
108    #[must_use]
109    pub const fn from_cols_array(m: &[f64; 16]) -> Self {
110        Self::new(
111            m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13],
112            m[14], m[15],
113        )
114    }
115
116    /// Creates a `[f64; 16]` array storing data in column major order.
117    /// If you require data in row major order `transpose` the matrix first.
118    #[inline]
119    #[must_use]
120    pub const fn to_cols_array(&self) -> [f64; 16] {
121        [
122            self.x_axis.x,
123            self.x_axis.y,
124            self.x_axis.z,
125            self.x_axis.w,
126            self.y_axis.x,
127            self.y_axis.y,
128            self.y_axis.z,
129            self.y_axis.w,
130            self.z_axis.x,
131            self.z_axis.y,
132            self.z_axis.z,
133            self.z_axis.w,
134            self.w_axis.x,
135            self.w_axis.y,
136            self.w_axis.z,
137            self.w_axis.w,
138        ]
139    }
140
141    /// Creates a 4x4 matrix from a `[[f64; 4]; 4]` 4D array stored in column major order.
142    /// If your data is in row major order you will need to `transpose` the returned
143    /// matrix.
144    #[inline]
145    #[must_use]
146    pub const fn from_cols_array_2d(m: &[[f64; 4]; 4]) -> Self {
147        Self::from_cols(
148            DVec4::from_array(m[0]),
149            DVec4::from_array(m[1]),
150            DVec4::from_array(m[2]),
151            DVec4::from_array(m[3]),
152        )
153    }
154
155    /// Creates a `[[f64; 4]; 4]` 4D array storing data in column major order.
156    /// If you require data in row major order `transpose` the matrix first.
157    #[inline]
158    #[must_use]
159    pub const fn to_cols_array_2d(&self) -> [[f64; 4]; 4] {
160        [
161            self.x_axis.to_array(),
162            self.y_axis.to_array(),
163            self.z_axis.to_array(),
164            self.w_axis.to_array(),
165        ]
166    }
167
168    /// Creates a 4x4 matrix with its diagonal set to `diagonal` and all other entries set to 0.
169    #[doc(alias = "scale")]
170    #[inline]
171    #[must_use]
172    pub const fn from_diagonal(diagonal: DVec4) -> Self {
173        Self::new(
174            diagonal.x, 0.0, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, 0.0, diagonal.z, 0.0, 0.0,
175            0.0, 0.0, diagonal.w,
176        )
177    }
178
179    #[inline]
180    #[must_use]
181    fn quat_to_axes(rotation: DQuat) -> (DVec4, DVec4, DVec4) {
182        glam_assert!(rotation.is_normalized());
183
184        let (x, y, z, w) = rotation.into();
185        let x2 = x + x;
186        let y2 = y + y;
187        let z2 = z + z;
188        let xx = x * x2;
189        let xy = x * y2;
190        let xz = x * z2;
191        let yy = y * y2;
192        let yz = y * z2;
193        let zz = z * z2;
194        let wx = w * x2;
195        let wy = w * y2;
196        let wz = w * z2;
197
198        let x_axis = DVec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
199        let y_axis = DVec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
200        let z_axis = DVec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
201        (x_axis, y_axis, z_axis)
202    }
203
204    /// Creates an affine transformation matrix from the given 3D `scale`, `rotation` and
205    /// `translation`.
206    ///
207    /// The resulting matrix can be used to transform 3D points and vectors. See
208    /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
209    ///
210    /// # Panics
211    ///
212    /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
213    #[inline]
214    #[must_use]
215    pub fn from_scale_rotation_translation(
216        scale: DVec3,
217        rotation: DQuat,
218        translation: DVec3,
219    ) -> Self {
220        let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
221        Self::from_cols(
222            x_axis.mul(scale.x),
223            y_axis.mul(scale.y),
224            z_axis.mul(scale.z),
225            DVec4::from((translation, 1.0)),
226        )
227    }
228
229    /// Creates an affine transformation matrix from the given 3D `translation`.
230    ///
231    /// The resulting matrix can be used to transform 3D points and vectors. See
232    /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
233    ///
234    /// # Panics
235    ///
236    /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
237    #[inline]
238    #[must_use]
239    pub fn from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self {
240        let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
241        Self::from_cols(x_axis, y_axis, z_axis, DVec4::from((translation, 1.0)))
242    }
243
244    /// Extracts `scale`, `rotation` and `translation` from `self`. The input matrix is
245    /// expected to be a 3D affine transformation matrix otherwise the output will be invalid.
246    ///
247    /// # Panics
248    ///
249    /// Will panic if the determinant of `self` is zero or if the resulting scale vector
250    /// contains any zero elements when `glam_assert` is enabled.
251    #[inline]
252    #[must_use]
253    pub fn to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3) {
254        let det = self.determinant();
255        glam_assert!(det != 0.0);
256
257        let scale = DVec3::new(
258            self.x_axis.length() * math::signum(det),
259            self.y_axis.length(),
260            self.z_axis.length(),
261        );
262
263        glam_assert!(scale.cmpne(DVec3::ZERO).all());
264
265        let inv_scale = scale.recip();
266
267        let rotation = DQuat::from_rotation_axes(
268            self.x_axis.mul(inv_scale.x).xyz(),
269            self.y_axis.mul(inv_scale.y).xyz(),
270            self.z_axis.mul(inv_scale.z).xyz(),
271        );
272
273        let translation = self.w_axis.xyz();
274
275        (scale, rotation, translation)
276    }
277
278    /// Creates an affine transformation matrix from the given `rotation` quaternion.
279    ///
280    /// The resulting matrix can be used to transform 3D points and vectors. See
281    /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
282    ///
283    /// # Panics
284    ///
285    /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
286    #[inline]
287    #[must_use]
288    pub fn from_quat(rotation: DQuat) -> Self {
289        let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
290        Self::from_cols(x_axis, y_axis, z_axis, DVec4::W)
291    }
292
293    /// Creates an affine transformation matrix from the given 3x3 linear transformation
294    /// matrix.
295    ///
296    /// The resulting matrix can be used to transform 3D points and vectors. See
297    /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
298    #[inline]
299    #[must_use]
300    pub fn from_mat3(m: DMat3) -> Self {
301        Self::from_cols(
302            DVec4::from((m.x_axis, 0.0)),
303            DVec4::from((m.y_axis, 0.0)),
304            DVec4::from((m.z_axis, 0.0)),
305            DVec4::W,
306        )
307    }
308
309    /// Creates an affine transformation matrics from a 3x3 matrix (expressing scale, shear and
310    /// rotation) and a translation vector.
311    ///
312    /// Equivalent to `DMat4::from_translation(translation) * DMat4::from_mat3(mat3)`
313    #[inline]
314    #[must_use]
315    pub fn from_mat3_translation(mat3: DMat3, translation: DVec3) -> Self {
316        Self::from_cols(
317            DVec4::from((mat3.x_axis, 0.0)),
318            DVec4::from((mat3.y_axis, 0.0)),
319            DVec4::from((mat3.z_axis, 0.0)),
320            DVec4::from((translation, 1.0)),
321        )
322    }
323
324    /// Creates an affine transformation matrix from the given 3D `translation`.
325    ///
326    /// The resulting matrix can be used to transform 3D points and vectors. See
327    /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
328    #[inline]
329    #[must_use]
330    pub fn from_translation(translation: DVec3) -> Self {
331        Self::from_cols(
332            DVec4::X,
333            DVec4::Y,
334            DVec4::Z,
335            DVec4::new(translation.x, translation.y, translation.z, 1.0),
336        )
337    }
338
339    /// Creates an affine transformation matrix containing a 3D rotation around a normalized
340    /// rotation `axis` of `angle` (in radians).
341    ///
342    /// The resulting matrix can be used to transform 3D points and vectors. See
343    /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
344    ///
345    /// # Panics
346    ///
347    /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
348    #[inline]
349    #[must_use]
350    pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
351        glam_assert!(axis.is_normalized());
352
353        let (sin, cos) = math::sin_cos(angle);
354        let axis_sin = axis.mul(sin);
355        let axis_sq = axis.mul(axis);
356        let omc = 1.0 - cos;
357        let xyomc = axis.x * axis.y * omc;
358        let xzomc = axis.x * axis.z * omc;
359        let yzomc = axis.y * axis.z * omc;
360        Self::from_cols(
361            DVec4::new(
362                axis_sq.x * omc + cos,
363                xyomc + axis_sin.z,
364                xzomc - axis_sin.y,
365                0.0,
366            ),
367            DVec4::new(
368                xyomc - axis_sin.z,
369                axis_sq.y * omc + cos,
370                yzomc + axis_sin.x,
371                0.0,
372            ),
373            DVec4::new(
374                xzomc + axis_sin.y,
375                yzomc - axis_sin.x,
376                axis_sq.z * omc + cos,
377                0.0,
378            ),
379            DVec4::W,
380        )
381    }
382
383    /// Creates a affine transformation matrix containing a rotation from the given euler
384    /// rotation sequence and angles (in radians).
385    ///
386    /// The resulting matrix can be used to transform 3D points and vectors. See
387    /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
388    #[inline]
389    #[must_use]
390    pub fn from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self {
391        Self::from_euler_angles(order, a, b, c)
392    }
393
394    /// Extract Euler angles with the given Euler rotation order.
395    ///
396    /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations
397    /// then the resulting Euler angles will be ill-defined.
398    ///
399    /// # Panics
400    ///
401    /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when
402    /// `glam_assert` is enabled.
403    #[inline]
404    #[must_use]
405    pub fn to_euler(&self, order: EulerRot) -> (f64, f64, f64) {
406        glam_assert!(
407            self.x_axis.xyz().is_normalized()
408                && self.y_axis.xyz().is_normalized()
409                && self.z_axis.xyz().is_normalized()
410        );
411        self.to_euler_angles(order)
412    }
413
414    /// Creates an affine transformation matrix containing a 3D rotation around the x axis of
415    /// `angle` (in radians).
416    ///
417    /// The resulting matrix can be used to transform 3D points and vectors. See
418    /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
419    #[inline]
420    #[must_use]
421    pub fn from_rotation_x(angle: f64) -> Self {
422        let (sina, cosa) = math::sin_cos(angle);
423        Self::from_cols(
424            DVec4::X,
425            DVec4::new(0.0, cosa, sina, 0.0),
426            DVec4::new(0.0, -sina, cosa, 0.0),
427            DVec4::W,
428        )
429    }
430
431    /// Creates an affine transformation matrix containing a 3D rotation around the y axis of
432    /// `angle` (in radians).
433    ///
434    /// The resulting matrix can be used to transform 3D points and vectors. See
435    /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
436    #[inline]
437    #[must_use]
438    pub fn from_rotation_y(angle: f64) -> Self {
439        let (sina, cosa) = math::sin_cos(angle);
440        Self::from_cols(
441            DVec4::new(cosa, 0.0, -sina, 0.0),
442            DVec4::Y,
443            DVec4::new(sina, 0.0, cosa, 0.0),
444            DVec4::W,
445        )
446    }
447
448    /// Creates an affine transformation matrix containing a 3D rotation around the z axis of
449    /// `angle` (in radians).
450    ///
451    /// The resulting matrix can be used to transform 3D points and vectors. See
452    /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
453    #[inline]
454    #[must_use]
455    pub fn from_rotation_z(angle: f64) -> Self {
456        let (sina, cosa) = math::sin_cos(angle);
457        Self::from_cols(
458            DVec4::new(cosa, sina, 0.0, 0.0),
459            DVec4::new(-sina, cosa, 0.0, 0.0),
460            DVec4::Z,
461            DVec4::W,
462        )
463    }
464
465    /// Creates an affine transformation matrix containing the given 3D non-uniform `scale`.
466    ///
467    /// The resulting matrix can be used to transform 3D points and vectors. See
468    /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
469    ///
470    /// # Panics
471    ///
472    /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
473    #[inline]
474    #[must_use]
475    pub fn from_scale(scale: DVec3) -> Self {
476        // Do not panic as long as any component is non-zero
477        glam_assert!(scale.cmpne(DVec3::ZERO).any());
478
479        Self::from_cols(
480            DVec4::new(scale.x, 0.0, 0.0, 0.0),
481            DVec4::new(0.0, scale.y, 0.0, 0.0),
482            DVec4::new(0.0, 0.0, scale.z, 0.0),
483            DVec4::W,
484        )
485    }
486
487    /// Creates a 4x4 matrix from the first 16 values in `slice`.
488    ///
489    /// # Panics
490    ///
491    /// Panics if `slice` is less than 16 elements long.
492    #[inline]
493    #[must_use]
494    pub const fn from_cols_slice(slice: &[f64]) -> Self {
495        Self::new(
496            slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
497            slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
498        )
499    }
500
501    /// Writes the columns of `self` to the first 16 elements in `slice`.
502    ///
503    /// # Panics
504    ///
505    /// Panics if `slice` is less than 16 elements long.
506    #[inline]
507    pub fn write_cols_to_slice(&self, slice: &mut [f64]) {
508        slice[0] = self.x_axis.x;
509        slice[1] = self.x_axis.y;
510        slice[2] = self.x_axis.z;
511        slice[3] = self.x_axis.w;
512        slice[4] = self.y_axis.x;
513        slice[5] = self.y_axis.y;
514        slice[6] = self.y_axis.z;
515        slice[7] = self.y_axis.w;
516        slice[8] = self.z_axis.x;
517        slice[9] = self.z_axis.y;
518        slice[10] = self.z_axis.z;
519        slice[11] = self.z_axis.w;
520        slice[12] = self.w_axis.x;
521        slice[13] = self.w_axis.y;
522        slice[14] = self.w_axis.z;
523        slice[15] = self.w_axis.w;
524    }
525
526    /// Returns the matrix column for the given `index`.
527    ///
528    /// # Panics
529    ///
530    /// Panics if `index` is greater than 3.
531    #[inline]
532    #[must_use]
533    pub fn col(&self, index: usize) -> DVec4 {
534        match index {
535            0 => self.x_axis,
536            1 => self.y_axis,
537            2 => self.z_axis,
538            3 => self.w_axis,
539            _ => panic!("index out of bounds"),
540        }
541    }
542
543    /// Returns a mutable reference to the matrix column for the given `index`.
544    ///
545    /// # Panics
546    ///
547    /// Panics if `index` is greater than 3.
548    #[inline]
549    pub fn col_mut(&mut self, index: usize) -> &mut DVec4 {
550        match index {
551            0 => &mut self.x_axis,
552            1 => &mut self.y_axis,
553            2 => &mut self.z_axis,
554            3 => &mut self.w_axis,
555            _ => panic!("index out of bounds"),
556        }
557    }
558
559    /// Returns the matrix row for the given `index`.
560    ///
561    /// # Panics
562    ///
563    /// Panics if `index` is greater than 3.
564    #[inline]
565    #[must_use]
566    pub fn row(&self, index: usize) -> DVec4 {
567        match index {
568            0 => DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
569            1 => DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
570            2 => DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
571            3 => DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
572            _ => panic!("index out of bounds"),
573        }
574    }
575
576    /// Returns `true` if, and only if, all elements are finite.
577    /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
578    #[inline]
579    #[must_use]
580    pub fn is_finite(&self) -> bool {
581        self.x_axis.is_finite()
582            && self.y_axis.is_finite()
583            && self.z_axis.is_finite()
584            && self.w_axis.is_finite()
585    }
586
587    /// Returns `true` if any elements are `NaN`.
588    #[inline]
589    #[must_use]
590    pub fn is_nan(&self) -> bool {
591        self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
592    }
593
594    /// Returns the transpose of `self`.
595    #[inline]
596    #[must_use]
597    pub fn transpose(&self) -> Self {
598        Self {
599            x_axis: DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
600            y_axis: DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
601            z_axis: DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
602            w_axis: DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
603        }
604    }
605
606    /// Returns the diagonal of `self`.
607    #[inline]
608    #[must_use]
609    pub fn diagonal(&self) -> DVec4 {
610        DVec4::new(self.x_axis.x, self.y_axis.y, self.z_axis.z, self.w_axis.w)
611    }
612
613    /// Returns the determinant of `self`.
614    #[must_use]
615    pub fn determinant(&self) -> f64 {
616        let (m00, m01, m02, m03) = self.x_axis.into();
617        let (m10, m11, m12, m13) = self.y_axis.into();
618        let (m20, m21, m22, m23) = self.z_axis.into();
619        let (m30, m31, m32, m33) = self.w_axis.into();
620
621        let a2323 = m22 * m33 - m23 * m32;
622        let a1323 = m21 * m33 - m23 * m31;
623        let a1223 = m21 * m32 - m22 * m31;
624        let a0323 = m20 * m33 - m23 * m30;
625        let a0223 = m20 * m32 - m22 * m30;
626        let a0123 = m20 * m31 - m21 * m30;
627
628        m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223)
629            - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223)
630            + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123)
631            - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123)
632    }
633
634    /// If `CHECKED` is true then if the determinant is zero this function will return a tuple
635    /// containing a zero matrix and false. If the determinant is non zero a tuple containing the
636    /// inverted matrix and true is returned.
637    ///
638    /// If `CHECKED` is false then the determinant is not checked and if it is zero the resulting
639    /// inverted matrix will be invalid. Will panic if the determinant of `self` is zero when
640    /// `glam_assert` is enabled.
641    ///
642    /// A tuple containing the inverted matrix and a bool is used instead of an option here as
643    /// regular Rust enums put the discriminant first which can result in a lot of padding if the
644    /// matrix is aligned.
645    #[inline(always)]
646    #[must_use]
647    fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
648        let (m00, m01, m02, m03) = self.x_axis.into();
649        let (m10, m11, m12, m13) = self.y_axis.into();
650        let (m20, m21, m22, m23) = self.z_axis.into();
651        let (m30, m31, m32, m33) = self.w_axis.into();
652
653        let coef00 = m22 * m33 - m32 * m23;
654        let coef02 = m12 * m33 - m32 * m13;
655        let coef03 = m12 * m23 - m22 * m13;
656
657        let coef04 = m21 * m33 - m31 * m23;
658        let coef06 = m11 * m33 - m31 * m13;
659        let coef07 = m11 * m23 - m21 * m13;
660
661        let coef08 = m21 * m32 - m31 * m22;
662        let coef10 = m11 * m32 - m31 * m12;
663        let coef11 = m11 * m22 - m21 * m12;
664
665        let coef12 = m20 * m33 - m30 * m23;
666        let coef14 = m10 * m33 - m30 * m13;
667        let coef15 = m10 * m23 - m20 * m13;
668
669        let coef16 = m20 * m32 - m30 * m22;
670        let coef18 = m10 * m32 - m30 * m12;
671        let coef19 = m10 * m22 - m20 * m12;
672
673        let coef20 = m20 * m31 - m30 * m21;
674        let coef22 = m10 * m31 - m30 * m11;
675        let coef23 = m10 * m21 - m20 * m11;
676
677        let fac0 = DVec4::new(coef00, coef00, coef02, coef03);
678        let fac1 = DVec4::new(coef04, coef04, coef06, coef07);
679        let fac2 = DVec4::new(coef08, coef08, coef10, coef11);
680        let fac3 = DVec4::new(coef12, coef12, coef14, coef15);
681        let fac4 = DVec4::new(coef16, coef16, coef18, coef19);
682        let fac5 = DVec4::new(coef20, coef20, coef22, coef23);
683
684        let vec0 = DVec4::new(m10, m00, m00, m00);
685        let vec1 = DVec4::new(m11, m01, m01, m01);
686        let vec2 = DVec4::new(m12, m02, m02, m02);
687        let vec3 = DVec4::new(m13, m03, m03, m03);
688
689        let inv0 = vec1.mul(fac0).sub(vec2.mul(fac1)).add(vec3.mul(fac2));
690        let inv1 = vec0.mul(fac0).sub(vec2.mul(fac3)).add(vec3.mul(fac4));
691        let inv2 = vec0.mul(fac1).sub(vec1.mul(fac3)).add(vec3.mul(fac5));
692        let inv3 = vec0.mul(fac2).sub(vec1.mul(fac4)).add(vec2.mul(fac5));
693
694        let sign_a = DVec4::new(1.0, -1.0, 1.0, -1.0);
695        let sign_b = DVec4::new(-1.0, 1.0, -1.0, 1.0);
696
697        let inverse = Self::from_cols(
698            inv0.mul(sign_a),
699            inv1.mul(sign_b),
700            inv2.mul(sign_a),
701            inv3.mul(sign_b),
702        );
703
704        let col0 = DVec4::new(
705            inverse.x_axis.x,
706            inverse.y_axis.x,
707            inverse.z_axis.x,
708            inverse.w_axis.x,
709        );
710
711        let dot0 = self.x_axis.mul(col0);
712        let dot1 = dot0.x + dot0.y + dot0.z + dot0.w;
713
714        if CHECKED {
715            if dot1 == 0.0 {
716                return (Self::ZERO, false);
717            }
718        } else {
719            glam_assert!(dot1 != 0.0);
720        }
721
722        let rcp_det = dot1.recip();
723        (inverse.mul(rcp_det), true)
724    }
725
726    /// Returns the inverse of `self`.
727    ///
728    /// If the matrix is not invertible the returned matrix will be invalid.
729    ///
730    /// # Panics
731    ///
732    /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
733    #[must_use]
734    pub fn inverse(&self) -> Self {
735        self.inverse_checked::<false>().0
736    }
737
738    /// Returns the inverse of `self` or `None` if the matrix is not invertible.
739    #[must_use]
740    pub fn try_inverse(&self) -> Option<Self> {
741        let (m, is_valid) = self.inverse_checked::<true>();
742        if is_valid {
743            Some(m)
744        } else {
745            None
746        }
747    }
748
749    /// Returns the inverse of `self` or `DMat4::ZERO` if the matrix is not invertible.
750    #[must_use]
751    pub fn inverse_or_zero(&self) -> Self {
752        self.inverse_checked::<true>().0
753    }
754
755    /// Creates a left-handed view matrix using a camera position, a facing direction and an up
756    /// direction
757    ///
758    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
759    ///
760    /// # Panics
761    ///
762    /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled.
763    #[deprecated(
764        since = "0.33.1",
765        note = "use the `glam::dcamera::lh::view::look_to_mat4` function instead"
766    )]
767    #[inline]
768    #[must_use]
769    pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
770        #[allow(deprecated)]
771        Self::look_to_rh(eye, -dir, up)
772    }
773
774    /// Creates a right-handed view matrix using a camera position, a facing direction, and an up
775    /// direction.
776    ///
777    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
778    ///
779    /// # Panics
780    ///
781    /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled.
782    #[deprecated(
783        since = "0.33.1",
784        note = "use the `glam::dcamera::rh::view::look_to_mat4` function instead"
785    )]
786    #[inline]
787    #[must_use]
788    pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
789        glam_assert!(dir.is_normalized());
790        glam_assert!(up.is_normalized());
791        let f = dir;
792        let s = f.cross(up).normalize();
793        let u = s.cross(f);
794
795        Self::from_cols(
796            DVec4::new(s.x, u.x, -f.x, 0.0),
797            DVec4::new(s.y, u.y, -f.y, 0.0),
798            DVec4::new(s.z, u.z, -f.z, 0.0),
799            DVec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
800        )
801    }
802
803    /// Creates a left-handed view matrix using a camera position, a focal points and an up
804    /// direction.
805    ///
806    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
807    ///
808    /// # Panics
809    ///
810    /// Will panic if `up` is not normalized when `glam_assert` is enabled.
811    #[deprecated(
812        since = "0.33.1",
813        note = "use the `glam::dcamera::lh::view::look_at_mat4` function instead"
814    )]
815    #[inline]
816    #[must_use]
817    pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
818        #[allow(deprecated)]
819        Self::look_to_lh(eye, center.sub(eye).normalize(), up)
820    }
821
822    /// Creates a right-handed view matrix using a camera position, a focal point, and an up
823    /// direction.
824    ///
825    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
826    ///
827    /// # Panics
828    ///
829    /// Will panic if `up` is not normalized when `glam_assert` is enabled.
830    #[deprecated(
831        since = "0.33.1",
832        note = "use the `glam::dcamera::rh::view::look_at_mat4` function instead"
833    )]
834    #[inline]
835    pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
836        #[allow(deprecated)]
837        Self::look_to_rh(eye, center.sub(eye).normalize(), up)
838    }
839
840    /// Creates a right-handed perspective projection matrix with [-1,1] depth range.
841    ///
842    /// This is the same as the OpenGL `glFrustum` function.
843    ///
844    /// See <https://registry.khronos.org/OpenGL-Refpages/gl2.1/xhtml/glFrustum.xml>
845    #[deprecated(
846        since = "0.33.1",
847        note = "use the `glam::dcamera::rh::proj::opengl::frustum` function instead"
848    )]
849    #[inline]
850    #[must_use]
851    pub fn frustum_rh_gl(
852        left: f64,
853        right: f64,
854        bottom: f64,
855        top: f64,
856        z_near: f64,
857        z_far: f64,
858    ) -> Self {
859        let inv_width = 1.0 / (right - left);
860        let inv_height = 1.0 / (top - bottom);
861        let inv_depth = 1.0 / (z_far - z_near);
862        let a = (right + left) * inv_width;
863        let b = (top + bottom) * inv_height;
864        let c = -(z_far + z_near) * inv_depth;
865        let d = -(2.0 * z_far * z_near) * inv_depth;
866        let two_z_near = 2.0 * z_near;
867        Self::from_cols(
868            DVec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
869            DVec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
870            DVec4::new(a, b, c, -1.0),
871            DVec4::new(0.0, 0.0, d, 0.0),
872        )
873    }
874
875    /// Creates a left-handed perspective projection matrix with `[0,1]` depth range.
876    ///
877    /// # Panics
878    ///
879    /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
880    /// enabled.
881    #[deprecated(
882        since = "0.33.1",
883        note = "use the `glam::dcamera::lh::proj::directx::frustum` function instead"
884    )]
885    #[inline]
886    #[must_use]
887    pub fn frustum_lh(
888        left: f64,
889        right: f64,
890        bottom: f64,
891        top: f64,
892        z_near: f64,
893        z_far: f64,
894    ) -> Self {
895        glam_assert!(z_near > 0.0 && z_far > 0.0);
896        let inv_width = 1.0 / (right - left);
897        let inv_height = 1.0 / (top - bottom);
898        let inv_depth = 1.0 / (z_far - z_near);
899        let a = (right + left) * inv_width;
900        let b = (top + bottom) * inv_height;
901        let c = z_far * inv_depth;
902        let d = -(z_far * z_near) * inv_depth;
903        let two_z_near = 2.0 * z_near;
904        Self::from_cols(
905            DVec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
906            DVec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
907            DVec4::new(a, b, c, 1.0),
908            DVec4::new(0.0, 0.0, d, 0.0),
909        )
910    }
911
912    /// Creates a right-handed perspective projection matrix with `[0,1]` depth range.
913    ///
914    /// # Panics
915    ///
916    /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
917    /// enabled.
918    #[deprecated(
919        since = "0.33.1",
920        note = "use the `glam::dcamera::rh::proj::directx::frustum` function instead"
921    )]
922    #[inline]
923    #[must_use]
924    pub fn frustum_rh(
925        left: f64,
926        right: f64,
927        bottom: f64,
928        top: f64,
929        z_near: f64,
930        z_far: f64,
931    ) -> Self {
932        glam_assert!(z_near > 0.0 && z_far > 0.0);
933        let inv_width = 1.0 / (right - left);
934        let inv_height = 1.0 / (top - bottom);
935        let inv_depth = 1.0 / (z_far - z_near);
936        let a = (right + left) * inv_width;
937        let b = (top + bottom) * inv_height;
938        let c = -z_far * inv_depth;
939        let d = -(z_far * z_near) * inv_depth;
940        let two_z_near = 2.0 * z_near;
941        Self::from_cols(
942            DVec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
943            DVec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
944            DVec4::new(a, b, c, -1.0),
945            DVec4::new(0.0, 0.0, d, 0.0),
946        )
947    }
948
949    /// Creates a right-handed perspective projection matrix with `[-1,1]` depth range.
950    ///
951    /// Useful to map the standard right-handed coordinate system into what OpenGL expects.
952    ///
953    /// This is the same as the OpenGL `gluPerspective` function.
954    /// See <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml>
955    #[deprecated(
956        since = "0.33.1",
957        note = "use the `glam::dcamera::rh::proj::opengl::perspective` function instead"
958    )]
959    #[inline]
960    #[must_use]
961    pub fn perspective_rh_gl(
962        fov_y_radians: f64,
963        aspect_ratio: f64,
964        z_near: f64,
965        z_far: f64,
966    ) -> Self {
967        let inv_length = 1.0 / (z_near - z_far);
968        let f = 1.0 / math::tan(0.5 * fov_y_radians);
969        let a = f / aspect_ratio;
970        let b = (z_near + z_far) * inv_length;
971        let c = (2.0 * z_near * z_far) * inv_length;
972        Self::from_cols(
973            DVec4::new(a, 0.0, 0.0, 0.0),
974            DVec4::new(0.0, f, 0.0, 0.0),
975            DVec4::new(0.0, 0.0, b, -1.0),
976            DVec4::new(0.0, 0.0, c, 0.0),
977        )
978    }
979
980    /// Creates a left-handed perspective projection matrix with `[0,1]` depth range.
981    ///
982    /// Useful to map the standard left-handed coordinate system into what WebGPU/Metal/Direct3D expect.
983    ///
984    /// # Panics
985    ///
986    /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
987    /// enabled.
988    #[deprecated(
989        since = "0.33.1",
990        note = "use the `glam::dcamera::lh::proj::directx::perspective` function instead"
991    )]
992    #[inline]
993    #[must_use]
994    pub fn perspective_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
995        glam_assert!(z_near > 0.0 && z_far > 0.0);
996        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
997        let h = cos_fov / sin_fov;
998        let w = h / aspect_ratio;
999        let r = z_far / (z_far - z_near);
1000        Self::from_cols(
1001            DVec4::new(w, 0.0, 0.0, 0.0),
1002            DVec4::new(0.0, h, 0.0, 0.0),
1003            DVec4::new(0.0, 0.0, r, 1.0),
1004            DVec4::new(0.0, 0.0, -r * z_near, 0.0),
1005        )
1006    }
1007
1008    /// Creates a right-handed perspective projection matrix with `[0,1]` depth range.
1009    ///
1010    /// Useful to map the standard right-handed coordinate system into what WebGPU/Metal/Direct3D expect.
1011    ///
1012    /// # Panics
1013    ///
1014    /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
1015    /// enabled.
1016    #[deprecated(
1017        since = "0.33.1",
1018        note = "use the `glam::dcamera::rh::proj::directx::perspective` function instead"
1019    )]
1020    #[inline]
1021    #[must_use]
1022    pub fn perspective_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
1023        glam_assert!(z_near > 0.0 && z_far > 0.0);
1024        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1025        let h = cos_fov / sin_fov;
1026        let w = h / aspect_ratio;
1027        let r = z_far / (z_near - z_far);
1028        Self::from_cols(
1029            DVec4::new(w, 0.0, 0.0, 0.0),
1030            DVec4::new(0.0, h, 0.0, 0.0),
1031            DVec4::new(0.0, 0.0, r, -1.0),
1032            DVec4::new(0.0, 0.0, r * z_near, 0.0),
1033        )
1034    }
1035
1036    /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range.
1037    ///
1038    /// Like `perspective_lh`, but with an infinite value for `z_far`.
1039    /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`.
1040    ///
1041    /// # Panics
1042    ///
1043    /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
1044    /// enabled.
1045    #[deprecated(
1046        since = "0.33.1",
1047        note = "use the `glam::dcamera::lh::proj::directx::perspective_infinite` function instead"
1048    )]
1049    #[inline]
1050    #[must_use]
1051    pub fn perspective_infinite_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
1052        glam_assert!(z_near > 0.0);
1053        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1054        let h = cos_fov / sin_fov;
1055        let w = h / aspect_ratio;
1056        Self::from_cols(
1057            DVec4::new(w, 0.0, 0.0, 0.0),
1058            DVec4::new(0.0, h, 0.0, 0.0),
1059            DVec4::new(0.0, 0.0, 1.0, 1.0),
1060            DVec4::new(0.0, 0.0, -z_near, 0.0),
1061        )
1062    }
1063
1064    /// Creates an infinite reverse left-handed perspective projection matrix with `[0,1]` depth range.
1065    ///
1066    /// Similar to `perspective_infinite_lh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`.
1067    ///
1068    /// # Panics
1069    ///
1070    /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
1071    #[deprecated(
1072        since = "0.33.1",
1073        note = "use the `glam::dcamera::lh::proj::directx::perspective_infinite_reverse` function instead"
1074    )]
1075    #[inline]
1076    #[must_use]
1077    pub fn perspective_infinite_reverse_lh(
1078        fov_y_radians: f64,
1079        aspect_ratio: f64,
1080        z_near: f64,
1081    ) -> Self {
1082        glam_assert!(z_near > 0.0);
1083        let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1084        let h = cos_fov / sin_fov;
1085        let w = h / aspect_ratio;
1086        Self::from_cols(
1087            DVec4::new(w, 0.0, 0.0, 0.0),
1088            DVec4::new(0.0, h, 0.0, 0.0),
1089            DVec4::new(0.0, 0.0, 0.0, 1.0),
1090            DVec4::new(0.0, 0.0, z_near, 0.0),
1091        )
1092    }
1093
1094    /// Creates an infinite right-handed perspective projection matrix with `[0,1]` depth range.
1095    ///
1096    /// Like `perspective_rh`, but with an infinite value for `z_far`.
1097    /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`.
1098    ///
1099    /// # Panics
1100    ///
1101    /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
1102    /// enabled.
1103    #[deprecated(
1104        since = "0.33.1",
1105        note = "use the `glam::dcamera::rh::proj::directx::perspective_infinite` function instead"
1106    )]
1107    #[inline]
1108    #[must_use]
1109    pub fn perspective_infinite_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
1110        glam_assert!(z_near > 0.0);
1111        let f = 1.0 / math::tan(0.5 * fov_y_radians);
1112        Self::from_cols(
1113            DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1114            DVec4::new(0.0, f, 0.0, 0.0),
1115            DVec4::new(0.0, 0.0, -1.0, -1.0),
1116            DVec4::new(0.0, 0.0, -z_near, 0.0),
1117        )
1118    }
1119
1120    /// Creates an infinite reverse right-handed perspective projection matrix with `[0,1]` depth range.
1121    ///
1122    /// Similar to `perspective_infinite_rh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`.
1123    ///
1124    /// # Panics
1125    ///
1126    /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
1127    #[deprecated(
1128        since = "0.33.1",
1129        note = "use the `glam::dcamera::rh::proj::directx::perspective_infinite_reverse` function instead"
1130    )]
1131    #[inline]
1132    #[must_use]
1133    pub fn perspective_infinite_reverse_rh(
1134        fov_y_radians: f64,
1135        aspect_ratio: f64,
1136        z_near: f64,
1137    ) -> Self {
1138        glam_assert!(z_near > 0.0);
1139        let f = 1.0 / math::tan(0.5 * fov_y_radians);
1140        Self::from_cols(
1141            DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1142            DVec4::new(0.0, f, 0.0, 0.0),
1143            DVec4::new(0.0, 0.0, 0.0, -1.0),
1144            DVec4::new(0.0, 0.0, z_near, 0.0),
1145        )
1146    }
1147
1148    /// Creates a right-handed orthographic projection matrix with `[-1,1]` depth
1149    /// range.  This is the same as the OpenGL `glOrtho` function in OpenGL.
1150    /// See
1151    /// <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml>
1152    ///
1153    /// Useful to map a right-handed coordinate system to the normalized device coordinates that OpenGL expects.
1154    #[deprecated(
1155        since = "0.33.1",
1156        note = "use the `glam::dcamera::rh::proj::opengl::orthographic` function instead"
1157    )]
1158    #[inline]
1159    #[must_use]
1160    pub fn orthographic_rh_gl(
1161        left: f64,
1162        right: f64,
1163        bottom: f64,
1164        top: f64,
1165        near: f64,
1166        far: f64,
1167    ) -> Self {
1168        let a = 2.0 / (right - left);
1169        let b = 2.0 / (top - bottom);
1170        let c = 2.0 / (near - far);
1171        let tx = -(right + left) / (right - left);
1172        let ty = -(top + bottom) / (top - bottom);
1173        let tz = -(far + near) / (far - near);
1174
1175        Self::from_cols(
1176            DVec4::new(a, 0.0, 0.0, 0.0),
1177            DVec4::new(0.0, b, 0.0, 0.0),
1178            DVec4::new(0.0, 0.0, c, 0.0),
1179            DVec4::new(tx, ty, tz, 1.0),
1180        )
1181    }
1182
1183    /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range.
1184    ///
1185    /// Useful to map a left-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect.
1186    #[deprecated(
1187        since = "0.33.1",
1188        note = "use the `glam::dcamera::lh::proj::directx::orthographic` function instead"
1189    )]
1190    #[inline]
1191    #[must_use]
1192    pub fn orthographic_lh(
1193        left: f64,
1194        right: f64,
1195        bottom: f64,
1196        top: f64,
1197        near: f64,
1198        far: f64,
1199    ) -> Self {
1200        let rcp_width = 1.0 / (right - left);
1201        let rcp_height = 1.0 / (top - bottom);
1202        let r = 1.0 / (far - near);
1203        Self::from_cols(
1204            DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1205            DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1206            DVec4::new(0.0, 0.0, r, 0.0),
1207            DVec4::new(
1208                -(left + right) * rcp_width,
1209                -(top + bottom) * rcp_height,
1210                -r * near,
1211                1.0,
1212            ),
1213        )
1214    }
1215
1216    /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range.
1217    ///
1218    /// Useful to map a right-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect.
1219    #[deprecated(
1220        since = "0.33.1",
1221        note = "use the `glam::dcamera::rh::proj::directx::orthographic` function instead"
1222    )]
1223    #[inline]
1224    #[must_use]
1225    pub fn orthographic_rh(
1226        left: f64,
1227        right: f64,
1228        bottom: f64,
1229        top: f64,
1230        near: f64,
1231        far: f64,
1232    ) -> Self {
1233        let rcp_width = 1.0 / (right - left);
1234        let rcp_height = 1.0 / (top - bottom);
1235        let r = 1.0 / (near - far);
1236        Self::from_cols(
1237            DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1238            DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1239            DVec4::new(0.0, 0.0, r, 0.0),
1240            DVec4::new(
1241                -(left + right) * rcp_width,
1242                -(top + bottom) * rcp_height,
1243                r * near,
1244                1.0,
1245            ),
1246        )
1247    }
1248
1249    /// Transforms the given 3D vector as a point, applying perspective correction.
1250    ///
1251    /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is `1.0`.
1252    /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
1253    ///
1254    /// This method assumes that `self` contains a projective transform.
1255    #[inline]
1256    #[must_use]
1257    pub fn project_point3(&self, rhs: DVec3) -> DVec3 {
1258        let mut res = self.x_axis.mul(rhs.x);
1259        res = self.y_axis.mul(rhs.y).add(res);
1260        res = self.z_axis.mul(rhs.z).add(res);
1261        res = self.w_axis.add(res);
1262        res = res.div(res.w);
1263        res.xyz()
1264    }
1265
1266    /// Transforms the given 3D vector as a point.
1267    ///
1268    /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
1269    /// `1.0`.
1270    ///
1271    /// This method assumes that `self` contains a valid affine transform. It does not perform
1272    /// a perspective divide, if `self` contains a perspective transform, or if you are unsure,
1273    /// the [`Self::project_point3()`] method should be used instead.
1274    ///
1275    /// # Panics
1276    ///
1277    /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1278    #[inline]
1279    #[must_use]
1280    pub fn transform_point3(&self, rhs: DVec3) -> DVec3 {
1281        glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
1282        let mut res = self.x_axis.mul(rhs.x);
1283        res = self.y_axis.mul(rhs.y).add(res);
1284        res = self.z_axis.mul(rhs.z).add(res);
1285        res = self.w_axis.add(res);
1286        res.xyz()
1287    }
1288
1289    /// Transforms the given 3D vector as a direction.
1290    ///
1291    /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
1292    /// `0.0`.
1293    ///
1294    /// This method assumes that `self` contains a valid affine transform.
1295    ///
1296    /// # Panics
1297    ///
1298    /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1299    #[inline]
1300    #[must_use]
1301    pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 {
1302        glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
1303        let mut res = self.x_axis.mul(rhs.x);
1304        res = self.y_axis.mul(rhs.y).add(res);
1305        res = self.z_axis.mul(rhs.z).add(res);
1306        res.xyz()
1307    }
1308
1309    /// Transforms a 4D vector.
1310    #[inline]
1311    #[must_use]
1312    pub fn mul_vec4(&self, rhs: DVec4) -> DVec4 {
1313        let mut res = self.x_axis.mul(rhs.x);
1314        res = res.add(self.y_axis.mul(rhs.y));
1315        res = res.add(self.z_axis.mul(rhs.z));
1316        res = res.add(self.w_axis.mul(rhs.w));
1317        res
1318    }
1319
1320    /// Transforms a 4D vector by the transpose of `self`.
1321    #[inline]
1322    #[must_use]
1323    pub fn mul_transpose_vec4(&self, rhs: DVec4) -> DVec4 {
1324        DVec4::new(
1325            self.x_axis.dot(rhs),
1326            self.y_axis.dot(rhs),
1327            self.z_axis.dot(rhs),
1328            self.w_axis.dot(rhs),
1329        )
1330    }
1331
1332    /// Multiplies two 4x4 matrices.
1333    #[inline]
1334    #[must_use]
1335    pub fn mul_mat4(&self, rhs: &Self) -> Self {
1336        self.mul(rhs)
1337    }
1338
1339    /// Adds two 4x4 matrices.
1340    #[inline]
1341    #[must_use]
1342    pub fn add_mat4(&self, rhs: &Self) -> Self {
1343        self.add(rhs)
1344    }
1345
1346    /// Subtracts two 4x4 matrices.
1347    #[inline]
1348    #[must_use]
1349    pub fn sub_mat4(&self, rhs: &Self) -> Self {
1350        self.sub(rhs)
1351    }
1352
1353    /// Multiplies a 4x4 matrix by a scalar.
1354    #[inline]
1355    #[must_use]
1356    pub fn mul_scalar(&self, rhs: f64) -> Self {
1357        Self::from_cols(
1358            self.x_axis.mul(rhs),
1359            self.y_axis.mul(rhs),
1360            self.z_axis.mul(rhs),
1361            self.w_axis.mul(rhs),
1362        )
1363    }
1364
1365    /// Multiply `self` by a scaling vector `scale`.
1366    /// This is faster than creating a whole diagonal scaling matrix and then multiplying that.
1367    /// This operation is commutative.
1368    #[inline]
1369    #[must_use]
1370    pub fn mul_diagonal_scale(&self, scale: DVec4) -> Self {
1371        Self::from_cols(
1372            self.x_axis * scale.x,
1373            self.y_axis * scale.y,
1374            self.z_axis * scale.z,
1375            self.w_axis * scale.w,
1376        )
1377    }
1378
1379    /// Divides a 4x4 matrix by a scalar.
1380    #[inline]
1381    #[must_use]
1382    pub fn div_scalar(&self, rhs: f64) -> Self {
1383        let rhs = DVec4::splat(rhs);
1384        Self::from_cols(
1385            self.x_axis.div(rhs),
1386            self.y_axis.div(rhs),
1387            self.z_axis.div(rhs),
1388            self.w_axis.div(rhs),
1389        )
1390    }
1391
1392    /// Returns a matrix containing the reciprocal `1.0/n` of each element of `self`.
1393    #[inline]
1394    #[must_use]
1395    pub fn recip(&self) -> Self {
1396        Self::from_cols(
1397            self.x_axis.recip(),
1398            self.y_axis.recip(),
1399            self.z_axis.recip(),
1400            self.w_axis.recip(),
1401        )
1402    }
1403
1404    /// Returns true if the absolute difference of all elements between `self` and `rhs`
1405    /// is less than or equal to `max_abs_diff`.
1406    ///
1407    /// This can be used to compare if two matrices contain similar elements. It works best
1408    /// when comparing with a known value. The `max_abs_diff` that should be used used
1409    /// depends on the values being compared against.
1410    ///
1411    /// For more see
1412    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
1413    #[inline]
1414    #[must_use]
1415    pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
1416        self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1417            && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1418            && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1419            && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1420    }
1421
1422    /// Takes the absolute value of each element in `self`
1423    #[inline]
1424    #[must_use]
1425    pub fn abs(&self) -> Self {
1426        Self::from_cols(
1427            self.x_axis.abs(),
1428            self.y_axis.abs(),
1429            self.z_axis.abs(),
1430            self.w_axis.abs(),
1431        )
1432    }
1433
1434    #[cfg(feature = "f64")]
1435    #[inline]
1436    #[must_use]
1437    pub fn as_mat4(&self) -> Mat4 {
1438        Mat4::from_cols(
1439            self.x_axis.as_vec4(),
1440            self.y_axis.as_vec4(),
1441            self.z_axis.as_vec4(),
1442            self.w_axis.as_vec4(),
1443        )
1444    }
1445}
1446
1447impl Default for DMat4 {
1448    #[inline]
1449    fn default() -> Self {
1450        Self::IDENTITY
1451    }
1452}
1453
1454impl Add for DMat4 {
1455    type Output = Self;
1456    #[inline]
1457    fn add(self, rhs: Self) -> Self {
1458        Self::from_cols(
1459            self.x_axis.add(rhs.x_axis),
1460            self.y_axis.add(rhs.y_axis),
1461            self.z_axis.add(rhs.z_axis),
1462            self.w_axis.add(rhs.w_axis),
1463        )
1464    }
1465}
1466
1467impl Add<&Self> for DMat4 {
1468    type Output = Self;
1469    #[inline]
1470    fn add(self, rhs: &Self) -> Self {
1471        self.add(*rhs)
1472    }
1473}
1474
1475impl Add<&DMat4> for &DMat4 {
1476    type Output = DMat4;
1477    #[inline]
1478    fn add(self, rhs: &DMat4) -> DMat4 {
1479        (*self).add(*rhs)
1480    }
1481}
1482
1483impl Add<DMat4> for &DMat4 {
1484    type Output = DMat4;
1485    #[inline]
1486    fn add(self, rhs: DMat4) -> DMat4 {
1487        (*self).add(rhs)
1488    }
1489}
1490
1491impl AddAssign for DMat4 {
1492    #[inline]
1493    fn add_assign(&mut self, rhs: Self) {
1494        *self = self.add(rhs);
1495    }
1496}
1497
1498impl AddAssign<&Self> for DMat4 {
1499    #[inline]
1500    fn add_assign(&mut self, rhs: &Self) {
1501        self.add_assign(*rhs);
1502    }
1503}
1504
1505impl Sub for DMat4 {
1506    type Output = Self;
1507    #[inline]
1508    fn sub(self, rhs: Self) -> Self {
1509        Self::from_cols(
1510            self.x_axis.sub(rhs.x_axis),
1511            self.y_axis.sub(rhs.y_axis),
1512            self.z_axis.sub(rhs.z_axis),
1513            self.w_axis.sub(rhs.w_axis),
1514        )
1515    }
1516}
1517
1518impl Sub<&Self> for DMat4 {
1519    type Output = Self;
1520    #[inline]
1521    fn sub(self, rhs: &Self) -> Self {
1522        self.sub(*rhs)
1523    }
1524}
1525
1526impl Sub<&DMat4> for &DMat4 {
1527    type Output = DMat4;
1528    #[inline]
1529    fn sub(self, rhs: &DMat4) -> DMat4 {
1530        (*self).sub(*rhs)
1531    }
1532}
1533
1534impl Sub<DMat4> for &DMat4 {
1535    type Output = DMat4;
1536    #[inline]
1537    fn sub(self, rhs: DMat4) -> DMat4 {
1538        (*self).sub(rhs)
1539    }
1540}
1541
1542impl SubAssign for DMat4 {
1543    #[inline]
1544    fn sub_assign(&mut self, rhs: Self) {
1545        *self = self.sub(rhs);
1546    }
1547}
1548
1549impl SubAssign<&Self> for DMat4 {
1550    #[inline]
1551    fn sub_assign(&mut self, rhs: &Self) {
1552        self.sub_assign(*rhs);
1553    }
1554}
1555
1556impl Neg for DMat4 {
1557    type Output = Self;
1558    #[inline]
1559    fn neg(self) -> Self::Output {
1560        Self::from_cols(
1561            self.x_axis.neg(),
1562            self.y_axis.neg(),
1563            self.z_axis.neg(),
1564            self.w_axis.neg(),
1565        )
1566    }
1567}
1568
1569impl Neg for &DMat4 {
1570    type Output = DMat4;
1571    #[inline]
1572    fn neg(self) -> DMat4 {
1573        (*self).neg()
1574    }
1575}
1576
1577impl Mul for DMat4 {
1578    type Output = Self;
1579    #[inline]
1580    fn mul(self, rhs: Self) -> Self {
1581        Self::from_cols(
1582            self.mul(rhs.x_axis),
1583            self.mul(rhs.y_axis),
1584            self.mul(rhs.z_axis),
1585            self.mul(rhs.w_axis),
1586        )
1587    }
1588}
1589
1590impl Mul<&Self> for DMat4 {
1591    type Output = Self;
1592    #[inline]
1593    fn mul(self, rhs: &Self) -> Self {
1594        self.mul(*rhs)
1595    }
1596}
1597
1598impl Mul<&DMat4> for &DMat4 {
1599    type Output = DMat4;
1600    #[inline]
1601    fn mul(self, rhs: &DMat4) -> DMat4 {
1602        (*self).mul(*rhs)
1603    }
1604}
1605
1606impl Mul<DMat4> for &DMat4 {
1607    type Output = DMat4;
1608    #[inline]
1609    fn mul(self, rhs: DMat4) -> DMat4 {
1610        (*self).mul(rhs)
1611    }
1612}
1613
1614impl MulAssign for DMat4 {
1615    #[inline]
1616    fn mul_assign(&mut self, rhs: Self) {
1617        *self = self.mul(rhs);
1618    }
1619}
1620
1621impl MulAssign<&Self> for DMat4 {
1622    #[inline]
1623    fn mul_assign(&mut self, rhs: &Self) {
1624        self.mul_assign(*rhs);
1625    }
1626}
1627
1628impl Mul<DVec4> for DMat4 {
1629    type Output = DVec4;
1630    #[inline]
1631    fn mul(self, rhs: DVec4) -> Self::Output {
1632        self.mul_vec4(rhs)
1633    }
1634}
1635
1636impl Mul<&DVec4> for DMat4 {
1637    type Output = DVec4;
1638    #[inline]
1639    fn mul(self, rhs: &DVec4) -> DVec4 {
1640        self.mul(*rhs)
1641    }
1642}
1643
1644impl Mul<&DVec4> for &DMat4 {
1645    type Output = DVec4;
1646    #[inline]
1647    fn mul(self, rhs: &DVec4) -> DVec4 {
1648        (*self).mul(*rhs)
1649    }
1650}
1651
1652impl Mul<DVec4> for &DMat4 {
1653    type Output = DVec4;
1654    #[inline]
1655    fn mul(self, rhs: DVec4) -> DVec4 {
1656        (*self).mul(rhs)
1657    }
1658}
1659
1660impl Mul<DMat4> for f64 {
1661    type Output = DMat4;
1662    #[inline]
1663    fn mul(self, rhs: DMat4) -> Self::Output {
1664        rhs.mul_scalar(self)
1665    }
1666}
1667
1668impl Mul<&DMat4> for f64 {
1669    type Output = DMat4;
1670    #[inline]
1671    fn mul(self, rhs: &DMat4) -> DMat4 {
1672        self.mul(*rhs)
1673    }
1674}
1675
1676impl Mul<&DMat4> for &f64 {
1677    type Output = DMat4;
1678    #[inline]
1679    fn mul(self, rhs: &DMat4) -> DMat4 {
1680        (*self).mul(*rhs)
1681    }
1682}
1683
1684impl Mul<DMat4> for &f64 {
1685    type Output = DMat4;
1686    #[inline]
1687    fn mul(self, rhs: DMat4) -> DMat4 {
1688        (*self).mul(rhs)
1689    }
1690}
1691
1692impl Mul<f64> for DMat4 {
1693    type Output = Self;
1694    #[inline]
1695    fn mul(self, rhs: f64) -> Self {
1696        self.mul_scalar(rhs)
1697    }
1698}
1699
1700impl Mul<&f64> for DMat4 {
1701    type Output = Self;
1702    #[inline]
1703    fn mul(self, rhs: &f64) -> Self {
1704        self.mul(*rhs)
1705    }
1706}
1707
1708impl Mul<&f64> for &DMat4 {
1709    type Output = DMat4;
1710    #[inline]
1711    fn mul(self, rhs: &f64) -> DMat4 {
1712        (*self).mul(*rhs)
1713    }
1714}
1715
1716impl Mul<f64> for &DMat4 {
1717    type Output = DMat4;
1718    #[inline]
1719    fn mul(self, rhs: f64) -> DMat4 {
1720        (*self).mul(rhs)
1721    }
1722}
1723
1724impl MulAssign<f64> for DMat4 {
1725    #[inline]
1726    fn mul_assign(&mut self, rhs: f64) {
1727        *self = self.mul(rhs);
1728    }
1729}
1730
1731impl MulAssign<&f64> for DMat4 {
1732    #[inline]
1733    fn mul_assign(&mut self, rhs: &f64) {
1734        self.mul_assign(*rhs);
1735    }
1736}
1737
1738impl Div<DMat4> for f64 {
1739    type Output = DMat4;
1740    #[inline]
1741    fn div(self, rhs: DMat4) -> Self::Output {
1742        DMat4::from_cols(
1743            self.div(rhs.x_axis),
1744            self.div(rhs.y_axis),
1745            self.div(rhs.z_axis),
1746            self.div(rhs.w_axis),
1747        )
1748    }
1749}
1750
1751impl Div<&DMat4> for f64 {
1752    type Output = DMat4;
1753    #[inline]
1754    fn div(self, rhs: &DMat4) -> DMat4 {
1755        self.div(*rhs)
1756    }
1757}
1758
1759impl Div<&DMat4> for &f64 {
1760    type Output = DMat4;
1761    #[inline]
1762    fn div(self, rhs: &DMat4) -> DMat4 {
1763        (*self).div(*rhs)
1764    }
1765}
1766
1767impl Div<DMat4> for &f64 {
1768    type Output = DMat4;
1769    #[inline]
1770    fn div(self, rhs: DMat4) -> DMat4 {
1771        (*self).div(rhs)
1772    }
1773}
1774
1775impl Div<f64> for DMat4 {
1776    type Output = Self;
1777    #[inline]
1778    fn div(self, rhs: f64) -> Self {
1779        self.div_scalar(rhs)
1780    }
1781}
1782
1783impl Div<&f64> for DMat4 {
1784    type Output = Self;
1785    #[inline]
1786    fn div(self, rhs: &f64) -> Self {
1787        self.div(*rhs)
1788    }
1789}
1790
1791impl Div<&f64> for &DMat4 {
1792    type Output = DMat4;
1793    #[inline]
1794    fn div(self, rhs: &f64) -> DMat4 {
1795        (*self).div(*rhs)
1796    }
1797}
1798
1799impl Div<f64> for &DMat4 {
1800    type Output = DMat4;
1801    #[inline]
1802    fn div(self, rhs: f64) -> DMat4 {
1803        (*self).div(rhs)
1804    }
1805}
1806
1807impl DivAssign<f64> for DMat4 {
1808    #[inline]
1809    fn div_assign(&mut self, rhs: f64) {
1810        *self = self.div(rhs);
1811    }
1812}
1813
1814impl DivAssign<&f64> for DMat4 {
1815    #[inline]
1816    fn div_assign(&mut self, rhs: &f64) {
1817        self.div_assign(*rhs);
1818    }
1819}
1820
1821impl Sum<Self> for DMat4 {
1822    fn sum<I>(iter: I) -> Self
1823    where
1824        I: Iterator<Item = Self>,
1825    {
1826        iter.fold(Self::ZERO, Self::add)
1827    }
1828}
1829
1830impl<'a> Sum<&'a Self> for DMat4 {
1831    fn sum<I>(iter: I) -> Self
1832    where
1833        I: Iterator<Item = &'a Self>,
1834    {
1835        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1836    }
1837}
1838
1839impl Product for DMat4 {
1840    fn product<I>(iter: I) -> Self
1841    where
1842        I: Iterator<Item = Self>,
1843    {
1844        iter.fold(Self::IDENTITY, Self::mul)
1845    }
1846}
1847
1848impl<'a> Product<&'a Self> for DMat4 {
1849    fn product<I>(iter: I) -> Self
1850    where
1851        I: Iterator<Item = &'a Self>,
1852    {
1853        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1854    }
1855}
1856
1857impl PartialEq for DMat4 {
1858    #[inline]
1859    fn eq(&self, rhs: &Self) -> bool {
1860        self.x_axis.eq(&rhs.x_axis)
1861            && self.y_axis.eq(&rhs.y_axis)
1862            && self.z_axis.eq(&rhs.z_axis)
1863            && self.w_axis.eq(&rhs.w_axis)
1864    }
1865}
1866
1867impl AsRef<[f64; 16]> for DMat4 {
1868    #[inline]
1869    fn as_ref(&self) -> &[f64; 16] {
1870        unsafe { &*(self as *const Self as *const [f64; 16]) }
1871    }
1872}
1873
1874impl AsMut<[f64; 16]> for DMat4 {
1875    #[inline]
1876    fn as_mut(&mut self) -> &mut [f64; 16] {
1877        unsafe { &mut *(self as *mut Self as *mut [f64; 16]) }
1878    }
1879}
1880
1881impl fmt::Debug for DMat4 {
1882    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1883        fmt.debug_struct(stringify!(DMat4))
1884            .field("x_axis", &self.x_axis)
1885            .field("y_axis", &self.y_axis)
1886            .field("z_axis", &self.z_axis)
1887            .field("w_axis", &self.w_axis)
1888            .finish()
1889    }
1890}
1891
1892impl fmt::Display for DMat4 {
1893    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1894        if let Some(p) = f.precision() {
1895            write!(
1896                f,
1897                "[{:.*}, {:.*}, {:.*}, {:.*}]",
1898                p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
1899            )
1900        } else {
1901            write!(
1902                f,
1903                "[{}, {}, {}, {}]",
1904                self.x_axis, self.y_axis, self.z_axis, self.w_axis
1905            )
1906        }
1907    }
1908}