glam/f32/sse2/
mat4.rs

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