glam/f64/
dmat3.rs

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