1 // Generated from mat.rs.tera template. Edit the template, not the generated file.
2 
3 use crate::{f32::math, swizzles::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4};
4 #[cfg(not(target_arch = "spirv"))]
5 use core::fmt;
6 use core::iter::{Product, Sum};
7 use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
8 
9 /// Creates a 4x4 matrix from four column vectors.
10 #[inline(always)]
11 #[must_use]
mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat412 pub const fn mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat4 {
13     Mat4::from_cols(x_axis, y_axis, z_axis, w_axis)
14 }
15 
16 /// A 4x4 column major matrix.
17 ///
18 /// This 4x4 matrix type features convenience methods for creating and using affine transforms and
19 /// perspective projections. If you are primarily dealing with 3D affine transformations
20 /// considering using [`Affine3A`](crate::Affine3A) which is faster than a 4x4 matrix
21 /// for some affine operations.
22 ///
23 /// Affine transformations including 3D translation, rotation and scale can be created
24 /// using methods such as [`Self::from_translation()`], [`Self::from_quat()`],
25 /// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`].
26 ///
27 /// Orthographic projections can be created using the methods [`Self::orthographic_lh()`] for
28 /// left-handed coordinate systems and [`Self::orthographic_rh()`] for right-handed
29 /// systems. The resulting matrix is also an affine transformation.
30 ///
31 /// The [`Self::transform_point3()`] and [`Self::transform_vector3()`] convenience methods
32 /// are provided for performing affine transformations on 3D vectors and points. These
33 /// multiply 3D inputs as 4D vectors with an implicit `w` value of `1` for points and `0`
34 /// for vectors respectively. These methods assume that `Self` contains a valid affine
35 /// transform.
36 ///
37 /// Perspective projections can be created using methods such as
38 /// [`Self::perspective_lh()`], [`Self::perspective_infinite_lh()`] and
39 /// [`Self::perspective_infinite_reverse_lh()`] for left-handed co-ordinate systems and
40 /// [`Self::perspective_rh()`], [`Self::perspective_infinite_rh()`] and
41 /// [`Self::perspective_infinite_reverse_rh()`] for right-handed co-ordinate systems.
42 ///
43 /// The resulting perspective project can be use to transform 3D vectors as points with
44 /// perspective correction using the [`Self::project_point3()`] convenience method.
45 #[derive(Clone, Copy)]
46 #[cfg_attr(
47     any(
48         not(any(feature = "scalar-math", target_arch = "spirv")),
49         feature = "cuda"
50     ),
51     repr(align(16))
52 )]
53 #[repr(C)]
54 pub struct Mat4 {
55     pub x_axis: Vec4,
56     pub y_axis: Vec4,
57     pub z_axis: Vec4,
58     pub w_axis: Vec4,
59 }
60 
61 impl Mat4 {
62     /// A 4x4 matrix with all elements set to `0.0`.
63     pub const ZERO: Self = Self::from_cols(Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO);
64 
65     /// A 4x4 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
66     pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W);
67 
68     /// All NAN:s.
69     pub const NAN: Self = Self::from_cols(Vec4::NAN, Vec4::NAN, Vec4::NAN, Vec4::NAN);
70 
71     #[allow(clippy::too_many_arguments)]
72     #[inline(always)]
73     #[must_use]
new( m00: f32, m01: f32, m02: f32, m03: f32, m10: f32, m11: f32, m12: f32, m13: f32, m20: f32, m21: f32, m22: f32, m23: f32, m30: f32, m31: f32, m32: f32, m33: f32, ) -> Self74     const fn new(
75         m00: f32,
76         m01: f32,
77         m02: f32,
78         m03: f32,
79         m10: f32,
80         m11: f32,
81         m12: f32,
82         m13: f32,
83         m20: f32,
84         m21: f32,
85         m22: f32,
86         m23: f32,
87         m30: f32,
88         m31: f32,
89         m32: f32,
90         m33: f32,
91     ) -> Self {
92         Self {
93             x_axis: Vec4::new(m00, m01, m02, m03),
94             y_axis: Vec4::new(m10, m11, m12, m13),
95             z_axis: Vec4::new(m20, m21, m22, m23),
96             w_axis: Vec4::new(m30, m31, m32, m33),
97         }
98     }
99 
100     /// Creates a 4x4 matrix from four column vectors.
101     #[inline(always)]
102     #[must_use]
from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self103     pub const fn from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self {
104         Self {
105             x_axis,
106             y_axis,
107             z_axis,
108             w_axis,
109         }
110     }
111 
112     /// Creates a 4x4 matrix from a `[f32; 16]` array stored in column major order.
113     /// If your data is stored in row major you will need to `transpose` the returned
114     /// matrix.
115     #[inline]
116     #[must_use]
from_cols_array(m: &[f32; 16]) -> Self117     pub const fn from_cols_array(m: &[f32; 16]) -> Self {
118         Self::new(
119             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],
120             m[14], m[15],
121         )
122     }
123 
124     /// Creates a `[f32; 16]` array storing data in column major order.
125     /// If you require data in row major order `transpose` the matrix first.
126     #[inline]
127     #[must_use]
to_cols_array(&self) -> [f32; 16]128     pub const fn to_cols_array(&self) -> [f32; 16] {
129         [
130             self.x_axis.x,
131             self.x_axis.y,
132             self.x_axis.z,
133             self.x_axis.w,
134             self.y_axis.x,
135             self.y_axis.y,
136             self.y_axis.z,
137             self.y_axis.w,
138             self.z_axis.x,
139             self.z_axis.y,
140             self.z_axis.z,
141             self.z_axis.w,
142             self.w_axis.x,
143             self.w_axis.y,
144             self.w_axis.z,
145             self.w_axis.w,
146         ]
147     }
148 
149     /// Creates a 4x4 matrix from a `[[f32; 4]; 4]` 4D array stored in column major order.
150     /// If your data is in row major order you will need to `transpose` the returned
151     /// matrix.
152     #[inline]
153     #[must_use]
from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self154     pub const fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self {
155         Self::from_cols(
156             Vec4::from_array(m[0]),
157             Vec4::from_array(m[1]),
158             Vec4::from_array(m[2]),
159             Vec4::from_array(m[3]),
160         )
161     }
162 
163     /// Creates a `[[f32; 4]; 4]` 4D array storing data in column major order.
164     /// If you require data in row major order `transpose` the matrix first.
165     #[inline]
166     #[must_use]
to_cols_array_2d(&self) -> [[f32; 4]; 4]167     pub const fn to_cols_array_2d(&self) -> [[f32; 4]; 4] {
168         [
169             self.x_axis.to_array(),
170             self.y_axis.to_array(),
171             self.z_axis.to_array(),
172             self.w_axis.to_array(),
173         ]
174     }
175 
176     /// Creates a 4x4 matrix with its diagonal set to `diagonal` and all other entries set to 0.
177     #[doc(alias = "scale")]
178     #[inline]
179     #[must_use]
from_diagonal(diagonal: Vec4) -> Self180     pub const fn from_diagonal(diagonal: Vec4) -> Self {
181         Self::new(
182             diagonal.x, 0.0, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, 0.0, diagonal.z, 0.0, 0.0,
183             0.0, 0.0, diagonal.w,
184         )
185     }
186 
187     #[inline]
188     #[must_use]
quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4)189     fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) {
190         glam_assert!(rotation.is_normalized());
191 
192         let (x, y, z, w) = rotation.into();
193         let x2 = x + x;
194         let y2 = y + y;
195         let z2 = z + z;
196         let xx = x * x2;
197         let xy = x * y2;
198         let xz = x * z2;
199         let yy = y * y2;
200         let yz = y * z2;
201         let zz = z * z2;
202         let wx = w * x2;
203         let wy = w * y2;
204         let wz = w * z2;
205 
206         let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
207         let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
208         let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
209         (x_axis, y_axis, z_axis)
210     }
211 
212     /// Creates an affine transformation matrix from the given 3D `scale`, `rotation` and
213     /// `translation`.
214     ///
215     /// The resulting matrix can be used to transform 3D points and vectors. See
216     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
217     ///
218     /// # Panics
219     ///
220     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
221     #[inline]
222     #[must_use]
from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self223     pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
224         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
225         Self::from_cols(
226             x_axis.mul(scale.x),
227             y_axis.mul(scale.y),
228             z_axis.mul(scale.z),
229             Vec4::from((translation, 1.0)),
230         )
231     }
232 
233     /// Creates an affine transformation matrix from the given 3D `translation`.
234     ///
235     /// The resulting matrix can be used to transform 3D points and vectors. See
236     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
237     ///
238     /// # Panics
239     ///
240     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
241     #[inline]
242     #[must_use]
from_rotation_translation(rotation: Quat, translation: Vec3) -> Self243     pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
244         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
245         Self::from_cols(x_axis, y_axis, z_axis, Vec4::from((translation, 1.0)))
246     }
247 
248     /// Extracts `scale`, `rotation` and `translation` from `self`. The input matrix is
249     /// expected to be a 3D affine transformation matrix otherwise the output will be invalid.
250     ///
251     /// # Panics
252     ///
253     /// Will panic if the determinant of `self` is zero or if the resulting scale vector
254     /// contains any zero elements when `glam_assert` is enabled.
255     #[inline]
256     #[must_use]
to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3)257     pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
258         let det = self.determinant();
259         glam_assert!(det != 0.0);
260 
261         let scale = Vec3::new(
262             self.x_axis.length() * math::signum(det),
263             self.y_axis.length(),
264             self.z_axis.length(),
265         );
266 
267         glam_assert!(scale.cmpne(Vec3::ZERO).all());
268 
269         let inv_scale = scale.recip();
270 
271         let rotation = Quat::from_rotation_axes(
272             self.x_axis.mul(inv_scale.x).xyz(),
273             self.y_axis.mul(inv_scale.y).xyz(),
274             self.z_axis.mul(inv_scale.z).xyz(),
275         );
276 
277         let translation = self.w_axis.xyz();
278 
279         (scale, rotation, translation)
280     }
281 
282     /// Creates an affine transformation matrix from the given `rotation` quaternion.
283     ///
284     /// The resulting matrix can be used to transform 3D points and vectors. See
285     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
286     ///
287     /// # Panics
288     ///
289     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
290     #[inline]
291     #[must_use]
from_quat(rotation: Quat) -> Self292     pub fn from_quat(rotation: Quat) -> Self {
293         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
294         Self::from_cols(x_axis, y_axis, z_axis, Vec4::W)
295     }
296 
297     /// Creates an affine transformation matrix from the given 3x3 linear transformation
298     /// matrix.
299     ///
300     /// The resulting matrix can be used to transform 3D points and vectors. See
301     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
302     #[inline]
303     #[must_use]
from_mat3(m: Mat3) -> Self304     pub fn from_mat3(m: Mat3) -> Self {
305         Self::from_cols(
306             Vec4::from((m.x_axis, 0.0)),
307             Vec4::from((m.y_axis, 0.0)),
308             Vec4::from((m.z_axis, 0.0)),
309             Vec4::W,
310         )
311     }
312 
313     /// Creates an affine transformation matrix from the given 3x3 linear transformation
314     /// matrix.
315     ///
316     /// The resulting matrix can be used to transform 3D points and vectors. See
317     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
318     #[inline]
319     #[must_use]
from_mat3a(m: Mat3A) -> Self320     pub fn from_mat3a(m: Mat3A) -> Self {
321         Self::from_cols(
322             Vec4::from((m.x_axis, 0.0)),
323             Vec4::from((m.y_axis, 0.0)),
324             Vec4::from((m.z_axis, 0.0)),
325             Vec4::W,
326         )
327     }
328 
329     /// Creates an affine transformation matrix from the given 3D `translation`.
330     ///
331     /// The resulting matrix can be used to transform 3D points and vectors. See
332     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
333     #[inline]
334     #[must_use]
from_translation(translation: Vec3) -> Self335     pub fn from_translation(translation: Vec3) -> Self {
336         Self::from_cols(
337             Vec4::X,
338             Vec4::Y,
339             Vec4::Z,
340             Vec4::new(translation.x, translation.y, translation.z, 1.0),
341         )
342     }
343 
344     /// Creates an affine transformation matrix containing a 3D rotation around a normalized
345     /// rotation `axis` of `angle` (in radians).
346     ///
347     /// The resulting matrix can be used to transform 3D points and vectors. See
348     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
349     ///
350     /// # Panics
351     ///
352     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
353     #[inline]
354     #[must_use]
from_axis_angle(axis: Vec3, angle: f32) -> Self355     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
356         glam_assert!(axis.is_normalized());
357 
358         let (sin, cos) = math::sin_cos(angle);
359         let axis_sin = axis.mul(sin);
360         let axis_sq = axis.mul(axis);
361         let omc = 1.0 - cos;
362         let xyomc = axis.x * axis.y * omc;
363         let xzomc = axis.x * axis.z * omc;
364         let yzomc = axis.y * axis.z * omc;
365         Self::from_cols(
366             Vec4::new(
367                 axis_sq.x * omc + cos,
368                 xyomc + axis_sin.z,
369                 xzomc - axis_sin.y,
370                 0.0,
371             ),
372             Vec4::new(
373                 xyomc - axis_sin.z,
374                 axis_sq.y * omc + cos,
375                 yzomc + axis_sin.x,
376                 0.0,
377             ),
378             Vec4::new(
379                 xzomc + axis_sin.y,
380                 yzomc - axis_sin.x,
381                 axis_sq.z * omc + cos,
382                 0.0,
383             ),
384             Vec4::W,
385         )
386     }
387 
388     /// Creates a affine transformation matrix containing a rotation from the given euler
389     /// rotation sequence and angles (in radians).
390     ///
391     /// The resulting matrix can be used to transform 3D points and vectors. See
392     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
393     #[inline]
394     #[must_use]
from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self395     pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
396         let quat = Quat::from_euler(order, a, b, c);
397         Self::from_quat(quat)
398     }
399 
400     /// Creates an affine transformation matrix containing a 3D rotation around the x axis of
401     /// `angle` (in radians).
402     ///
403     /// The resulting matrix can be used to transform 3D points and vectors. See
404     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
405     #[inline]
406     #[must_use]
from_rotation_x(angle: f32) -> Self407     pub fn from_rotation_x(angle: f32) -> Self {
408         let (sina, cosa) = math::sin_cos(angle);
409         Self::from_cols(
410             Vec4::X,
411             Vec4::new(0.0, cosa, sina, 0.0),
412             Vec4::new(0.0, -sina, cosa, 0.0),
413             Vec4::W,
414         )
415     }
416 
417     /// Creates an affine transformation matrix containing a 3D rotation around the y axis of
418     /// `angle` (in radians).
419     ///
420     /// The resulting matrix can be used to transform 3D points and vectors. See
421     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
422     #[inline]
423     #[must_use]
from_rotation_y(angle: f32) -> Self424     pub fn from_rotation_y(angle: f32) -> Self {
425         let (sina, cosa) = math::sin_cos(angle);
426         Self::from_cols(
427             Vec4::new(cosa, 0.0, -sina, 0.0),
428             Vec4::Y,
429             Vec4::new(sina, 0.0, cosa, 0.0),
430             Vec4::W,
431         )
432     }
433 
434     /// Creates an affine transformation matrix containing a 3D rotation around the z axis of
435     /// `angle` (in radians).
436     ///
437     /// The resulting matrix can be used to transform 3D points and vectors. See
438     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
439     #[inline]
440     #[must_use]
from_rotation_z(angle: f32) -> Self441     pub fn from_rotation_z(angle: f32) -> Self {
442         let (sina, cosa) = math::sin_cos(angle);
443         Self::from_cols(
444             Vec4::new(cosa, sina, 0.0, 0.0),
445             Vec4::new(-sina, cosa, 0.0, 0.0),
446             Vec4::Z,
447             Vec4::W,
448         )
449     }
450 
451     /// Creates an affine transformation matrix containing the given 3D non-uniform `scale`.
452     ///
453     /// The resulting matrix can be used to transform 3D points and vectors. See
454     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
455     ///
456     /// # Panics
457     ///
458     /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
459     #[inline]
460     #[must_use]
from_scale(scale: Vec3) -> Self461     pub fn from_scale(scale: Vec3) -> Self {
462         // Do not panic as long as any component is non-zero
463         glam_assert!(scale.cmpne(Vec3::ZERO).any());
464 
465         Self::from_cols(
466             Vec4::new(scale.x, 0.0, 0.0, 0.0),
467             Vec4::new(0.0, scale.y, 0.0, 0.0),
468             Vec4::new(0.0, 0.0, scale.z, 0.0),
469             Vec4::W,
470         )
471     }
472 
473     /// Creates a 4x4 matrix from the first 16 values in `slice`.
474     ///
475     /// # Panics
476     ///
477     /// Panics if `slice` is less than 16 elements long.
478     #[inline]
479     #[must_use]
from_cols_slice(slice: &[f32]) -> Self480     pub const fn from_cols_slice(slice: &[f32]) -> Self {
481         Self::new(
482             slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
483             slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
484         )
485     }
486 
487     /// Writes the columns of `self` to the first 16 elements in `slice`.
488     ///
489     /// # Panics
490     ///
491     /// Panics if `slice` is less than 16 elements long.
492     #[inline]
write_cols_to_slice(self, slice: &mut [f32])493     pub fn write_cols_to_slice(self, slice: &mut [f32]) {
494         slice[0] = self.x_axis.x;
495         slice[1] = self.x_axis.y;
496         slice[2] = self.x_axis.z;
497         slice[3] = self.x_axis.w;
498         slice[4] = self.y_axis.x;
499         slice[5] = self.y_axis.y;
500         slice[6] = self.y_axis.z;
501         slice[7] = self.y_axis.w;
502         slice[8] = self.z_axis.x;
503         slice[9] = self.z_axis.y;
504         slice[10] = self.z_axis.z;
505         slice[11] = self.z_axis.w;
506         slice[12] = self.w_axis.x;
507         slice[13] = self.w_axis.y;
508         slice[14] = self.w_axis.z;
509         slice[15] = self.w_axis.w;
510     }
511 
512     /// Returns the matrix column for the given `index`.
513     ///
514     /// # Panics
515     ///
516     /// Panics if `index` is greater than 3.
517     #[inline]
518     #[must_use]
col(&self, index: usize) -> Vec4519     pub fn col(&self, index: usize) -> Vec4 {
520         match index {
521             0 => self.x_axis,
522             1 => self.y_axis,
523             2 => self.z_axis,
524             3 => self.w_axis,
525             _ => panic!("index out of bounds"),
526         }
527     }
528 
529     /// Returns a mutable reference to the matrix column for the given `index`.
530     ///
531     /// # Panics
532     ///
533     /// Panics if `index` is greater than 3.
534     #[inline]
col_mut(&mut self, index: usize) -> &mut Vec4535     pub fn col_mut(&mut self, index: usize) -> &mut Vec4 {
536         match index {
537             0 => &mut self.x_axis,
538             1 => &mut self.y_axis,
539             2 => &mut self.z_axis,
540             3 => &mut self.w_axis,
541             _ => panic!("index out of bounds"),
542         }
543     }
544 
545     /// Returns the matrix row for the given `index`.
546     ///
547     /// # Panics
548     ///
549     /// Panics if `index` is greater than 3.
550     #[inline]
551     #[must_use]
row(&self, index: usize) -> Vec4552     pub fn row(&self, index: usize) -> Vec4 {
553         match index {
554             0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
555             1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
556             2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
557             3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
558             _ => panic!("index out of bounds"),
559         }
560     }
561 
562     /// Returns `true` if, and only if, all elements are finite.
563     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
564     #[inline]
565     #[must_use]
is_finite(&self) -> bool566     pub fn is_finite(&self) -> bool {
567         self.x_axis.is_finite()
568             && self.y_axis.is_finite()
569             && self.z_axis.is_finite()
570             && self.w_axis.is_finite()
571     }
572 
573     /// Returns `true` if any elements are `NaN`.
574     #[inline]
575     #[must_use]
is_nan(&self) -> bool576     pub fn is_nan(&self) -> bool {
577         self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
578     }
579 
580     /// Returns the transpose of `self`.
581     #[inline]
582     #[must_use]
transpose(&self) -> Self583     pub fn transpose(&self) -> Self {
584         Self {
585             x_axis: Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
586             y_axis: Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
587             z_axis: Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
588             w_axis: Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
589         }
590     }
591 
592     /// Returns the determinant of `self`.
593     #[must_use]
determinant(&self) -> f32594     pub fn determinant(&self) -> f32 {
595         let (m00, m01, m02, m03) = self.x_axis.into();
596         let (m10, m11, m12, m13) = self.y_axis.into();
597         let (m20, m21, m22, m23) = self.z_axis.into();
598         let (m30, m31, m32, m33) = self.w_axis.into();
599 
600         let a2323 = m22 * m33 - m23 * m32;
601         let a1323 = m21 * m33 - m23 * m31;
602         let a1223 = m21 * m32 - m22 * m31;
603         let a0323 = m20 * m33 - m23 * m30;
604         let a0223 = m20 * m32 - m22 * m30;
605         let a0123 = m20 * m31 - m21 * m30;
606 
607         m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223)
608             - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223)
609             + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123)
610             - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123)
611     }
612 
613     /// Returns the inverse of `self`.
614     ///
615     /// If the matrix is not invertible the returned matrix will be invalid.
616     ///
617     /// # Panics
618     ///
619     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
620     #[must_use]
inverse(&self) -> Self621     pub fn inverse(&self) -> Self {
622         let (m00, m01, m02, m03) = self.x_axis.into();
623         let (m10, m11, m12, m13) = self.y_axis.into();
624         let (m20, m21, m22, m23) = self.z_axis.into();
625         let (m30, m31, m32, m33) = self.w_axis.into();
626 
627         let coef00 = m22 * m33 - m32 * m23;
628         let coef02 = m12 * m33 - m32 * m13;
629         let coef03 = m12 * m23 - m22 * m13;
630 
631         let coef04 = m21 * m33 - m31 * m23;
632         let coef06 = m11 * m33 - m31 * m13;
633         let coef07 = m11 * m23 - m21 * m13;
634 
635         let coef08 = m21 * m32 - m31 * m22;
636         let coef10 = m11 * m32 - m31 * m12;
637         let coef11 = m11 * m22 - m21 * m12;
638 
639         let coef12 = m20 * m33 - m30 * m23;
640         let coef14 = m10 * m33 - m30 * m13;
641         let coef15 = m10 * m23 - m20 * m13;
642 
643         let coef16 = m20 * m32 - m30 * m22;
644         let coef18 = m10 * m32 - m30 * m12;
645         let coef19 = m10 * m22 - m20 * m12;
646 
647         let coef20 = m20 * m31 - m30 * m21;
648         let coef22 = m10 * m31 - m30 * m11;
649         let coef23 = m10 * m21 - m20 * m11;
650 
651         let fac0 = Vec4::new(coef00, coef00, coef02, coef03);
652         let fac1 = Vec4::new(coef04, coef04, coef06, coef07);
653         let fac2 = Vec4::new(coef08, coef08, coef10, coef11);
654         let fac3 = Vec4::new(coef12, coef12, coef14, coef15);
655         let fac4 = Vec4::new(coef16, coef16, coef18, coef19);
656         let fac5 = Vec4::new(coef20, coef20, coef22, coef23);
657 
658         let vec0 = Vec4::new(m10, m00, m00, m00);
659         let vec1 = Vec4::new(m11, m01, m01, m01);
660         let vec2 = Vec4::new(m12, m02, m02, m02);
661         let vec3 = Vec4::new(m13, m03, m03, m03);
662 
663         let inv0 = vec1.mul(fac0).sub(vec2.mul(fac1)).add(vec3.mul(fac2));
664         let inv1 = vec0.mul(fac0).sub(vec2.mul(fac3)).add(vec3.mul(fac4));
665         let inv2 = vec0.mul(fac1).sub(vec1.mul(fac3)).add(vec3.mul(fac5));
666         let inv3 = vec0.mul(fac2).sub(vec1.mul(fac4)).add(vec2.mul(fac5));
667 
668         let sign_a = Vec4::new(1.0, -1.0, 1.0, -1.0);
669         let sign_b = Vec4::new(-1.0, 1.0, -1.0, 1.0);
670 
671         let inverse = Self::from_cols(
672             inv0.mul(sign_a),
673             inv1.mul(sign_b),
674             inv2.mul(sign_a),
675             inv3.mul(sign_b),
676         );
677 
678         let col0 = Vec4::new(
679             inverse.x_axis.x,
680             inverse.y_axis.x,
681             inverse.z_axis.x,
682             inverse.w_axis.x,
683         );
684 
685         let dot0 = self.x_axis.mul(col0);
686         let dot1 = dot0.x + dot0.y + dot0.z + dot0.w;
687 
688         glam_assert!(dot1 != 0.0);
689 
690         let rcp_det = dot1.recip();
691         inverse.mul(rcp_det)
692     }
693 
694     /// Creates a left-handed view matrix using a camera position, an up direction, and a facing
695     /// direction.
696     ///
697     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
698     #[inline]
699     #[must_use]
look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self700     pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
701         Self::look_to_rh(eye, -dir, up)
702     }
703 
704     /// Creates a right-handed view matrix using a camera position, an up direction, and a facing
705     /// direction.
706     ///
707     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
708     #[inline]
709     #[must_use]
look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self710     pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
711         let f = dir.normalize();
712         let s = f.cross(up).normalize();
713         let u = s.cross(f);
714 
715         Self::from_cols(
716             Vec4::new(s.x, u.x, -f.x, 0.0),
717             Vec4::new(s.y, u.y, -f.y, 0.0),
718             Vec4::new(s.z, u.z, -f.z, 0.0),
719             Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
720         )
721     }
722 
723     /// Creates a left-handed view matrix using a camera position, an up direction, and a focal
724     /// point.
725     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
726     ///
727     /// # Panics
728     ///
729     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
730     #[inline]
731     #[must_use]
look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self732     pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
733         glam_assert!(up.is_normalized());
734         Self::look_to_lh(eye, center.sub(eye), up)
735     }
736 
737     /// Creates a right-handed view matrix using a camera position, an up direction, and a focal
738     /// point.
739     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
740     ///
741     /// # Panics
742     ///
743     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
744     #[inline]
look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self745     pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
746         glam_assert!(up.is_normalized());
747         Self::look_to_rh(eye, center.sub(eye), up)
748     }
749 
750     /// Creates a right-handed perspective projection matrix with [-1,1] depth range.
751     /// This is the same as the OpenGL `gluPerspective` function.
752     /// See <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml>
753     #[inline]
754     #[must_use]
perspective_rh_gl( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32, ) -> Self755     pub fn perspective_rh_gl(
756         fov_y_radians: f32,
757         aspect_ratio: f32,
758         z_near: f32,
759         z_far: f32,
760     ) -> Self {
761         let inv_length = 1.0 / (z_near - z_far);
762         let f = 1.0 / math::tan(0.5 * fov_y_radians);
763         let a = f / aspect_ratio;
764         let b = (z_near + z_far) * inv_length;
765         let c = (2.0 * z_near * z_far) * inv_length;
766         Self::from_cols(
767             Vec4::new(a, 0.0, 0.0, 0.0),
768             Vec4::new(0.0, f, 0.0, 0.0),
769             Vec4::new(0.0, 0.0, b, -1.0),
770             Vec4::new(0.0, 0.0, c, 0.0),
771         )
772     }
773 
774     /// Creates a left-handed perspective projection matrix with `[0,1]` depth range.
775     ///
776     /// # Panics
777     ///
778     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
779     /// enabled.
780     #[inline]
781     #[must_use]
perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self782     pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
783         glam_assert!(z_near > 0.0 && z_far > 0.0);
784         let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
785         let h = cos_fov / sin_fov;
786         let w = h / aspect_ratio;
787         let r = z_far / (z_far - z_near);
788         Self::from_cols(
789             Vec4::new(w, 0.0, 0.0, 0.0),
790             Vec4::new(0.0, h, 0.0, 0.0),
791             Vec4::new(0.0, 0.0, r, 1.0),
792             Vec4::new(0.0, 0.0, -r * z_near, 0.0),
793         )
794     }
795 
796     /// Creates a right-handed perspective projection matrix with `[0,1]` depth range.
797     ///
798     /// # Panics
799     ///
800     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
801     /// enabled.
802     #[inline]
803     #[must_use]
perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self804     pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
805         glam_assert!(z_near > 0.0 && z_far > 0.0);
806         let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
807         let h = cos_fov / sin_fov;
808         let w = h / aspect_ratio;
809         let r = z_far / (z_near - z_far);
810         Self::from_cols(
811             Vec4::new(w, 0.0, 0.0, 0.0),
812             Vec4::new(0.0, h, 0.0, 0.0),
813             Vec4::new(0.0, 0.0, r, -1.0),
814             Vec4::new(0.0, 0.0, r * z_near, 0.0),
815         )
816     }
817 
818     /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range.
819     ///
820     /// # Panics
821     ///
822     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
823     #[inline]
824     #[must_use]
perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self825     pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
826         glam_assert!(z_near > 0.0);
827         let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
828         let h = cos_fov / sin_fov;
829         let w = h / aspect_ratio;
830         Self::from_cols(
831             Vec4::new(w, 0.0, 0.0, 0.0),
832             Vec4::new(0.0, h, 0.0, 0.0),
833             Vec4::new(0.0, 0.0, 1.0, 1.0),
834             Vec4::new(0.0, 0.0, -z_near, 0.0),
835         )
836     }
837 
838     /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range.
839     ///
840     /// # Panics
841     ///
842     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
843     #[inline]
844     #[must_use]
perspective_infinite_reverse_lh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self845     pub fn perspective_infinite_reverse_lh(
846         fov_y_radians: f32,
847         aspect_ratio: f32,
848         z_near: f32,
849     ) -> Self {
850         glam_assert!(z_near > 0.0);
851         let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
852         let h = cos_fov / sin_fov;
853         let w = h / aspect_ratio;
854         Self::from_cols(
855             Vec4::new(w, 0.0, 0.0, 0.0),
856             Vec4::new(0.0, h, 0.0, 0.0),
857             Vec4::new(0.0, 0.0, 0.0, 1.0),
858             Vec4::new(0.0, 0.0, z_near, 0.0),
859         )
860     }
861 
862     /// Creates an infinite right-handed perspective projection matrix with
863     /// `[0,1]` depth range.
864     #[inline]
865     #[must_use]
perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self866     pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
867         glam_assert!(z_near > 0.0);
868         let f = 1.0 / math::tan(0.5 * fov_y_radians);
869         Self::from_cols(
870             Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
871             Vec4::new(0.0, f, 0.0, 0.0),
872             Vec4::new(0.0, 0.0, -1.0, -1.0),
873             Vec4::new(0.0, 0.0, -z_near, 0.0),
874         )
875     }
876 
877     /// Creates an infinite reverse right-handed perspective projection matrix
878     /// with `[0,1]` depth range.
879     #[inline]
880     #[must_use]
perspective_infinite_reverse_rh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self881     pub fn perspective_infinite_reverse_rh(
882         fov_y_radians: f32,
883         aspect_ratio: f32,
884         z_near: f32,
885     ) -> Self {
886         glam_assert!(z_near > 0.0);
887         let f = 1.0 / math::tan(0.5 * fov_y_radians);
888         Self::from_cols(
889             Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
890             Vec4::new(0.0, f, 0.0, 0.0),
891             Vec4::new(0.0, 0.0, 0.0, -1.0),
892             Vec4::new(0.0, 0.0, z_near, 0.0),
893         )
894     }
895 
896     /// Creates a right-handed orthographic projection matrix with `[-1,1]` depth
897     /// range.  This is the same as the OpenGL `glOrtho` function in OpenGL.
898     /// See
899     /// <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml>
900     #[inline]
901     #[must_use]
orthographic_rh_gl( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self902     pub fn orthographic_rh_gl(
903         left: f32,
904         right: f32,
905         bottom: f32,
906         top: f32,
907         near: f32,
908         far: f32,
909     ) -> Self {
910         let a = 2.0 / (right - left);
911         let b = 2.0 / (top - bottom);
912         let c = -2.0 / (far - near);
913         let tx = -(right + left) / (right - left);
914         let ty = -(top + bottom) / (top - bottom);
915         let tz = -(far + near) / (far - near);
916 
917         Self::from_cols(
918             Vec4::new(a, 0.0, 0.0, 0.0),
919             Vec4::new(0.0, b, 0.0, 0.0),
920             Vec4::new(0.0, 0.0, c, 0.0),
921             Vec4::new(tx, ty, tz, 1.0),
922         )
923     }
924 
925     /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range.
926     #[inline]
927     #[must_use]
orthographic_lh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self928     pub fn orthographic_lh(
929         left: f32,
930         right: f32,
931         bottom: f32,
932         top: f32,
933         near: f32,
934         far: f32,
935     ) -> Self {
936         let rcp_width = 1.0 / (right - left);
937         let rcp_height = 1.0 / (top - bottom);
938         let r = 1.0 / (far - near);
939         Self::from_cols(
940             Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
941             Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
942             Vec4::new(0.0, 0.0, r, 0.0),
943             Vec4::new(
944                 -(left + right) * rcp_width,
945                 -(top + bottom) * rcp_height,
946                 -r * near,
947                 1.0,
948             ),
949         )
950     }
951 
952     /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range.
953     #[inline]
954     #[must_use]
orthographic_rh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self955     pub fn orthographic_rh(
956         left: f32,
957         right: f32,
958         bottom: f32,
959         top: f32,
960         near: f32,
961         far: f32,
962     ) -> Self {
963         let rcp_width = 1.0 / (right - left);
964         let rcp_height = 1.0 / (top - bottom);
965         let r = 1.0 / (near - far);
966         Self::from_cols(
967             Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
968             Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
969             Vec4::new(0.0, 0.0, r, 0.0),
970             Vec4::new(
971                 -(left + right) * rcp_width,
972                 -(top + bottom) * rcp_height,
973                 r * near,
974                 1.0,
975             ),
976         )
977     }
978 
979     /// Transforms the given 3D vector as a point, applying perspective correction.
980     ///
981     /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is `1.0`.
982     /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
983     ///
984     /// This method assumes that `self` contains a projective transform.
985     #[inline]
986     #[must_use]
project_point3(&self, rhs: Vec3) -> Vec3987     pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
988         let mut res = self.x_axis.mul(rhs.x);
989         res = self.y_axis.mul(rhs.y).add(res);
990         res = self.z_axis.mul(rhs.z).add(res);
991         res = self.w_axis.add(res);
992         res = res.mul(res.wwww().recip());
993         res.xyz()
994     }
995 
996     /// Transforms the given 3D vector as a point.
997     ///
998     /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
999     /// `1.0`.
1000     ///
1001     /// This method assumes that `self` contains a valid affine transform. It does not perform
1002     /// a persective divide, if `self` contains a perspective transform, or if you are unsure,
1003     /// the [`Self::project_point3()`] method should be used instead.
1004     ///
1005     /// # Panics
1006     ///
1007     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1008     #[inline]
1009     #[must_use]
transform_point3(&self, rhs: Vec3) -> Vec31010     pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1011         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1012         let mut res = self.x_axis.mul(rhs.x);
1013         res = self.y_axis.mul(rhs.y).add(res);
1014         res = self.z_axis.mul(rhs.z).add(res);
1015         res = self.w_axis.add(res);
1016         res.xyz()
1017     }
1018 
1019     /// Transforms the give 3D vector as a direction.
1020     ///
1021     /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
1022     /// `0.0`.
1023     ///
1024     /// This method assumes that `self` contains a valid affine transform.
1025     ///
1026     /// # Panics
1027     ///
1028     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1029     #[inline]
1030     #[must_use]
transform_vector3(&self, rhs: Vec3) -> Vec31031     pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1032         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1033         let mut res = self.x_axis.mul(rhs.x);
1034         res = self.y_axis.mul(rhs.y).add(res);
1035         res = self.z_axis.mul(rhs.z).add(res);
1036         res.xyz()
1037     }
1038 
1039     /// Transforms the given [`Vec3A`] as 3D point.
1040     ///
1041     /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
1042     #[inline]
1043     #[must_use]
transform_point3a(&self, rhs: Vec3A) -> Vec3A1044     pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1045         self.transform_point3(rhs.into()).into()
1046     }
1047 
1048     /// Transforms the give [`Vec3A`] as 3D vector.
1049     ///
1050     /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `0.0`.
1051     #[inline]
1052     #[must_use]
transform_vector3a(&self, rhs: Vec3A) -> Vec3A1053     pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1054         self.transform_vector3(rhs.into()).into()
1055     }
1056 
1057     /// Transforms a 4D vector.
1058     #[inline]
1059     #[must_use]
mul_vec4(&self, rhs: Vec4) -> Vec41060     pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1061         let mut res = self.x_axis.mul(rhs.x);
1062         res = res.add(self.y_axis.mul(rhs.y));
1063         res = res.add(self.z_axis.mul(rhs.z));
1064         res = res.add(self.w_axis.mul(rhs.w));
1065         res
1066     }
1067 
1068     /// Multiplies two 4x4 matrices.
1069     #[inline]
1070     #[must_use]
mul_mat4(&self, rhs: &Self) -> Self1071     pub fn mul_mat4(&self, rhs: &Self) -> Self {
1072         Self::from_cols(
1073             self.mul(rhs.x_axis),
1074             self.mul(rhs.y_axis),
1075             self.mul(rhs.z_axis),
1076             self.mul(rhs.w_axis),
1077         )
1078     }
1079 
1080     /// Adds two 4x4 matrices.
1081     #[inline]
1082     #[must_use]
add_mat4(&self, rhs: &Self) -> Self1083     pub fn add_mat4(&self, rhs: &Self) -> Self {
1084         Self::from_cols(
1085             self.x_axis.add(rhs.x_axis),
1086             self.y_axis.add(rhs.y_axis),
1087             self.z_axis.add(rhs.z_axis),
1088             self.w_axis.add(rhs.w_axis),
1089         )
1090     }
1091 
1092     /// Subtracts two 4x4 matrices.
1093     #[inline]
1094     #[must_use]
sub_mat4(&self, rhs: &Self) -> Self1095     pub fn sub_mat4(&self, rhs: &Self) -> Self {
1096         Self::from_cols(
1097             self.x_axis.sub(rhs.x_axis),
1098             self.y_axis.sub(rhs.y_axis),
1099             self.z_axis.sub(rhs.z_axis),
1100             self.w_axis.sub(rhs.w_axis),
1101         )
1102     }
1103 
1104     /// Multiplies a 4x4 matrix by a scalar.
1105     #[inline]
1106     #[must_use]
mul_scalar(&self, rhs: f32) -> Self1107     pub fn mul_scalar(&self, rhs: f32) -> Self {
1108         Self::from_cols(
1109             self.x_axis.mul(rhs),
1110             self.y_axis.mul(rhs),
1111             self.z_axis.mul(rhs),
1112             self.w_axis.mul(rhs),
1113         )
1114     }
1115 
1116     /// Returns true if the absolute difference of all elements between `self` and `rhs`
1117     /// is less than or equal to `max_abs_diff`.
1118     ///
1119     /// This can be used to compare if two matrices contain similar elements. It works best
1120     /// when comparing with a known value. The `max_abs_diff` that should be used used
1121     /// depends on the values being compared against.
1122     ///
1123     /// For more see
1124     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
1125     #[inline]
1126     #[must_use]
abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool1127     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1128         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1129             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1130             && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1131             && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1132     }
1133 
1134     #[inline]
as_dmat4(&self) -> DMat41135     pub fn as_dmat4(&self) -> DMat4 {
1136         DMat4::from_cols(
1137             self.x_axis.as_dvec4(),
1138             self.y_axis.as_dvec4(),
1139             self.z_axis.as_dvec4(),
1140             self.w_axis.as_dvec4(),
1141         )
1142     }
1143 }
1144 
1145 impl Default for Mat4 {
1146     #[inline]
default() -> Self1147     fn default() -> Self {
1148         Self::IDENTITY
1149     }
1150 }
1151 
1152 impl Add<Mat4> for Mat4 {
1153     type Output = Self;
1154     #[inline]
add(self, rhs: Self) -> Self::Output1155     fn add(self, rhs: Self) -> Self::Output {
1156         self.add_mat4(&rhs)
1157     }
1158 }
1159 
1160 impl AddAssign<Mat4> for Mat4 {
1161     #[inline]
add_assign(&mut self, rhs: Self)1162     fn add_assign(&mut self, rhs: Self) {
1163         *self = self.add_mat4(&rhs);
1164     }
1165 }
1166 
1167 impl Sub<Mat4> for Mat4 {
1168     type Output = Self;
1169     #[inline]
sub(self, rhs: Self) -> Self::Output1170     fn sub(self, rhs: Self) -> Self::Output {
1171         self.sub_mat4(&rhs)
1172     }
1173 }
1174 
1175 impl SubAssign<Mat4> for Mat4 {
1176     #[inline]
sub_assign(&mut self, rhs: Self)1177     fn sub_assign(&mut self, rhs: Self) {
1178         *self = self.sub_mat4(&rhs);
1179     }
1180 }
1181 
1182 impl Neg for Mat4 {
1183     type Output = Self;
1184     #[inline]
neg(self) -> Self::Output1185     fn neg(self) -> Self::Output {
1186         Self::from_cols(
1187             self.x_axis.neg(),
1188             self.y_axis.neg(),
1189             self.z_axis.neg(),
1190             self.w_axis.neg(),
1191         )
1192     }
1193 }
1194 
1195 impl Mul<Mat4> for Mat4 {
1196     type Output = Self;
1197     #[inline]
mul(self, rhs: Self) -> Self::Output1198     fn mul(self, rhs: Self) -> Self::Output {
1199         self.mul_mat4(&rhs)
1200     }
1201 }
1202 
1203 impl MulAssign<Mat4> for Mat4 {
1204     #[inline]
mul_assign(&mut self, rhs: Self)1205     fn mul_assign(&mut self, rhs: Self) {
1206         *self = self.mul_mat4(&rhs);
1207     }
1208 }
1209 
1210 impl Mul<Vec4> for Mat4 {
1211     type Output = Vec4;
1212     #[inline]
mul(self, rhs: Vec4) -> Self::Output1213     fn mul(self, rhs: Vec4) -> Self::Output {
1214         self.mul_vec4(rhs)
1215     }
1216 }
1217 
1218 impl Mul<Mat4> for f32 {
1219     type Output = Mat4;
1220     #[inline]
mul(self, rhs: Mat4) -> Self::Output1221     fn mul(self, rhs: Mat4) -> Self::Output {
1222         rhs.mul_scalar(self)
1223     }
1224 }
1225 
1226 impl Mul<f32> for Mat4 {
1227     type Output = Self;
1228     #[inline]
mul(self, rhs: f32) -> Self::Output1229     fn mul(self, rhs: f32) -> Self::Output {
1230         self.mul_scalar(rhs)
1231     }
1232 }
1233 
1234 impl MulAssign<f32> for Mat4 {
1235     #[inline]
mul_assign(&mut self, rhs: f32)1236     fn mul_assign(&mut self, rhs: f32) {
1237         *self = self.mul_scalar(rhs);
1238     }
1239 }
1240 
1241 impl Sum<Self> for Mat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,1242     fn sum<I>(iter: I) -> Self
1243     where
1244         I: Iterator<Item = Self>,
1245     {
1246         iter.fold(Self::ZERO, Self::add)
1247     }
1248 }
1249 
1250 impl<'a> Sum<&'a Self> for Mat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,1251     fn sum<I>(iter: I) -> Self
1252     where
1253         I: Iterator<Item = &'a Self>,
1254     {
1255         iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1256     }
1257 }
1258 
1259 impl Product for Mat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,1260     fn product<I>(iter: I) -> Self
1261     where
1262         I: Iterator<Item = Self>,
1263     {
1264         iter.fold(Self::IDENTITY, Self::mul)
1265     }
1266 }
1267 
1268 impl<'a> Product<&'a Self> for Mat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,1269     fn product<I>(iter: I) -> Self
1270     where
1271         I: Iterator<Item = &'a Self>,
1272     {
1273         iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1274     }
1275 }
1276 
1277 impl PartialEq for Mat4 {
1278     #[inline]
eq(&self, rhs: &Self) -> bool1279     fn eq(&self, rhs: &Self) -> bool {
1280         self.x_axis.eq(&rhs.x_axis)
1281             && self.y_axis.eq(&rhs.y_axis)
1282             && self.z_axis.eq(&rhs.z_axis)
1283             && self.w_axis.eq(&rhs.w_axis)
1284     }
1285 }
1286 
1287 #[cfg(not(target_arch = "spirv"))]
1288 impl AsRef<[f32; 16]> for Mat4 {
1289     #[inline]
as_ref(&self) -> &[f32; 16]1290     fn as_ref(&self) -> &[f32; 16] {
1291         unsafe { &*(self as *const Self as *const [f32; 16]) }
1292     }
1293 }
1294 
1295 #[cfg(not(target_arch = "spirv"))]
1296 impl AsMut<[f32; 16]> for Mat4 {
1297     #[inline]
as_mut(&mut self) -> &mut [f32; 16]1298     fn as_mut(&mut self) -> &mut [f32; 16] {
1299         unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
1300     }
1301 }
1302 
1303 #[cfg(not(target_arch = "spirv"))]
1304 impl fmt::Debug for Mat4 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result1305     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1306         fmt.debug_struct(stringify!(Mat4))
1307             .field("x_axis", &self.x_axis)
1308             .field("y_axis", &self.y_axis)
1309             .field("z_axis", &self.z_axis)
1310             .field("w_axis", &self.w_axis)
1311             .finish()
1312     }
1313 }
1314 
1315 #[cfg(not(target_arch = "spirv"))]
1316 impl fmt::Display for Mat4 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1317     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1318         write!(
1319             f,
1320             "[{}, {}, {}, {}]",
1321             self.x_axis, self.y_axis, self.z_axis, self.w_axis
1322         )
1323     }
1324 }
1325