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