Skip to main content

glam/f32/sse2/
mat4.rs

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