• 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     DMat2, DMat4, DQuat, DVec2, DVec3, EulerRot, Mat3,
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 3x3 matrix from three column vectors.
14 #[inline(always)]
15 #[must_use]
dmat3(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> DMat316 pub const fn dmat3(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> DMat3 {
17     DMat3::from_cols(x_axis, y_axis, z_axis)
18 }
19 
20 /// A 3x3 column major matrix.
21 ///
22 /// This 3x3 matrix type features convenience methods for creating and using linear and
23 /// affine transformations. If you are primarily dealing with 2D affine transformations the
24 /// [`DAffine2`](crate::DAffine2) type is much faster and more space efficient than
25 /// using a 3x3 matrix.
26 ///
27 /// Linear transformations including 3D rotation and scale can be created using methods
28 /// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`],
29 /// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or
30 /// [`Self::from_rotation_z()`].
31 ///
32 /// The resulting matrices can be use to transform 3D vectors using regular vector
33 /// multiplication.
34 ///
35 /// Affine transformations including 2D translation, rotation and scale can be created
36 /// using methods such as [`Self::from_translation()`], [`Self::from_angle()`],
37 /// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`].
38 ///
39 /// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods
40 /// are provided for performing affine transforms on 2D vectors and points. These multiply
41 /// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for
42 /// vectors respectively. These methods assume that `Self` contains a valid affine
43 /// transform.
44 #[derive(Clone, Copy)]
45 #[repr(C)]
46 pub struct DMat3 {
47     pub x_axis: DVec3,
48     pub y_axis: DVec3,
49     pub z_axis: DVec3,
50 }
51 
52 impl DMat3 {
53     /// A 3x3 matrix with all elements set to `0.0`.
54     pub const ZERO: Self = Self::from_cols(DVec3::ZERO, DVec3::ZERO, DVec3::ZERO);
55 
56     /// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
57     pub const IDENTITY: Self = Self::from_cols(DVec3::X, DVec3::Y, DVec3::Z);
58 
59     /// All NAN:s.
60     pub const NAN: Self = Self::from_cols(DVec3::NAN, DVec3::NAN, DVec3::NAN);
61 
62     #[allow(clippy::too_many_arguments)]
63     #[inline(always)]
64     #[must_use]
new( m00: f64, m01: f64, m02: f64, m10: f64, m11: f64, m12: f64, m20: f64, m21: f64, m22: f64, ) -> Self65     const fn new(
66         m00: f64,
67         m01: f64,
68         m02: f64,
69         m10: f64,
70         m11: f64,
71         m12: f64,
72         m20: f64,
73         m21: f64,
74         m22: f64,
75     ) -> Self {
76         Self {
77             x_axis: DVec3::new(m00, m01, m02),
78             y_axis: DVec3::new(m10, m11, m12),
79             z_axis: DVec3::new(m20, m21, m22),
80         }
81     }
82 
83     /// Creates a 3x3 matrix from three column vectors.
84     #[inline(always)]
85     #[must_use]
from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> Self86     pub const fn from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> Self {
87         Self {
88             x_axis,
89             y_axis,
90             z_axis,
91         }
92     }
93 
94     /// Creates a 3x3 matrix from a `[f64; 9]` array stored in column major order.
95     /// If your data is stored in row major you will need to `transpose` the returned
96     /// matrix.
97     #[inline]
98     #[must_use]
from_cols_array(m: &[f64; 9]) -> Self99     pub const fn from_cols_array(m: &[f64; 9]) -> Self {
100         Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
101     }
102 
103     /// Creates a `[f64; 9]` array storing data in column major order.
104     /// If you require data in row major order `transpose` the matrix first.
105     #[inline]
106     #[must_use]
to_cols_array(&self) -> [f64; 9]107     pub const fn to_cols_array(&self) -> [f64; 9] {
108         [
109             self.x_axis.x,
110             self.x_axis.y,
111             self.x_axis.z,
112             self.y_axis.x,
113             self.y_axis.y,
114             self.y_axis.z,
115             self.z_axis.x,
116             self.z_axis.y,
117             self.z_axis.z,
118         ]
119     }
120 
121     /// Creates a 3x3 matrix from a `[[f64; 3]; 3]` 3D array stored in column major order.
122     /// If your data is in row major order you will need to `transpose` the returned
123     /// matrix.
124     #[inline]
125     #[must_use]
from_cols_array_2d(m: &[[f64; 3]; 3]) -> Self126     pub const fn from_cols_array_2d(m: &[[f64; 3]; 3]) -> Self {
127         Self::from_cols(
128             DVec3::from_array(m[0]),
129             DVec3::from_array(m[1]),
130             DVec3::from_array(m[2]),
131         )
132     }
133 
134     /// Creates a `[[f64; 3]; 3]` 3D array storing data in column major order.
135     /// If you require data in row major order `transpose` the matrix first.
136     #[inline]
137     #[must_use]
to_cols_array_2d(&self) -> [[f64; 3]; 3]138     pub const fn to_cols_array_2d(&self) -> [[f64; 3]; 3] {
139         [
140             self.x_axis.to_array(),
141             self.y_axis.to_array(),
142             self.z_axis.to_array(),
143         ]
144     }
145 
146     /// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
147     #[doc(alias = "scale")]
148     #[inline]
149     #[must_use]
from_diagonal(diagonal: DVec3) -> Self150     pub const fn from_diagonal(diagonal: DVec3) -> Self {
151         Self::new(
152             diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
153         )
154     }
155 
156     /// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
157     #[inline]
158     #[must_use]
from_mat4(m: DMat4) -> Self159     pub fn from_mat4(m: DMat4) -> Self {
160         Self::from_cols(
161             DVec3::from_vec4(m.x_axis),
162             DVec3::from_vec4(m.y_axis),
163             DVec3::from_vec4(m.z_axis),
164         )
165     }
166 
167     /// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column
168     /// and `j`th row.
169     ///
170     /// # Panics
171     ///
172     /// Panics if `i` or `j` is greater than 3.
173     #[inline]
174     #[must_use]
from_mat4_minor(m: DMat4, i: usize, j: usize) -> Self175     pub fn from_mat4_minor(m: DMat4, i: usize, j: usize) -> Self {
176         match (i, j) {
177             (0, 0) => Self::from_cols(m.y_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()),
178             (0, 1) => Self::from_cols(m.y_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()),
179             (0, 2) => Self::from_cols(m.y_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()),
180             (0, 3) => Self::from_cols(m.y_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()),
181             (1, 0) => Self::from_cols(m.x_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()),
182             (1, 1) => Self::from_cols(m.x_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()),
183             (1, 2) => Self::from_cols(m.x_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()),
184             (1, 3) => Self::from_cols(m.x_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()),
185             (2, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.w_axis.yzw()),
186             (2, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.w_axis.xzw()),
187             (2, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.w_axis.xyw()),
188             (2, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.w_axis.xyz()),
189             (3, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.z_axis.yzw()),
190             (3, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.z_axis.xzw()),
191             (3, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.z_axis.xyw()),
192             (3, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.z_axis.xyz()),
193             _ => panic!("index out of bounds"),
194         }
195     }
196 
197     /// Creates a 3D rotation matrix from the given quaternion.
198     ///
199     /// # Panics
200     ///
201     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
202     #[inline]
203     #[must_use]
from_quat(rotation: DQuat) -> Self204     pub fn from_quat(rotation: DQuat) -> Self {
205         glam_assert!(rotation.is_normalized());
206 
207         let x2 = rotation.x + rotation.x;
208         let y2 = rotation.y + rotation.y;
209         let z2 = rotation.z + rotation.z;
210         let xx = rotation.x * x2;
211         let xy = rotation.x * y2;
212         let xz = rotation.x * z2;
213         let yy = rotation.y * y2;
214         let yz = rotation.y * z2;
215         let zz = rotation.z * z2;
216         let wx = rotation.w * x2;
217         let wy = rotation.w * y2;
218         let wz = rotation.w * z2;
219 
220         Self::from_cols(
221             DVec3::new(1.0 - (yy + zz), xy + wz, xz - wy),
222             DVec3::new(xy - wz, 1.0 - (xx + zz), yz + wx),
223             DVec3::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
224         )
225     }
226 
227     /// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in
228     /// radians).
229     ///
230     /// # Panics
231     ///
232     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
233     #[inline]
234     #[must_use]
from_axis_angle(axis: DVec3, angle: f64) -> Self235     pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
236         glam_assert!(axis.is_normalized());
237 
238         let (sin, cos) = math::sin_cos(angle);
239         let (xsin, ysin, zsin) = axis.mul(sin).into();
240         let (x, y, z) = axis.into();
241         let (x2, y2, z2) = axis.mul(axis).into();
242         let omc = 1.0 - cos;
243         let xyomc = x * y * omc;
244         let xzomc = x * z * omc;
245         let yzomc = y * z * omc;
246         Self::from_cols(
247             DVec3::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
248             DVec3::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
249             DVec3::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
250         )
251     }
252 
253     /// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
254     /// radians).
255     #[inline]
256     #[must_use]
from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self257     pub fn from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self {
258         Self::from_euler_angles(order, a, b, c)
259     }
260 
261     /// Extract Euler angles with the given Euler rotation order.
262     ///
263     /// Note if the input matrix contains scales, shears, or other non-rotation transformations then
264     /// the resulting Euler angles will be ill-defined.
265     ///
266     /// # Panics
267     ///
268     /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
269     #[inline]
270     #[must_use]
to_euler(&self, order: EulerRot) -> (f64, f64, f64)271     pub fn to_euler(&self, order: EulerRot) -> (f64, f64, f64) {
272         glam_assert!(
273             self.x_axis.is_normalized()
274                 && self.y_axis.is_normalized()
275                 && self.z_axis.is_normalized()
276         );
277         self.to_euler_angles(order)
278     }
279 
280     /// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
281     #[inline]
282     #[must_use]
from_rotation_x(angle: f64) -> Self283     pub fn from_rotation_x(angle: f64) -> Self {
284         let (sina, cosa) = math::sin_cos(angle);
285         Self::from_cols(
286             DVec3::X,
287             DVec3::new(0.0, cosa, sina),
288             DVec3::new(0.0, -sina, cosa),
289         )
290     }
291 
292     /// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
293     #[inline]
294     #[must_use]
from_rotation_y(angle: f64) -> Self295     pub fn from_rotation_y(angle: f64) -> Self {
296         let (sina, cosa) = math::sin_cos(angle);
297         Self::from_cols(
298             DVec3::new(cosa, 0.0, -sina),
299             DVec3::Y,
300             DVec3::new(sina, 0.0, cosa),
301         )
302     }
303 
304     /// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
305     #[inline]
306     #[must_use]
from_rotation_z(angle: f64) -> Self307     pub fn from_rotation_z(angle: f64) -> Self {
308         let (sina, cosa) = math::sin_cos(angle);
309         Self::from_cols(
310             DVec3::new(cosa, sina, 0.0),
311             DVec3::new(-sina, cosa, 0.0),
312             DVec3::Z,
313         )
314     }
315 
316     /// Creates an affine transformation matrix from the given 2D `translation`.
317     ///
318     /// The resulting matrix can be used to transform 2D points and vectors. See
319     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
320     #[inline]
321     #[must_use]
from_translation(translation: DVec2) -> Self322     pub fn from_translation(translation: DVec2) -> Self {
323         Self::from_cols(
324             DVec3::X,
325             DVec3::Y,
326             DVec3::new(translation.x, translation.y, 1.0),
327         )
328     }
329 
330     /// Creates an affine transformation matrix from the given 2D rotation `angle` (in
331     /// radians).
332     ///
333     /// The resulting matrix can be used to transform 2D points and vectors. See
334     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
335     #[inline]
336     #[must_use]
from_angle(angle: f64) -> Self337     pub fn from_angle(angle: f64) -> Self {
338         let (sin, cos) = math::sin_cos(angle);
339         Self::from_cols(
340             DVec3::new(cos, sin, 0.0),
341             DVec3::new(-sin, cos, 0.0),
342             DVec3::Z,
343         )
344     }
345 
346     /// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in
347     /// radians) and `translation`.
348     ///
349     /// The resulting matrix can be used to transform 2D points and vectors. See
350     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
351     #[inline]
352     #[must_use]
from_scale_angle_translation(scale: DVec2, angle: f64, translation: DVec2) -> Self353     pub fn from_scale_angle_translation(scale: DVec2, angle: f64, translation: DVec2) -> Self {
354         let (sin, cos) = math::sin_cos(angle);
355         Self::from_cols(
356             DVec3::new(cos * scale.x, sin * scale.x, 0.0),
357             DVec3::new(-sin * scale.y, cos * scale.y, 0.0),
358             DVec3::new(translation.x, translation.y, 1.0),
359         )
360     }
361 
362     /// Creates an affine transformation matrix from the given non-uniform 2D `scale`.
363     ///
364     /// The resulting matrix can be used to transform 2D points and vectors. See
365     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
366     ///
367     /// # Panics
368     ///
369     /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
370     #[inline]
371     #[must_use]
from_scale(scale: DVec2) -> Self372     pub fn from_scale(scale: DVec2) -> Self {
373         // Do not panic as long as any component is non-zero
374         glam_assert!(scale.cmpne(DVec2::ZERO).any());
375 
376         Self::from_cols(
377             DVec3::new(scale.x, 0.0, 0.0),
378             DVec3::new(0.0, scale.y, 0.0),
379             DVec3::Z,
380         )
381     }
382 
383     /// Creates an affine transformation matrix from the given 2x2 matrix.
384     ///
385     /// The resulting matrix can be used to transform 2D points and vectors. See
386     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
387     #[inline]
from_mat2(m: DMat2) -> Self388     pub fn from_mat2(m: DMat2) -> Self {
389         Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), DVec3::Z)
390     }
391 
392     /// Creates a 3x3 matrix from the first 9 values in `slice`.
393     ///
394     /// # Panics
395     ///
396     /// Panics if `slice` is less than 9 elements long.
397     #[inline]
398     #[must_use]
from_cols_slice(slice: &[f64]) -> Self399     pub const fn from_cols_slice(slice: &[f64]) -> Self {
400         Self::new(
401             slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
402             slice[8],
403         )
404     }
405 
406     /// Writes the columns of `self` to the first 9 elements in `slice`.
407     ///
408     /// # Panics
409     ///
410     /// Panics if `slice` is less than 9 elements long.
411     #[inline]
write_cols_to_slice(self, slice: &mut [f64])412     pub fn write_cols_to_slice(self, slice: &mut [f64]) {
413         slice[0] = self.x_axis.x;
414         slice[1] = self.x_axis.y;
415         slice[2] = self.x_axis.z;
416         slice[3] = self.y_axis.x;
417         slice[4] = self.y_axis.y;
418         slice[5] = self.y_axis.z;
419         slice[6] = self.z_axis.x;
420         slice[7] = self.z_axis.y;
421         slice[8] = self.z_axis.z;
422     }
423 
424     /// Returns the matrix column for the given `index`.
425     ///
426     /// # Panics
427     ///
428     /// Panics if `index` is greater than 2.
429     #[inline]
430     #[must_use]
col(&self, index: usize) -> DVec3431     pub fn col(&self, index: usize) -> DVec3 {
432         match index {
433             0 => self.x_axis,
434             1 => self.y_axis,
435             2 => self.z_axis,
436             _ => panic!("index out of bounds"),
437         }
438     }
439 
440     /// Returns a mutable reference to the matrix column for the given `index`.
441     ///
442     /// # Panics
443     ///
444     /// Panics if `index` is greater than 2.
445     #[inline]
col_mut(&mut self, index: usize) -> &mut DVec3446     pub fn col_mut(&mut self, index: usize) -> &mut DVec3 {
447         match index {
448             0 => &mut self.x_axis,
449             1 => &mut self.y_axis,
450             2 => &mut self.z_axis,
451             _ => panic!("index out of bounds"),
452         }
453     }
454 
455     /// Returns the matrix row for the given `index`.
456     ///
457     /// # Panics
458     ///
459     /// Panics if `index` is greater than 2.
460     #[inline]
461     #[must_use]
row(&self, index: usize) -> DVec3462     pub fn row(&self, index: usize) -> DVec3 {
463         match index {
464             0 => DVec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
465             1 => DVec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
466             2 => DVec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
467             _ => panic!("index out of bounds"),
468         }
469     }
470 
471     /// Returns `true` if, and only if, all elements are finite.
472     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
473     #[inline]
474     #[must_use]
is_finite(&self) -> bool475     pub fn is_finite(&self) -> bool {
476         self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
477     }
478 
479     /// Returns `true` if any elements are `NaN`.
480     #[inline]
481     #[must_use]
is_nan(&self) -> bool482     pub fn is_nan(&self) -> bool {
483         self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
484     }
485 
486     /// Returns the transpose of `self`.
487     #[inline]
488     #[must_use]
transpose(&self) -> Self489     pub fn transpose(&self) -> Self {
490         Self {
491             x_axis: DVec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
492             y_axis: DVec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
493             z_axis: DVec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
494         }
495     }
496 
497     /// Returns the determinant of `self`.
498     #[inline]
499     #[must_use]
determinant(&self) -> f64500     pub fn determinant(&self) -> f64 {
501         self.z_axis.dot(self.x_axis.cross(self.y_axis))
502     }
503 
504     /// Returns the inverse of `self`.
505     ///
506     /// If the matrix is not invertible the returned matrix will be invalid.
507     ///
508     /// # Panics
509     ///
510     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
511     #[inline]
512     #[must_use]
inverse(&self) -> Self513     pub fn inverse(&self) -> Self {
514         let tmp0 = self.y_axis.cross(self.z_axis);
515         let tmp1 = self.z_axis.cross(self.x_axis);
516         let tmp2 = self.x_axis.cross(self.y_axis);
517         let det = self.z_axis.dot(tmp2);
518         glam_assert!(det != 0.0);
519         let inv_det = DVec3::splat(det.recip());
520         Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose()
521     }
522 
523     /// Transforms the given 2D vector as a point.
524     ///
525     /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`.
526     ///
527     /// This method assumes that `self` contains a valid affine transform.
528     ///
529     /// # Panics
530     ///
531     /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
532     #[inline]
533     #[must_use]
transform_point2(&self, rhs: DVec2) -> DVec2534     pub fn transform_point2(&self, rhs: DVec2) -> DVec2 {
535         glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
536         DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
537     }
538 
539     /// Rotates the given 2D vector.
540     ///
541     /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`.
542     ///
543     /// This method assumes that `self` contains a valid affine transform.
544     ///
545     /// # Panics
546     ///
547     /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
548     #[inline]
549     #[must_use]
transform_vector2(&self, rhs: DVec2) -> DVec2550     pub fn transform_vector2(&self, rhs: DVec2) -> DVec2 {
551         glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
552         DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
553     }
554 
555     /// Creates a left-handed view matrix using a facing direction and an up direction.
556     ///
557     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
558     ///
559     /// # Panics
560     ///
561     /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled.
562     #[inline]
563     #[must_use]
look_to_lh(dir: DVec3, up: DVec3) -> Self564     pub fn look_to_lh(dir: DVec3, up: DVec3) -> Self {
565         Self::look_to_rh(-dir, up)
566     }
567 
568     /// Creates a right-handed view matrix using a facing direction and an up direction.
569     ///
570     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
571     ///
572     /// # Panics
573     ///
574     /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled.
575     #[inline]
576     #[must_use]
look_to_rh(dir: DVec3, up: DVec3) -> Self577     pub fn look_to_rh(dir: DVec3, up: DVec3) -> Self {
578         glam_assert!(dir.is_normalized());
579         glam_assert!(up.is_normalized());
580         let f = dir;
581         let s = f.cross(up).normalize();
582         let u = s.cross(f);
583 
584         Self::from_cols(
585             DVec3::new(s.x, u.x, -f.x),
586             DVec3::new(s.y, u.y, -f.y),
587             DVec3::new(s.z, u.z, -f.z),
588         )
589     }
590 
591     /// Creates a left-handed view matrix using a camera position, a focal point and an up
592     /// direction.
593     ///
594     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
595     ///
596     /// # Panics
597     ///
598     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
599     #[inline]
600     #[must_use]
look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self601     pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
602         Self::look_to_lh(center.sub(eye).normalize(), up)
603     }
604 
605     /// Creates a right-handed view matrix using a camera position, a focal point and an up
606     /// direction.
607     ///
608     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
609     ///
610     /// # Panics
611     ///
612     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
613     #[inline]
look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self614     pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
615         Self::look_to_rh(center.sub(eye).normalize(), up)
616     }
617 
618     /// Transforms a 3D vector.
619     #[inline]
620     #[must_use]
mul_vec3(&self, rhs: DVec3) -> DVec3621     pub fn mul_vec3(&self, rhs: DVec3) -> DVec3 {
622         let mut res = self.x_axis.mul(rhs.x);
623         res = res.add(self.y_axis.mul(rhs.y));
624         res = res.add(self.z_axis.mul(rhs.z));
625         res
626     }
627 
628     /// Multiplies two 3x3 matrices.
629     #[inline]
630     #[must_use]
mul_mat3(&self, rhs: &Self) -> Self631     pub fn mul_mat3(&self, rhs: &Self) -> Self {
632         Self::from_cols(
633             self.mul(rhs.x_axis),
634             self.mul(rhs.y_axis),
635             self.mul(rhs.z_axis),
636         )
637     }
638 
639     /// Adds two 3x3 matrices.
640     #[inline]
641     #[must_use]
add_mat3(&self, rhs: &Self) -> Self642     pub fn add_mat3(&self, rhs: &Self) -> Self {
643         Self::from_cols(
644             self.x_axis.add(rhs.x_axis),
645             self.y_axis.add(rhs.y_axis),
646             self.z_axis.add(rhs.z_axis),
647         )
648     }
649 
650     /// Subtracts two 3x3 matrices.
651     #[inline]
652     #[must_use]
sub_mat3(&self, rhs: &Self) -> Self653     pub fn sub_mat3(&self, rhs: &Self) -> Self {
654         Self::from_cols(
655             self.x_axis.sub(rhs.x_axis),
656             self.y_axis.sub(rhs.y_axis),
657             self.z_axis.sub(rhs.z_axis),
658         )
659     }
660 
661     /// Multiplies a 3x3 matrix by a scalar.
662     #[inline]
663     #[must_use]
mul_scalar(&self, rhs: f64) -> Self664     pub fn mul_scalar(&self, rhs: f64) -> Self {
665         Self::from_cols(
666             self.x_axis.mul(rhs),
667             self.y_axis.mul(rhs),
668             self.z_axis.mul(rhs),
669         )
670     }
671 
672     /// Divides a 3x3 matrix by a scalar.
673     #[inline]
674     #[must_use]
div_scalar(&self, rhs: f64) -> Self675     pub fn div_scalar(&self, rhs: f64) -> Self {
676         let rhs = DVec3::splat(rhs);
677         Self::from_cols(
678             self.x_axis.div(rhs),
679             self.y_axis.div(rhs),
680             self.z_axis.div(rhs),
681         )
682     }
683 
684     /// Returns true if the absolute difference of all elements between `self` and `rhs`
685     /// is less than or equal to `max_abs_diff`.
686     ///
687     /// This can be used to compare if two matrices contain similar elements. It works best
688     /// when comparing with a known value. The `max_abs_diff` that should be used used
689     /// depends on the values being compared against.
690     ///
691     /// For more see
692     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
693     #[inline]
694     #[must_use]
abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool695     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
696         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
697             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
698             && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
699     }
700 
701     /// Takes the absolute value of each element in `self`
702     #[inline]
703     #[must_use]
abs(&self) -> Self704     pub fn abs(&self) -> Self {
705         Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
706     }
707 
708     #[inline]
as_mat3(&self) -> Mat3709     pub fn as_mat3(&self) -> Mat3 {
710         Mat3::from_cols(
711             self.x_axis.as_vec3(),
712             self.y_axis.as_vec3(),
713             self.z_axis.as_vec3(),
714         )
715     }
716 }
717 
718 impl Default for DMat3 {
719     #[inline]
default() -> Self720     fn default() -> Self {
721         Self::IDENTITY
722     }
723 }
724 
725 impl Add<DMat3> for DMat3 {
726     type Output = Self;
727     #[inline]
add(self, rhs: Self) -> Self::Output728     fn add(self, rhs: Self) -> Self::Output {
729         self.add_mat3(&rhs)
730     }
731 }
732 
733 impl AddAssign<DMat3> for DMat3 {
734     #[inline]
add_assign(&mut self, rhs: Self)735     fn add_assign(&mut self, rhs: Self) {
736         *self = self.add_mat3(&rhs);
737     }
738 }
739 
740 impl Sub<DMat3> for DMat3 {
741     type Output = Self;
742     #[inline]
sub(self, rhs: Self) -> Self::Output743     fn sub(self, rhs: Self) -> Self::Output {
744         self.sub_mat3(&rhs)
745     }
746 }
747 
748 impl SubAssign<DMat3> for DMat3 {
749     #[inline]
sub_assign(&mut self, rhs: Self)750     fn sub_assign(&mut self, rhs: Self) {
751         *self = self.sub_mat3(&rhs);
752     }
753 }
754 
755 impl Neg for DMat3 {
756     type Output = Self;
757     #[inline]
neg(self) -> Self::Output758     fn neg(self) -> Self::Output {
759         Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
760     }
761 }
762 
763 impl Mul<DMat3> for DMat3 {
764     type Output = Self;
765     #[inline]
mul(self, rhs: Self) -> Self::Output766     fn mul(self, rhs: Self) -> Self::Output {
767         self.mul_mat3(&rhs)
768     }
769 }
770 
771 impl MulAssign<DMat3> for DMat3 {
772     #[inline]
mul_assign(&mut self, rhs: Self)773     fn mul_assign(&mut self, rhs: Self) {
774         *self = self.mul_mat3(&rhs);
775     }
776 }
777 
778 impl Mul<DVec3> for DMat3 {
779     type Output = DVec3;
780     #[inline]
mul(self, rhs: DVec3) -> Self::Output781     fn mul(self, rhs: DVec3) -> Self::Output {
782         self.mul_vec3(rhs)
783     }
784 }
785 
786 impl Mul<DMat3> for f64 {
787     type Output = DMat3;
788     #[inline]
mul(self, rhs: DMat3) -> Self::Output789     fn mul(self, rhs: DMat3) -> Self::Output {
790         rhs.mul_scalar(self)
791     }
792 }
793 
794 impl Mul<f64> for DMat3 {
795     type Output = Self;
796     #[inline]
mul(self, rhs: f64) -> Self::Output797     fn mul(self, rhs: f64) -> Self::Output {
798         self.mul_scalar(rhs)
799     }
800 }
801 
802 impl MulAssign<f64> for DMat3 {
803     #[inline]
mul_assign(&mut self, rhs: f64)804     fn mul_assign(&mut self, rhs: f64) {
805         *self = self.mul_scalar(rhs);
806     }
807 }
808 
809 impl Div<DMat3> for f64 {
810     type Output = DMat3;
811     #[inline]
div(self, rhs: DMat3) -> Self::Output812     fn div(self, rhs: DMat3) -> Self::Output {
813         rhs.div_scalar(self)
814     }
815 }
816 
817 impl Div<f64> for DMat3 {
818     type Output = Self;
819     #[inline]
div(self, rhs: f64) -> Self::Output820     fn div(self, rhs: f64) -> Self::Output {
821         self.div_scalar(rhs)
822     }
823 }
824 
825 impl DivAssign<f64> for DMat3 {
826     #[inline]
div_assign(&mut self, rhs: f64)827     fn div_assign(&mut self, rhs: f64) {
828         *self = self.div_scalar(rhs);
829     }
830 }
831 
832 impl Sum<Self> for DMat3 {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,833     fn sum<I>(iter: I) -> Self
834     where
835         I: Iterator<Item = Self>,
836     {
837         iter.fold(Self::ZERO, Self::add)
838     }
839 }
840 
841 impl<'a> Sum<&'a Self> for DMat3 {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,842     fn sum<I>(iter: I) -> Self
843     where
844         I: Iterator<Item = &'a Self>,
845     {
846         iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
847     }
848 }
849 
850 impl Product for DMat3 {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,851     fn product<I>(iter: I) -> Self
852     where
853         I: Iterator<Item = Self>,
854     {
855         iter.fold(Self::IDENTITY, Self::mul)
856     }
857 }
858 
859 impl<'a> Product<&'a Self> for DMat3 {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,860     fn product<I>(iter: I) -> Self
861     where
862         I: Iterator<Item = &'a Self>,
863     {
864         iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
865     }
866 }
867 
868 impl PartialEq for DMat3 {
869     #[inline]
eq(&self, rhs: &Self) -> bool870     fn eq(&self, rhs: &Self) -> bool {
871         self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
872     }
873 }
874 
875 #[cfg(not(target_arch = "spirv"))]
876 impl AsRef<[f64; 9]> for DMat3 {
877     #[inline]
as_ref(&self) -> &[f64; 9]878     fn as_ref(&self) -> &[f64; 9] {
879         unsafe { &*(self as *const Self as *const [f64; 9]) }
880     }
881 }
882 
883 #[cfg(not(target_arch = "spirv"))]
884 impl AsMut<[f64; 9]> for DMat3 {
885     #[inline]
as_mut(&mut self) -> &mut [f64; 9]886     fn as_mut(&mut self) -> &mut [f64; 9] {
887         unsafe { &mut *(self as *mut Self as *mut [f64; 9]) }
888     }
889 }
890 
891 impl fmt::Debug for DMat3 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result892     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
893         fmt.debug_struct(stringify!(DMat3))
894             .field("x_axis", &self.x_axis)
895             .field("y_axis", &self.y_axis)
896             .field("z_axis", &self.z_axis)
897             .finish()
898     }
899 }
900 
901 impl fmt::Display for DMat3 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result902     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
903         if let Some(p) = f.precision() {
904             write!(
905                 f,
906                 "[{:.*}, {:.*}, {:.*}]",
907                 p, self.x_axis, p, self.y_axis, p, self.z_axis
908             )
909         } else {
910             write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
911         }
912     }
913 }
914