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