• 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     DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4,
8 };
9 use core::fmt;
10 use core::iter::{Product, Sum};
11 use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
12 
13 /// Creates a 4x4 matrix from four column vectors.
14 #[inline(always)]
15 #[must_use]
mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat416 pub const fn mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat4 {
17     Mat4::from_cols(x_axis, y_axis, z_axis, w_axis)
18 }
19 
20 /// A 4x4 column major matrix.
21 ///
22 /// This 4x4 matrix type features convenience methods for creating and using affine transforms and
23 /// perspective projections. If you are primarily dealing with 3D affine transformations
24 /// considering using [`Affine3A`](crate::Affine3A) which is faster than a 4x4 matrix
25 /// for some affine operations.
26 ///
27 /// Affine transformations including 3D translation, rotation and scale can be created
28 /// using methods such as [`Self::from_translation()`], [`Self::from_quat()`],
29 /// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`].
30 ///
31 /// Orthographic projections can be created using the methods [`Self::orthographic_lh()`] for
32 /// left-handed coordinate systems and [`Self::orthographic_rh()`] for right-handed
33 /// systems. The resulting matrix is also an affine transformation.
34 ///
35 /// The [`Self::transform_point3()`] and [`Self::transform_vector3()`] convenience methods
36 /// are provided for performing affine transformations on 3D vectors and points. These
37 /// multiply 3D inputs as 4D vectors with an implicit `w` value of `1` for points and `0`
38 /// for vectors respectively. These methods assume that `Self` contains a valid affine
39 /// transform.
40 ///
41 /// Perspective projections can be created using methods such as
42 /// [`Self::perspective_lh()`], [`Self::perspective_infinite_lh()`] and
43 /// [`Self::perspective_infinite_reverse_lh()`] for left-handed co-ordinate systems and
44 /// [`Self::perspective_rh()`], [`Self::perspective_infinite_rh()`] and
45 /// [`Self::perspective_infinite_reverse_rh()`] for right-handed co-ordinate systems.
46 ///
47 /// The resulting perspective project can be use to transform 3D vectors as points with
48 /// perspective correction using the [`Self::project_point3()`] convenience method.
49 #[derive(Clone, Copy)]
50 #[cfg_attr(
51     any(
52         not(any(feature = "scalar-math", target_arch = "spirv")),
53         feature = "cuda"
54     ),
55     repr(align(16))
56 )]
57 #[repr(C)]
58 pub struct Mat4 {
59     pub x_axis: Vec4,
60     pub y_axis: Vec4,
61     pub z_axis: Vec4,
62     pub w_axis: Vec4,
63 }
64 
65 impl Mat4 {
66     /// A 4x4 matrix with all elements set to `0.0`.
67     pub const ZERO: Self = Self::from_cols(Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO);
68 
69     /// A 4x4 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
70     pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W);
71 
72     /// All NAN:s.
73     pub const NAN: Self = Self::from_cols(Vec4::NAN, Vec4::NAN, Vec4::NAN, Vec4::NAN);
74 
75     #[allow(clippy::too_many_arguments)]
76     #[inline(always)]
77     #[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, ) -> Self78     const fn new(
79         m00: f32,
80         m01: f32,
81         m02: f32,
82         m03: f32,
83         m10: f32,
84         m11: f32,
85         m12: f32,
86         m13: f32,
87         m20: f32,
88         m21: f32,
89         m22: f32,
90         m23: f32,
91         m30: f32,
92         m31: f32,
93         m32: f32,
94         m33: f32,
95     ) -> Self {
96         Self {
97             x_axis: Vec4::new(m00, m01, m02, m03),
98             y_axis: Vec4::new(m10, m11, m12, m13),
99             z_axis: Vec4::new(m20, m21, m22, m23),
100             w_axis: Vec4::new(m30, m31, m32, m33),
101         }
102     }
103 
104     /// Creates a 4x4 matrix from four column vectors.
105     #[inline(always)]
106     #[must_use]
from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self107     pub const fn from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self {
108         Self {
109             x_axis,
110             y_axis,
111             z_axis,
112             w_axis,
113         }
114     }
115 
116     /// Creates a 4x4 matrix from a `[f32; 16]` array stored in column major order.
117     /// If your data is stored in row major you will need to `transpose` the returned
118     /// matrix.
119     #[inline]
120     #[must_use]
from_cols_array(m: &[f32; 16]) -> Self121     pub const fn from_cols_array(m: &[f32; 16]) -> Self {
122         Self::new(
123             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],
124             m[14], m[15],
125         )
126     }
127 
128     /// Creates a `[f32; 16]` array storing data in column major order.
129     /// If you require data in row major order `transpose` the matrix first.
130     #[inline]
131     #[must_use]
to_cols_array(&self) -> [f32; 16]132     pub const fn to_cols_array(&self) -> [f32; 16] {
133         [
134             self.x_axis.x,
135             self.x_axis.y,
136             self.x_axis.z,
137             self.x_axis.w,
138             self.y_axis.x,
139             self.y_axis.y,
140             self.y_axis.z,
141             self.y_axis.w,
142             self.z_axis.x,
143             self.z_axis.y,
144             self.z_axis.z,
145             self.z_axis.w,
146             self.w_axis.x,
147             self.w_axis.y,
148             self.w_axis.z,
149             self.w_axis.w,
150         ]
151     }
152 
153     /// Creates a 4x4 matrix from a `[[f32; 4]; 4]` 4D array stored in column major order.
154     /// If your data is in row major order you will need to `transpose` the returned
155     /// matrix.
156     #[inline]
157     #[must_use]
from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self158     pub const fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self {
159         Self::from_cols(
160             Vec4::from_array(m[0]),
161             Vec4::from_array(m[1]),
162             Vec4::from_array(m[2]),
163             Vec4::from_array(m[3]),
164         )
165     }
166 
167     /// Creates a `[[f32; 4]; 4]` 4D array storing data in column major order.
168     /// If you require data in row major order `transpose` the matrix first.
169     #[inline]
170     #[must_use]
to_cols_array_2d(&self) -> [[f32; 4]; 4]171     pub const fn to_cols_array_2d(&self) -> [[f32; 4]; 4] {
172         [
173             self.x_axis.to_array(),
174             self.y_axis.to_array(),
175             self.z_axis.to_array(),
176             self.w_axis.to_array(),
177         ]
178     }
179 
180     /// Creates a 4x4 matrix with its diagonal set to `diagonal` and all other entries set to 0.
181     #[doc(alias = "scale")]
182     #[inline]
183     #[must_use]
from_diagonal(diagonal: Vec4) -> Self184     pub const fn from_diagonal(diagonal: Vec4) -> Self {
185         Self::new(
186             diagonal.x, 0.0, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, 0.0, diagonal.z, 0.0, 0.0,
187             0.0, 0.0, diagonal.w,
188         )
189     }
190 
191     #[inline]
192     #[must_use]
quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4)193     fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) {
194         glam_assert!(rotation.is_normalized());
195 
196         let (x, y, z, w) = rotation.into();
197         let x2 = x + x;
198         let y2 = y + y;
199         let z2 = z + z;
200         let xx = x * x2;
201         let xy = x * y2;
202         let xz = x * z2;
203         let yy = y * y2;
204         let yz = y * z2;
205         let zz = z * z2;
206         let wx = w * x2;
207         let wy = w * y2;
208         let wz = w * z2;
209 
210         let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
211         let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
212         let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
213         (x_axis, y_axis, z_axis)
214     }
215 
216     /// Creates an affine transformation matrix from the given 3D `scale`, `rotation` and
217     /// `translation`.
218     ///
219     /// The resulting matrix can be used to transform 3D points and vectors. See
220     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
221     ///
222     /// # Panics
223     ///
224     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
225     #[inline]
226     #[must_use]
from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self227     pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
228         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
229         Self::from_cols(
230             x_axis.mul(scale.x),
231             y_axis.mul(scale.y),
232             z_axis.mul(scale.z),
233             Vec4::from((translation, 1.0)),
234         )
235     }
236 
237     /// Creates an affine transformation matrix from the given 3D `translation`.
238     ///
239     /// The resulting matrix can be used to transform 3D points and vectors. See
240     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
241     ///
242     /// # Panics
243     ///
244     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
245     #[inline]
246     #[must_use]
from_rotation_translation(rotation: Quat, translation: Vec3) -> Self247     pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
248         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
249         Self::from_cols(x_axis, y_axis, z_axis, Vec4::from((translation, 1.0)))
250     }
251 
252     /// Extracts `scale`, `rotation` and `translation` from `self`. The input matrix is
253     /// expected to be a 3D affine transformation matrix otherwise the output will be invalid.
254     ///
255     /// # Panics
256     ///
257     /// Will panic if the determinant of `self` is zero or if the resulting scale vector
258     /// contains any zero elements when `glam_assert` is enabled.
259     #[inline]
260     #[must_use]
to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3)261     pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
262         let det = self.determinant();
263         glam_assert!(det != 0.0);
264 
265         let scale = Vec3::new(
266             self.x_axis.length() * math::signum(det),
267             self.y_axis.length(),
268             self.z_axis.length(),
269         );
270 
271         glam_assert!(scale.cmpne(Vec3::ZERO).all());
272 
273         let inv_scale = scale.recip();
274 
275         let rotation = Quat::from_rotation_axes(
276             self.x_axis.mul(inv_scale.x).xyz(),
277             self.y_axis.mul(inv_scale.y).xyz(),
278             self.z_axis.mul(inv_scale.z).xyz(),
279         );
280 
281         let translation = self.w_axis.xyz();
282 
283         (scale, rotation, translation)
284     }
285 
286     /// Creates an affine transformation matrix from the given `rotation` quaternion.
287     ///
288     /// The resulting matrix can be used to transform 3D points and vectors. See
289     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
290     ///
291     /// # Panics
292     ///
293     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
294     #[inline]
295     #[must_use]
from_quat(rotation: Quat) -> Self296     pub fn from_quat(rotation: Quat) -> Self {
297         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
298         Self::from_cols(x_axis, y_axis, z_axis, Vec4::W)
299     }
300 
301     /// Creates an affine transformation matrix from the given 3x3 linear transformation
302     /// matrix.
303     ///
304     /// The resulting matrix can be used to transform 3D points and vectors. See
305     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
306     #[inline]
307     #[must_use]
from_mat3(m: Mat3) -> Self308     pub fn from_mat3(m: Mat3) -> Self {
309         Self::from_cols(
310             Vec4::from((m.x_axis, 0.0)),
311             Vec4::from((m.y_axis, 0.0)),
312             Vec4::from((m.z_axis, 0.0)),
313             Vec4::W,
314         )
315     }
316 
317     /// Creates an affine transformation matrics from a 3x3 matrix (expressing scale, shear and
318     /// rotation) and a translation vector.
319     ///
320     /// Equivalent to `Mat4::from_translation(translation) * Mat4::from_mat3(mat3)`
321     #[inline]
322     #[must_use]
from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self323     pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
324         Self::from_cols(
325             Vec4::from((mat3.x_axis, 0.0)),
326             Vec4::from((mat3.y_axis, 0.0)),
327             Vec4::from((mat3.z_axis, 0.0)),
328             Vec4::from((translation, 1.0)),
329         )
330     }
331 
332     /// Creates an affine transformation matrix from the given 3x3 linear transformation
333     /// matrix.
334     ///
335     /// The resulting matrix can be used to transform 3D points and vectors. See
336     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
337     #[inline]
338     #[must_use]
from_mat3a(m: Mat3A) -> Self339     pub fn from_mat3a(m: Mat3A) -> Self {
340         Self::from_cols(
341             Vec4::from((m.x_axis, 0.0)),
342             Vec4::from((m.y_axis, 0.0)),
343             Vec4::from((m.z_axis, 0.0)),
344             Vec4::W,
345         )
346     }
347 
348     /// Creates an affine transformation matrix from the given 3D `translation`.
349     ///
350     /// The resulting matrix can be used to transform 3D points and vectors. See
351     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
352     #[inline]
353     #[must_use]
from_translation(translation: Vec3) -> Self354     pub fn from_translation(translation: Vec3) -> Self {
355         Self::from_cols(
356             Vec4::X,
357             Vec4::Y,
358             Vec4::Z,
359             Vec4::new(translation.x, translation.y, translation.z, 1.0),
360         )
361     }
362 
363     /// Creates an affine transformation matrix containing a 3D rotation around a normalized
364     /// rotation `axis` of `angle` (in radians).
365     ///
366     /// The resulting matrix can be used to transform 3D points and vectors. See
367     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
368     ///
369     /// # Panics
370     ///
371     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
372     #[inline]
373     #[must_use]
from_axis_angle(axis: Vec3, angle: f32) -> Self374     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
375         glam_assert!(axis.is_normalized());
376 
377         let (sin, cos) = math::sin_cos(angle);
378         let axis_sin = axis.mul(sin);
379         let axis_sq = axis.mul(axis);
380         let omc = 1.0 - cos;
381         let xyomc = axis.x * axis.y * omc;
382         let xzomc = axis.x * axis.z * omc;
383         let yzomc = axis.y * axis.z * omc;
384         Self::from_cols(
385             Vec4::new(
386                 axis_sq.x * omc + cos,
387                 xyomc + axis_sin.z,
388                 xzomc - axis_sin.y,
389                 0.0,
390             ),
391             Vec4::new(
392                 xyomc - axis_sin.z,
393                 axis_sq.y * omc + cos,
394                 yzomc + axis_sin.x,
395                 0.0,
396             ),
397             Vec4::new(
398                 xzomc + axis_sin.y,
399                 yzomc - axis_sin.x,
400                 axis_sq.z * omc + cos,
401                 0.0,
402             ),
403             Vec4::W,
404         )
405     }
406 
407     /// Creates a affine transformation matrix containing a rotation from the given euler
408     /// rotation sequence and angles (in radians).
409     ///
410     /// The resulting matrix can be used to transform 3D points and vectors. See
411     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
412     #[inline]
413     #[must_use]
from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self414     pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
415         Self::from_euler_angles(order, a, b, c)
416     }
417 
418     /// Extract Euler angles with the given Euler rotation order.
419     ///
420     /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations
421     /// then the resulting Euler angles will be ill-defined.
422     ///
423     /// # Panics
424     ///
425     /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when
426     /// `glam_assert` is enabled.
427     #[inline]
428     #[must_use]
to_euler(&self, order: EulerRot) -> (f32, f32, f32)429     pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
430         glam_assert!(
431             self.x_axis.xyz().is_normalized()
432                 && self.y_axis.xyz().is_normalized()
433                 && self.z_axis.xyz().is_normalized()
434         );
435         self.to_euler_angles(order)
436     }
437 
438     /// Creates an affine transformation matrix containing a 3D rotation around the x axis of
439     /// `angle` (in radians).
440     ///
441     /// The resulting matrix can be used to transform 3D points and vectors. See
442     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
443     #[inline]
444     #[must_use]
from_rotation_x(angle: f32) -> Self445     pub fn from_rotation_x(angle: f32) -> Self {
446         let (sina, cosa) = math::sin_cos(angle);
447         Self::from_cols(
448             Vec4::X,
449             Vec4::new(0.0, cosa, sina, 0.0),
450             Vec4::new(0.0, -sina, cosa, 0.0),
451             Vec4::W,
452         )
453     }
454 
455     /// Creates an affine transformation matrix containing a 3D rotation around the y axis of
456     /// `angle` (in radians).
457     ///
458     /// The resulting matrix can be used to transform 3D points and vectors. See
459     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
460     #[inline]
461     #[must_use]
from_rotation_y(angle: f32) -> Self462     pub fn from_rotation_y(angle: f32) -> Self {
463         let (sina, cosa) = math::sin_cos(angle);
464         Self::from_cols(
465             Vec4::new(cosa, 0.0, -sina, 0.0),
466             Vec4::Y,
467             Vec4::new(sina, 0.0, cosa, 0.0),
468             Vec4::W,
469         )
470     }
471 
472     /// Creates an affine transformation matrix containing a 3D rotation around the z axis of
473     /// `angle` (in radians).
474     ///
475     /// The resulting matrix can be used to transform 3D points and vectors. See
476     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
477     #[inline]
478     #[must_use]
from_rotation_z(angle: f32) -> Self479     pub fn from_rotation_z(angle: f32) -> Self {
480         let (sina, cosa) = math::sin_cos(angle);
481         Self::from_cols(
482             Vec4::new(cosa, sina, 0.0, 0.0),
483             Vec4::new(-sina, cosa, 0.0, 0.0),
484             Vec4::Z,
485             Vec4::W,
486         )
487     }
488 
489     /// Creates an affine transformation matrix containing the given 3D non-uniform `scale`.
490     ///
491     /// The resulting matrix can be used to transform 3D points and vectors. See
492     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
493     ///
494     /// # Panics
495     ///
496     /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
497     #[inline]
498     #[must_use]
from_scale(scale: Vec3) -> Self499     pub fn from_scale(scale: Vec3) -> Self {
500         // Do not panic as long as any component is non-zero
501         glam_assert!(scale.cmpne(Vec3::ZERO).any());
502 
503         Self::from_cols(
504             Vec4::new(scale.x, 0.0, 0.0, 0.0),
505             Vec4::new(0.0, scale.y, 0.0, 0.0),
506             Vec4::new(0.0, 0.0, scale.z, 0.0),
507             Vec4::W,
508         )
509     }
510 
511     /// Creates a 4x4 matrix from the first 16 values in `slice`.
512     ///
513     /// # Panics
514     ///
515     /// Panics if `slice` is less than 16 elements long.
516     #[inline]
517     #[must_use]
from_cols_slice(slice: &[f32]) -> Self518     pub const fn from_cols_slice(slice: &[f32]) -> Self {
519         Self::new(
520             slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
521             slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
522         )
523     }
524 
525     /// Writes the columns of `self` to the first 16 elements in `slice`.
526     ///
527     /// # Panics
528     ///
529     /// Panics if `slice` is less than 16 elements long.
530     #[inline]
write_cols_to_slice(self, slice: &mut [f32])531     pub fn write_cols_to_slice(self, slice: &mut [f32]) {
532         slice[0] = self.x_axis.x;
533         slice[1] = self.x_axis.y;
534         slice[2] = self.x_axis.z;
535         slice[3] = self.x_axis.w;
536         slice[4] = self.y_axis.x;
537         slice[5] = self.y_axis.y;
538         slice[6] = self.y_axis.z;
539         slice[7] = self.y_axis.w;
540         slice[8] = self.z_axis.x;
541         slice[9] = self.z_axis.y;
542         slice[10] = self.z_axis.z;
543         slice[11] = self.z_axis.w;
544         slice[12] = self.w_axis.x;
545         slice[13] = self.w_axis.y;
546         slice[14] = self.w_axis.z;
547         slice[15] = self.w_axis.w;
548     }
549 
550     /// Returns the matrix column for the given `index`.
551     ///
552     /// # Panics
553     ///
554     /// Panics if `index` is greater than 3.
555     #[inline]
556     #[must_use]
col(&self, index: usize) -> Vec4557     pub fn col(&self, index: usize) -> Vec4 {
558         match index {
559             0 => self.x_axis,
560             1 => self.y_axis,
561             2 => self.z_axis,
562             3 => self.w_axis,
563             _ => panic!("index out of bounds"),
564         }
565     }
566 
567     /// Returns a mutable reference to the matrix column for the given `index`.
568     ///
569     /// # Panics
570     ///
571     /// Panics if `index` is greater than 3.
572     #[inline]
col_mut(&mut self, index: usize) -> &mut Vec4573     pub fn col_mut(&mut self, index: usize) -> &mut Vec4 {
574         match index {
575             0 => &mut self.x_axis,
576             1 => &mut self.y_axis,
577             2 => &mut self.z_axis,
578             3 => &mut self.w_axis,
579             _ => panic!("index out of bounds"),
580         }
581     }
582 
583     /// Returns the matrix row for the given `index`.
584     ///
585     /// # Panics
586     ///
587     /// Panics if `index` is greater than 3.
588     #[inline]
589     #[must_use]
row(&self, index: usize) -> Vec4590     pub fn row(&self, index: usize) -> Vec4 {
591         match index {
592             0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
593             1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
594             2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
595             3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
596             _ => panic!("index out of bounds"),
597         }
598     }
599 
600     /// Returns `true` if, and only if, all elements are finite.
601     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
602     #[inline]
603     #[must_use]
is_finite(&self) -> bool604     pub fn is_finite(&self) -> bool {
605         self.x_axis.is_finite()
606             && self.y_axis.is_finite()
607             && self.z_axis.is_finite()
608             && self.w_axis.is_finite()
609     }
610 
611     /// Returns `true` if any elements are `NaN`.
612     #[inline]
613     #[must_use]
is_nan(&self) -> bool614     pub fn is_nan(&self) -> bool {
615         self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
616     }
617 
618     /// Returns the transpose of `self`.
619     #[inline]
620     #[must_use]
transpose(&self) -> Self621     pub fn transpose(&self) -> Self {
622         Self {
623             x_axis: Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
624             y_axis: Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
625             z_axis: Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
626             w_axis: Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
627         }
628     }
629 
630     /// Returns the determinant of `self`.
631     #[must_use]
determinant(&self) -> f32632     pub fn determinant(&self) -> f32 {
633         let (m00, m01, m02, m03) = self.x_axis.into();
634         let (m10, m11, m12, m13) = self.y_axis.into();
635         let (m20, m21, m22, m23) = self.z_axis.into();
636         let (m30, m31, m32, m33) = self.w_axis.into();
637 
638         let a2323 = m22 * m33 - m23 * m32;
639         let a1323 = m21 * m33 - m23 * m31;
640         let a1223 = m21 * m32 - m22 * m31;
641         let a0323 = m20 * m33 - m23 * m30;
642         let a0223 = m20 * m32 - m22 * m30;
643         let a0123 = m20 * m31 - m21 * m30;
644 
645         m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223)
646             - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223)
647             + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123)
648             - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123)
649     }
650 
651     /// Returns the inverse of `self`.
652     ///
653     /// If the matrix is not invertible the returned matrix will be invalid.
654     ///
655     /// # Panics
656     ///
657     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
658     #[must_use]
inverse(&self) -> Self659     pub fn inverse(&self) -> Self {
660         let (m00, m01, m02, m03) = self.x_axis.into();
661         let (m10, m11, m12, m13) = self.y_axis.into();
662         let (m20, m21, m22, m23) = self.z_axis.into();
663         let (m30, m31, m32, m33) = self.w_axis.into();
664 
665         let coef00 = m22 * m33 - m32 * m23;
666         let coef02 = m12 * m33 - m32 * m13;
667         let coef03 = m12 * m23 - m22 * m13;
668 
669         let coef04 = m21 * m33 - m31 * m23;
670         let coef06 = m11 * m33 - m31 * m13;
671         let coef07 = m11 * m23 - m21 * m13;
672 
673         let coef08 = m21 * m32 - m31 * m22;
674         let coef10 = m11 * m32 - m31 * m12;
675         let coef11 = m11 * m22 - m21 * m12;
676 
677         let coef12 = m20 * m33 - m30 * m23;
678         let coef14 = m10 * m33 - m30 * m13;
679         let coef15 = m10 * m23 - m20 * m13;
680 
681         let coef16 = m20 * m32 - m30 * m22;
682         let coef18 = m10 * m32 - m30 * m12;
683         let coef19 = m10 * m22 - m20 * m12;
684 
685         let coef20 = m20 * m31 - m30 * m21;
686         let coef22 = m10 * m31 - m30 * m11;
687         let coef23 = m10 * m21 - m20 * m11;
688 
689         let fac0 = Vec4::new(coef00, coef00, coef02, coef03);
690         let fac1 = Vec4::new(coef04, coef04, coef06, coef07);
691         let fac2 = Vec4::new(coef08, coef08, coef10, coef11);
692         let fac3 = Vec4::new(coef12, coef12, coef14, coef15);
693         let fac4 = Vec4::new(coef16, coef16, coef18, coef19);
694         let fac5 = Vec4::new(coef20, coef20, coef22, coef23);
695 
696         let vec0 = Vec4::new(m10, m00, m00, m00);
697         let vec1 = Vec4::new(m11, m01, m01, m01);
698         let vec2 = Vec4::new(m12, m02, m02, m02);
699         let vec3 = Vec4::new(m13, m03, m03, m03);
700 
701         let inv0 = vec1.mul(fac0).sub(vec2.mul(fac1)).add(vec3.mul(fac2));
702         let inv1 = vec0.mul(fac0).sub(vec2.mul(fac3)).add(vec3.mul(fac4));
703         let inv2 = vec0.mul(fac1).sub(vec1.mul(fac3)).add(vec3.mul(fac5));
704         let inv3 = vec0.mul(fac2).sub(vec1.mul(fac4)).add(vec2.mul(fac5));
705 
706         let sign_a = Vec4::new(1.0, -1.0, 1.0, -1.0);
707         let sign_b = Vec4::new(-1.0, 1.0, -1.0, 1.0);
708 
709         let inverse = Self::from_cols(
710             inv0.mul(sign_a),
711             inv1.mul(sign_b),
712             inv2.mul(sign_a),
713             inv3.mul(sign_b),
714         );
715 
716         let col0 = Vec4::new(
717             inverse.x_axis.x,
718             inverse.y_axis.x,
719             inverse.z_axis.x,
720             inverse.w_axis.x,
721         );
722 
723         let dot0 = self.x_axis.mul(col0);
724         let dot1 = dot0.x + dot0.y + dot0.z + dot0.w;
725 
726         glam_assert!(dot1 != 0.0);
727 
728         let rcp_det = dot1.recip();
729         inverse.mul(rcp_det)
730     }
731 
732     /// Creates a left-handed view matrix using a camera position, a facing direction and an up
733     /// direction
734     ///
735     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
736     ///
737     /// # Panics
738     ///
739     /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled.
740     #[inline]
741     #[must_use]
look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self742     pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
743         Self::look_to_rh(eye, -dir, up)
744     }
745 
746     /// Creates a right-handed view matrix using a camera position, a facing direction, and an up
747     /// direction.
748     ///
749     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
750     ///
751     /// # Panics
752     ///
753     /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled.
754     #[inline]
755     #[must_use]
look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self756     pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
757         glam_assert!(dir.is_normalized());
758         glam_assert!(up.is_normalized());
759         let f = dir;
760         let s = f.cross(up).normalize();
761         let u = s.cross(f);
762 
763         Self::from_cols(
764             Vec4::new(s.x, u.x, -f.x, 0.0),
765             Vec4::new(s.y, u.y, -f.y, 0.0),
766             Vec4::new(s.z, u.z, -f.z, 0.0),
767             Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
768         )
769     }
770 
771     /// Creates a left-handed view matrix using a camera position, a focal points and an up
772     /// direction.
773     ///
774     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
775     ///
776     /// # Panics
777     ///
778     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
779     #[inline]
780     #[must_use]
look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self781     pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
782         Self::look_to_lh(eye, center.sub(eye).normalize(), up)
783     }
784 
785     /// Creates a right-handed view matrix using a camera position, a focal point, and an up
786     /// direction.
787     ///
788     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
789     ///
790     /// # Panics
791     ///
792     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
793     #[inline]
look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self794     pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
795         Self::look_to_rh(eye, center.sub(eye).normalize(), up)
796     }
797 
798     /// Creates a right-handed perspective projection matrix with `[-1,1]` depth range.
799     ///
800     /// Useful to map the standard right-handed coordinate system into what OpenGL expects.
801     ///
802     /// This is the same as the OpenGL `gluPerspective` function.
803     /// See <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml>
804     #[inline]
805     #[must_use]
perspective_rh_gl( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32, ) -> Self806     pub fn perspective_rh_gl(
807         fov_y_radians: f32,
808         aspect_ratio: f32,
809         z_near: f32,
810         z_far: f32,
811     ) -> Self {
812         let inv_length = 1.0 / (z_near - z_far);
813         let f = 1.0 / math::tan(0.5 * fov_y_radians);
814         let a = f / aspect_ratio;
815         let b = (z_near + z_far) * inv_length;
816         let c = (2.0 * z_near * z_far) * inv_length;
817         Self::from_cols(
818             Vec4::new(a, 0.0, 0.0, 0.0),
819             Vec4::new(0.0, f, 0.0, 0.0),
820             Vec4::new(0.0, 0.0, b, -1.0),
821             Vec4::new(0.0, 0.0, c, 0.0),
822         )
823     }
824 
825     /// Creates a left-handed perspective projection matrix with `[0,1]` depth range.
826     ///
827     /// Useful to map the standard left-handed coordinate system into what WebGPU/Metal/Direct3D expect.
828     ///
829     /// # Panics
830     ///
831     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
832     /// enabled.
833     #[inline]
834     #[must_use]
perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self835     pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
836         glam_assert!(z_near > 0.0 && z_far > 0.0);
837         let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
838         let h = cos_fov / sin_fov;
839         let w = h / aspect_ratio;
840         let r = z_far / (z_far - z_near);
841         Self::from_cols(
842             Vec4::new(w, 0.0, 0.0, 0.0),
843             Vec4::new(0.0, h, 0.0, 0.0),
844             Vec4::new(0.0, 0.0, r, 1.0),
845             Vec4::new(0.0, 0.0, -r * z_near, 0.0),
846         )
847     }
848 
849     /// Creates a right-handed perspective projection matrix with `[0,1]` depth range.
850     ///
851     /// Useful to map the standard right-handed coordinate system into what WebGPU/Metal/Direct3D expect.
852     ///
853     /// # Panics
854     ///
855     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
856     /// enabled.
857     #[inline]
858     #[must_use]
perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self859     pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
860         glam_assert!(z_near > 0.0 && z_far > 0.0);
861         let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
862         let h = cos_fov / sin_fov;
863         let w = h / aspect_ratio;
864         let r = z_far / (z_near - z_far);
865         Self::from_cols(
866             Vec4::new(w, 0.0, 0.0, 0.0),
867             Vec4::new(0.0, h, 0.0, 0.0),
868             Vec4::new(0.0, 0.0, r, -1.0),
869             Vec4::new(0.0, 0.0, r * z_near, 0.0),
870         )
871     }
872 
873     /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range.
874     ///
875     /// Like `perspective_lh`, but with an infinite value for `z_far`.
876     /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`.
877     ///
878     /// # Panics
879     ///
880     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
881     /// enabled.
882     #[inline]
883     #[must_use]
perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self884     pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
885         glam_assert!(z_near > 0.0);
886         let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
887         let h = cos_fov / sin_fov;
888         let w = h / aspect_ratio;
889         Self::from_cols(
890             Vec4::new(w, 0.0, 0.0, 0.0),
891             Vec4::new(0.0, h, 0.0, 0.0),
892             Vec4::new(0.0, 0.0, 1.0, 1.0),
893             Vec4::new(0.0, 0.0, -z_near, 0.0),
894         )
895     }
896 
897     /// Creates an infinite reverse left-handed perspective projection matrix with `[0,1]` depth range.
898     ///
899     /// Similar to `perspective_infinite_lh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`.
900     ///
901     /// # Panics
902     ///
903     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
904     #[inline]
905     #[must_use]
perspective_infinite_reverse_lh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self906     pub fn perspective_infinite_reverse_lh(
907         fov_y_radians: f32,
908         aspect_ratio: f32,
909         z_near: f32,
910     ) -> Self {
911         glam_assert!(z_near > 0.0);
912         let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
913         let h = cos_fov / sin_fov;
914         let w = h / aspect_ratio;
915         Self::from_cols(
916             Vec4::new(w, 0.0, 0.0, 0.0),
917             Vec4::new(0.0, h, 0.0, 0.0),
918             Vec4::new(0.0, 0.0, 0.0, 1.0),
919             Vec4::new(0.0, 0.0, z_near, 0.0),
920         )
921     }
922 
923     /// Creates an infinite right-handed perspective projection matrix with `[0,1]` depth range.
924     ///
925     /// Like `perspective_rh`, but with an infinite value for `z_far`.
926     /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`.
927     ///
928     /// # Panics
929     ///
930     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
931     /// enabled.
932     #[inline]
933     #[must_use]
perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self934     pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
935         glam_assert!(z_near > 0.0);
936         let f = 1.0 / math::tan(0.5 * fov_y_radians);
937         Self::from_cols(
938             Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
939             Vec4::new(0.0, f, 0.0, 0.0),
940             Vec4::new(0.0, 0.0, -1.0, -1.0),
941             Vec4::new(0.0, 0.0, -z_near, 0.0),
942         )
943     }
944 
945     /// Creates an infinite reverse right-handed perspective projection matrix with `[0,1]` depth range.
946     ///
947     /// Similar to `perspective_infinite_rh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`.
948     ///
949     /// # Panics
950     ///
951     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
952     #[inline]
953     #[must_use]
perspective_infinite_reverse_rh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self954     pub fn perspective_infinite_reverse_rh(
955         fov_y_radians: f32,
956         aspect_ratio: f32,
957         z_near: f32,
958     ) -> Self {
959         glam_assert!(z_near > 0.0);
960         let f = 1.0 / math::tan(0.5 * fov_y_radians);
961         Self::from_cols(
962             Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
963             Vec4::new(0.0, f, 0.0, 0.0),
964             Vec4::new(0.0, 0.0, 0.0, -1.0),
965             Vec4::new(0.0, 0.0, z_near, 0.0),
966         )
967     }
968 
969     /// Creates a right-handed orthographic projection matrix with `[-1,1]` depth
970     /// range.  This is the same as the OpenGL `glOrtho` function in OpenGL.
971     /// See
972     /// <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml>
973     ///
974     /// Useful to map a right-handed coordinate system to the normalized device coordinates that OpenGL expects.
975     #[inline]
976     #[must_use]
orthographic_rh_gl( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self977     pub fn orthographic_rh_gl(
978         left: f32,
979         right: f32,
980         bottom: f32,
981         top: f32,
982         near: f32,
983         far: f32,
984     ) -> Self {
985         let a = 2.0 / (right - left);
986         let b = 2.0 / (top - bottom);
987         let c = -2.0 / (far - near);
988         let tx = -(right + left) / (right - left);
989         let ty = -(top + bottom) / (top - bottom);
990         let tz = -(far + near) / (far - near);
991 
992         Self::from_cols(
993             Vec4::new(a, 0.0, 0.0, 0.0),
994             Vec4::new(0.0, b, 0.0, 0.0),
995             Vec4::new(0.0, 0.0, c, 0.0),
996             Vec4::new(tx, ty, tz, 1.0),
997         )
998     }
999 
1000     /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range.
1001     ///
1002     /// Useful to map a left-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect.
1003     #[inline]
1004     #[must_use]
orthographic_lh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self1005     pub fn orthographic_lh(
1006         left: f32,
1007         right: f32,
1008         bottom: f32,
1009         top: f32,
1010         near: f32,
1011         far: f32,
1012     ) -> Self {
1013         let rcp_width = 1.0 / (right - left);
1014         let rcp_height = 1.0 / (top - bottom);
1015         let r = 1.0 / (far - near);
1016         Self::from_cols(
1017             Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1018             Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1019             Vec4::new(0.0, 0.0, r, 0.0),
1020             Vec4::new(
1021                 -(left + right) * rcp_width,
1022                 -(top + bottom) * rcp_height,
1023                 -r * near,
1024                 1.0,
1025             ),
1026         )
1027     }
1028 
1029     /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range.
1030     ///
1031     /// Useful to map a right-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect.
1032     #[inline]
1033     #[must_use]
orthographic_rh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self1034     pub fn orthographic_rh(
1035         left: f32,
1036         right: f32,
1037         bottom: f32,
1038         top: f32,
1039         near: f32,
1040         far: f32,
1041     ) -> Self {
1042         let rcp_width = 1.0 / (right - left);
1043         let rcp_height = 1.0 / (top - bottom);
1044         let r = 1.0 / (near - far);
1045         Self::from_cols(
1046             Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1047             Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1048             Vec4::new(0.0, 0.0, r, 0.0),
1049             Vec4::new(
1050                 -(left + right) * rcp_width,
1051                 -(top + bottom) * rcp_height,
1052                 r * near,
1053                 1.0,
1054             ),
1055         )
1056     }
1057 
1058     /// Transforms the given 3D vector as a point, applying perspective correction.
1059     ///
1060     /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is `1.0`.
1061     /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
1062     ///
1063     /// This method assumes that `self` contains a projective transform.
1064     #[inline]
1065     #[must_use]
project_point3(&self, rhs: Vec3) -> Vec31066     pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
1067         let mut res = self.x_axis.mul(rhs.x);
1068         res = self.y_axis.mul(rhs.y).add(res);
1069         res = self.z_axis.mul(rhs.z).add(res);
1070         res = self.w_axis.add(res);
1071         res = res.div(res.w);
1072         res.xyz()
1073     }
1074 
1075     /// Transforms the given 3D vector as a point.
1076     ///
1077     /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
1078     /// `1.0`.
1079     ///
1080     /// This method assumes that `self` contains a valid affine transform. It does not perform
1081     /// a perspective divide, if `self` contains a perspective transform, or if you are unsure,
1082     /// the [`Self::project_point3()`] method should be used instead.
1083     ///
1084     /// # Panics
1085     ///
1086     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1087     #[inline]
1088     #[must_use]
transform_point3(&self, rhs: Vec3) -> Vec31089     pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1090         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1091         let mut res = self.x_axis.mul(rhs.x);
1092         res = self.y_axis.mul(rhs.y).add(res);
1093         res = self.z_axis.mul(rhs.z).add(res);
1094         res = self.w_axis.add(res);
1095         res.xyz()
1096     }
1097 
1098     /// Transforms the give 3D vector as a direction.
1099     ///
1100     /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
1101     /// `0.0`.
1102     ///
1103     /// This method assumes that `self` contains a valid affine transform.
1104     ///
1105     /// # Panics
1106     ///
1107     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1108     #[inline]
1109     #[must_use]
transform_vector3(&self, rhs: Vec3) -> Vec31110     pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1111         glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1112         let mut res = self.x_axis.mul(rhs.x);
1113         res = self.y_axis.mul(rhs.y).add(res);
1114         res = self.z_axis.mul(rhs.z).add(res);
1115         res.xyz()
1116     }
1117 
1118     /// Transforms the given [`Vec3A`] as a 3D point, applying perspective correction.
1119     ///
1120     /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
1121     /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
1122     ///
1123     /// This method assumes that `self` contains a projective transform.
1124     #[inline]
1125     #[must_use]
project_point3a(&self, rhs: Vec3A) -> Vec3A1126     pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
1127         self.project_point3(rhs.into()).into()
1128     }
1129 
1130     /// Transforms the given [`Vec3A`] as 3D point.
1131     ///
1132     /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
1133     #[inline]
1134     #[must_use]
transform_point3a(&self, rhs: Vec3A) -> Vec3A1135     pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1136         self.transform_point3(rhs.into()).into()
1137     }
1138 
1139     /// Transforms the give [`Vec3A`] as 3D vector.
1140     ///
1141     /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `0.0`.
1142     #[inline]
1143     #[must_use]
transform_vector3a(&self, rhs: Vec3A) -> Vec3A1144     pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1145         self.transform_vector3(rhs.into()).into()
1146     }
1147 
1148     /// Transforms a 4D vector.
1149     #[inline]
1150     #[must_use]
mul_vec4(&self, rhs: Vec4) -> Vec41151     pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1152         let mut res = self.x_axis.mul(rhs.x);
1153         res = res.add(self.y_axis.mul(rhs.y));
1154         res = res.add(self.z_axis.mul(rhs.z));
1155         res = res.add(self.w_axis.mul(rhs.w));
1156         res
1157     }
1158 
1159     /// Multiplies two 4x4 matrices.
1160     #[inline]
1161     #[must_use]
mul_mat4(&self, rhs: &Self) -> Self1162     pub fn mul_mat4(&self, rhs: &Self) -> Self {
1163         Self::from_cols(
1164             self.mul(rhs.x_axis),
1165             self.mul(rhs.y_axis),
1166             self.mul(rhs.z_axis),
1167             self.mul(rhs.w_axis),
1168         )
1169     }
1170 
1171     /// Adds two 4x4 matrices.
1172     #[inline]
1173     #[must_use]
add_mat4(&self, rhs: &Self) -> Self1174     pub fn add_mat4(&self, rhs: &Self) -> Self {
1175         Self::from_cols(
1176             self.x_axis.add(rhs.x_axis),
1177             self.y_axis.add(rhs.y_axis),
1178             self.z_axis.add(rhs.z_axis),
1179             self.w_axis.add(rhs.w_axis),
1180         )
1181     }
1182 
1183     /// Subtracts two 4x4 matrices.
1184     #[inline]
1185     #[must_use]
sub_mat4(&self, rhs: &Self) -> Self1186     pub fn sub_mat4(&self, rhs: &Self) -> Self {
1187         Self::from_cols(
1188             self.x_axis.sub(rhs.x_axis),
1189             self.y_axis.sub(rhs.y_axis),
1190             self.z_axis.sub(rhs.z_axis),
1191             self.w_axis.sub(rhs.w_axis),
1192         )
1193     }
1194 
1195     /// Multiplies a 4x4 matrix by a scalar.
1196     #[inline]
1197     #[must_use]
mul_scalar(&self, rhs: f32) -> Self1198     pub fn mul_scalar(&self, rhs: f32) -> Self {
1199         Self::from_cols(
1200             self.x_axis.mul(rhs),
1201             self.y_axis.mul(rhs),
1202             self.z_axis.mul(rhs),
1203             self.w_axis.mul(rhs),
1204         )
1205     }
1206 
1207     /// Divides a 4x4 matrix by a scalar.
1208     #[inline]
1209     #[must_use]
div_scalar(&self, rhs: f32) -> Self1210     pub fn div_scalar(&self, rhs: f32) -> Self {
1211         let rhs = Vec4::splat(rhs);
1212         Self::from_cols(
1213             self.x_axis.div(rhs),
1214             self.y_axis.div(rhs),
1215             self.z_axis.div(rhs),
1216             self.w_axis.div(rhs),
1217         )
1218     }
1219 
1220     /// Returns true if the absolute difference of all elements between `self` and `rhs`
1221     /// is less than or equal to `max_abs_diff`.
1222     ///
1223     /// This can be used to compare if two matrices contain similar elements. It works best
1224     /// when comparing with a known value. The `max_abs_diff` that should be used used
1225     /// depends on the values being compared against.
1226     ///
1227     /// For more see
1228     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
1229     #[inline]
1230     #[must_use]
abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool1231     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1232         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1233             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1234             && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1235             && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1236     }
1237 
1238     /// Takes the absolute value of each element in `self`
1239     #[inline]
1240     #[must_use]
abs(&self) -> Self1241     pub fn abs(&self) -> Self {
1242         Self::from_cols(
1243             self.x_axis.abs(),
1244             self.y_axis.abs(),
1245             self.z_axis.abs(),
1246             self.w_axis.abs(),
1247         )
1248     }
1249 
1250     #[inline]
as_dmat4(&self) -> DMat41251     pub fn as_dmat4(&self) -> DMat4 {
1252         DMat4::from_cols(
1253             self.x_axis.as_dvec4(),
1254             self.y_axis.as_dvec4(),
1255             self.z_axis.as_dvec4(),
1256             self.w_axis.as_dvec4(),
1257         )
1258     }
1259 }
1260 
1261 impl Default for Mat4 {
1262     #[inline]
default() -> Self1263     fn default() -> Self {
1264         Self::IDENTITY
1265     }
1266 }
1267 
1268 impl Add<Mat4> for Mat4 {
1269     type Output = Self;
1270     #[inline]
add(self, rhs: Self) -> Self::Output1271     fn add(self, rhs: Self) -> Self::Output {
1272         self.add_mat4(&rhs)
1273     }
1274 }
1275 
1276 impl AddAssign<Mat4> for Mat4 {
1277     #[inline]
add_assign(&mut self, rhs: Self)1278     fn add_assign(&mut self, rhs: Self) {
1279         *self = self.add_mat4(&rhs);
1280     }
1281 }
1282 
1283 impl Sub<Mat4> for Mat4 {
1284     type Output = Self;
1285     #[inline]
sub(self, rhs: Self) -> Self::Output1286     fn sub(self, rhs: Self) -> Self::Output {
1287         self.sub_mat4(&rhs)
1288     }
1289 }
1290 
1291 impl SubAssign<Mat4> for Mat4 {
1292     #[inline]
sub_assign(&mut self, rhs: Self)1293     fn sub_assign(&mut self, rhs: Self) {
1294         *self = self.sub_mat4(&rhs);
1295     }
1296 }
1297 
1298 impl Neg for Mat4 {
1299     type Output = Self;
1300     #[inline]
neg(self) -> Self::Output1301     fn neg(self) -> Self::Output {
1302         Self::from_cols(
1303             self.x_axis.neg(),
1304             self.y_axis.neg(),
1305             self.z_axis.neg(),
1306             self.w_axis.neg(),
1307         )
1308     }
1309 }
1310 
1311 impl Mul<Mat4> for Mat4 {
1312     type Output = Self;
1313     #[inline]
mul(self, rhs: Self) -> Self::Output1314     fn mul(self, rhs: Self) -> Self::Output {
1315         self.mul_mat4(&rhs)
1316     }
1317 }
1318 
1319 impl MulAssign<Mat4> for Mat4 {
1320     #[inline]
mul_assign(&mut self, rhs: Self)1321     fn mul_assign(&mut self, rhs: Self) {
1322         *self = self.mul_mat4(&rhs);
1323     }
1324 }
1325 
1326 impl Mul<Vec4> for Mat4 {
1327     type Output = Vec4;
1328     #[inline]
mul(self, rhs: Vec4) -> Self::Output1329     fn mul(self, rhs: Vec4) -> Self::Output {
1330         self.mul_vec4(rhs)
1331     }
1332 }
1333 
1334 impl Mul<Mat4> for f32 {
1335     type Output = Mat4;
1336     #[inline]
mul(self, rhs: Mat4) -> Self::Output1337     fn mul(self, rhs: Mat4) -> Self::Output {
1338         rhs.mul_scalar(self)
1339     }
1340 }
1341 
1342 impl Mul<f32> for Mat4 {
1343     type Output = Self;
1344     #[inline]
mul(self, rhs: f32) -> Self::Output1345     fn mul(self, rhs: f32) -> Self::Output {
1346         self.mul_scalar(rhs)
1347     }
1348 }
1349 
1350 impl MulAssign<f32> for Mat4 {
1351     #[inline]
mul_assign(&mut self, rhs: f32)1352     fn mul_assign(&mut self, rhs: f32) {
1353         *self = self.mul_scalar(rhs);
1354     }
1355 }
1356 
1357 impl Div<Mat4> for f32 {
1358     type Output = Mat4;
1359     #[inline]
div(self, rhs: Mat4) -> Self::Output1360     fn div(self, rhs: Mat4) -> Self::Output {
1361         rhs.div_scalar(self)
1362     }
1363 }
1364 
1365 impl Div<f32> for Mat4 {
1366     type Output = Self;
1367     #[inline]
div(self, rhs: f32) -> Self::Output1368     fn div(self, rhs: f32) -> Self::Output {
1369         self.div_scalar(rhs)
1370     }
1371 }
1372 
1373 impl DivAssign<f32> for Mat4 {
1374     #[inline]
div_assign(&mut self, rhs: f32)1375     fn div_assign(&mut self, rhs: f32) {
1376         *self = self.div_scalar(rhs);
1377     }
1378 }
1379 
1380 impl Sum<Self> for Mat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,1381     fn sum<I>(iter: I) -> Self
1382     where
1383         I: Iterator<Item = Self>,
1384     {
1385         iter.fold(Self::ZERO, Self::add)
1386     }
1387 }
1388 
1389 impl<'a> Sum<&'a Self> for Mat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,1390     fn sum<I>(iter: I) -> Self
1391     where
1392         I: Iterator<Item = &'a Self>,
1393     {
1394         iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1395     }
1396 }
1397 
1398 impl Product for Mat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,1399     fn product<I>(iter: I) -> Self
1400     where
1401         I: Iterator<Item = Self>,
1402     {
1403         iter.fold(Self::IDENTITY, Self::mul)
1404     }
1405 }
1406 
1407 impl<'a> Product<&'a Self> for Mat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,1408     fn product<I>(iter: I) -> Self
1409     where
1410         I: Iterator<Item = &'a Self>,
1411     {
1412         iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1413     }
1414 }
1415 
1416 impl PartialEq for Mat4 {
1417     #[inline]
eq(&self, rhs: &Self) -> bool1418     fn eq(&self, rhs: &Self) -> bool {
1419         self.x_axis.eq(&rhs.x_axis)
1420             && self.y_axis.eq(&rhs.y_axis)
1421             && self.z_axis.eq(&rhs.z_axis)
1422             && self.w_axis.eq(&rhs.w_axis)
1423     }
1424 }
1425 
1426 #[cfg(not(target_arch = "spirv"))]
1427 impl AsRef<[f32; 16]> for Mat4 {
1428     #[inline]
as_ref(&self) -> &[f32; 16]1429     fn as_ref(&self) -> &[f32; 16] {
1430         unsafe { &*(self as *const Self as *const [f32; 16]) }
1431     }
1432 }
1433 
1434 #[cfg(not(target_arch = "spirv"))]
1435 impl AsMut<[f32; 16]> for Mat4 {
1436     #[inline]
as_mut(&mut self) -> &mut [f32; 16]1437     fn as_mut(&mut self) -> &mut [f32; 16] {
1438         unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
1439     }
1440 }
1441 
1442 impl fmt::Debug for Mat4 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result1443     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1444         fmt.debug_struct(stringify!(Mat4))
1445             .field("x_axis", &self.x_axis)
1446             .field("y_axis", &self.y_axis)
1447             .field("z_axis", &self.z_axis)
1448             .field("w_axis", &self.w_axis)
1449             .finish()
1450     }
1451 }
1452 
1453 impl fmt::Display for Mat4 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1454     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1455         if let Some(p) = f.precision() {
1456             write!(
1457                 f,
1458                 "[{:.*}, {:.*}, {:.*}, {:.*}]",
1459                 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
1460             )
1461         } else {
1462             write!(
1463                 f,
1464                 "[{}, {}, {}, {}]",
1465                 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1466             )
1467         }
1468     }
1469 }
1470