glam/f64/
dmat3.rs

1// Generated from mat.rs.tera template. Edit the template, not the generated file.
2
3use crate::{
4    euler::{FromEuler, ToEuler},
5    f64::math,
6    swizzles::*,
7    DMat2, DMat4, DQuat, DVec2, DVec3, EulerRot, Mat3,
8};
9use core::fmt;
10use core::iter::{Product, Sum};
11use 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]
16pub 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)]
46pub struct DMat3 {
47    pub x_axis: DVec3,
48    pub y_axis: DVec3,
49    pub z_axis: DVec3,
50}
51
52impl 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]
65    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]
86    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]
99    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]
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]
126    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]
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]
150    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]
159    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]
175    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]
204    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]
235    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]
257    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]
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]
283    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]
295    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]
307    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]
322    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]
337    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]
353    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]
372    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]
388    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]
399    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]
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]
431    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]
446    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]
462    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]
475    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]
482    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]
489    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]
500    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]
513    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]
534    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]
550    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]
564    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]
577    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]
601    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]
614    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]
621    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]
631    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]
642    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]
653    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]
664    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]
675    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]
695    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]
704    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]
709    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
718impl Default for DMat3 {
719    #[inline]
720    fn default() -> Self {
721        Self::IDENTITY
722    }
723}
724
725impl Add<DMat3> for DMat3 {
726    type Output = Self;
727    #[inline]
728    fn add(self, rhs: Self) -> Self::Output {
729        self.add_mat3(&rhs)
730    }
731}
732
733impl AddAssign<DMat3> for DMat3 {
734    #[inline]
735    fn add_assign(&mut self, rhs: Self) {
736        *self = self.add_mat3(&rhs);
737    }
738}
739
740impl Sub<DMat3> for DMat3 {
741    type Output = Self;
742    #[inline]
743    fn sub(self, rhs: Self) -> Self::Output {
744        self.sub_mat3(&rhs)
745    }
746}
747
748impl SubAssign<DMat3> for DMat3 {
749    #[inline]
750    fn sub_assign(&mut self, rhs: Self) {
751        *self = self.sub_mat3(&rhs);
752    }
753}
754
755impl Neg for DMat3 {
756    type Output = Self;
757    #[inline]
758    fn neg(self) -> Self::Output {
759        Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
760    }
761}
762
763impl Mul<DMat3> for DMat3 {
764    type Output = Self;
765    #[inline]
766    fn mul(self, rhs: Self) -> Self::Output {
767        self.mul_mat3(&rhs)
768    }
769}
770
771impl MulAssign<DMat3> for DMat3 {
772    #[inline]
773    fn mul_assign(&mut self, rhs: Self) {
774        *self = self.mul_mat3(&rhs);
775    }
776}
777
778impl Mul<DVec3> for DMat3 {
779    type Output = DVec3;
780    #[inline]
781    fn mul(self, rhs: DVec3) -> Self::Output {
782        self.mul_vec3(rhs)
783    }
784}
785
786impl Mul<DMat3> for f64 {
787    type Output = DMat3;
788    #[inline]
789    fn mul(self, rhs: DMat3) -> Self::Output {
790        rhs.mul_scalar(self)
791    }
792}
793
794impl Mul<f64> for DMat3 {
795    type Output = Self;
796    #[inline]
797    fn mul(self, rhs: f64) -> Self::Output {
798        self.mul_scalar(rhs)
799    }
800}
801
802impl MulAssign<f64> for DMat3 {
803    #[inline]
804    fn mul_assign(&mut self, rhs: f64) {
805        *self = self.mul_scalar(rhs);
806    }
807}
808
809impl Div<DMat3> for f64 {
810    type Output = DMat3;
811    #[inline]
812    fn div(self, rhs: DMat3) -> Self::Output {
813        rhs.div_scalar(self)
814    }
815}
816
817impl Div<f64> for DMat3 {
818    type Output = Self;
819    #[inline]
820    fn div(self, rhs: f64) -> Self::Output {
821        self.div_scalar(rhs)
822    }
823}
824
825impl DivAssign<f64> for DMat3 {
826    #[inline]
827    fn div_assign(&mut self, rhs: f64) {
828        *self = self.div_scalar(rhs);
829    }
830}
831
832impl Sum<Self> for DMat3 {
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
841impl<'a> Sum<&'a Self> for DMat3 {
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
850impl Product for DMat3 {
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
859impl<'a> Product<&'a Self> for DMat3 {
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
868impl PartialEq for DMat3 {
869    #[inline]
870    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"))]
876impl AsRef<[f64; 9]> for DMat3 {
877    #[inline]
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"))]
884impl AsMut<[f64; 9]> for DMat3 {
885    #[inline]
886    fn as_mut(&mut self) -> &mut [f64; 9] {
887        unsafe { &mut *(self as *mut Self as *mut [f64; 9]) }
888    }
889}
890
891impl fmt::Debug for DMat3 {
892    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
901impl fmt::Display for DMat3 {
902    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}