Skip to main content

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#[cfg(feature = "zerocopy")]
14use zerocopy_derive::*;
15
16/// Creates a 3x3 matrix from three column vectors.
17#[inline(always)]
18#[must_use]
19pub const fn dmat3(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> DMat3 {
20    DMat3::from_cols(x_axis, y_axis, z_axis)
21}
22
23/// A 3x3 column major matrix.
24///
25/// This 3x3 matrix type features convenience methods for creating and using linear and
26/// affine transformations. If you are primarily dealing with 2D affine transformations the
27/// [`DAffine2`](crate::DAffine2) type is much faster and more space efficient than
28/// using a 3x3 matrix.
29///
30/// Linear transformations including 3D rotation and scale can be created using methods
31/// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`],
32/// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or
33/// [`Self::from_rotation_z()`].
34///
35/// The resulting matrices can be use to transform 3D vectors using regular vector
36/// multiplication.
37///
38/// Affine transformations including 2D translation, rotation and scale can be created
39/// using methods such as [`Self::from_translation()`], [`Self::from_angle()`],
40/// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`].
41///
42/// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods
43/// are provided for performing affine transforms on 2D vectors and points. These multiply
44/// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for
45/// vectors respectively. These methods assume that `Self` contains a valid affine
46/// transform.
47#[derive(Clone, Copy)]
48#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
49#[cfg_attr(
50    feature = "zerocopy",
51    derive(FromBytes, Immutable, IntoBytes, KnownLayout)
52)]
53#[repr(C)]
54pub struct DMat3 {
55    pub x_axis: DVec3,
56    pub y_axis: DVec3,
57    pub z_axis: DVec3,
58}
59
60impl DMat3 {
61    /// A 3x3 matrix with all elements set to `0.0`.
62    pub const ZERO: Self = Self::from_cols(DVec3::ZERO, DVec3::ZERO, DVec3::ZERO);
63
64    /// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
65    pub const IDENTITY: Self = Self::from_cols(DVec3::X, DVec3::Y, DVec3::Z);
66
67    /// All NAN:s.
68    pub const NAN: Self = Self::from_cols(DVec3::NAN, DVec3::NAN, DVec3::NAN);
69
70    #[allow(clippy::too_many_arguments)]
71    #[inline(always)]
72    #[must_use]
73    const fn new(
74        m00: f64,
75        m01: f64,
76        m02: f64,
77        m10: f64,
78        m11: f64,
79        m12: f64,
80        m20: f64,
81        m21: f64,
82        m22: f64,
83    ) -> Self {
84        Self {
85            x_axis: DVec3::new(m00, m01, m02),
86            y_axis: DVec3::new(m10, m11, m12),
87            z_axis: DVec3::new(m20, m21, m22),
88        }
89    }
90
91    /// Creates a 3x3 matrix from three column vectors.
92    #[inline(always)]
93    #[must_use]
94    pub const fn from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> Self {
95        Self {
96            x_axis,
97            y_axis,
98            z_axis,
99        }
100    }
101
102    /// Creates a 3x3 matrix from a `[f64; 9]` array stored in column major order.
103    /// If your data is stored in row major you will need to `transpose` the returned
104    /// matrix.
105    #[inline]
106    #[must_use]
107    pub const fn from_cols_array(m: &[f64; 9]) -> Self {
108        Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
109    }
110
111    /// Creates a `[f64; 9]` array storing data in column major order.
112    /// If you require data in row major order `transpose` the matrix first.
113    #[inline]
114    #[must_use]
115    pub const fn to_cols_array(&self) -> [f64; 9] {
116        [
117            self.x_axis.x,
118            self.x_axis.y,
119            self.x_axis.z,
120            self.y_axis.x,
121            self.y_axis.y,
122            self.y_axis.z,
123            self.z_axis.x,
124            self.z_axis.y,
125            self.z_axis.z,
126        ]
127    }
128
129    /// Creates a 3x3 matrix from a `[[f64; 3]; 3]` 3D array stored in column major order.
130    /// If your data is in row major order you will need to `transpose` the returned
131    /// matrix.
132    #[inline]
133    #[must_use]
134    pub const fn from_cols_array_2d(m: &[[f64; 3]; 3]) -> Self {
135        Self::from_cols(
136            DVec3::from_array(m[0]),
137            DVec3::from_array(m[1]),
138            DVec3::from_array(m[2]),
139        )
140    }
141
142    /// Creates a `[[f64; 3]; 3]` 3D array storing data in column major order.
143    /// If you require data in row major order `transpose` the matrix first.
144    #[inline]
145    #[must_use]
146    pub const fn to_cols_array_2d(&self) -> [[f64; 3]; 3] {
147        [
148            self.x_axis.to_array(),
149            self.y_axis.to_array(),
150            self.z_axis.to_array(),
151        ]
152    }
153
154    /// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
155    #[doc(alias = "scale")]
156    #[inline]
157    #[must_use]
158    pub const fn from_diagonal(diagonal: DVec3) -> Self {
159        Self::new(
160            diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
161        )
162    }
163
164    /// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
165    #[inline]
166    #[must_use]
167    pub fn from_mat4(m: DMat4) -> Self {
168        Self::from_cols(
169            DVec3::from_vec4(m.x_axis),
170            DVec3::from_vec4(m.y_axis),
171            DVec3::from_vec4(m.z_axis),
172        )
173    }
174
175    /// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column
176    /// and `j`th row.
177    ///
178    /// # Panics
179    ///
180    /// Panics if `i` or `j` is greater than 3.
181    #[inline]
182    #[must_use]
183    pub fn from_mat4_minor(m: DMat4, i: usize, j: usize) -> Self {
184        match (i, j) {
185            (0, 0) => Self::from_cols(m.y_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()),
186            (0, 1) => Self::from_cols(m.y_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()),
187            (0, 2) => Self::from_cols(m.y_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()),
188            (0, 3) => Self::from_cols(m.y_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()),
189            (1, 0) => Self::from_cols(m.x_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()),
190            (1, 1) => Self::from_cols(m.x_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()),
191            (1, 2) => Self::from_cols(m.x_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()),
192            (1, 3) => Self::from_cols(m.x_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()),
193            (2, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.w_axis.yzw()),
194            (2, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.w_axis.xzw()),
195            (2, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.w_axis.xyw()),
196            (2, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.w_axis.xyz()),
197            (3, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.z_axis.yzw()),
198            (3, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.z_axis.xzw()),
199            (3, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.z_axis.xyw()),
200            (3, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.z_axis.xyz()),
201            _ => panic!("index out of bounds"),
202        }
203    }
204
205    /// Creates a 3D rotation matrix from the given quaternion.
206    ///
207    /// # Panics
208    ///
209    /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
210    #[inline]
211    #[must_use]
212    pub fn from_quat(rotation: DQuat) -> Self {
213        glam_assert!(rotation.is_normalized());
214
215        let x2 = rotation.x + rotation.x;
216        let y2 = rotation.y + rotation.y;
217        let z2 = rotation.z + rotation.z;
218        let xx = rotation.x * x2;
219        let xy = rotation.x * y2;
220        let xz = rotation.x * z2;
221        let yy = rotation.y * y2;
222        let yz = rotation.y * z2;
223        let zz = rotation.z * z2;
224        let wx = rotation.w * x2;
225        let wy = rotation.w * y2;
226        let wz = rotation.w * z2;
227
228        Self::from_cols(
229            DVec3::new(1.0 - (yy + zz), xy + wz, xz - wy),
230            DVec3::new(xy - wz, 1.0 - (xx + zz), yz + wx),
231            DVec3::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
232        )
233    }
234
235    /// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in
236    /// radians).
237    ///
238    /// # Panics
239    ///
240    /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
241    #[inline]
242    #[must_use]
243    pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
244        glam_assert!(axis.is_normalized());
245
246        let (sin, cos) = math::sin_cos(angle);
247        let (xsin, ysin, zsin) = axis.mul(sin).into();
248        let (x, y, z) = axis.into();
249        let (x2, y2, z2) = axis.mul(axis).into();
250        let omc = 1.0 - cos;
251        let xyomc = x * y * omc;
252        let xzomc = x * z * omc;
253        let yzomc = y * z * omc;
254        Self::from_cols(
255            DVec3::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
256            DVec3::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
257            DVec3::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
258        )
259    }
260
261    /// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
262    /// radians).
263    #[inline]
264    #[must_use]
265    pub fn from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self {
266        Self::from_euler_angles(order, a, b, c)
267    }
268
269    /// Extract Euler angles with the given Euler rotation order.
270    ///
271    /// Note if the input matrix contains scales, shears, or other non-rotation transformations then
272    /// the resulting Euler angles will be ill-defined.
273    ///
274    /// # Panics
275    ///
276    /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
277    #[inline]
278    #[must_use]
279    pub fn to_euler(&self, order: EulerRot) -> (f64, f64, f64) {
280        glam_assert!(
281            self.x_axis.is_normalized()
282                && self.y_axis.is_normalized()
283                && self.z_axis.is_normalized()
284        );
285        self.to_euler_angles(order)
286    }
287
288    /// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
289    #[inline]
290    #[must_use]
291    pub fn from_rotation_x(angle: f64) -> Self {
292        let (sina, cosa) = math::sin_cos(angle);
293        Self::from_cols(
294            DVec3::X,
295            DVec3::new(0.0, cosa, sina),
296            DVec3::new(0.0, -sina, cosa),
297        )
298    }
299
300    /// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
301    #[inline]
302    #[must_use]
303    pub fn from_rotation_y(angle: f64) -> Self {
304        let (sina, cosa) = math::sin_cos(angle);
305        Self::from_cols(
306            DVec3::new(cosa, 0.0, -sina),
307            DVec3::Y,
308            DVec3::new(sina, 0.0, cosa),
309        )
310    }
311
312    /// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
313    #[inline]
314    #[must_use]
315    pub fn from_rotation_z(angle: f64) -> Self {
316        let (sina, cosa) = math::sin_cos(angle);
317        Self::from_cols(
318            DVec3::new(cosa, sina, 0.0),
319            DVec3::new(-sina, cosa, 0.0),
320            DVec3::Z,
321        )
322    }
323
324    /// Creates an affine transformation matrix from the given 2D `translation`.
325    ///
326    /// The resulting matrix can be used to transform 2D points and vectors. See
327    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
328    #[inline]
329    #[must_use]
330    pub fn from_translation(translation: DVec2) -> Self {
331        Self::from_cols(
332            DVec3::X,
333            DVec3::Y,
334            DVec3::new(translation.x, translation.y, 1.0),
335        )
336    }
337
338    /// Creates an affine transformation matrix from the given 2D rotation `angle` (in
339    /// radians).
340    ///
341    /// The resulting matrix can be used to transform 2D points and vectors. See
342    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
343    #[inline]
344    #[must_use]
345    pub fn from_angle(angle: f64) -> Self {
346        let (sin, cos) = math::sin_cos(angle);
347        Self::from_cols(
348            DVec3::new(cos, sin, 0.0),
349            DVec3::new(-sin, cos, 0.0),
350            DVec3::Z,
351        )
352    }
353
354    /// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in
355    /// radians) and `translation`.
356    ///
357    /// The resulting matrix can be used to transform 2D points and vectors. See
358    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
359    #[inline]
360    #[must_use]
361    pub fn from_scale_angle_translation(scale: DVec2, angle: f64, translation: DVec2) -> Self {
362        let (sin, cos) = math::sin_cos(angle);
363        Self::from_cols(
364            DVec3::new(cos * scale.x, sin * scale.x, 0.0),
365            DVec3::new(-sin * scale.y, cos * scale.y, 0.0),
366            DVec3::new(translation.x, translation.y, 1.0),
367        )
368    }
369
370    /// Creates an affine transformation matrix from the given non-uniform 2D `scale`.
371    ///
372    /// The resulting matrix can be used to transform 2D points and vectors. See
373    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
374    ///
375    /// # Panics
376    ///
377    /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
378    #[inline]
379    #[must_use]
380    pub fn from_scale(scale: DVec2) -> Self {
381        // Do not panic as long as any component is non-zero
382        glam_assert!(scale.cmpne(DVec2::ZERO).any());
383
384        Self::from_cols(
385            DVec3::new(scale.x, 0.0, 0.0),
386            DVec3::new(0.0, scale.y, 0.0),
387            DVec3::Z,
388        )
389    }
390
391    /// Creates an affine transformation matrix from the given 2x2 matrix.
392    ///
393    /// The resulting matrix can be used to transform 2D points and vectors. See
394    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
395    #[inline]
396    pub fn from_mat2(m: DMat2) -> Self {
397        Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), DVec3::Z)
398    }
399
400    /// Creates a 3x3 matrix from the first 9 values in `slice`.
401    ///
402    /// # Panics
403    ///
404    /// Panics if `slice` is less than 9 elements long.
405    #[inline]
406    #[must_use]
407    pub const fn from_cols_slice(slice: &[f64]) -> Self {
408        Self::new(
409            slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
410            slice[8],
411        )
412    }
413
414    /// Writes the columns of `self` to the first 9 elements in `slice`.
415    ///
416    /// # Panics
417    ///
418    /// Panics if `slice` is less than 9 elements long.
419    #[inline]
420    pub fn write_cols_to_slice(&self, slice: &mut [f64]) {
421        slice[0] = self.x_axis.x;
422        slice[1] = self.x_axis.y;
423        slice[2] = self.x_axis.z;
424        slice[3] = self.y_axis.x;
425        slice[4] = self.y_axis.y;
426        slice[5] = self.y_axis.z;
427        slice[6] = self.z_axis.x;
428        slice[7] = self.z_axis.y;
429        slice[8] = self.z_axis.z;
430    }
431
432    /// Returns the matrix column for the given `index`.
433    ///
434    /// # Panics
435    ///
436    /// Panics if `index` is greater than 2.
437    #[inline]
438    #[must_use]
439    pub fn col(&self, index: usize) -> DVec3 {
440        match index {
441            0 => self.x_axis,
442            1 => self.y_axis,
443            2 => self.z_axis,
444            _ => panic!("index out of bounds"),
445        }
446    }
447
448    /// Returns a mutable reference to the matrix column for the given `index`.
449    ///
450    /// # Panics
451    ///
452    /// Panics if `index` is greater than 2.
453    #[inline]
454    pub fn col_mut(&mut self, index: usize) -> &mut DVec3 {
455        match index {
456            0 => &mut self.x_axis,
457            1 => &mut self.y_axis,
458            2 => &mut self.z_axis,
459            _ => panic!("index out of bounds"),
460        }
461    }
462
463    /// Returns the matrix row for the given `index`.
464    ///
465    /// # Panics
466    ///
467    /// Panics if `index` is greater than 2.
468    #[inline]
469    #[must_use]
470    pub fn row(&self, index: usize) -> DVec3 {
471        match index {
472            0 => DVec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
473            1 => DVec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
474            2 => DVec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
475            _ => panic!("index out of bounds"),
476        }
477    }
478
479    /// Returns `true` if, and only if, all elements are finite.
480    /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
481    #[inline]
482    #[must_use]
483    pub fn is_finite(&self) -> bool {
484        self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
485    }
486
487    /// Returns `true` if any elements are `NaN`.
488    #[inline]
489    #[must_use]
490    pub fn is_nan(&self) -> bool {
491        self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
492    }
493
494    /// Returns the transpose of `self`.
495    #[inline]
496    #[must_use]
497    pub fn transpose(&self) -> Self {
498        Self {
499            x_axis: DVec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
500            y_axis: DVec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
501            z_axis: DVec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
502        }
503    }
504
505    /// Returns the diagonal of `self`.
506    #[inline]
507    #[must_use]
508    pub fn diagonal(&self) -> DVec3 {
509        DVec3::new(self.x_axis.x, self.y_axis.y, self.z_axis.z)
510    }
511
512    /// Returns the determinant of `self`.
513    #[inline]
514    #[must_use]
515    pub fn determinant(&self) -> f64 {
516        self.z_axis.dot(self.x_axis.cross(self.y_axis))
517    }
518
519    /// If `CHECKED` is true then if the determinant is zero this function will return a tuple
520    /// containing a zero matrix and false. If the determinant is non zero a tuple containing the
521    /// inverted matrix and true is returned.
522    ///
523    /// If `CHECKED` is false then the determinant is not checked and if it is zero the resulting
524    /// inverted matrix will be invalid. Will panic if the determinant of `self` is zero when
525    /// `glam_assert` is enabled.
526    ///
527    /// A tuple containing the inverted matrix and a bool is used instead of an option here as
528    /// regular Rust enums put the discriminant first which can result in a lot of padding if the
529    /// matrix is aligned.
530    #[inline(always)]
531    #[must_use]
532    fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
533        let tmp0 = self.y_axis.cross(self.z_axis);
534        let tmp1 = self.z_axis.cross(self.x_axis);
535        let tmp2 = self.x_axis.cross(self.y_axis);
536        let det = self.z_axis.dot(tmp2);
537        if CHECKED {
538            if det == 0.0 {
539                return (Self::ZERO, false);
540            }
541        } else {
542            glam_assert!(det != 0.0);
543        }
544        let inv_det = DVec3::splat(det.recip());
545        (
546            Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose(),
547            true,
548        )
549    }
550
551    /// Returns the inverse of `self`.
552    ///
553    /// If the matrix is not invertible the returned matrix will be invalid.
554    ///
555    /// # Panics
556    ///
557    /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
558    #[inline]
559    #[must_use]
560    pub fn inverse(&self) -> Self {
561        self.inverse_checked::<false>().0
562    }
563
564    /// Returns the inverse of `self` or `None` if the matrix is not invertible.
565    #[inline]
566    #[must_use]
567    pub fn try_inverse(&self) -> Option<Self> {
568        let (m, is_valid) = self.inverse_checked::<true>();
569        if is_valid {
570            Some(m)
571        } else {
572            None
573        }
574    }
575
576    /// Returns the inverse of `self` or `DMat3::ZERO` if the matrix is not invertible.
577    #[inline]
578    #[must_use]
579    pub fn inverse_or_zero(&self) -> Self {
580        self.inverse_checked::<true>().0
581    }
582
583    /// Transforms the given 2D vector as a point.
584    ///
585    /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`.
586    ///
587    /// This method assumes that `self` contains a valid affine transform.
588    ///
589    /// # Panics
590    ///
591    /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
592    #[inline]
593    #[must_use]
594    pub fn transform_point2(&self, rhs: DVec2) -> DVec2 {
595        glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
596        DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
597    }
598
599    /// Rotates the given 2D vector.
600    ///
601    /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`.
602    ///
603    /// This method assumes that `self` contains a valid affine transform.
604    ///
605    /// # Panics
606    ///
607    /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
608    #[inline]
609    #[must_use]
610    pub fn transform_vector2(&self, rhs: DVec2) -> DVec2 {
611        glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
612        DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
613    }
614
615    /// Creates a left-handed view matrix using a facing direction and an up direction.
616    ///
617    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
618    ///
619    /// # Panics
620    ///
621    /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled.
622    #[deprecated(
623        since = "0.33.1",
624        note = "use the `glam::dcamera::lh::view::look_to_mat3` function instead"
625    )]
626    #[inline]
627    #[must_use]
628    pub fn look_to_lh(dir: DVec3, up: DVec3) -> Self {
629        #[allow(deprecated)]
630        Self::look_to_rh(-dir, up)
631    }
632
633    /// Creates a right-handed view matrix using a facing direction and an up direction.
634    ///
635    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
636    ///
637    /// # Panics
638    ///
639    /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled.
640    #[deprecated(
641        since = "0.33.1",
642        note = "use the `glam::dcamera::rh::view::look_to_mat3` function instead"
643    )]
644    #[inline]
645    #[must_use]
646    pub fn look_to_rh(dir: DVec3, up: DVec3) -> Self {
647        glam_assert!(dir.is_normalized());
648        glam_assert!(up.is_normalized());
649        let f = dir;
650        let s = f.cross(up).normalize();
651        let u = s.cross(f);
652
653        Self::from_cols(
654            DVec3::new(s.x, u.x, -f.x),
655            DVec3::new(s.y, u.y, -f.y),
656            DVec3::new(s.z, u.z, -f.z),
657        )
658    }
659
660    /// Creates a left-handed view matrix using a camera position, a focal point and an up
661    /// direction.
662    ///
663    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
664    ///
665    /// # Panics
666    ///
667    /// Will panic if `up` is not normalized when `glam_assert` is enabled.
668    #[deprecated(
669        since = "0.33.1",
670        note = "use the `glam::dcamera::lh::view::look_at_mat3` function instead"
671    )]
672    #[inline]
673    #[must_use]
674    pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
675        #[allow(deprecated)]
676        Self::look_to_lh(center.sub(eye).normalize(), up)
677    }
678
679    /// Creates a right-handed view matrix using a camera position, a focal point and an up
680    /// direction.
681    ///
682    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
683    ///
684    /// # Panics
685    ///
686    /// Will panic if `up` is not normalized when `glam_assert` is enabled.
687    #[deprecated(
688        since = "0.33.1",
689        note = "use the `glam::dcamera::rh::view::look_at_mat3` function instead"
690    )]
691    #[inline]
692    pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
693        #[allow(deprecated)]
694        Self::look_to_rh(center.sub(eye).normalize(), up)
695    }
696
697    /// Transforms a 3D vector.
698    #[inline]
699    #[must_use]
700    pub fn mul_vec3(&self, rhs: DVec3) -> DVec3 {
701        let mut res = self.x_axis.mul(rhs.x);
702        res = res.add(self.y_axis.mul(rhs.y));
703        res = res.add(self.z_axis.mul(rhs.z));
704        res
705    }
706
707    /// Transforms a 3D vector by the transpose of `self`.
708    #[inline]
709    #[must_use]
710    pub fn mul_transpose_vec3(&self, rhs: DVec3) -> DVec3 {
711        DVec3::new(
712            self.x_axis.dot(rhs),
713            self.y_axis.dot(rhs),
714            self.z_axis.dot(rhs),
715        )
716    }
717
718    /// Multiplies two 3x3 matrices.
719    #[inline]
720    #[must_use]
721    pub fn mul_mat3(&self, rhs: &Self) -> Self {
722        self.mul(rhs)
723    }
724
725    /// Adds two 3x3 matrices.
726    #[inline]
727    #[must_use]
728    pub fn add_mat3(&self, rhs: &Self) -> Self {
729        self.add(rhs)
730    }
731
732    /// Subtracts two 3x3 matrices.
733    #[inline]
734    #[must_use]
735    pub fn sub_mat3(&self, rhs: &Self) -> Self {
736        self.sub(rhs)
737    }
738
739    /// Multiplies a 3x3 matrix by a scalar.
740    #[inline]
741    #[must_use]
742    pub fn mul_scalar(&self, rhs: f64) -> Self {
743        Self::from_cols(
744            self.x_axis.mul(rhs),
745            self.y_axis.mul(rhs),
746            self.z_axis.mul(rhs),
747        )
748    }
749
750    /// Multiply `self` by a scaling vector `scale`.
751    /// This is faster than creating a whole diagonal scaling matrix and then multiplying that.
752    /// This operation is commutative.
753    #[inline]
754    #[must_use]
755    pub fn mul_diagonal_scale(&self, scale: DVec3) -> Self {
756        Self::from_cols(
757            self.x_axis * scale.x,
758            self.y_axis * scale.y,
759            self.z_axis * scale.z,
760        )
761    }
762
763    /// Divides a 3x3 matrix by a scalar.
764    #[inline]
765    #[must_use]
766    pub fn div_scalar(&self, rhs: f64) -> Self {
767        let rhs = DVec3::splat(rhs);
768        Self::from_cols(
769            self.x_axis.div(rhs),
770            self.y_axis.div(rhs),
771            self.z_axis.div(rhs),
772        )
773    }
774
775    /// Returns a matrix containing the reciprocal `1.0/n` of each element of `self`.
776    #[inline]
777    #[must_use]
778    pub fn recip(&self) -> Self {
779        Self::from_cols(
780            self.x_axis.recip(),
781            self.y_axis.recip(),
782            self.z_axis.recip(),
783        )
784    }
785
786    /// Returns true if the absolute difference of all elements between `self` and `rhs`
787    /// is less than or equal to `max_abs_diff`.
788    ///
789    /// This can be used to compare if two matrices contain similar elements. It works best
790    /// when comparing with a known value. The `max_abs_diff` that should be used used
791    /// depends on the values being compared against.
792    ///
793    /// For more see
794    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
795    #[inline]
796    #[must_use]
797    pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
798        self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
799            && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
800            && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
801    }
802
803    /// Takes the absolute value of each element in `self`
804    #[inline]
805    #[must_use]
806    pub fn abs(&self) -> Self {
807        Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
808    }
809
810    #[cfg(feature = "f64")]
811    #[inline]
812    #[must_use]
813    pub fn as_mat3(&self) -> Mat3 {
814        Mat3::from_cols(
815            self.x_axis.as_vec3(),
816            self.y_axis.as_vec3(),
817            self.z_axis.as_vec3(),
818        )
819    }
820}
821
822impl Default for DMat3 {
823    #[inline]
824    fn default() -> Self {
825        Self::IDENTITY
826    }
827}
828
829impl Add for DMat3 {
830    type Output = Self;
831    #[inline]
832    fn add(self, rhs: Self) -> Self {
833        Self::from_cols(
834            self.x_axis.add(rhs.x_axis),
835            self.y_axis.add(rhs.y_axis),
836            self.z_axis.add(rhs.z_axis),
837        )
838    }
839}
840
841impl Add<&Self> for DMat3 {
842    type Output = Self;
843    #[inline]
844    fn add(self, rhs: &Self) -> Self {
845        self.add(*rhs)
846    }
847}
848
849impl Add<&DMat3> for &DMat3 {
850    type Output = DMat3;
851    #[inline]
852    fn add(self, rhs: &DMat3) -> DMat3 {
853        (*self).add(*rhs)
854    }
855}
856
857impl Add<DMat3> for &DMat3 {
858    type Output = DMat3;
859    #[inline]
860    fn add(self, rhs: DMat3) -> DMat3 {
861        (*self).add(rhs)
862    }
863}
864
865impl AddAssign for DMat3 {
866    #[inline]
867    fn add_assign(&mut self, rhs: Self) {
868        *self = self.add(rhs);
869    }
870}
871
872impl AddAssign<&Self> for DMat3 {
873    #[inline]
874    fn add_assign(&mut self, rhs: &Self) {
875        self.add_assign(*rhs);
876    }
877}
878
879impl Sub for DMat3 {
880    type Output = Self;
881    #[inline]
882    fn sub(self, rhs: Self) -> Self {
883        Self::from_cols(
884            self.x_axis.sub(rhs.x_axis),
885            self.y_axis.sub(rhs.y_axis),
886            self.z_axis.sub(rhs.z_axis),
887        )
888    }
889}
890
891impl Sub<&Self> for DMat3 {
892    type Output = Self;
893    #[inline]
894    fn sub(self, rhs: &Self) -> Self {
895        self.sub(*rhs)
896    }
897}
898
899impl Sub<&DMat3> for &DMat3 {
900    type Output = DMat3;
901    #[inline]
902    fn sub(self, rhs: &DMat3) -> DMat3 {
903        (*self).sub(*rhs)
904    }
905}
906
907impl Sub<DMat3> for &DMat3 {
908    type Output = DMat3;
909    #[inline]
910    fn sub(self, rhs: DMat3) -> DMat3 {
911        (*self).sub(rhs)
912    }
913}
914
915impl SubAssign for DMat3 {
916    #[inline]
917    fn sub_assign(&mut self, rhs: Self) {
918        *self = self.sub(rhs);
919    }
920}
921
922impl SubAssign<&Self> for DMat3 {
923    #[inline]
924    fn sub_assign(&mut self, rhs: &Self) {
925        self.sub_assign(*rhs);
926    }
927}
928
929impl Neg for DMat3 {
930    type Output = Self;
931    #[inline]
932    fn neg(self) -> Self::Output {
933        Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
934    }
935}
936
937impl Neg for &DMat3 {
938    type Output = DMat3;
939    #[inline]
940    fn neg(self) -> DMat3 {
941        (*self).neg()
942    }
943}
944
945impl Mul for DMat3 {
946    type Output = Self;
947    #[inline]
948    fn mul(self, rhs: Self) -> Self {
949        Self::from_cols(
950            self.mul(rhs.x_axis),
951            self.mul(rhs.y_axis),
952            self.mul(rhs.z_axis),
953        )
954    }
955}
956
957impl Mul<&Self> for DMat3 {
958    type Output = Self;
959    #[inline]
960    fn mul(self, rhs: &Self) -> Self {
961        self.mul(*rhs)
962    }
963}
964
965impl Mul<&DMat3> for &DMat3 {
966    type Output = DMat3;
967    #[inline]
968    fn mul(self, rhs: &DMat3) -> DMat3 {
969        (*self).mul(*rhs)
970    }
971}
972
973impl Mul<DMat3> for &DMat3 {
974    type Output = DMat3;
975    #[inline]
976    fn mul(self, rhs: DMat3) -> DMat3 {
977        (*self).mul(rhs)
978    }
979}
980
981impl MulAssign for DMat3 {
982    #[inline]
983    fn mul_assign(&mut self, rhs: Self) {
984        *self = self.mul(rhs);
985    }
986}
987
988impl MulAssign<&Self> for DMat3 {
989    #[inline]
990    fn mul_assign(&mut self, rhs: &Self) {
991        self.mul_assign(*rhs);
992    }
993}
994
995impl Mul<DVec3> for DMat3 {
996    type Output = DVec3;
997    #[inline]
998    fn mul(self, rhs: DVec3) -> Self::Output {
999        self.mul_vec3(rhs)
1000    }
1001}
1002
1003impl Mul<&DVec3> for DMat3 {
1004    type Output = DVec3;
1005    #[inline]
1006    fn mul(self, rhs: &DVec3) -> DVec3 {
1007        self.mul(*rhs)
1008    }
1009}
1010
1011impl Mul<&DVec3> for &DMat3 {
1012    type Output = DVec3;
1013    #[inline]
1014    fn mul(self, rhs: &DVec3) -> DVec3 {
1015        (*self).mul(*rhs)
1016    }
1017}
1018
1019impl Mul<DVec3> for &DMat3 {
1020    type Output = DVec3;
1021    #[inline]
1022    fn mul(self, rhs: DVec3) -> DVec3 {
1023        (*self).mul(rhs)
1024    }
1025}
1026
1027impl Mul<DMat3> for f64 {
1028    type Output = DMat3;
1029    #[inline]
1030    fn mul(self, rhs: DMat3) -> Self::Output {
1031        rhs.mul_scalar(self)
1032    }
1033}
1034
1035impl Mul<&DMat3> for f64 {
1036    type Output = DMat3;
1037    #[inline]
1038    fn mul(self, rhs: &DMat3) -> DMat3 {
1039        self.mul(*rhs)
1040    }
1041}
1042
1043impl Mul<&DMat3> for &f64 {
1044    type Output = DMat3;
1045    #[inline]
1046    fn mul(self, rhs: &DMat3) -> DMat3 {
1047        (*self).mul(*rhs)
1048    }
1049}
1050
1051impl Mul<DMat3> for &f64 {
1052    type Output = DMat3;
1053    #[inline]
1054    fn mul(self, rhs: DMat3) -> DMat3 {
1055        (*self).mul(rhs)
1056    }
1057}
1058
1059impl Mul<f64> for DMat3 {
1060    type Output = Self;
1061    #[inline]
1062    fn mul(self, rhs: f64) -> Self {
1063        self.mul_scalar(rhs)
1064    }
1065}
1066
1067impl Mul<&f64> for DMat3 {
1068    type Output = Self;
1069    #[inline]
1070    fn mul(self, rhs: &f64) -> Self {
1071        self.mul(*rhs)
1072    }
1073}
1074
1075impl Mul<&f64> for &DMat3 {
1076    type Output = DMat3;
1077    #[inline]
1078    fn mul(self, rhs: &f64) -> DMat3 {
1079        (*self).mul(*rhs)
1080    }
1081}
1082
1083impl Mul<f64> for &DMat3 {
1084    type Output = DMat3;
1085    #[inline]
1086    fn mul(self, rhs: f64) -> DMat3 {
1087        (*self).mul(rhs)
1088    }
1089}
1090
1091impl MulAssign<f64> for DMat3 {
1092    #[inline]
1093    fn mul_assign(&mut self, rhs: f64) {
1094        *self = self.mul(rhs);
1095    }
1096}
1097
1098impl MulAssign<&f64> for DMat3 {
1099    #[inline]
1100    fn mul_assign(&mut self, rhs: &f64) {
1101        self.mul_assign(*rhs);
1102    }
1103}
1104
1105impl Div<DMat3> for f64 {
1106    type Output = DMat3;
1107    #[inline]
1108    fn div(self, rhs: DMat3) -> Self::Output {
1109        DMat3::from_cols(
1110            self.div(rhs.x_axis),
1111            self.div(rhs.y_axis),
1112            self.div(rhs.z_axis),
1113        )
1114    }
1115}
1116
1117impl Div<&DMat3> for f64 {
1118    type Output = DMat3;
1119    #[inline]
1120    fn div(self, rhs: &DMat3) -> DMat3 {
1121        self.div(*rhs)
1122    }
1123}
1124
1125impl Div<&DMat3> for &f64 {
1126    type Output = DMat3;
1127    #[inline]
1128    fn div(self, rhs: &DMat3) -> DMat3 {
1129        (*self).div(*rhs)
1130    }
1131}
1132
1133impl Div<DMat3> for &f64 {
1134    type Output = DMat3;
1135    #[inline]
1136    fn div(self, rhs: DMat3) -> DMat3 {
1137        (*self).div(rhs)
1138    }
1139}
1140
1141impl Div<f64> for DMat3 {
1142    type Output = Self;
1143    #[inline]
1144    fn div(self, rhs: f64) -> Self {
1145        self.div_scalar(rhs)
1146    }
1147}
1148
1149impl Div<&f64> for DMat3 {
1150    type Output = Self;
1151    #[inline]
1152    fn div(self, rhs: &f64) -> Self {
1153        self.div(*rhs)
1154    }
1155}
1156
1157impl Div<&f64> for &DMat3 {
1158    type Output = DMat3;
1159    #[inline]
1160    fn div(self, rhs: &f64) -> DMat3 {
1161        (*self).div(*rhs)
1162    }
1163}
1164
1165impl Div<f64> for &DMat3 {
1166    type Output = DMat3;
1167    #[inline]
1168    fn div(self, rhs: f64) -> DMat3 {
1169        (*self).div(rhs)
1170    }
1171}
1172
1173impl DivAssign<f64> for DMat3 {
1174    #[inline]
1175    fn div_assign(&mut self, rhs: f64) {
1176        *self = self.div(rhs);
1177    }
1178}
1179
1180impl DivAssign<&f64> for DMat3 {
1181    #[inline]
1182    fn div_assign(&mut self, rhs: &f64) {
1183        self.div_assign(*rhs);
1184    }
1185}
1186
1187impl Sum<Self> for DMat3 {
1188    fn sum<I>(iter: I) -> Self
1189    where
1190        I: Iterator<Item = Self>,
1191    {
1192        iter.fold(Self::ZERO, Self::add)
1193    }
1194}
1195
1196impl<'a> Sum<&'a Self> for DMat3 {
1197    fn sum<I>(iter: I) -> Self
1198    where
1199        I: Iterator<Item = &'a Self>,
1200    {
1201        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1202    }
1203}
1204
1205impl Product for DMat3 {
1206    fn product<I>(iter: I) -> Self
1207    where
1208        I: Iterator<Item = Self>,
1209    {
1210        iter.fold(Self::IDENTITY, Self::mul)
1211    }
1212}
1213
1214impl<'a> Product<&'a Self> for DMat3 {
1215    fn product<I>(iter: I) -> Self
1216    where
1217        I: Iterator<Item = &'a Self>,
1218    {
1219        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1220    }
1221}
1222
1223impl PartialEq for DMat3 {
1224    #[inline]
1225    fn eq(&self, rhs: &Self) -> bool {
1226        self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
1227    }
1228}
1229
1230impl AsRef<[f64; 9]> for DMat3 {
1231    #[inline]
1232    fn as_ref(&self) -> &[f64; 9] {
1233        unsafe { &*(self as *const Self as *const [f64; 9]) }
1234    }
1235}
1236
1237impl AsMut<[f64; 9]> for DMat3 {
1238    #[inline]
1239    fn as_mut(&mut self) -> &mut [f64; 9] {
1240        unsafe { &mut *(self as *mut Self as *mut [f64; 9]) }
1241    }
1242}
1243
1244impl fmt::Debug for DMat3 {
1245    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1246        fmt.debug_struct(stringify!(DMat3))
1247            .field("x_axis", &self.x_axis)
1248            .field("y_axis", &self.y_axis)
1249            .field("z_axis", &self.z_axis)
1250            .finish()
1251    }
1252}
1253
1254impl fmt::Display for DMat3 {
1255    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1256        if let Some(p) = f.precision() {
1257            write!(
1258                f,
1259                "[{:.*}, {:.*}, {:.*}]",
1260                p, self.x_axis, p, self.y_axis, p, self.z_axis
1261            )
1262        } else {
1263            write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
1264        }
1265    }
1266}