Skip to main content

glam/f32/
mat3.rs

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