1use crate::{
4 euler::{FromEuler, ToEuler},
5 f32::math,
6 swizzles::*,
7 DMat3, EulerRot, Mat2, Mat3A, 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
13#[inline(always)]
15#[must_use]
16pub const fn mat3(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Mat3 {
17 Mat3::from_cols(x_axis, y_axis, z_axis)
18}
19
20#[derive(Clone, Copy)]
45#[repr(C)]
46pub struct Mat3 {
47 pub x_axis: Vec3,
48 pub y_axis: Vec3,
49 pub z_axis: Vec3,
50}
51
52impl Mat3 {
53 pub const ZERO: Self = Self::from_cols(Vec3::ZERO, Vec3::ZERO, Vec3::ZERO);
55
56 pub const IDENTITY: Self = Self::from_cols(Vec3::X, Vec3::Y, Vec3::Z);
58
59 pub const NAN: Self = Self::from_cols(Vec3::NAN, Vec3::NAN, Vec3::NAN);
61
62 #[allow(clippy::too_many_arguments)]
63 #[inline(always)]
64 #[must_use]
65 const fn new(
66 m00: f32,
67 m01: f32,
68 m02: f32,
69 m10: f32,
70 m11: f32,
71 m12: f32,
72 m20: f32,
73 m21: f32,
74 m22: f32,
75 ) -> Self {
76 Self {
77 x_axis: Vec3::new(m00, m01, m02),
78 y_axis: Vec3::new(m10, m11, m12),
79 z_axis: Vec3::new(m20, m21, m22),
80 }
81 }
82
83 #[inline(always)]
85 #[must_use]
86 pub const fn from_cols(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self {
87 Self {
88 x_axis,
89 y_axis,
90 z_axis,
91 }
92 }
93
94 #[inline]
98 #[must_use]
99 pub const fn from_cols_array(m: &[f32; 9]) -> Self {
100 Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
101 }
102
103 #[inline]
106 #[must_use]
107 pub const fn to_cols_array(&self) -> [f32; 9] {
108 [
109 self.x_axis.x,
110 self.x_axis.y,
111 self.x_axis.z,
112 self.y_axis.x,
113 self.y_axis.y,
114 self.y_axis.z,
115 self.z_axis.x,
116 self.z_axis.y,
117 self.z_axis.z,
118 ]
119 }
120
121 #[inline]
125 #[must_use]
126 pub const fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self {
127 Self::from_cols(
128 Vec3::from_array(m[0]),
129 Vec3::from_array(m[1]),
130 Vec3::from_array(m[2]),
131 )
132 }
133
134 #[inline]
137 #[must_use]
138 pub const fn to_cols_array_2d(&self) -> [[f32; 3]; 3] {
139 [
140 self.x_axis.to_array(),
141 self.y_axis.to_array(),
142 self.z_axis.to_array(),
143 ]
144 }
145
146 #[doc(alias = "scale")]
148 #[inline]
149 #[must_use]
150 pub const fn from_diagonal(diagonal: Vec3) -> Self {
151 Self::new(
152 diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
153 )
154 }
155
156 #[inline]
158 #[must_use]
159 pub fn from_mat4(m: Mat4) -> Self {
160 Self::from_cols(
161 Vec3::from_vec4(m.x_axis),
162 Vec3::from_vec4(m.y_axis),
163 Vec3::from_vec4(m.z_axis),
164 )
165 }
166
167 #[inline]
174 #[must_use]
175 pub fn from_mat4_minor(m: Mat4, i: usize, j: usize) -> Self {
176 match (i, j) {
177 (0, 0) => Self::from_cols(m.y_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()),
178 (0, 1) => Self::from_cols(m.y_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()),
179 (0, 2) => Self::from_cols(m.y_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()),
180 (0, 3) => Self::from_cols(m.y_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()),
181 (1, 0) => Self::from_cols(m.x_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()),
182 (1, 1) => Self::from_cols(m.x_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()),
183 (1, 2) => Self::from_cols(m.x_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()),
184 (1, 3) => Self::from_cols(m.x_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()),
185 (2, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.w_axis.yzw()),
186 (2, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.w_axis.xzw()),
187 (2, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.w_axis.xyw()),
188 (2, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.w_axis.xyz()),
189 (3, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.z_axis.yzw()),
190 (3, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.z_axis.xzw()),
191 (3, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.z_axis.xyw()),
192 (3, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.z_axis.xyz()),
193 _ => panic!("index out of bounds"),
194 }
195 }
196
197 #[inline]
203 #[must_use]
204 pub fn from_quat(rotation: Quat) -> Self {
205 glam_assert!(rotation.is_normalized());
206
207 let x2 = rotation.x + rotation.x;
208 let y2 = rotation.y + rotation.y;
209 let z2 = rotation.z + rotation.z;
210 let xx = rotation.x * x2;
211 let xy = rotation.x * y2;
212 let xz = rotation.x * z2;
213 let yy = rotation.y * y2;
214 let yz = rotation.y * z2;
215 let zz = rotation.z * z2;
216 let wx = rotation.w * x2;
217 let wy = rotation.w * y2;
218 let wz = rotation.w * z2;
219
220 Self::from_cols(
221 Vec3::new(1.0 - (yy + zz), xy + wz, xz - wy),
222 Vec3::new(xy - wz, 1.0 - (xx + zz), yz + wx),
223 Vec3::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
224 )
225 }
226
227 #[inline]
234 #[must_use]
235 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
236 glam_assert!(axis.is_normalized());
237
238 let (sin, cos) = math::sin_cos(angle);
239 let (xsin, ysin, zsin) = axis.mul(sin).into();
240 let (x, y, z) = axis.into();
241 let (x2, y2, z2) = axis.mul(axis).into();
242 let omc = 1.0 - cos;
243 let xyomc = x * y * omc;
244 let xzomc = x * z * omc;
245 let yzomc = y * z * omc;
246 Self::from_cols(
247 Vec3::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
248 Vec3::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
249 Vec3::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
250 )
251 }
252
253 #[inline]
256 #[must_use]
257 pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
258 Self::from_euler_angles(order, a, b, c)
259 }
260
261 #[inline]
270 #[must_use]
271 pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
272 glam_assert!(
273 self.x_axis.is_normalized()
274 && self.y_axis.is_normalized()
275 && self.z_axis.is_normalized()
276 );
277 self.to_euler_angles(order)
278 }
279
280 #[inline]
282 #[must_use]
283 pub fn from_rotation_x(angle: f32) -> Self {
284 let (sina, cosa) = math::sin_cos(angle);
285 Self::from_cols(
286 Vec3::X,
287 Vec3::new(0.0, cosa, sina),
288 Vec3::new(0.0, -sina, cosa),
289 )
290 }
291
292 #[inline]
294 #[must_use]
295 pub fn from_rotation_y(angle: f32) -> Self {
296 let (sina, cosa) = math::sin_cos(angle);
297 Self::from_cols(
298 Vec3::new(cosa, 0.0, -sina),
299 Vec3::Y,
300 Vec3::new(sina, 0.0, cosa),
301 )
302 }
303
304 #[inline]
306 #[must_use]
307 pub fn from_rotation_z(angle: f32) -> Self {
308 let (sina, cosa) = math::sin_cos(angle);
309 Self::from_cols(
310 Vec3::new(cosa, sina, 0.0),
311 Vec3::new(-sina, cosa, 0.0),
312 Vec3::Z,
313 )
314 }
315
316 #[inline]
321 #[must_use]
322 pub fn from_translation(translation: Vec2) -> Self {
323 Self::from_cols(
324 Vec3::X,
325 Vec3::Y,
326 Vec3::new(translation.x, translation.y, 1.0),
327 )
328 }
329
330 #[inline]
336 #[must_use]
337 pub fn from_angle(angle: f32) -> Self {
338 let (sin, cos) = math::sin_cos(angle);
339 Self::from_cols(Vec3::new(cos, sin, 0.0), Vec3::new(-sin, cos, 0.0), Vec3::Z)
340 }
341
342 #[inline]
348 #[must_use]
349 pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
350 let (sin, cos) = math::sin_cos(angle);
351 Self::from_cols(
352 Vec3::new(cos * scale.x, sin * scale.x, 0.0),
353 Vec3::new(-sin * scale.y, cos * scale.y, 0.0),
354 Vec3::new(translation.x, translation.y, 1.0),
355 )
356 }
357
358 #[inline]
367 #[must_use]
368 pub fn from_scale(scale: Vec2) -> Self {
369 glam_assert!(scale.cmpne(Vec2::ZERO).any());
371
372 Self::from_cols(
373 Vec3::new(scale.x, 0.0, 0.0),
374 Vec3::new(0.0, scale.y, 0.0),
375 Vec3::Z,
376 )
377 }
378
379 #[inline]
384 pub fn from_mat2(m: Mat2) -> Self {
385 Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), Vec3::Z)
386 }
387
388 #[inline]
394 #[must_use]
395 pub const fn from_cols_slice(slice: &[f32]) -> Self {
396 Self::new(
397 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
398 slice[8],
399 )
400 }
401
402 #[inline]
408 pub fn write_cols_to_slice(self, slice: &mut [f32]) {
409 slice[0] = self.x_axis.x;
410 slice[1] = self.x_axis.y;
411 slice[2] = self.x_axis.z;
412 slice[3] = self.y_axis.x;
413 slice[4] = self.y_axis.y;
414 slice[5] = self.y_axis.z;
415 slice[6] = self.z_axis.x;
416 slice[7] = self.z_axis.y;
417 slice[8] = self.z_axis.z;
418 }
419
420 #[inline]
426 #[must_use]
427 pub fn col(&self, index: usize) -> Vec3 {
428 match index {
429 0 => self.x_axis,
430 1 => self.y_axis,
431 2 => self.z_axis,
432 _ => panic!("index out of bounds"),
433 }
434 }
435
436 #[inline]
442 pub fn col_mut(&mut self, index: usize) -> &mut Vec3 {
443 match index {
444 0 => &mut self.x_axis,
445 1 => &mut self.y_axis,
446 2 => &mut self.z_axis,
447 _ => panic!("index out of bounds"),
448 }
449 }
450
451 #[inline]
457 #[must_use]
458 pub fn row(&self, index: usize) -> Vec3 {
459 match index {
460 0 => Vec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
461 1 => Vec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
462 2 => Vec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
463 _ => panic!("index out of bounds"),
464 }
465 }
466
467 #[inline]
470 #[must_use]
471 pub fn is_finite(&self) -> bool {
472 self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
473 }
474
475 #[inline]
477 #[must_use]
478 pub fn is_nan(&self) -> bool {
479 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
480 }
481
482 #[inline]
484 #[must_use]
485 pub fn transpose(&self) -> Self {
486 Self {
487 x_axis: Vec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
488 y_axis: Vec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
489 z_axis: Vec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
490 }
491 }
492
493 #[inline]
495 #[must_use]
496 pub fn determinant(&self) -> f32 {
497 self.z_axis.dot(self.x_axis.cross(self.y_axis))
498 }
499
500 #[inline]
508 #[must_use]
509 pub fn inverse(&self) -> Self {
510 let tmp0 = self.y_axis.cross(self.z_axis);
511 let tmp1 = self.z_axis.cross(self.x_axis);
512 let tmp2 = self.x_axis.cross(self.y_axis);
513 let det = self.z_axis.dot(tmp2);
514 glam_assert!(det != 0.0);
515 let inv_det = Vec3::splat(det.recip());
516 Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose()
517 }
518
519 #[inline]
529 #[must_use]
530 pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
531 glam_assert!(self.row(2).abs_diff_eq(Vec3::Z, 1e-6));
532 Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
533 }
534
535 #[inline]
545 #[must_use]
546 pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
547 glam_assert!(self.row(2).abs_diff_eq(Vec3::Z, 1e-6));
548 Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
549 }
550
551 #[inline]
553 #[must_use]
554 pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 {
555 let mut res = self.x_axis.mul(rhs.x);
556 res = res.add(self.y_axis.mul(rhs.y));
557 res = res.add(self.z_axis.mul(rhs.z));
558 res
559 }
560
561 #[inline]
563 #[must_use]
564 pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A {
565 self.mul_vec3(rhs.into()).into()
566 }
567
568 #[inline]
570 #[must_use]
571 pub fn mul_mat3(&self, rhs: &Self) -> Self {
572 Self::from_cols(
573 self.mul(rhs.x_axis),
574 self.mul(rhs.y_axis),
575 self.mul(rhs.z_axis),
576 )
577 }
578
579 #[inline]
581 #[must_use]
582 pub fn add_mat3(&self, rhs: &Self) -> Self {
583 Self::from_cols(
584 self.x_axis.add(rhs.x_axis),
585 self.y_axis.add(rhs.y_axis),
586 self.z_axis.add(rhs.z_axis),
587 )
588 }
589
590 #[inline]
592 #[must_use]
593 pub fn sub_mat3(&self, rhs: &Self) -> Self {
594 Self::from_cols(
595 self.x_axis.sub(rhs.x_axis),
596 self.y_axis.sub(rhs.y_axis),
597 self.z_axis.sub(rhs.z_axis),
598 )
599 }
600
601 #[inline]
603 #[must_use]
604 pub fn mul_scalar(&self, rhs: f32) -> Self {
605 Self::from_cols(
606 self.x_axis.mul(rhs),
607 self.y_axis.mul(rhs),
608 self.z_axis.mul(rhs),
609 )
610 }
611
612 #[inline]
614 #[must_use]
615 pub fn div_scalar(&self, rhs: f32) -> Self {
616 let rhs = Vec3::splat(rhs);
617 Self::from_cols(
618 self.x_axis.div(rhs),
619 self.y_axis.div(rhs),
620 self.z_axis.div(rhs),
621 )
622 }
623
624 #[inline]
634 #[must_use]
635 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
636 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
637 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
638 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
639 }
640
641 #[inline]
643 #[must_use]
644 pub fn abs(&self) -> Self {
645 Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
646 }
647
648 #[inline]
649 pub fn as_dmat3(&self) -> DMat3 {
650 DMat3::from_cols(
651 self.x_axis.as_dvec3(),
652 self.y_axis.as_dvec3(),
653 self.z_axis.as_dvec3(),
654 )
655 }
656}
657
658impl Default for Mat3 {
659 #[inline]
660 fn default() -> Self {
661 Self::IDENTITY
662 }
663}
664
665impl Add<Mat3> for Mat3 {
666 type Output = Self;
667 #[inline]
668 fn add(self, rhs: Self) -> Self::Output {
669 self.add_mat3(&rhs)
670 }
671}
672
673impl AddAssign<Mat3> for Mat3 {
674 #[inline]
675 fn add_assign(&mut self, rhs: Self) {
676 *self = self.add_mat3(&rhs);
677 }
678}
679
680impl Sub<Mat3> for Mat3 {
681 type Output = Self;
682 #[inline]
683 fn sub(self, rhs: Self) -> Self::Output {
684 self.sub_mat3(&rhs)
685 }
686}
687
688impl SubAssign<Mat3> for Mat3 {
689 #[inline]
690 fn sub_assign(&mut self, rhs: Self) {
691 *self = self.sub_mat3(&rhs);
692 }
693}
694
695impl Neg for Mat3 {
696 type Output = Self;
697 #[inline]
698 fn neg(self) -> Self::Output {
699 Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
700 }
701}
702
703impl Mul<Mat3> for Mat3 {
704 type Output = Self;
705 #[inline]
706 fn mul(self, rhs: Self) -> Self::Output {
707 self.mul_mat3(&rhs)
708 }
709}
710
711impl MulAssign<Mat3> for Mat3 {
712 #[inline]
713 fn mul_assign(&mut self, rhs: Self) {
714 *self = self.mul_mat3(&rhs);
715 }
716}
717
718impl Mul<Vec3> for Mat3 {
719 type Output = Vec3;
720 #[inline]
721 fn mul(self, rhs: Vec3) -> Self::Output {
722 self.mul_vec3(rhs)
723 }
724}
725
726impl Mul<Mat3> for f32 {
727 type Output = Mat3;
728 #[inline]
729 fn mul(self, rhs: Mat3) -> Self::Output {
730 rhs.mul_scalar(self)
731 }
732}
733
734impl Mul<f32> for Mat3 {
735 type Output = Self;
736 #[inline]
737 fn mul(self, rhs: f32) -> Self::Output {
738 self.mul_scalar(rhs)
739 }
740}
741
742impl MulAssign<f32> for Mat3 {
743 #[inline]
744 fn mul_assign(&mut self, rhs: f32) {
745 *self = self.mul_scalar(rhs);
746 }
747}
748
749impl Div<Mat3> for f32 {
750 type Output = Mat3;
751 #[inline]
752 fn div(self, rhs: Mat3) -> Self::Output {
753 rhs.div_scalar(self)
754 }
755}
756
757impl Div<f32> for Mat3 {
758 type Output = Self;
759 #[inline]
760 fn div(self, rhs: f32) -> Self::Output {
761 self.div_scalar(rhs)
762 }
763}
764
765impl DivAssign<f32> for Mat3 {
766 #[inline]
767 fn div_assign(&mut self, rhs: f32) {
768 *self = self.div_scalar(rhs);
769 }
770}
771
772impl Mul<Vec3A> for Mat3 {
773 type Output = Vec3A;
774 #[inline]
775 fn mul(self, rhs: Vec3A) -> Vec3A {
776 self.mul_vec3a(rhs)
777 }
778}
779
780impl From<Mat3A> for Mat3 {
781 #[inline]
782 fn from(m: Mat3A) -> Self {
783 Self {
784 x_axis: m.x_axis.into(),
785 y_axis: m.y_axis.into(),
786 z_axis: m.z_axis.into(),
787 }
788 }
789}
790
791impl Sum<Self> for Mat3 {
792 fn sum<I>(iter: I) -> Self
793 where
794 I: Iterator<Item = Self>,
795 {
796 iter.fold(Self::ZERO, Self::add)
797 }
798}
799
800impl<'a> Sum<&'a Self> for Mat3 {
801 fn sum<I>(iter: I) -> Self
802 where
803 I: Iterator<Item = &'a Self>,
804 {
805 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
806 }
807}
808
809impl Product for Mat3 {
810 fn product<I>(iter: I) -> Self
811 where
812 I: Iterator<Item = Self>,
813 {
814 iter.fold(Self::IDENTITY, Self::mul)
815 }
816}
817
818impl<'a> Product<&'a Self> for Mat3 {
819 fn product<I>(iter: I) -> Self
820 where
821 I: Iterator<Item = &'a Self>,
822 {
823 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
824 }
825}
826
827impl PartialEq for Mat3 {
828 #[inline]
829 fn eq(&self, rhs: &Self) -> bool {
830 self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
831 }
832}
833
834#[cfg(not(target_arch = "spirv"))]
835impl AsRef<[f32; 9]> for Mat3 {
836 #[inline]
837 fn as_ref(&self) -> &[f32; 9] {
838 unsafe { &*(self as *const Self as *const [f32; 9]) }
839 }
840}
841
842#[cfg(not(target_arch = "spirv"))]
843impl AsMut<[f32; 9]> for Mat3 {
844 #[inline]
845 fn as_mut(&mut self) -> &mut [f32; 9] {
846 unsafe { &mut *(self as *mut Self as *mut [f32; 9]) }
847 }
848}
849
850impl fmt::Debug for Mat3 {
851 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
852 fmt.debug_struct(stringify!(Mat3))
853 .field("x_axis", &self.x_axis)
854 .field("y_axis", &self.y_axis)
855 .field("z_axis", &self.z_axis)
856 .finish()
857 }
858}
859
860impl fmt::Display for Mat3 {
861 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
862 if let Some(p) = f.precision() {
863 write!(
864 f,
865 "[{:.*}, {:.*}, {:.*}]",
866 p, self.x_axis, p, self.y_axis, p, self.z_axis
867 )
868 } else {
869 write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
870 }
871 }
872}