glam/f32/neon/
mat3a.rs

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