1 // Generated from mat.rs.tera template. Edit the template, not the generated file.
2 
3 use crate::{
4     f32::math, swizzles::*, wasm32::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4,
5 };
6 #[cfg(not(target_arch = "spirv"))]
7 use core::fmt;
8 use core::iter::{Product, Sum};
9 use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
10 
11 use core::arch::wasm32::*;
12 
13 /// Creates a 4x4 matrix from four column vectors.
14 #[inline(always)]
15 #[must_use]
mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat416 pub const fn mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat4 {
17     Mat4::from_cols(x_axis, y_axis, z_axis, w_axis)
18 }
19 
20 /// A 4x4 column major matrix.
21 ///
22 /// This 4x4 matrix type features convenience methods for creating and using affine transforms and
23 /// perspective projections. If you are primarily dealing with 3D affine transformations
24 /// considering using [`Affine3A`](crate::Affine3A) which is faster than a 4x4 matrix
25 /// for some affine operations.
26 ///
27 /// Affine transformations including 3D translation, rotation and scale can be created
28 /// using methods such as [`Self::from_translation()`], [`Self::from_quat()`],
29 /// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`].
30 ///
31 /// Orthographic projections can be created using the methods [`Self::orthographic_lh()`] for
32 /// left-handed coordinate systems and [`Self::orthographic_rh()`] for right-handed
33 /// systems. The resulting matrix is also an affine transformation.
34 ///
35 /// The [`Self::transform_point3()`] and [`Self::transform_vector3()`] convenience methods
36 /// are provided for performing affine transformations on 3D vectors and points. These
37 /// multiply 3D inputs as 4D vectors with an implicit `w` value of `1` for points and `0`
38 /// for vectors respectively. These methods assume that `Self` contains a valid affine
39 /// transform.
40 ///
41 /// Perspective projections can be created using methods such as
42 /// [`Self::perspective_lh()`], [`Self::perspective_infinite_lh()`] and
43 /// [`Self::perspective_infinite_reverse_lh()`] for left-handed co-ordinate systems and
44 /// [`Self::perspective_rh()`], [`Self::perspective_infinite_rh()`] and
45 /// [`Self::perspective_infinite_reverse_rh()`] for right-handed co-ordinate systems.
46 ///
47 /// The resulting perspective project can be use to transform 3D vectors as points with
48 /// perspective correction using the [`Self::project_point3()`] convenience method.
49 #[derive(Clone, Copy)]
50 #[repr(C)]
51 pub struct Mat4 {
52     pub x_axis: Vec4,
53     pub y_axis: Vec4,
54     pub z_axis: Vec4,
55     pub w_axis: Vec4,
56 }
57 
58 impl Mat4 {
59     /// A 4x4 matrix with all elements set to `0.0`.
60     pub const ZERO: Self = Self::from_cols(Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO);
61 
62     /// A 4x4 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
63     pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W);
64 
65     /// All NAN:s.
66     pub const NAN: Self = Self::from_cols(Vec4::NAN, Vec4::NAN, Vec4::NAN, Vec4::NAN);
67 
68     #[allow(clippy::too_many_arguments)]
69     #[inline(always)]
70     #[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, ) -> Self71     const fn new(
72         m00: f32,
73         m01: f32,
74         m02: f32,
75         m03: f32,
76         m10: f32,
77         m11: f32,
78         m12: f32,
79         m13: f32,
80         m20: f32,
81         m21: f32,
82         m22: f32,
83         m23: f32,
84         m30: f32,
85         m31: f32,
86         m32: f32,
87         m33: f32,
88     ) -> Self {
89         Self {
90             x_axis: Vec4::new(m00, m01, m02, m03),
91             y_axis: Vec4::new(m10, m11, m12, m13),
92             z_axis: Vec4::new(m20, m21, m22, m23),
93             w_axis: Vec4::new(m30, m31, m32, m33),
94         }
95     }
96 
97     /// Creates a 4x4 matrix from four column vectors.
98     #[inline(always)]
99     #[must_use]
from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self100     pub const fn from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self {
101         Self {
102             x_axis,
103             y_axis,
104             z_axis,
105             w_axis,
106         }
107     }
108 
109     /// Creates a 4x4 matrix from a `[f32; 16]` array stored in column major order.
110     /// If your data is stored in row major you will need to `transpose` the returned
111     /// matrix.
112     #[inline]
113     #[must_use]
from_cols_array(m: &[f32; 16]) -> Self114     pub const fn from_cols_array(m: &[f32; 16]) -> Self {
115         Self::new(
116             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],
117             m[14], m[15],
118         )
119     }
120 
121     /// Creates a `[f32; 16]` array storing data in column major order.
122     /// If you require data in row major order `transpose` the matrix first.
123     #[inline]
124     #[must_use]
to_cols_array(&self) -> [f32; 16]125     pub const fn to_cols_array(&self) -> [f32; 16] {
126         let [x_axis_x, x_axis_y, x_axis_z, x_axis_w] = self.x_axis.to_array();
127         let [y_axis_x, y_axis_y, y_axis_z, y_axis_w] = self.y_axis.to_array();
128         let [z_axis_x, z_axis_y, z_axis_z, z_axis_w] = self.z_axis.to_array();
129         let [w_axis_x, w_axis_y, w_axis_z, w_axis_w] = self.w_axis.to_array();
130 
131         [
132             x_axis_x, x_axis_y, x_axis_z, x_axis_w, y_axis_x, y_axis_y, y_axis_z, y_axis_w,
133             z_axis_x, z_axis_y, z_axis_z, z_axis_w, w_axis_x, w_axis_y, w_axis_z, w_axis_w,
134         ]
135     }
136 
137     /// Creates a 4x4 matrix from a `[[f32; 4]; 4]` 4D array stored in column major order.
138     /// If your data is in row major order you will need to `transpose` the returned
139     /// matrix.
140     #[inline]
141     #[must_use]
from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self142     pub const fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self {
143         Self::from_cols(
144             Vec4::from_array(m[0]),
145             Vec4::from_array(m[1]),
146             Vec4::from_array(m[2]),
147             Vec4::from_array(m[3]),
148         )
149     }
150 
151     /// Creates a `[[f32; 4]; 4]` 4D array storing data in column major order.
152     /// If you require data in row major order `transpose` the matrix first.
153     #[inline]
154     #[must_use]
to_cols_array_2d(&self) -> [[f32; 4]; 4]155     pub const fn to_cols_array_2d(&self) -> [[f32; 4]; 4] {
156         [
157             self.x_axis.to_array(),
158             self.y_axis.to_array(),
159             self.z_axis.to_array(),
160             self.w_axis.to_array(),
161         ]
162     }
163 
164     /// Creates a 4x4 matrix with its diagonal set to `diagonal` and all other entries set to 0.
165     #[doc(alias = "scale")]
166     #[inline]
167     #[must_use]
from_diagonal(diagonal: Vec4) -> Self168     pub const fn from_diagonal(diagonal: Vec4) -> Self {
169         // diagonal.x, diagonal.y etc can't be done in a const-context
170         let [x, y, z, w] = diagonal.to_array();
171         Self::new(
172             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,
173         )
174     }
175 
176     #[inline]
177     #[must_use]
quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4)178     fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) {
179         glam_assert!(rotation.is_normalized());
180 
181         let (x, y, z, w) = rotation.into();
182         let x2 = x + x;
183         let y2 = y + y;
184         let z2 = z + z;
185         let xx = x * x2;
186         let xy = x * y2;
187         let xz = x * z2;
188         let yy = y * y2;
189         let yz = y * z2;
190         let zz = z * z2;
191         let wx = w * x2;
192         let wy = w * y2;
193         let wz = w * z2;
194 
195         let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
196         let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
197         let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
198         (x_axis, y_axis, z_axis)
199     }
200 
201     /// Creates an affine transformation matrix from the given 3D `scale`, `rotation` and
202     /// `translation`.
203     ///
204     /// The resulting matrix can be used to transform 3D points and vectors. See
205     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
206     ///
207     /// # Panics
208     ///
209     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
210     #[inline]
211     #[must_use]
from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self212     pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
213         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
214         Self::from_cols(
215             x_axis.mul(scale.x),
216             y_axis.mul(scale.y),
217             z_axis.mul(scale.z),
218             Vec4::from((translation, 1.0)),
219         )
220     }
221 
222     /// Creates an affine transformation matrix from the given 3D `translation`.
223     ///
224     /// The resulting matrix can be used to transform 3D points and vectors. See
225     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
226     ///
227     /// # Panics
228     ///
229     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
230     #[inline]
231     #[must_use]
from_rotation_translation(rotation: Quat, translation: Vec3) -> Self232     pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
233         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
234         Self::from_cols(x_axis, y_axis, z_axis, Vec4::from((translation, 1.0)))
235     }
236 
237     /// Extracts `scale`, `rotation` and `translation` from `self`. The input matrix is
238     /// expected to be a 3D affine transformation matrix otherwise the output will be invalid.
239     ///
240     /// # Panics
241     ///
242     /// Will panic if the determinant of `self` is zero or if the resulting scale vector
243     /// contains any zero elements when `glam_assert` is enabled.
244     #[inline]
245     #[must_use]
to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3)246     pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
247         let det = self.determinant();
248         glam_assert!(det != 0.0);
249 
250         let scale = Vec3::new(
251             self.x_axis.length() * math::signum(det),
252             self.y_axis.length(),
253             self.z_axis.length(),
254         );
255 
256         glam_assert!(scale.cmpne(Vec3::ZERO).all());
257 
258         let inv_scale = scale.recip();
259 
260         let rotation = Quat::from_rotation_axes(
261             self.x_axis.mul(inv_scale.x).xyz(),
262             self.y_axis.mul(inv_scale.y).xyz(),
263             self.z_axis.mul(inv_scale.z).xyz(),
264         );
265 
266         let translation = self.w_axis.xyz();
267 
268         (scale, rotation, translation)
269     }
270 
271     /// Creates an affine transformation matrix from the given `rotation` quaternion.
272     ///
273     /// The resulting matrix can be used to transform 3D points and vectors. See
274     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
275     ///
276     /// # Panics
277     ///
278     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
279     #[inline]
280     #[must_use]
from_quat(rotation: Quat) -> Self281     pub fn from_quat(rotation: Quat) -> Self {
282         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
283         Self::from_cols(x_axis, y_axis, z_axis, Vec4::W)
284     }
285 
286     /// Creates an affine transformation matrix from the given 3x3 linear transformation
287     /// matrix.
288     ///
289     /// The resulting matrix can be used to transform 3D points and vectors. See
290     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
291     #[inline]
292     #[must_use]
from_mat3(m: Mat3) -> Self293     pub fn from_mat3(m: Mat3) -> Self {
294         Self::from_cols(
295             Vec4::from((m.x_axis, 0.0)),
296             Vec4::from((m.y_axis, 0.0)),
297             Vec4::from((m.z_axis, 0.0)),
298             Vec4::W,
299         )
300     }
301 
302     /// Creates an affine transformation matrix from the given 3x3 linear transformation
303     /// matrix.
304     ///
305     /// The resulting matrix can be used to transform 3D points and vectors. See
306     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
307     #[inline]
308     #[must_use]
from_mat3a(m: Mat3A) -> Self309     pub fn from_mat3a(m: Mat3A) -> Self {
310         Self::from_cols(
311             Vec4::from((m.x_axis, 0.0)),
312             Vec4::from((m.y_axis, 0.0)),
313             Vec4::from((m.z_axis, 0.0)),
314             Vec4::W,
315         )
316     }
317 
318     /// Creates an affine transformation matrix from the given 3D `translation`.
319     ///
320     /// The resulting matrix can be used to transform 3D points and vectors. See
321     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
322     #[inline]
323     #[must_use]
from_translation(translation: Vec3) -> Self324     pub fn from_translation(translation: Vec3) -> Self {
325         Self::from_cols(
326             Vec4::X,
327             Vec4::Y,
328             Vec4::Z,
329             Vec4::new(translation.x, translation.y, translation.z, 1.0),
330         )
331     }
332 
333     /// Creates an affine transformation matrix containing a 3D rotation around a normalized
334     /// rotation `axis` of `angle` (in radians).
335     ///
336     /// The resulting matrix can be used to transform 3D points and vectors. See
337     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
338     ///
339     /// # Panics
340     ///
341     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
342     #[inline]
343     #[must_use]
from_axis_angle(axis: Vec3, angle: f32) -> Self344     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
345         glam_assert!(axis.is_normalized());
346 
347         let (sin, cos) = math::sin_cos(angle);
348         let axis_sin = axis.mul(sin);
349         let axis_sq = axis.mul(axis);
350         let omc = 1.0 - cos;
351         let xyomc = axis.x * axis.y * omc;
352         let xzomc = axis.x * axis.z * omc;
353         let yzomc = axis.y * axis.z * omc;
354         Self::from_cols(
355             Vec4::new(
356                 axis_sq.x * omc + cos,
357                 xyomc + axis_sin.z,
358                 xzomc - axis_sin.y,
359                 0.0,
360             ),
361             Vec4::new(
362                 xyomc - axis_sin.z,
363                 axis_sq.y * omc + cos,
364                 yzomc + axis_sin.x,
365                 0.0,
366             ),
367             Vec4::new(
368                 xzomc + axis_sin.y,
369                 yzomc - axis_sin.x,
370                 axis_sq.z * omc + cos,
371                 0.0,
372             ),
373             Vec4::W,
374         )
375     }
376 
377     /// Creates a affine transformation matrix containing a rotation from the given euler
378     /// rotation sequence and angles (in radians).
379     ///
380     /// The resulting matrix can be used to transform 3D points and vectors. See
381     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
382     #[inline]
383     #[must_use]
from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self384     pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
385         let quat = Quat::from_euler(order, a, b, c);
386         Self::from_quat(quat)
387     }
388 
389     /// Creates an affine transformation matrix containing a 3D rotation around the x axis of
390     /// `angle` (in radians).
391     ///
392     /// The resulting matrix can be used to transform 3D points and vectors. See
393     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
394     #[inline]
395     #[must_use]
from_rotation_x(angle: f32) -> Self396     pub fn from_rotation_x(angle: f32) -> Self {
397         let (sina, cosa) = math::sin_cos(angle);
398         Self::from_cols(
399             Vec4::X,
400             Vec4::new(0.0, cosa, sina, 0.0),
401             Vec4::new(0.0, -sina, cosa, 0.0),
402             Vec4::W,
403         )
404     }
405 
406     /// Creates an affine transformation matrix containing a 3D rotation around the y axis of
407     /// `angle` (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]
from_rotation_y(angle: f32) -> Self413     pub fn from_rotation_y(angle: f32) -> Self {
414         let (sina, cosa) = math::sin_cos(angle);
415         Self::from_cols(
416             Vec4::new(cosa, 0.0, -sina, 0.0),
417             Vec4::Y,
418             Vec4::new(sina, 0.0, cosa, 0.0),
419             Vec4::W,
420         )
421     }
422 
423     /// Creates an affine transformation matrix containing a 3D rotation around the z axis of
424     /// `angle` (in radians).
425     ///
426     /// The resulting matrix can be used to transform 3D points and vectors. See
427     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
428     #[inline]
429     #[must_use]
from_rotation_z(angle: f32) -> Self430     pub fn from_rotation_z(angle: f32) -> Self {
431         let (sina, cosa) = math::sin_cos(angle);
432         Self::from_cols(
433             Vec4::new(cosa, sina, 0.0, 0.0),
434             Vec4::new(-sina, cosa, 0.0, 0.0),
435             Vec4::Z,
436             Vec4::W,
437         )
438     }
439 
440     /// Creates an affine transformation matrix containing the given 3D non-uniform `scale`.
441     ///
442     /// The resulting matrix can be used to transform 3D points and vectors. See
443     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
444     ///
445     /// # Panics
446     ///
447     /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
448     #[inline]
449     #[must_use]
from_scale(scale: Vec3) -> Self450     pub fn from_scale(scale: Vec3) -> Self {
451         // Do not panic as long as any component is non-zero
452         glam_assert!(scale.cmpne(Vec3::ZERO).any());
453 
454         Self::from_cols(
455             Vec4::new(scale.x, 0.0, 0.0, 0.0),
456             Vec4::new(0.0, scale.y, 0.0, 0.0),
457             Vec4::new(0.0, 0.0, scale.z, 0.0),
458             Vec4::W,
459         )
460     }
461 
462     /// Creates a 4x4 matrix from the first 16 values in `slice`.
463     ///
464     /// # Panics
465     ///
466     /// Panics if `slice` is less than 16 elements long.
467     #[inline]
468     #[must_use]
from_cols_slice(slice: &[f32]) -> Self469     pub const fn from_cols_slice(slice: &[f32]) -> Self {
470         Self::new(
471             slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
472             slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
473         )
474     }
475 
476     /// Writes the columns of `self` to the first 16 elements in `slice`.
477     ///
478     /// # Panics
479     ///
480     /// Panics if `slice` is less than 16 elements long.
481     #[inline]
write_cols_to_slice(self, slice: &mut [f32])482     pub fn write_cols_to_slice(self, slice: &mut [f32]) {
483         slice[0] = self.x_axis.x;
484         slice[1] = self.x_axis.y;
485         slice[2] = self.x_axis.z;
486         slice[3] = self.x_axis.w;
487         slice[4] = self.y_axis.x;
488         slice[5] = self.y_axis.y;
489         slice[6] = self.y_axis.z;
490         slice[7] = self.y_axis.w;
491         slice[8] = self.z_axis.x;
492         slice[9] = self.z_axis.y;
493         slice[10] = self.z_axis.z;
494         slice[11] = self.z_axis.w;
495         slice[12] = self.w_axis.x;
496         slice[13] = self.w_axis.y;
497         slice[14] = self.w_axis.z;
498         slice[15] = self.w_axis.w;
499     }
500 
501     /// Returns the matrix column for the given `index`.
502     ///
503     /// # Panics
504     ///
505     /// Panics if `index` is greater than 3.
506     #[inline]
507     #[must_use]
col(&self, index: usize) -> Vec4508     pub fn col(&self, index: usize) -> Vec4 {
509         match index {
510             0 => self.x_axis,
511             1 => self.y_axis,
512             2 => self.z_axis,
513             3 => self.w_axis,
514             _ => panic!("index out of bounds"),
515         }
516     }
517 
518     /// Returns a mutable reference to the matrix column for the given `index`.
519     ///
520     /// # Panics
521     ///
522     /// Panics if `index` is greater than 3.
523     #[inline]
col_mut(&mut self, index: usize) -> &mut Vec4524     pub fn col_mut(&mut self, index: usize) -> &mut Vec4 {
525         match index {
526             0 => &mut self.x_axis,
527             1 => &mut self.y_axis,
528             2 => &mut self.z_axis,
529             3 => &mut self.w_axis,
530             _ => panic!("index out of bounds"),
531         }
532     }
533 
534     /// Returns the matrix row for the given `index`.
535     ///
536     /// # Panics
537     ///
538     /// Panics if `index` is greater than 3.
539     #[inline]
540     #[must_use]
row(&self, index: usize) -> Vec4541     pub fn row(&self, index: usize) -> Vec4 {
542         match index {
543             0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
544             1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
545             2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
546             3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
547             _ => panic!("index out of bounds"),
548         }
549     }
550 
551     /// Returns `true` if, and only if, all elements are finite.
552     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
553     #[inline]
554     #[must_use]
is_finite(&self) -> bool555     pub fn is_finite(&self) -> bool {
556         self.x_axis.is_finite()
557             && self.y_axis.is_finite()
558             && self.z_axis.is_finite()
559             && self.w_axis.is_finite()
560     }
561 
562     /// Returns `true` if any elements are `NaN`.
563     #[inline]
564     #[must_use]
is_nan(&self) -> bool565     pub fn is_nan(&self) -> bool {
566         self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
567     }
568 
569     /// Returns the transpose of `self`.
570     #[inline]
571     #[must_use]
transpose(&self) -> Self572     pub fn transpose(&self) -> Self {
573         // Based on https://github.com/microsoft/DirectXMath `XMMatrixTranspose`
574         let tmp0 = i32x4_shuffle::<0, 1, 4, 5>(self.x_axis.0, self.y_axis.0);
575         let tmp1 = i32x4_shuffle::<2, 3, 6, 7>(self.x_axis.0, self.y_axis.0);
576         let tmp2 = i32x4_shuffle::<0, 1, 4, 5>(self.z_axis.0, self.w_axis.0);
577         let tmp3 = i32x4_shuffle::<2, 3, 6, 7>(self.z_axis.0, self.w_axis.0);
578 
579         Self {
580             x_axis: Vec4(i32x4_shuffle::<0, 2, 4, 6>(tmp0, tmp2)),
581             y_axis: Vec4(i32x4_shuffle::<1, 3, 5, 7>(tmp0, tmp2)),
582             z_axis: Vec4(i32x4_shuffle::<0, 2, 4, 6>(tmp1, tmp3)),
583             w_axis: Vec4(i32x4_shuffle::<1, 3, 5, 7>(tmp1, tmp3)),
584         }
585     }
586 
587     /// Returns the determinant of `self`.
588     #[must_use]
determinant(&self) -> f32589     pub fn determinant(&self) -> f32 {
590         // Based on https://github.com/g-truc/glm `glm_mat4_determinant`
591         let swp2a = i32x4_shuffle::<2, 1, 1, 0>(self.z_axis.0, self.z_axis.0);
592         let swp3a = i32x4_shuffle::<3, 3, 2, 3>(self.w_axis.0, self.w_axis.0);
593         let swp2b = i32x4_shuffle::<3, 3, 2, 3>(self.z_axis.0, self.z_axis.0);
594         let swp3b = i32x4_shuffle::<2, 1, 1, 0>(self.w_axis.0, self.w_axis.0);
595         let swp2c = i32x4_shuffle::<2, 1, 0, 0>(self.z_axis.0, self.z_axis.0);
596         let swp3c = i32x4_shuffle::<0, 0, 2, 1>(self.w_axis.0, self.w_axis.0);
597 
598         let mula = f32x4_mul(swp2a, swp3a);
599         let mulb = f32x4_mul(swp2b, swp3b);
600         let mulc = f32x4_mul(swp2c, swp3c);
601         let sube = f32x4_sub(mula, mulb);
602         let subf = f32x4_sub(i32x4_shuffle::<6, 7, 2, 3>(mulc, mulc), mulc);
603 
604         let subfaca = i32x4_shuffle::<0, 0, 1, 2>(sube, sube);
605         let swpfaca = i32x4_shuffle::<1, 0, 0, 0>(self.y_axis.0, self.y_axis.0);
606         let mulfaca = f32x4_mul(swpfaca, subfaca);
607 
608         let subtmpb = i32x4_shuffle::<1, 3, 4, 4>(sube, subf);
609         let subfacb = i32x4_shuffle::<0, 1, 1, 3>(subtmpb, subtmpb);
610         let swpfacb = i32x4_shuffle::<2, 2, 1, 1>(self.y_axis.0, self.y_axis.0);
611         let mulfacb = f32x4_mul(swpfacb, subfacb);
612 
613         let subres = f32x4_sub(mulfaca, mulfacb);
614         let subtmpc = i32x4_shuffle::<2, 2, 4, 5>(sube, subf);
615         let subfacc = i32x4_shuffle::<0, 2, 3, 3>(subtmpc, subtmpc);
616         let swpfacc = i32x4_shuffle::<3, 3, 3, 2>(self.y_axis.0, self.y_axis.0);
617         let mulfacc = f32x4_mul(swpfacc, subfacc);
618 
619         let addres = f32x4_add(subres, mulfacc);
620         let detcof = f32x4_mul(addres, f32x4(1.0, -1.0, 1.0, -1.0));
621 
622         dot4(self.x_axis.0, detcof)
623     }
624 
625     /// Returns the inverse of `self`.
626     ///
627     /// If the matrix is not invertible the returned matrix will be invalid.
628     ///
629     /// # Panics
630     ///
631     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
632     #[must_use]
inverse(&self) -> Self633     pub fn inverse(&self) -> Self {
634         // Based on https://github.com/g-truc/glm `glm_mat4_inverse`
635         let fac0 = {
636             let swp0a = i32x4_shuffle::<3, 3, 7, 7>(self.w_axis.0, self.z_axis.0);
637             let swp0b = i32x4_shuffle::<2, 2, 6, 6>(self.w_axis.0, self.z_axis.0);
638 
639             let swp00 = i32x4_shuffle::<2, 2, 6, 6>(self.z_axis.0, self.y_axis.0);
640             let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
641             let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
642             let swp03 = i32x4_shuffle::<3, 3, 7, 7>(self.z_axis.0, self.y_axis.0);
643 
644             let mul00 = f32x4_mul(swp00, swp01);
645             let mul01 = f32x4_mul(swp02, swp03);
646             f32x4_sub(mul00, mul01)
647         };
648         let fac1 = {
649             let swp0a = i32x4_shuffle::<3, 3, 7, 7>(self.w_axis.0, self.z_axis.0);
650             let swp0b = i32x4_shuffle::<1, 1, 5, 5>(self.w_axis.0, self.z_axis.0);
651 
652             let swp00 = i32x4_shuffle::<1, 1, 5, 5>(self.z_axis.0, self.y_axis.0);
653             let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
654             let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
655             let swp03 = i32x4_shuffle::<3, 3, 7, 7>(self.z_axis.0, self.y_axis.0);
656 
657             let mul00 = f32x4_mul(swp00, swp01);
658             let mul01 = f32x4_mul(swp02, swp03);
659             f32x4_sub(mul00, mul01)
660         };
661         let fac2 = {
662             let swp0a = i32x4_shuffle::<2, 2, 6, 6>(self.w_axis.0, self.z_axis.0);
663             let swp0b = i32x4_shuffle::<1, 1, 5, 5>(self.w_axis.0, self.z_axis.0);
664 
665             let swp00 = i32x4_shuffle::<1, 1, 5, 5>(self.z_axis.0, self.y_axis.0);
666             let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
667             let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
668             let swp03 = i32x4_shuffle::<2, 2, 6, 6>(self.z_axis.0, self.y_axis.0);
669 
670             let mul00 = f32x4_mul(swp00, swp01);
671             let mul01 = f32x4_mul(swp02, swp03);
672             f32x4_sub(mul00, mul01)
673         };
674         let fac3 = {
675             let swp0a = i32x4_shuffle::<3, 3, 7, 7>(self.w_axis.0, self.z_axis.0);
676             let swp0b = i32x4_shuffle::<0, 0, 4, 4>(self.w_axis.0, self.z_axis.0);
677 
678             let swp00 = i32x4_shuffle::<0, 0, 4, 4>(self.z_axis.0, self.y_axis.0);
679             let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
680             let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
681             let swp03 = i32x4_shuffle::<3, 3, 7, 7>(self.z_axis.0, self.y_axis.0);
682 
683             let mul00 = f32x4_mul(swp00, swp01);
684             let mul01 = f32x4_mul(swp02, swp03);
685             f32x4_sub(mul00, mul01)
686         };
687         let fac4 = {
688             let swp0a = i32x4_shuffle::<2, 2, 6, 6>(self.w_axis.0, self.z_axis.0);
689             let swp0b = i32x4_shuffle::<0, 0, 4, 4>(self.w_axis.0, self.z_axis.0);
690 
691             let swp00 = i32x4_shuffle::<0, 0, 4, 4>(self.z_axis.0, self.y_axis.0);
692             let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
693             let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
694             let swp03 = i32x4_shuffle::<2, 2, 6, 6>(self.z_axis.0, self.y_axis.0);
695 
696             let mul00 = f32x4_mul(swp00, swp01);
697             let mul01 = f32x4_mul(swp02, swp03);
698             f32x4_sub(mul00, mul01)
699         };
700         let fac5 = {
701             let swp0a = i32x4_shuffle::<1, 1, 5, 5>(self.w_axis.0, self.z_axis.0);
702             let swp0b = i32x4_shuffle::<0, 0, 4, 4>(self.w_axis.0, self.z_axis.0);
703 
704             let swp00 = i32x4_shuffle::<0, 0, 4, 4>(self.z_axis.0, self.y_axis.0);
705             let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
706             let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
707             let swp03 = i32x4_shuffle::<1, 1, 5, 5>(self.z_axis.0, self.y_axis.0);
708 
709             let mul00 = f32x4_mul(swp00, swp01);
710             let mul01 = f32x4_mul(swp02, swp03);
711             f32x4_sub(mul00, mul01)
712         };
713         let sign_a = f32x4(-1.0, 1.0, -1.0, 1.0);
714         let sign_b = f32x4(1.0, -1.0, 1.0, -1.0);
715 
716         let temp0 = i32x4_shuffle::<0, 0, 4, 4>(self.y_axis.0, self.x_axis.0);
717         let vec0 = i32x4_shuffle::<0, 2, 6, 6>(temp0, temp0);
718 
719         let temp1 = i32x4_shuffle::<1, 1, 5, 5>(self.y_axis.0, self.x_axis.0);
720         let vec1 = i32x4_shuffle::<0, 2, 6, 6>(temp1, temp1);
721 
722         let temp2 = i32x4_shuffle::<2, 2, 6, 6>(self.y_axis.0, self.x_axis.0);
723         let vec2 = i32x4_shuffle::<0, 2, 6, 6>(temp2, temp2);
724 
725         let temp3 = i32x4_shuffle::<3, 3, 7, 7>(self.y_axis.0, self.x_axis.0);
726         let vec3 = i32x4_shuffle::<0, 2, 6, 6>(temp3, temp3);
727 
728         let mul00 = f32x4_mul(vec1, fac0);
729         let mul01 = f32x4_mul(vec2, fac1);
730         let mul02 = f32x4_mul(vec3, fac2);
731         let sub00 = f32x4_sub(mul00, mul01);
732         let add00 = f32x4_add(sub00, mul02);
733         let inv0 = f32x4_mul(sign_b, add00);
734 
735         let mul03 = f32x4_mul(vec0, fac0);
736         let mul04 = f32x4_mul(vec2, fac3);
737         let mul05 = f32x4_mul(vec3, fac4);
738         let sub01 = f32x4_sub(mul03, mul04);
739         let add01 = f32x4_add(sub01, mul05);
740         let inv1 = f32x4_mul(sign_a, add01);
741 
742         let mul06 = f32x4_mul(vec0, fac1);
743         let mul07 = f32x4_mul(vec1, fac3);
744         let mul08 = f32x4_mul(vec3, fac5);
745         let sub02 = f32x4_sub(mul06, mul07);
746         let add02 = f32x4_add(sub02, mul08);
747         let inv2 = f32x4_mul(sign_b, add02);
748 
749         let mul09 = f32x4_mul(vec0, fac2);
750         let mul10 = f32x4_mul(vec1, fac4);
751         let mul11 = f32x4_mul(vec2, fac5);
752         let sub03 = f32x4_sub(mul09, mul10);
753         let add03 = f32x4_add(sub03, mul11);
754         let inv3 = f32x4_mul(sign_a, add03);
755 
756         let row0 = i32x4_shuffle::<0, 0, 4, 4>(inv0, inv1);
757         let row1 = i32x4_shuffle::<0, 0, 4, 4>(inv2, inv3);
758         let row2 = i32x4_shuffle::<0, 2, 4, 6>(row0, row1);
759 
760         let dot0 = dot4(self.x_axis.0, row2);
761         glam_assert!(dot0 != 0.0);
762 
763         let rcp0 = f32x4_splat(dot0.recip());
764 
765         Self {
766             x_axis: Vec4(f32x4_mul(inv0, rcp0)),
767             y_axis: Vec4(f32x4_mul(inv1, rcp0)),
768             z_axis: Vec4(f32x4_mul(inv2, rcp0)),
769             w_axis: Vec4(f32x4_mul(inv3, rcp0)),
770         }
771     }
772 
773     /// Creates a left-handed view matrix using a camera position, an up direction, and a facing
774     /// direction.
775     ///
776     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
777     #[inline]
778     #[must_use]
look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self779     pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
780         Self::look_to_rh(eye, -dir, up)
781     }
782 
783     /// Creates a right-handed view matrix using a camera position, an up direction, and a facing
784     /// direction.
785     ///
786     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
787     #[inline]
788     #[must_use]
look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self789     pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
790         let f = dir.normalize();
791         let s = f.cross(up).normalize();
792         let u = s.cross(f);
793 
794         Self::from_cols(
795             Vec4::new(s.x, u.x, -f.x, 0.0),
796             Vec4::new(s.y, u.y, -f.y, 0.0),
797             Vec4::new(s.z, u.z, -f.z, 0.0),
798             Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
799         )
800     }
801 
802     /// Creates a left-handed view matrix using a camera position, an up direction, and a focal
803     /// point.
804     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
805     ///
806     /// # Panics
807     ///
808     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
809     #[inline]
810     #[must_use]
look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self811     pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
812         glam_assert!(up.is_normalized());
813         Self::look_to_lh(eye, center.sub(eye), up)
814     }
815 
816     /// Creates a right-handed view matrix using a camera position, an up direction, and a focal
817     /// point.
818     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
819     ///
820     /// # Panics
821     ///
822     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
823     #[inline]
look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self824     pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
825         glam_assert!(up.is_normalized());
826         Self::look_to_rh(eye, center.sub(eye), up)
827     }
828 
829     /// Creates a right-handed perspective projection matrix with [-1,1] depth range.
830     /// This is the same as the OpenGL `gluPerspective` function.
831     /// See <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml>
832     #[inline]
833     #[must_use]
perspective_rh_gl( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32, ) -> Self834     pub fn perspective_rh_gl(
835         fov_y_radians: f32,
836         aspect_ratio: f32,
837         z_near: f32,
838         z_far: f32,
839     ) -> Self {
840         let inv_length = 1.0 / (z_near - z_far);
841         let f = 1.0 / math::tan(0.5 * fov_y_radians);
842         let a = f / aspect_ratio;
843         let b = (z_near + z_far) * inv_length;
844         let c = (2.0 * z_near * z_far) * inv_length;
845         Self::from_cols(
846             Vec4::new(a, 0.0, 0.0, 0.0),
847             Vec4::new(0.0, f, 0.0, 0.0),
848             Vec4::new(0.0, 0.0, b, -1.0),
849             Vec4::new(0.0, 0.0, c, 0.0),
850         )
851     }
852 
853     /// Creates a left-handed perspective projection matrix with `[0,1]` depth range.
854     ///
855     /// # Panics
856     ///
857     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
858     /// enabled.
859     #[inline]
860     #[must_use]
perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self861     pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
862         glam_assert!(z_near > 0.0 && z_far > 0.0);
863         let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
864         let h = cos_fov / sin_fov;
865         let w = h / aspect_ratio;
866         let r = z_far / (z_far - z_near);
867         Self::from_cols(
868             Vec4::new(w, 0.0, 0.0, 0.0),
869             Vec4::new(0.0, h, 0.0, 0.0),
870             Vec4::new(0.0, 0.0, r, 1.0),
871             Vec4::new(0.0, 0.0, -r * z_near, 0.0),
872         )
873     }
874 
875     /// Creates a right-handed perspective projection matrix with `[0,1]` depth range.
876     ///
877     /// # Panics
878     ///
879     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
880     /// enabled.
881     #[inline]
882     #[must_use]
perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self883     pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
884         glam_assert!(z_near > 0.0 && z_far > 0.0);
885         let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
886         let h = cos_fov / sin_fov;
887         let w = h / aspect_ratio;
888         let r = z_far / (z_near - z_far);
889         Self::from_cols(
890             Vec4::new(w, 0.0, 0.0, 0.0),
891             Vec4::new(0.0, h, 0.0, 0.0),
892             Vec4::new(0.0, 0.0, r, -1.0),
893             Vec4::new(0.0, 0.0, r * z_near, 0.0),
894         )
895     }
896 
897     /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range.
898     ///
899     /// # Panics
900     ///
901     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
902     #[inline]
903     #[must_use]
perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self904     pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
905         glam_assert!(z_near > 0.0);
906         let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
907         let h = cos_fov / sin_fov;
908         let w = h / aspect_ratio;
909         Self::from_cols(
910             Vec4::new(w, 0.0, 0.0, 0.0),
911             Vec4::new(0.0, h, 0.0, 0.0),
912             Vec4::new(0.0, 0.0, 1.0, 1.0),
913             Vec4::new(0.0, 0.0, -z_near, 0.0),
914         )
915     }
916 
917     /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range.
918     ///
919     /// # Panics
920     ///
921     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
922     #[inline]
923     #[must_use]
perspective_infinite_reverse_lh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self924     pub fn perspective_infinite_reverse_lh(
925         fov_y_radians: f32,
926         aspect_ratio: f32,
927         z_near: f32,
928     ) -> Self {
929         glam_assert!(z_near > 0.0);
930         let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
931         let h = cos_fov / sin_fov;
932         let w = h / aspect_ratio;
933         Self::from_cols(
934             Vec4::new(w, 0.0, 0.0, 0.0),
935             Vec4::new(0.0, h, 0.0, 0.0),
936             Vec4::new(0.0, 0.0, 0.0, 1.0),
937             Vec4::new(0.0, 0.0, z_near, 0.0),
938         )
939     }
940 
941     /// Creates an infinite right-handed perspective projection matrix with
942     /// `[0,1]` depth range.
943     #[inline]
944     #[must_use]
perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self945     pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
946         glam_assert!(z_near > 0.0);
947         let f = 1.0 / math::tan(0.5 * fov_y_radians);
948         Self::from_cols(
949             Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
950             Vec4::new(0.0, f, 0.0, 0.0),
951             Vec4::new(0.0, 0.0, -1.0, -1.0),
952             Vec4::new(0.0, 0.0, -z_near, 0.0),
953         )
954     }
955 
956     /// Creates an infinite reverse right-handed perspective projection matrix
957     /// with `[0,1]` depth range.
958     #[inline]
959     #[must_use]
perspective_infinite_reverse_rh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self960     pub fn perspective_infinite_reverse_rh(
961         fov_y_radians: f32,
962         aspect_ratio: f32,
963         z_near: f32,
964     ) -> Self {
965         glam_assert!(z_near > 0.0);
966         let f = 1.0 / math::tan(0.5 * fov_y_radians);
967         Self::from_cols(
968             Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
969             Vec4::new(0.0, f, 0.0, 0.0),
970             Vec4::new(0.0, 0.0, 0.0, -1.0),
971             Vec4::new(0.0, 0.0, z_near, 0.0),
972         )
973     }
974 
975     /// Creates a right-handed orthographic projection matrix with `[-1,1]` depth
976     /// range.  This is the same as the OpenGL `glOrtho` function in OpenGL.
977     /// See
978     /// <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml>
979     #[inline]
980     #[must_use]
orthographic_rh_gl( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self981     pub fn orthographic_rh_gl(
982         left: f32,
983         right: f32,
984         bottom: f32,
985         top: f32,
986         near: f32,
987         far: f32,
988     ) -> Self {
989         let a = 2.0 / (right - left);
990         let b = 2.0 / (top - bottom);
991         let c = -2.0 / (far - near);
992         let tx = -(right + left) / (right - left);
993         let ty = -(top + bottom) / (top - bottom);
994         let tz = -(far + near) / (far - near);
995 
996         Self::from_cols(
997             Vec4::new(a, 0.0, 0.0, 0.0),
998             Vec4::new(0.0, b, 0.0, 0.0),
999             Vec4::new(0.0, 0.0, c, 0.0),
1000             Vec4::new(tx, ty, tz, 1.0),
1001         )
1002     }
1003 
1004     /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range.
1005     #[inline]
1006     #[must_use]
orthographic_lh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self1007     pub fn orthographic_lh(
1008         left: f32,
1009         right: f32,
1010         bottom: f32,
1011         top: f32,
1012         near: f32,
1013         far: f32,
1014     ) -> Self {
1015         let rcp_width = 1.0 / (right - left);
1016         let rcp_height = 1.0 / (top - bottom);
1017         let r = 1.0 / (far - near);
1018         Self::from_cols(
1019             Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1020             Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1021             Vec4::new(0.0, 0.0, r, 0.0),
1022             Vec4::new(
1023                 -(left + right) * rcp_width,
1024                 -(top + bottom) * rcp_height,
1025                 -r * near,
1026                 1.0,
1027             ),
1028         )
1029     }
1030 
1031     /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range.
1032     #[inline]
1033     #[must_use]
orthographic_rh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self1034     pub fn orthographic_rh(
1035         left: f32,
1036         right: f32,
1037         bottom: f32,
1038         top: f32,
1039         near: f32,
1040         far: f32,
1041     ) -> Self {
1042         let rcp_width = 1.0 / (right - left);
1043         let rcp_height = 1.0 / (top - bottom);
1044         let r = 1.0 / (near - far);
1045         Self::from_cols(
1046             Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1047             Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1048             Vec4::new(0.0, 0.0, r, 0.0),
1049             Vec4::new(
1050                 -(left + right) * rcp_width,
1051                 -(top + bottom) * rcp_height,
1052                 r * near,
1053                 1.0,
1054             ),
1055         )
1056     }
1057 
1058     /// Transforms the given 3D vector as a point, applying perspective correction.
1059     ///
1060     /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is `1.0`.
1061     /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
1062     ///
1063     /// This method assumes that `self` contains a projective transform.
1064     #[inline]
1065     #[must_use]
project_point3(&self, rhs: Vec3) -> Vec31066     pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
1067         let mut res = self.x_axis.mul(rhs.x);
1068         res = self.y_axis.mul(rhs.y).add(res);
1069         res = self.z_axis.mul(rhs.z).add(res);
1070         res = self.w_axis.add(res);
1071         res = res.mul(res.wwww().recip());
1072         res.xyz()
1073     }
1074 
1075     /// Transforms the given 3D vector as a point.
1076     ///
1077     /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
1078     /// `1.0`.
1079     ///
1080     /// This method assumes that `self` contains a valid affine transform. It does not perform
1081     /// a persective divide, if `self` contains a perspective transform, or if you are unsure,
1082     /// the [`Self::project_point3()`] method should be used instead.
1083     ///
1084     /// # Panics
1085     ///
1086     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1087     #[inline]
1088     #[must_use]
transform_point3(&self, rhs: Vec3) -> Vec31089     pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1090         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1091         let mut res = self.x_axis.mul(rhs.x);
1092         res = self.y_axis.mul(rhs.y).add(res);
1093         res = self.z_axis.mul(rhs.z).add(res);
1094         res = self.w_axis.add(res);
1095         res.xyz()
1096     }
1097 
1098     /// Transforms the give 3D vector as a direction.
1099     ///
1100     /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
1101     /// `0.0`.
1102     ///
1103     /// This method assumes that `self` contains a valid affine transform.
1104     ///
1105     /// # Panics
1106     ///
1107     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1108     #[inline]
1109     #[must_use]
transform_vector3(&self, rhs: Vec3) -> Vec31110     pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1111         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1112         let mut res = self.x_axis.mul(rhs.x);
1113         res = self.y_axis.mul(rhs.y).add(res);
1114         res = self.z_axis.mul(rhs.z).add(res);
1115         res.xyz()
1116     }
1117 
1118     /// Transforms the given [`Vec3A`] as 3D point.
1119     ///
1120     /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
1121     #[inline]
1122     #[must_use]
transform_point3a(&self, rhs: Vec3A) -> Vec3A1123     pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1124         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1125         let mut res = self.x_axis.mul(rhs.xxxx());
1126         res = self.y_axis.mul(rhs.yyyy()).add(res);
1127         res = self.z_axis.mul(rhs.zzzz()).add(res);
1128         res = self.w_axis.add(res);
1129         res.into()
1130     }
1131 
1132     /// Transforms the give [`Vec3A`] as 3D vector.
1133     ///
1134     /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `0.0`.
1135     #[inline]
1136     #[must_use]
transform_vector3a(&self, rhs: Vec3A) -> Vec3A1137     pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1138         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1139         let mut res = self.x_axis.mul(rhs.xxxx());
1140         res = self.y_axis.mul(rhs.yyyy()).add(res);
1141         res = self.z_axis.mul(rhs.zzzz()).add(res);
1142         res.into()
1143     }
1144 
1145     /// Transforms a 4D vector.
1146     #[inline]
1147     #[must_use]
mul_vec4(&self, rhs: Vec4) -> Vec41148     pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1149         let mut res = self.x_axis.mul(rhs.xxxx());
1150         res = res.add(self.y_axis.mul(rhs.yyyy()));
1151         res = res.add(self.z_axis.mul(rhs.zzzz()));
1152         res = res.add(self.w_axis.mul(rhs.wwww()));
1153         res
1154     }
1155 
1156     /// Multiplies two 4x4 matrices.
1157     #[inline]
1158     #[must_use]
mul_mat4(&self, rhs: &Self) -> Self1159     pub fn mul_mat4(&self, rhs: &Self) -> Self {
1160         Self::from_cols(
1161             self.mul(rhs.x_axis),
1162             self.mul(rhs.y_axis),
1163             self.mul(rhs.z_axis),
1164             self.mul(rhs.w_axis),
1165         )
1166     }
1167 
1168     /// Adds two 4x4 matrices.
1169     #[inline]
1170     #[must_use]
add_mat4(&self, rhs: &Self) -> Self1171     pub fn add_mat4(&self, rhs: &Self) -> Self {
1172         Self::from_cols(
1173             self.x_axis.add(rhs.x_axis),
1174             self.y_axis.add(rhs.y_axis),
1175             self.z_axis.add(rhs.z_axis),
1176             self.w_axis.add(rhs.w_axis),
1177         )
1178     }
1179 
1180     /// Subtracts two 4x4 matrices.
1181     #[inline]
1182     #[must_use]
sub_mat4(&self, rhs: &Self) -> Self1183     pub fn sub_mat4(&self, rhs: &Self) -> Self {
1184         Self::from_cols(
1185             self.x_axis.sub(rhs.x_axis),
1186             self.y_axis.sub(rhs.y_axis),
1187             self.z_axis.sub(rhs.z_axis),
1188             self.w_axis.sub(rhs.w_axis),
1189         )
1190     }
1191 
1192     /// Multiplies a 4x4 matrix by a scalar.
1193     #[inline]
1194     #[must_use]
mul_scalar(&self, rhs: f32) -> Self1195     pub fn mul_scalar(&self, rhs: f32) -> Self {
1196         Self::from_cols(
1197             self.x_axis.mul(rhs),
1198             self.y_axis.mul(rhs),
1199             self.z_axis.mul(rhs),
1200             self.w_axis.mul(rhs),
1201         )
1202     }
1203 
1204     /// Returns true if the absolute difference of all elements between `self` and `rhs`
1205     /// is less than or equal to `max_abs_diff`.
1206     ///
1207     /// This can be used to compare if two matrices contain similar elements. It works best
1208     /// when comparing with a known value. The `max_abs_diff` that should be used used
1209     /// depends on the values being compared against.
1210     ///
1211     /// For more see
1212     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
1213     #[inline]
1214     #[must_use]
abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool1215     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1216         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1217             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1218             && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1219             && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1220     }
1221 
1222     #[inline]
as_dmat4(&self) -> DMat41223     pub fn as_dmat4(&self) -> DMat4 {
1224         DMat4::from_cols(
1225             self.x_axis.as_dvec4(),
1226             self.y_axis.as_dvec4(),
1227             self.z_axis.as_dvec4(),
1228             self.w_axis.as_dvec4(),
1229         )
1230     }
1231 }
1232 
1233 impl Default for Mat4 {
1234     #[inline]
default() -> Self1235     fn default() -> Self {
1236         Self::IDENTITY
1237     }
1238 }
1239 
1240 impl Add<Mat4> for Mat4 {
1241     type Output = Self;
1242     #[inline]
add(self, rhs: Self) -> Self::Output1243     fn add(self, rhs: Self) -> Self::Output {
1244         self.add_mat4(&rhs)
1245     }
1246 }
1247 
1248 impl AddAssign<Mat4> for Mat4 {
1249     #[inline]
add_assign(&mut self, rhs: Self)1250     fn add_assign(&mut self, rhs: Self) {
1251         *self = self.add_mat4(&rhs);
1252     }
1253 }
1254 
1255 impl Sub<Mat4> for Mat4 {
1256     type Output = Self;
1257     #[inline]
sub(self, rhs: Self) -> Self::Output1258     fn sub(self, rhs: Self) -> Self::Output {
1259         self.sub_mat4(&rhs)
1260     }
1261 }
1262 
1263 impl SubAssign<Mat4> for Mat4 {
1264     #[inline]
sub_assign(&mut self, rhs: Self)1265     fn sub_assign(&mut self, rhs: Self) {
1266         *self = self.sub_mat4(&rhs);
1267     }
1268 }
1269 
1270 impl Neg for Mat4 {
1271     type Output = Self;
1272     #[inline]
neg(self) -> Self::Output1273     fn neg(self) -> Self::Output {
1274         Self::from_cols(
1275             self.x_axis.neg(),
1276             self.y_axis.neg(),
1277             self.z_axis.neg(),
1278             self.w_axis.neg(),
1279         )
1280     }
1281 }
1282 
1283 impl Mul<Mat4> for Mat4 {
1284     type Output = Self;
1285     #[inline]
mul(self, rhs: Self) -> Self::Output1286     fn mul(self, rhs: Self) -> Self::Output {
1287         self.mul_mat4(&rhs)
1288     }
1289 }
1290 
1291 impl MulAssign<Mat4> for Mat4 {
1292     #[inline]
mul_assign(&mut self, rhs: Self)1293     fn mul_assign(&mut self, rhs: Self) {
1294         *self = self.mul_mat4(&rhs);
1295     }
1296 }
1297 
1298 impl Mul<Vec4> for Mat4 {
1299     type Output = Vec4;
1300     #[inline]
mul(self, rhs: Vec4) -> Self::Output1301     fn mul(self, rhs: Vec4) -> Self::Output {
1302         self.mul_vec4(rhs)
1303     }
1304 }
1305 
1306 impl Mul<Mat4> for f32 {
1307     type Output = Mat4;
1308     #[inline]
mul(self, rhs: Mat4) -> Self::Output1309     fn mul(self, rhs: Mat4) -> Self::Output {
1310         rhs.mul_scalar(self)
1311     }
1312 }
1313 
1314 impl Mul<f32> for Mat4 {
1315     type Output = Self;
1316     #[inline]
mul(self, rhs: f32) -> Self::Output1317     fn mul(self, rhs: f32) -> Self::Output {
1318         self.mul_scalar(rhs)
1319     }
1320 }
1321 
1322 impl MulAssign<f32> for Mat4 {
1323     #[inline]
mul_assign(&mut self, rhs: f32)1324     fn mul_assign(&mut self, rhs: f32) {
1325         *self = self.mul_scalar(rhs);
1326     }
1327 }
1328 
1329 impl Sum<Self> for Mat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,1330     fn sum<I>(iter: I) -> Self
1331     where
1332         I: Iterator<Item = Self>,
1333     {
1334         iter.fold(Self::ZERO, Self::add)
1335     }
1336 }
1337 
1338 impl<'a> Sum<&'a Self> for Mat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,1339     fn sum<I>(iter: I) -> Self
1340     where
1341         I: Iterator<Item = &'a Self>,
1342     {
1343         iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1344     }
1345 }
1346 
1347 impl Product for Mat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,1348     fn product<I>(iter: I) -> Self
1349     where
1350         I: Iterator<Item = Self>,
1351     {
1352         iter.fold(Self::IDENTITY, Self::mul)
1353     }
1354 }
1355 
1356 impl<'a> Product<&'a Self> for Mat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,1357     fn product<I>(iter: I) -> Self
1358     where
1359         I: Iterator<Item = &'a Self>,
1360     {
1361         iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1362     }
1363 }
1364 
1365 impl PartialEq for Mat4 {
1366     #[inline]
eq(&self, rhs: &Self) -> bool1367     fn eq(&self, rhs: &Self) -> bool {
1368         self.x_axis.eq(&rhs.x_axis)
1369             && self.y_axis.eq(&rhs.y_axis)
1370             && self.z_axis.eq(&rhs.z_axis)
1371             && self.w_axis.eq(&rhs.w_axis)
1372     }
1373 }
1374 
1375 #[cfg(not(target_arch = "spirv"))]
1376 impl AsRef<[f32; 16]> for Mat4 {
1377     #[inline]
as_ref(&self) -> &[f32; 16]1378     fn as_ref(&self) -> &[f32; 16] {
1379         unsafe { &*(self as *const Self as *const [f32; 16]) }
1380     }
1381 }
1382 
1383 #[cfg(not(target_arch = "spirv"))]
1384 impl AsMut<[f32; 16]> for Mat4 {
1385     #[inline]
as_mut(&mut self) -> &mut [f32; 16]1386     fn as_mut(&mut self) -> &mut [f32; 16] {
1387         unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
1388     }
1389 }
1390 
1391 #[cfg(not(target_arch = "spirv"))]
1392 impl fmt::Debug for Mat4 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result1393     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1394         fmt.debug_struct(stringify!(Mat4))
1395             .field("x_axis", &self.x_axis)
1396             .field("y_axis", &self.y_axis)
1397             .field("z_axis", &self.z_axis)
1398             .field("w_axis", &self.w_axis)
1399             .finish()
1400     }
1401 }
1402 
1403 #[cfg(not(target_arch = "spirv"))]
1404 impl fmt::Display for Mat4 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1405     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1406         write!(
1407             f,
1408             "[{}, {}, {}, {}]",
1409             self.x_axis, self.y_axis, self.z_axis, self.w_axis
1410         )
1411     }
1412 }
1413