• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Generated from mat.rs.tera template. Edit the template, not the generated file.
2 
3 use crate::{
4     euler::{FromEuler, ToEuler},
5     f32::math,
6     swizzles::*,
7     wasm32::*,
8     DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4,
9 };
10 use core::fmt;
11 use core::iter::{Product, Sum};
12 use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
13 
14 use core::arch::wasm32::*;
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 matrics from a 3x3 matrix (expressing scale, shear and
306     /// rotation) and a translation vector.
307     ///
308     /// Equivalent to `Mat4::from_translation(translation) * Mat4::from_mat3(mat3)`
309     #[inline]
310     #[must_use]
from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self311     pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
312         Self::from_cols(
313             Vec4::from((mat3.x_axis, 0.0)),
314             Vec4::from((mat3.y_axis, 0.0)),
315             Vec4::from((mat3.z_axis, 0.0)),
316             Vec4::from((translation, 1.0)),
317         )
318     }
319 
320     /// Creates an affine transformation matrix from the given 3x3 linear transformation
321     /// matrix.
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_mat3a(m: Mat3A) -> Self327     pub fn from_mat3a(m: Mat3A) -> Self {
328         Self::from_cols(
329             Vec4::from((m.x_axis, 0.0)),
330             Vec4::from((m.y_axis, 0.0)),
331             Vec4::from((m.z_axis, 0.0)),
332             Vec4::W,
333         )
334     }
335 
336     /// Creates an affine transformation matrix from the given 3D `translation`.
337     ///
338     /// The resulting matrix can be used to transform 3D points and vectors. See
339     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
340     #[inline]
341     #[must_use]
from_translation(translation: Vec3) -> Self342     pub fn from_translation(translation: Vec3) -> Self {
343         Self::from_cols(
344             Vec4::X,
345             Vec4::Y,
346             Vec4::Z,
347             Vec4::new(translation.x, translation.y, translation.z, 1.0),
348         )
349     }
350 
351     /// Creates an affine transformation matrix containing a 3D rotation around a normalized
352     /// rotation `axis` of `angle` (in radians).
353     ///
354     /// The resulting matrix can be used to transform 3D points and vectors. See
355     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
356     ///
357     /// # Panics
358     ///
359     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
360     #[inline]
361     #[must_use]
from_axis_angle(axis: Vec3, angle: f32) -> Self362     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
363         glam_assert!(axis.is_normalized());
364 
365         let (sin, cos) = math::sin_cos(angle);
366         let axis_sin = axis.mul(sin);
367         let axis_sq = axis.mul(axis);
368         let omc = 1.0 - cos;
369         let xyomc = axis.x * axis.y * omc;
370         let xzomc = axis.x * axis.z * omc;
371         let yzomc = axis.y * axis.z * omc;
372         Self::from_cols(
373             Vec4::new(
374                 axis_sq.x * omc + cos,
375                 xyomc + axis_sin.z,
376                 xzomc - axis_sin.y,
377                 0.0,
378             ),
379             Vec4::new(
380                 xyomc - axis_sin.z,
381                 axis_sq.y * omc + cos,
382                 yzomc + axis_sin.x,
383                 0.0,
384             ),
385             Vec4::new(
386                 xzomc + axis_sin.y,
387                 yzomc - axis_sin.x,
388                 axis_sq.z * omc + cos,
389                 0.0,
390             ),
391             Vec4::W,
392         )
393     }
394 
395     /// Creates a affine transformation matrix containing a rotation from the given euler
396     /// rotation sequence and angles (in radians).
397     ///
398     /// The resulting matrix can be used to transform 3D points and vectors. See
399     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
400     #[inline]
401     #[must_use]
from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self402     pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
403         Self::from_euler_angles(order, a, b, c)
404     }
405 
406     /// Extract Euler angles with the given Euler rotation order.
407     ///
408     /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations
409     /// then the resulting Euler angles will be ill-defined.
410     ///
411     /// # Panics
412     ///
413     /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when
414     /// `glam_assert` is enabled.
415     #[inline]
416     #[must_use]
to_euler(&self, order: EulerRot) -> (f32, f32, f32)417     pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
418         glam_assert!(
419             self.x_axis.xyz().is_normalized()
420                 && self.y_axis.xyz().is_normalized()
421                 && self.z_axis.xyz().is_normalized()
422         );
423         self.to_euler_angles(order)
424     }
425 
426     /// Creates an affine transformation matrix containing a 3D rotation around the x 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_x(angle: f32) -> Self433     pub fn from_rotation_x(angle: f32) -> Self {
434         let (sina, cosa) = math::sin_cos(angle);
435         Self::from_cols(
436             Vec4::X,
437             Vec4::new(0.0, cosa, sina, 0.0),
438             Vec4::new(0.0, -sina, cosa, 0.0),
439             Vec4::W,
440         )
441     }
442 
443     /// Creates an affine transformation matrix containing a 3D rotation around the y axis of
444     /// `angle` (in radians).
445     ///
446     /// The resulting matrix can be used to transform 3D points and vectors. See
447     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
448     #[inline]
449     #[must_use]
from_rotation_y(angle: f32) -> Self450     pub fn from_rotation_y(angle: f32) -> Self {
451         let (sina, cosa) = math::sin_cos(angle);
452         Self::from_cols(
453             Vec4::new(cosa, 0.0, -sina, 0.0),
454             Vec4::Y,
455             Vec4::new(sina, 0.0, cosa, 0.0),
456             Vec4::W,
457         )
458     }
459 
460     /// Creates an affine transformation matrix containing a 3D rotation around the z axis of
461     /// `angle` (in radians).
462     ///
463     /// The resulting matrix can be used to transform 3D points and vectors. See
464     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
465     #[inline]
466     #[must_use]
from_rotation_z(angle: f32) -> Self467     pub fn from_rotation_z(angle: f32) -> Self {
468         let (sina, cosa) = math::sin_cos(angle);
469         Self::from_cols(
470             Vec4::new(cosa, sina, 0.0, 0.0),
471             Vec4::new(-sina, cosa, 0.0, 0.0),
472             Vec4::Z,
473             Vec4::W,
474         )
475     }
476 
477     /// Creates an affine transformation matrix containing the given 3D non-uniform `scale`.
478     ///
479     /// The resulting matrix can be used to transform 3D points and vectors. See
480     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
481     ///
482     /// # Panics
483     ///
484     /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
485     #[inline]
486     #[must_use]
from_scale(scale: Vec3) -> Self487     pub fn from_scale(scale: Vec3) -> Self {
488         // Do not panic as long as any component is non-zero
489         glam_assert!(scale.cmpne(Vec3::ZERO).any());
490 
491         Self::from_cols(
492             Vec4::new(scale.x, 0.0, 0.0, 0.0),
493             Vec4::new(0.0, scale.y, 0.0, 0.0),
494             Vec4::new(0.0, 0.0, scale.z, 0.0),
495             Vec4::W,
496         )
497     }
498 
499     /// Creates a 4x4 matrix from the first 16 values in `slice`.
500     ///
501     /// # Panics
502     ///
503     /// Panics if `slice` is less than 16 elements long.
504     #[inline]
505     #[must_use]
from_cols_slice(slice: &[f32]) -> Self506     pub const fn from_cols_slice(slice: &[f32]) -> Self {
507         Self::new(
508             slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
509             slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
510         )
511     }
512 
513     /// Writes the columns of `self` to the first 16 elements in `slice`.
514     ///
515     /// # Panics
516     ///
517     /// Panics if `slice` is less than 16 elements long.
518     #[inline]
write_cols_to_slice(self, slice: &mut [f32])519     pub fn write_cols_to_slice(self, slice: &mut [f32]) {
520         slice[0] = self.x_axis.x;
521         slice[1] = self.x_axis.y;
522         slice[2] = self.x_axis.z;
523         slice[3] = self.x_axis.w;
524         slice[4] = self.y_axis.x;
525         slice[5] = self.y_axis.y;
526         slice[6] = self.y_axis.z;
527         slice[7] = self.y_axis.w;
528         slice[8] = self.z_axis.x;
529         slice[9] = self.z_axis.y;
530         slice[10] = self.z_axis.z;
531         slice[11] = self.z_axis.w;
532         slice[12] = self.w_axis.x;
533         slice[13] = self.w_axis.y;
534         slice[14] = self.w_axis.z;
535         slice[15] = self.w_axis.w;
536     }
537 
538     /// Returns the matrix column for the given `index`.
539     ///
540     /// # Panics
541     ///
542     /// Panics if `index` is greater than 3.
543     #[inline]
544     #[must_use]
col(&self, index: usize) -> Vec4545     pub fn col(&self, index: usize) -> Vec4 {
546         match index {
547             0 => self.x_axis,
548             1 => self.y_axis,
549             2 => self.z_axis,
550             3 => self.w_axis,
551             _ => panic!("index out of bounds"),
552         }
553     }
554 
555     /// Returns a mutable reference to the matrix column for the given `index`.
556     ///
557     /// # Panics
558     ///
559     /// Panics if `index` is greater than 3.
560     #[inline]
col_mut(&mut self, index: usize) -> &mut Vec4561     pub fn col_mut(&mut self, index: usize) -> &mut Vec4 {
562         match index {
563             0 => &mut self.x_axis,
564             1 => &mut self.y_axis,
565             2 => &mut self.z_axis,
566             3 => &mut self.w_axis,
567             _ => panic!("index out of bounds"),
568         }
569     }
570 
571     /// Returns the matrix row for the given `index`.
572     ///
573     /// # Panics
574     ///
575     /// Panics if `index` is greater than 3.
576     #[inline]
577     #[must_use]
row(&self, index: usize) -> Vec4578     pub fn row(&self, index: usize) -> Vec4 {
579         match index {
580             0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
581             1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
582             2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
583             3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
584             _ => panic!("index out of bounds"),
585         }
586     }
587 
588     /// Returns `true` if, and only if, all elements are finite.
589     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
590     #[inline]
591     #[must_use]
is_finite(&self) -> bool592     pub fn is_finite(&self) -> bool {
593         self.x_axis.is_finite()
594             && self.y_axis.is_finite()
595             && self.z_axis.is_finite()
596             && self.w_axis.is_finite()
597     }
598 
599     /// Returns `true` if any elements are `NaN`.
600     #[inline]
601     #[must_use]
is_nan(&self) -> bool602     pub fn is_nan(&self) -> bool {
603         self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
604     }
605 
606     /// Returns the transpose of `self`.
607     #[inline]
608     #[must_use]
transpose(&self) -> Self609     pub fn transpose(&self) -> Self {
610         // Based on https://github.com/microsoft/DirectXMath `XMMatrixTranspose`
611         let tmp0 = i32x4_shuffle::<0, 1, 4, 5>(self.x_axis.0, self.y_axis.0);
612         let tmp1 = i32x4_shuffle::<2, 3, 6, 7>(self.x_axis.0, self.y_axis.0);
613         let tmp2 = i32x4_shuffle::<0, 1, 4, 5>(self.z_axis.0, self.w_axis.0);
614         let tmp3 = i32x4_shuffle::<2, 3, 6, 7>(self.z_axis.0, self.w_axis.0);
615 
616         Self {
617             x_axis: Vec4(i32x4_shuffle::<0, 2, 4, 6>(tmp0, tmp2)),
618             y_axis: Vec4(i32x4_shuffle::<1, 3, 5, 7>(tmp0, tmp2)),
619             z_axis: Vec4(i32x4_shuffle::<0, 2, 4, 6>(tmp1, tmp3)),
620             w_axis: Vec4(i32x4_shuffle::<1, 3, 5, 7>(tmp1, tmp3)),
621         }
622     }
623 
624     /// Returns the determinant of `self`.
625     #[must_use]
determinant(&self) -> f32626     pub fn determinant(&self) -> f32 {
627         // Based on https://github.com/g-truc/glm `glm_mat4_determinant`
628         let swp2a = i32x4_shuffle::<2, 1, 1, 0>(self.z_axis.0, self.z_axis.0);
629         let swp3a = i32x4_shuffle::<3, 3, 2, 3>(self.w_axis.0, self.w_axis.0);
630         let swp2b = i32x4_shuffle::<3, 3, 2, 3>(self.z_axis.0, self.z_axis.0);
631         let swp3b = i32x4_shuffle::<2, 1, 1, 0>(self.w_axis.0, self.w_axis.0);
632         let swp2c = i32x4_shuffle::<2, 1, 0, 0>(self.z_axis.0, self.z_axis.0);
633         let swp3c = i32x4_shuffle::<0, 0, 2, 1>(self.w_axis.0, self.w_axis.0);
634 
635         let mula = f32x4_mul(swp2a, swp3a);
636         let mulb = f32x4_mul(swp2b, swp3b);
637         let mulc = f32x4_mul(swp2c, swp3c);
638         let sube = f32x4_sub(mula, mulb);
639         let subf = f32x4_sub(i32x4_shuffle::<6, 7, 2, 3>(mulc, mulc), mulc);
640 
641         let subfaca = i32x4_shuffle::<0, 0, 1, 2>(sube, sube);
642         let swpfaca = i32x4_shuffle::<1, 0, 0, 0>(self.y_axis.0, self.y_axis.0);
643         let mulfaca = f32x4_mul(swpfaca, subfaca);
644 
645         let subtmpb = i32x4_shuffle::<1, 3, 4, 4>(sube, subf);
646         let subfacb = i32x4_shuffle::<0, 1, 1, 3>(subtmpb, subtmpb);
647         let swpfacb = i32x4_shuffle::<2, 2, 1, 1>(self.y_axis.0, self.y_axis.0);
648         let mulfacb = f32x4_mul(swpfacb, subfacb);
649 
650         let subres = f32x4_sub(mulfaca, mulfacb);
651         let subtmpc = i32x4_shuffle::<2, 2, 4, 5>(sube, subf);
652         let subfacc = i32x4_shuffle::<0, 2, 3, 3>(subtmpc, subtmpc);
653         let swpfacc = i32x4_shuffle::<3, 3, 3, 2>(self.y_axis.0, self.y_axis.0);
654         let mulfacc = f32x4_mul(swpfacc, subfacc);
655 
656         let addres = f32x4_add(subres, mulfacc);
657         let detcof = f32x4_mul(addres, f32x4(1.0, -1.0, 1.0, -1.0));
658 
659         dot4(self.x_axis.0, detcof)
660     }
661 
662     /// Returns the inverse of `self`.
663     ///
664     /// If the matrix is not invertible the returned matrix will be invalid.
665     ///
666     /// # Panics
667     ///
668     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
669     #[must_use]
inverse(&self) -> Self670     pub fn inverse(&self) -> Self {
671         // Based on https://github.com/g-truc/glm `glm_mat4_inverse`
672         let fac0 = {
673             let swp0a = i32x4_shuffle::<3, 3, 7, 7>(self.w_axis.0, self.z_axis.0);
674             let swp0b = i32x4_shuffle::<2, 2, 6, 6>(self.w_axis.0, self.z_axis.0);
675 
676             let swp00 = i32x4_shuffle::<2, 2, 6, 6>(self.z_axis.0, self.y_axis.0);
677             let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
678             let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
679             let swp03 = i32x4_shuffle::<3, 3, 7, 7>(self.z_axis.0, self.y_axis.0);
680 
681             let mul00 = f32x4_mul(swp00, swp01);
682             let mul01 = f32x4_mul(swp02, swp03);
683             f32x4_sub(mul00, mul01)
684         };
685         let fac1 = {
686             let swp0a = i32x4_shuffle::<3, 3, 7, 7>(self.w_axis.0, self.z_axis.0);
687             let swp0b = i32x4_shuffle::<1, 1, 5, 5>(self.w_axis.0, self.z_axis.0);
688 
689             let swp00 = i32x4_shuffle::<1, 1, 5, 5>(self.z_axis.0, self.y_axis.0);
690             let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
691             let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
692             let swp03 = i32x4_shuffle::<3, 3, 7, 7>(self.z_axis.0, self.y_axis.0);
693 
694             let mul00 = f32x4_mul(swp00, swp01);
695             let mul01 = f32x4_mul(swp02, swp03);
696             f32x4_sub(mul00, mul01)
697         };
698         let fac2 = {
699             let swp0a = i32x4_shuffle::<2, 2, 6, 6>(self.w_axis.0, self.z_axis.0);
700             let swp0b = i32x4_shuffle::<1, 1, 5, 5>(self.w_axis.0, self.z_axis.0);
701 
702             let swp00 = i32x4_shuffle::<1, 1, 5, 5>(self.z_axis.0, self.y_axis.0);
703             let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
704             let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
705             let swp03 = i32x4_shuffle::<2, 2, 6, 6>(self.z_axis.0, self.y_axis.0);
706 
707             let mul00 = f32x4_mul(swp00, swp01);
708             let mul01 = f32x4_mul(swp02, swp03);
709             f32x4_sub(mul00, mul01)
710         };
711         let fac3 = {
712             let swp0a = i32x4_shuffle::<3, 3, 7, 7>(self.w_axis.0, self.z_axis.0);
713             let swp0b = i32x4_shuffle::<0, 0, 4, 4>(self.w_axis.0, self.z_axis.0);
714 
715             let swp00 = i32x4_shuffle::<0, 0, 4, 4>(self.z_axis.0, self.y_axis.0);
716             let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
717             let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
718             let swp03 = i32x4_shuffle::<3, 3, 7, 7>(self.z_axis.0, self.y_axis.0);
719 
720             let mul00 = f32x4_mul(swp00, swp01);
721             let mul01 = f32x4_mul(swp02, swp03);
722             f32x4_sub(mul00, mul01)
723         };
724         let fac4 = {
725             let swp0a = i32x4_shuffle::<2, 2, 6, 6>(self.w_axis.0, self.z_axis.0);
726             let swp0b = i32x4_shuffle::<0, 0, 4, 4>(self.w_axis.0, self.z_axis.0);
727 
728             let swp00 = i32x4_shuffle::<0, 0, 4, 4>(self.z_axis.0, self.y_axis.0);
729             let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
730             let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
731             let swp03 = i32x4_shuffle::<2, 2, 6, 6>(self.z_axis.0, self.y_axis.0);
732 
733             let mul00 = f32x4_mul(swp00, swp01);
734             let mul01 = f32x4_mul(swp02, swp03);
735             f32x4_sub(mul00, mul01)
736         };
737         let fac5 = {
738             let swp0a = i32x4_shuffle::<1, 1, 5, 5>(self.w_axis.0, self.z_axis.0);
739             let swp0b = i32x4_shuffle::<0, 0, 4, 4>(self.w_axis.0, self.z_axis.0);
740 
741             let swp00 = i32x4_shuffle::<0, 0, 4, 4>(self.z_axis.0, self.y_axis.0);
742             let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
743             let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
744             let swp03 = i32x4_shuffle::<1, 1, 5, 5>(self.z_axis.0, self.y_axis.0);
745 
746             let mul00 = f32x4_mul(swp00, swp01);
747             let mul01 = f32x4_mul(swp02, swp03);
748             f32x4_sub(mul00, mul01)
749         };
750         let sign_a = f32x4(-1.0, 1.0, -1.0, 1.0);
751         let sign_b = f32x4(1.0, -1.0, 1.0, -1.0);
752 
753         let temp0 = i32x4_shuffle::<0, 0, 4, 4>(self.y_axis.0, self.x_axis.0);
754         let vec0 = i32x4_shuffle::<0, 2, 6, 6>(temp0, temp0);
755 
756         let temp1 = i32x4_shuffle::<1, 1, 5, 5>(self.y_axis.0, self.x_axis.0);
757         let vec1 = i32x4_shuffle::<0, 2, 6, 6>(temp1, temp1);
758 
759         let temp2 = i32x4_shuffle::<2, 2, 6, 6>(self.y_axis.0, self.x_axis.0);
760         let vec2 = i32x4_shuffle::<0, 2, 6, 6>(temp2, temp2);
761 
762         let temp3 = i32x4_shuffle::<3, 3, 7, 7>(self.y_axis.0, self.x_axis.0);
763         let vec3 = i32x4_shuffle::<0, 2, 6, 6>(temp3, temp3);
764 
765         let mul00 = f32x4_mul(vec1, fac0);
766         let mul01 = f32x4_mul(vec2, fac1);
767         let mul02 = f32x4_mul(vec3, fac2);
768         let sub00 = f32x4_sub(mul00, mul01);
769         let add00 = f32x4_add(sub00, mul02);
770         let inv0 = f32x4_mul(sign_b, add00);
771 
772         let mul03 = f32x4_mul(vec0, fac0);
773         let mul04 = f32x4_mul(vec2, fac3);
774         let mul05 = f32x4_mul(vec3, fac4);
775         let sub01 = f32x4_sub(mul03, mul04);
776         let add01 = f32x4_add(sub01, mul05);
777         let inv1 = f32x4_mul(sign_a, add01);
778 
779         let mul06 = f32x4_mul(vec0, fac1);
780         let mul07 = f32x4_mul(vec1, fac3);
781         let mul08 = f32x4_mul(vec3, fac5);
782         let sub02 = f32x4_sub(mul06, mul07);
783         let add02 = f32x4_add(sub02, mul08);
784         let inv2 = f32x4_mul(sign_b, add02);
785 
786         let mul09 = f32x4_mul(vec0, fac2);
787         let mul10 = f32x4_mul(vec1, fac4);
788         let mul11 = f32x4_mul(vec2, fac5);
789         let sub03 = f32x4_sub(mul09, mul10);
790         let add03 = f32x4_add(sub03, mul11);
791         let inv3 = f32x4_mul(sign_a, add03);
792 
793         let row0 = i32x4_shuffle::<0, 0, 4, 4>(inv0, inv1);
794         let row1 = i32x4_shuffle::<0, 0, 4, 4>(inv2, inv3);
795         let row2 = i32x4_shuffle::<0, 2, 4, 6>(row0, row1);
796 
797         let dot0 = dot4(self.x_axis.0, row2);
798         glam_assert!(dot0 != 0.0);
799 
800         let rcp0 = f32x4_splat(dot0.recip());
801 
802         Self {
803             x_axis: Vec4(f32x4_mul(inv0, rcp0)),
804             y_axis: Vec4(f32x4_mul(inv1, rcp0)),
805             z_axis: Vec4(f32x4_mul(inv2, rcp0)),
806             w_axis: Vec4(f32x4_mul(inv3, rcp0)),
807         }
808     }
809 
810     /// Creates a left-handed view matrix using a camera position, a facing direction and an up
811     /// direction
812     ///
813     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
814     ///
815     /// # Panics
816     ///
817     /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled.
818     #[inline]
819     #[must_use]
look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self820     pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
821         Self::look_to_rh(eye, -dir, up)
822     }
823 
824     /// Creates a right-handed view matrix using a camera position, a facing direction, and an up
825     /// direction.
826     ///
827     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
828     ///
829     /// # Panics
830     ///
831     /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled.
832     #[inline]
833     #[must_use]
look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self834     pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
835         glam_assert!(dir.is_normalized());
836         glam_assert!(up.is_normalized());
837         let f = dir;
838         let s = f.cross(up).normalize();
839         let u = s.cross(f);
840 
841         Self::from_cols(
842             Vec4::new(s.x, u.x, -f.x, 0.0),
843             Vec4::new(s.y, u.y, -f.y, 0.0),
844             Vec4::new(s.z, u.z, -f.z, 0.0),
845             Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
846         )
847     }
848 
849     /// Creates a left-handed view matrix using a camera position, a focal points and an up
850     /// direction.
851     ///
852     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
853     ///
854     /// # Panics
855     ///
856     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
857     #[inline]
858     #[must_use]
look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self859     pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
860         Self::look_to_lh(eye, center.sub(eye).normalize(), up)
861     }
862 
863     /// Creates a right-handed view matrix using a camera position, a focal point, and an up
864     /// direction.
865     ///
866     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
867     ///
868     /// # Panics
869     ///
870     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
871     #[inline]
look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self872     pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
873         Self::look_to_rh(eye, center.sub(eye).normalize(), up)
874     }
875 
876     /// Creates a right-handed perspective projection matrix with `[-1,1]` depth range.
877     ///
878     /// Useful to map the standard right-handed coordinate system into what OpenGL expects.
879     ///
880     /// This is the same as the OpenGL `gluPerspective` function.
881     /// See <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml>
882     #[inline]
883     #[must_use]
perspective_rh_gl( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32, ) -> Self884     pub fn perspective_rh_gl(
885         fov_y_radians: f32,
886         aspect_ratio: f32,
887         z_near: f32,
888         z_far: f32,
889     ) -> Self {
890         let inv_length = 1.0 / (z_near - z_far);
891         let f = 1.0 / math::tan(0.5 * fov_y_radians);
892         let a = f / aspect_ratio;
893         let b = (z_near + z_far) * inv_length;
894         let c = (2.0 * z_near * z_far) * inv_length;
895         Self::from_cols(
896             Vec4::new(a, 0.0, 0.0, 0.0),
897             Vec4::new(0.0, f, 0.0, 0.0),
898             Vec4::new(0.0, 0.0, b, -1.0),
899             Vec4::new(0.0, 0.0, c, 0.0),
900         )
901     }
902 
903     /// Creates a left-handed perspective projection matrix with `[0,1]` depth range.
904     ///
905     /// Useful to map the standard left-handed coordinate system into what WebGPU/Metal/Direct3D expect.
906     ///
907     /// # Panics
908     ///
909     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
910     /// enabled.
911     #[inline]
912     #[must_use]
perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self913     pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
914         glam_assert!(z_near > 0.0 && z_far > 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         let r = z_far / (z_far - z_near);
919         Self::from_cols(
920             Vec4::new(w, 0.0, 0.0, 0.0),
921             Vec4::new(0.0, h, 0.0, 0.0),
922             Vec4::new(0.0, 0.0, r, 1.0),
923             Vec4::new(0.0, 0.0, -r * z_near, 0.0),
924         )
925     }
926 
927     /// Creates a right-handed perspective projection matrix with `[0,1]` depth range.
928     ///
929     /// Useful to map the standard right-handed coordinate system into what WebGPU/Metal/Direct3D expect.
930     ///
931     /// # Panics
932     ///
933     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
934     /// enabled.
935     #[inline]
936     #[must_use]
perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self937     pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
938         glam_assert!(z_near > 0.0 && z_far > 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         let r = z_far / (z_near - z_far);
943         Self::from_cols(
944             Vec4::new(w, 0.0, 0.0, 0.0),
945             Vec4::new(0.0, h, 0.0, 0.0),
946             Vec4::new(0.0, 0.0, r, -1.0),
947             Vec4::new(0.0, 0.0, r * z_near, 0.0),
948         )
949     }
950 
951     /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range.
952     ///
953     /// Like `perspective_lh`, but with an infinite value for `z_far`.
954     /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`.
955     ///
956     /// # Panics
957     ///
958     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
959     /// enabled.
960     #[inline]
961     #[must_use]
perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self962     pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
963         glam_assert!(z_near > 0.0);
964         let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
965         let h = cos_fov / sin_fov;
966         let w = h / aspect_ratio;
967         Self::from_cols(
968             Vec4::new(w, 0.0, 0.0, 0.0),
969             Vec4::new(0.0, h, 0.0, 0.0),
970             Vec4::new(0.0, 0.0, 1.0, 1.0),
971             Vec4::new(0.0, 0.0, -z_near, 0.0),
972         )
973     }
974 
975     /// Creates an infinite reverse left-handed perspective projection matrix with `[0,1]` depth range.
976     ///
977     /// Similar to `perspective_infinite_lh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`.
978     ///
979     /// # Panics
980     ///
981     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
982     #[inline]
983     #[must_use]
perspective_infinite_reverse_lh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self984     pub fn perspective_infinite_reverse_lh(
985         fov_y_radians: f32,
986         aspect_ratio: f32,
987         z_near: f32,
988     ) -> Self {
989         glam_assert!(z_near > 0.0);
990         let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
991         let h = cos_fov / sin_fov;
992         let w = h / aspect_ratio;
993         Self::from_cols(
994             Vec4::new(w, 0.0, 0.0, 0.0),
995             Vec4::new(0.0, h, 0.0, 0.0),
996             Vec4::new(0.0, 0.0, 0.0, 1.0),
997             Vec4::new(0.0, 0.0, z_near, 0.0),
998         )
999     }
1000 
1001     /// Creates an infinite right-handed perspective projection matrix with `[0,1]` depth range.
1002     ///
1003     /// Like `perspective_rh`, but with an infinite value for `z_far`.
1004     /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`.
1005     ///
1006     /// # Panics
1007     ///
1008     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
1009     /// enabled.
1010     #[inline]
1011     #[must_use]
perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self1012     pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1013         glam_assert!(z_near > 0.0);
1014         let f = 1.0 / math::tan(0.5 * fov_y_radians);
1015         Self::from_cols(
1016             Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1017             Vec4::new(0.0, f, 0.0, 0.0),
1018             Vec4::new(0.0, 0.0, -1.0, -1.0),
1019             Vec4::new(0.0, 0.0, -z_near, 0.0),
1020         )
1021     }
1022 
1023     /// Creates an infinite reverse right-handed perspective projection matrix with `[0,1]` depth range.
1024     ///
1025     /// Similar to `perspective_infinite_rh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`.
1026     ///
1027     /// # Panics
1028     ///
1029     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
1030     #[inline]
1031     #[must_use]
perspective_infinite_reverse_rh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self1032     pub fn perspective_infinite_reverse_rh(
1033         fov_y_radians: f32,
1034         aspect_ratio: f32,
1035         z_near: f32,
1036     ) -> Self {
1037         glam_assert!(z_near > 0.0);
1038         let f = 1.0 / math::tan(0.5 * fov_y_radians);
1039         Self::from_cols(
1040             Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1041             Vec4::new(0.0, f, 0.0, 0.0),
1042             Vec4::new(0.0, 0.0, 0.0, -1.0),
1043             Vec4::new(0.0, 0.0, z_near, 0.0),
1044         )
1045     }
1046 
1047     /// Creates a right-handed orthographic projection matrix with `[-1,1]` depth
1048     /// range.  This is the same as the OpenGL `glOrtho` function in OpenGL.
1049     /// See
1050     /// <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml>
1051     ///
1052     /// Useful to map a right-handed coordinate system to the normalized device coordinates that OpenGL expects.
1053     #[inline]
1054     #[must_use]
orthographic_rh_gl( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self1055     pub fn orthographic_rh_gl(
1056         left: f32,
1057         right: f32,
1058         bottom: f32,
1059         top: f32,
1060         near: f32,
1061         far: f32,
1062     ) -> Self {
1063         let a = 2.0 / (right - left);
1064         let b = 2.0 / (top - bottom);
1065         let c = -2.0 / (far - near);
1066         let tx = -(right + left) / (right - left);
1067         let ty = -(top + bottom) / (top - bottom);
1068         let tz = -(far + near) / (far - near);
1069 
1070         Self::from_cols(
1071             Vec4::new(a, 0.0, 0.0, 0.0),
1072             Vec4::new(0.0, b, 0.0, 0.0),
1073             Vec4::new(0.0, 0.0, c, 0.0),
1074             Vec4::new(tx, ty, tz, 1.0),
1075         )
1076     }
1077 
1078     /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range.
1079     ///
1080     /// Useful to map a left-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect.
1081     #[inline]
1082     #[must_use]
orthographic_lh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self1083     pub fn orthographic_lh(
1084         left: f32,
1085         right: f32,
1086         bottom: f32,
1087         top: f32,
1088         near: f32,
1089         far: f32,
1090     ) -> Self {
1091         let rcp_width = 1.0 / (right - left);
1092         let rcp_height = 1.0 / (top - bottom);
1093         let r = 1.0 / (far - near);
1094         Self::from_cols(
1095             Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1096             Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1097             Vec4::new(0.0, 0.0, r, 0.0),
1098             Vec4::new(
1099                 -(left + right) * rcp_width,
1100                 -(top + bottom) * rcp_height,
1101                 -r * near,
1102                 1.0,
1103             ),
1104         )
1105     }
1106 
1107     /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range.
1108     ///
1109     /// Useful to map a right-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect.
1110     #[inline]
1111     #[must_use]
orthographic_rh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self1112     pub fn orthographic_rh(
1113         left: f32,
1114         right: f32,
1115         bottom: f32,
1116         top: f32,
1117         near: f32,
1118         far: f32,
1119     ) -> Self {
1120         let rcp_width = 1.0 / (right - left);
1121         let rcp_height = 1.0 / (top - bottom);
1122         let r = 1.0 / (near - far);
1123         Self::from_cols(
1124             Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1125             Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1126             Vec4::new(0.0, 0.0, r, 0.0),
1127             Vec4::new(
1128                 -(left + right) * rcp_width,
1129                 -(top + bottom) * rcp_height,
1130                 r * near,
1131                 1.0,
1132             ),
1133         )
1134     }
1135 
1136     /// Transforms the given 3D vector as a point, applying perspective correction.
1137     ///
1138     /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is `1.0`.
1139     /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
1140     ///
1141     /// This method assumes that `self` contains a projective transform.
1142     #[inline]
1143     #[must_use]
project_point3(&self, rhs: Vec3) -> Vec31144     pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
1145         let mut res = self.x_axis.mul(rhs.x);
1146         res = self.y_axis.mul(rhs.y).add(res);
1147         res = self.z_axis.mul(rhs.z).add(res);
1148         res = self.w_axis.add(res);
1149         res = res.div(res.w);
1150         res.xyz()
1151     }
1152 
1153     /// Transforms the given 3D vector as a point.
1154     ///
1155     /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
1156     /// `1.0`.
1157     ///
1158     /// This method assumes that `self` contains a valid affine transform. It does not perform
1159     /// a perspective divide, if `self` contains a perspective transform, or if you are unsure,
1160     /// the [`Self::project_point3()`] method should be used instead.
1161     ///
1162     /// # Panics
1163     ///
1164     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1165     #[inline]
1166     #[must_use]
transform_point3(&self, rhs: Vec3) -> Vec31167     pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1168         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1169         let mut res = self.x_axis.mul(rhs.x);
1170         res = self.y_axis.mul(rhs.y).add(res);
1171         res = self.z_axis.mul(rhs.z).add(res);
1172         res = self.w_axis.add(res);
1173         res.xyz()
1174     }
1175 
1176     /// Transforms the give 3D vector as a direction.
1177     ///
1178     /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
1179     /// `0.0`.
1180     ///
1181     /// This method assumes that `self` contains a valid affine transform.
1182     ///
1183     /// # Panics
1184     ///
1185     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1186     #[inline]
1187     #[must_use]
transform_vector3(&self, rhs: Vec3) -> Vec31188     pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1189         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1190         let mut res = self.x_axis.mul(rhs.x);
1191         res = self.y_axis.mul(rhs.y).add(res);
1192         res = self.z_axis.mul(rhs.z).add(res);
1193         res.xyz()
1194     }
1195 
1196     /// Transforms the given [`Vec3A`] as a 3D point, applying perspective correction.
1197     ///
1198     /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
1199     /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
1200     ///
1201     /// This method assumes that `self` contains a projective transform.
1202     #[inline]
1203     #[must_use]
project_point3a(&self, rhs: Vec3A) -> Vec3A1204     pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
1205         let mut res = self.x_axis.mul(rhs.xxxx());
1206         res = self.y_axis.mul(rhs.yyyy()).add(res);
1207         res = self.z_axis.mul(rhs.zzzz()).add(res);
1208         res = self.w_axis.add(res);
1209         res = res.div(res.wwww());
1210         Vec3A::from_vec4(res)
1211     }
1212 
1213     /// Transforms the given [`Vec3A`] as 3D point.
1214     ///
1215     /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
1216     #[inline]
1217     #[must_use]
transform_point3a(&self, rhs: Vec3A) -> Vec3A1218     pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1219         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1220         let mut res = self.x_axis.mul(rhs.xxxx());
1221         res = self.y_axis.mul(rhs.yyyy()).add(res);
1222         res = self.z_axis.mul(rhs.zzzz()).add(res);
1223         res = self.w_axis.add(res);
1224         Vec3A::from_vec4(res)
1225     }
1226 
1227     /// Transforms the give [`Vec3A`] as 3D vector.
1228     ///
1229     /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `0.0`.
1230     #[inline]
1231     #[must_use]
transform_vector3a(&self, rhs: Vec3A) -> Vec3A1232     pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1233         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1234         let mut res = self.x_axis.mul(rhs.xxxx());
1235         res = self.y_axis.mul(rhs.yyyy()).add(res);
1236         res = self.z_axis.mul(rhs.zzzz()).add(res);
1237         Vec3A::from_vec4(res)
1238     }
1239 
1240     /// Transforms a 4D vector.
1241     #[inline]
1242     #[must_use]
mul_vec4(&self, rhs: Vec4) -> Vec41243     pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1244         let mut res = self.x_axis.mul(rhs.xxxx());
1245         res = res.add(self.y_axis.mul(rhs.yyyy()));
1246         res = res.add(self.z_axis.mul(rhs.zzzz()));
1247         res = res.add(self.w_axis.mul(rhs.wwww()));
1248         res
1249     }
1250 
1251     /// Multiplies two 4x4 matrices.
1252     #[inline]
1253     #[must_use]
mul_mat4(&self, rhs: &Self) -> Self1254     pub fn mul_mat4(&self, rhs: &Self) -> Self {
1255         Self::from_cols(
1256             self.mul(rhs.x_axis),
1257             self.mul(rhs.y_axis),
1258             self.mul(rhs.z_axis),
1259             self.mul(rhs.w_axis),
1260         )
1261     }
1262 
1263     /// Adds two 4x4 matrices.
1264     #[inline]
1265     #[must_use]
add_mat4(&self, rhs: &Self) -> Self1266     pub fn add_mat4(&self, rhs: &Self) -> Self {
1267         Self::from_cols(
1268             self.x_axis.add(rhs.x_axis),
1269             self.y_axis.add(rhs.y_axis),
1270             self.z_axis.add(rhs.z_axis),
1271             self.w_axis.add(rhs.w_axis),
1272         )
1273     }
1274 
1275     /// Subtracts two 4x4 matrices.
1276     #[inline]
1277     #[must_use]
sub_mat4(&self, rhs: &Self) -> Self1278     pub fn sub_mat4(&self, rhs: &Self) -> Self {
1279         Self::from_cols(
1280             self.x_axis.sub(rhs.x_axis),
1281             self.y_axis.sub(rhs.y_axis),
1282             self.z_axis.sub(rhs.z_axis),
1283             self.w_axis.sub(rhs.w_axis),
1284         )
1285     }
1286 
1287     /// Multiplies a 4x4 matrix by a scalar.
1288     #[inline]
1289     #[must_use]
mul_scalar(&self, rhs: f32) -> Self1290     pub fn mul_scalar(&self, rhs: f32) -> Self {
1291         Self::from_cols(
1292             self.x_axis.mul(rhs),
1293             self.y_axis.mul(rhs),
1294             self.z_axis.mul(rhs),
1295             self.w_axis.mul(rhs),
1296         )
1297     }
1298 
1299     /// Divides a 4x4 matrix by a scalar.
1300     #[inline]
1301     #[must_use]
div_scalar(&self, rhs: f32) -> Self1302     pub fn div_scalar(&self, rhs: f32) -> Self {
1303         let rhs = Vec4::splat(rhs);
1304         Self::from_cols(
1305             self.x_axis.div(rhs),
1306             self.y_axis.div(rhs),
1307             self.z_axis.div(rhs),
1308             self.w_axis.div(rhs),
1309         )
1310     }
1311 
1312     /// Returns true if the absolute difference of all elements between `self` and `rhs`
1313     /// is less than or equal to `max_abs_diff`.
1314     ///
1315     /// This can be used to compare if two matrices contain similar elements. It works best
1316     /// when comparing with a known value. The `max_abs_diff` that should be used used
1317     /// depends on the values being compared against.
1318     ///
1319     /// For more see
1320     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
1321     #[inline]
1322     #[must_use]
abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool1323     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1324         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1325             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1326             && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1327             && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1328     }
1329 
1330     /// Takes the absolute value of each element in `self`
1331     #[inline]
1332     #[must_use]
abs(&self) -> Self1333     pub fn abs(&self) -> Self {
1334         Self::from_cols(
1335             self.x_axis.abs(),
1336             self.y_axis.abs(),
1337             self.z_axis.abs(),
1338             self.w_axis.abs(),
1339         )
1340     }
1341 
1342     #[inline]
as_dmat4(&self) -> DMat41343     pub fn as_dmat4(&self) -> DMat4 {
1344         DMat4::from_cols(
1345             self.x_axis.as_dvec4(),
1346             self.y_axis.as_dvec4(),
1347             self.z_axis.as_dvec4(),
1348             self.w_axis.as_dvec4(),
1349         )
1350     }
1351 }
1352 
1353 impl Default for Mat4 {
1354     #[inline]
default() -> Self1355     fn default() -> Self {
1356         Self::IDENTITY
1357     }
1358 }
1359 
1360 impl Add<Mat4> for Mat4 {
1361     type Output = Self;
1362     #[inline]
add(self, rhs: Self) -> Self::Output1363     fn add(self, rhs: Self) -> Self::Output {
1364         self.add_mat4(&rhs)
1365     }
1366 }
1367 
1368 impl AddAssign<Mat4> for Mat4 {
1369     #[inline]
add_assign(&mut self, rhs: Self)1370     fn add_assign(&mut self, rhs: Self) {
1371         *self = self.add_mat4(&rhs);
1372     }
1373 }
1374 
1375 impl Sub<Mat4> for Mat4 {
1376     type Output = Self;
1377     #[inline]
sub(self, rhs: Self) -> Self::Output1378     fn sub(self, rhs: Self) -> Self::Output {
1379         self.sub_mat4(&rhs)
1380     }
1381 }
1382 
1383 impl SubAssign<Mat4> for Mat4 {
1384     #[inline]
sub_assign(&mut self, rhs: Self)1385     fn sub_assign(&mut self, rhs: Self) {
1386         *self = self.sub_mat4(&rhs);
1387     }
1388 }
1389 
1390 impl Neg for Mat4 {
1391     type Output = Self;
1392     #[inline]
neg(self) -> Self::Output1393     fn neg(self) -> Self::Output {
1394         Self::from_cols(
1395             self.x_axis.neg(),
1396             self.y_axis.neg(),
1397             self.z_axis.neg(),
1398             self.w_axis.neg(),
1399         )
1400     }
1401 }
1402 
1403 impl Mul<Mat4> for Mat4 {
1404     type Output = Self;
1405     #[inline]
mul(self, rhs: Self) -> Self::Output1406     fn mul(self, rhs: Self) -> Self::Output {
1407         self.mul_mat4(&rhs)
1408     }
1409 }
1410 
1411 impl MulAssign<Mat4> for Mat4 {
1412     #[inline]
mul_assign(&mut self, rhs: Self)1413     fn mul_assign(&mut self, rhs: Self) {
1414         *self = self.mul_mat4(&rhs);
1415     }
1416 }
1417 
1418 impl Mul<Vec4> for Mat4 {
1419     type Output = Vec4;
1420     #[inline]
mul(self, rhs: Vec4) -> Self::Output1421     fn mul(self, rhs: Vec4) -> Self::Output {
1422         self.mul_vec4(rhs)
1423     }
1424 }
1425 
1426 impl Mul<Mat4> for f32 {
1427     type Output = Mat4;
1428     #[inline]
mul(self, rhs: Mat4) -> Self::Output1429     fn mul(self, rhs: Mat4) -> Self::Output {
1430         rhs.mul_scalar(self)
1431     }
1432 }
1433 
1434 impl Mul<f32> for Mat4 {
1435     type Output = Self;
1436     #[inline]
mul(self, rhs: f32) -> Self::Output1437     fn mul(self, rhs: f32) -> Self::Output {
1438         self.mul_scalar(rhs)
1439     }
1440 }
1441 
1442 impl MulAssign<f32> for Mat4 {
1443     #[inline]
mul_assign(&mut self, rhs: f32)1444     fn mul_assign(&mut self, rhs: f32) {
1445         *self = self.mul_scalar(rhs);
1446     }
1447 }
1448 
1449 impl Div<Mat4> for f32 {
1450     type Output = Mat4;
1451     #[inline]
div(self, rhs: Mat4) -> Self::Output1452     fn div(self, rhs: Mat4) -> Self::Output {
1453         rhs.div_scalar(self)
1454     }
1455 }
1456 
1457 impl Div<f32> for Mat4 {
1458     type Output = Self;
1459     #[inline]
div(self, rhs: f32) -> Self::Output1460     fn div(self, rhs: f32) -> Self::Output {
1461         self.div_scalar(rhs)
1462     }
1463 }
1464 
1465 impl DivAssign<f32> for Mat4 {
1466     #[inline]
div_assign(&mut self, rhs: f32)1467     fn div_assign(&mut self, rhs: f32) {
1468         *self = self.div_scalar(rhs);
1469     }
1470 }
1471 
1472 impl Sum<Self> for Mat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,1473     fn sum<I>(iter: I) -> Self
1474     where
1475         I: Iterator<Item = Self>,
1476     {
1477         iter.fold(Self::ZERO, Self::add)
1478     }
1479 }
1480 
1481 impl<'a> Sum<&'a Self> for Mat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,1482     fn sum<I>(iter: I) -> Self
1483     where
1484         I: Iterator<Item = &'a Self>,
1485     {
1486         iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1487     }
1488 }
1489 
1490 impl Product for Mat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,1491     fn product<I>(iter: I) -> Self
1492     where
1493         I: Iterator<Item = Self>,
1494     {
1495         iter.fold(Self::IDENTITY, Self::mul)
1496     }
1497 }
1498 
1499 impl<'a> Product<&'a Self> for Mat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,1500     fn product<I>(iter: I) -> Self
1501     where
1502         I: Iterator<Item = &'a Self>,
1503     {
1504         iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1505     }
1506 }
1507 
1508 impl PartialEq for Mat4 {
1509     #[inline]
eq(&self, rhs: &Self) -> bool1510     fn eq(&self, rhs: &Self) -> bool {
1511         self.x_axis.eq(&rhs.x_axis)
1512             && self.y_axis.eq(&rhs.y_axis)
1513             && self.z_axis.eq(&rhs.z_axis)
1514             && self.w_axis.eq(&rhs.w_axis)
1515     }
1516 }
1517 
1518 #[cfg(not(target_arch = "spirv"))]
1519 impl AsRef<[f32; 16]> for Mat4 {
1520     #[inline]
as_ref(&self) -> &[f32; 16]1521     fn as_ref(&self) -> &[f32; 16] {
1522         unsafe { &*(self as *const Self as *const [f32; 16]) }
1523     }
1524 }
1525 
1526 #[cfg(not(target_arch = "spirv"))]
1527 impl AsMut<[f32; 16]> for Mat4 {
1528     #[inline]
as_mut(&mut self) -> &mut [f32; 16]1529     fn as_mut(&mut self) -> &mut [f32; 16] {
1530         unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
1531     }
1532 }
1533 
1534 impl fmt::Debug for Mat4 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result1535     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1536         fmt.debug_struct(stringify!(Mat4))
1537             .field("x_axis", &self.x_axis)
1538             .field("y_axis", &self.y_axis)
1539             .field("z_axis", &self.z_axis)
1540             .field("w_axis", &self.w_axis)
1541             .finish()
1542     }
1543 }
1544 
1545 impl fmt::Display for Mat4 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1546     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1547         if let Some(p) = f.precision() {
1548             write!(
1549                 f,
1550                 "[{:.*}, {:.*}, {:.*}, {:.*}]",
1551                 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
1552             )
1553         } else {
1554             write!(
1555                 f,
1556                 "[{}, {}, {}, {}]",
1557                 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1558             )
1559         }
1560     }
1561 }
1562