1use crate::{f32::math, swizzles::*, DMat3, EulerRot, Mat2, Mat3A, Mat4, Quat, Vec2, Vec3, Vec3A};
4#[cfg(not(target_arch = "spirv"))]
5use core::fmt;
6use core::iter::{Product, Sum};
7use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
8
9#[inline(always)]
11#[must_use]
12pub const fn mat3(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Mat3 {
13 Mat3::from_cols(x_axis, y_axis, z_axis)
14}
15
16#[derive(Clone, Copy)]
41#[repr(C)]
42pub struct Mat3 {
43 pub x_axis: Vec3,
44 pub y_axis: Vec3,
45 pub z_axis: Vec3,
46}
47
48impl Mat3 {
49 pub const ZERO: Self = Self::from_cols(Vec3::ZERO, Vec3::ZERO, Vec3::ZERO);
51
52 pub const IDENTITY: Self = Self::from_cols(Vec3::X, Vec3::Y, Vec3::Z);
54
55 pub const NAN: Self = Self::from_cols(Vec3::NAN, Vec3::NAN, Vec3::NAN);
57
58 #[allow(clippy::too_many_arguments)]
59 #[inline(always)]
60 #[must_use]
61 const fn new(
62 m00: f32,
63 m01: f32,
64 m02: f32,
65 m10: f32,
66 m11: f32,
67 m12: f32,
68 m20: f32,
69 m21: f32,
70 m22: f32,
71 ) -> Self {
72 Self {
73 x_axis: Vec3::new(m00, m01, m02),
74 y_axis: Vec3::new(m10, m11, m12),
75 z_axis: Vec3::new(m20, m21, m22),
76 }
77 }
78
79 #[inline(always)]
81 #[must_use]
82 pub const fn from_cols(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self {
83 Self {
84 x_axis,
85 y_axis,
86 z_axis,
87 }
88 }
89
90 #[inline]
94 #[must_use]
95 pub const fn from_cols_array(m: &[f32; 9]) -> Self {
96 Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
97 }
98
99 #[inline]
102 #[must_use]
103 pub const fn to_cols_array(&self) -> [f32; 9] {
104 [
105 self.x_axis.x,
106 self.x_axis.y,
107 self.x_axis.z,
108 self.y_axis.x,
109 self.y_axis.y,
110 self.y_axis.z,
111 self.z_axis.x,
112 self.z_axis.y,
113 self.z_axis.z,
114 ]
115 }
116
117 #[inline]
121 #[must_use]
122 pub const fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self {
123 Self::from_cols(
124 Vec3::from_array(m[0]),
125 Vec3::from_array(m[1]),
126 Vec3::from_array(m[2]),
127 )
128 }
129
130 #[inline]
133 #[must_use]
134 pub const fn to_cols_array_2d(&self) -> [[f32; 3]; 3] {
135 [
136 self.x_axis.to_array(),
137 self.y_axis.to_array(),
138 self.z_axis.to_array(),
139 ]
140 }
141
142 #[doc(alias = "scale")]
144 #[inline]
145 #[must_use]
146 pub const fn from_diagonal(diagonal: Vec3) -> Self {
147 Self::new(
148 diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
149 )
150 }
151
152 #[inline]
154 #[must_use]
155 pub fn from_mat4(m: Mat4) -> Self {
156 Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.z_axis.xyz())
157 }
158
159 #[inline]
165 #[must_use]
166 pub fn from_quat(rotation: Quat) -> Self {
167 glam_assert!(rotation.is_normalized());
168
169 let x2 = rotation.x + rotation.x;
170 let y2 = rotation.y + rotation.y;
171 let z2 = rotation.z + rotation.z;
172 let xx = rotation.x * x2;
173 let xy = rotation.x * y2;
174 let xz = rotation.x * z2;
175 let yy = rotation.y * y2;
176 let yz = rotation.y * z2;
177 let zz = rotation.z * z2;
178 let wx = rotation.w * x2;
179 let wy = rotation.w * y2;
180 let wz = rotation.w * z2;
181
182 Self::from_cols(
183 Vec3::new(1.0 - (yy + zz), xy + wz, xz - wy),
184 Vec3::new(xy - wz, 1.0 - (xx + zz), yz + wx),
185 Vec3::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
186 )
187 }
188
189 #[inline]
196 #[must_use]
197 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
198 glam_assert!(axis.is_normalized());
199
200 let (sin, cos) = math::sin_cos(angle);
201 let (xsin, ysin, zsin) = axis.mul(sin).into();
202 let (x, y, z) = axis.into();
203 let (x2, y2, z2) = axis.mul(axis).into();
204 let omc = 1.0 - cos;
205 let xyomc = x * y * omc;
206 let xzomc = x * z * omc;
207 let yzomc = y * z * omc;
208 Self::from_cols(
209 Vec3::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
210 Vec3::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
211 Vec3::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
212 )
213 }
214
215 #[inline]
218 #[must_use]
219 pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
220 let quat = Quat::from_euler(order, a, b, c);
221 Self::from_quat(quat)
222 }
223
224 #[inline]
226 #[must_use]
227 pub fn from_rotation_x(angle: f32) -> Self {
228 let (sina, cosa) = math::sin_cos(angle);
229 Self::from_cols(
230 Vec3::X,
231 Vec3::new(0.0, cosa, sina),
232 Vec3::new(0.0, -sina, cosa),
233 )
234 }
235
236 #[inline]
238 #[must_use]
239 pub fn from_rotation_y(angle: f32) -> Self {
240 let (sina, cosa) = math::sin_cos(angle);
241 Self::from_cols(
242 Vec3::new(cosa, 0.0, -sina),
243 Vec3::Y,
244 Vec3::new(sina, 0.0, cosa),
245 )
246 }
247
248 #[inline]
250 #[must_use]
251 pub fn from_rotation_z(angle: f32) -> Self {
252 let (sina, cosa) = math::sin_cos(angle);
253 Self::from_cols(
254 Vec3::new(cosa, sina, 0.0),
255 Vec3::new(-sina, cosa, 0.0),
256 Vec3::Z,
257 )
258 }
259
260 #[inline]
265 #[must_use]
266 pub fn from_translation(translation: Vec2) -> Self {
267 Self::from_cols(
268 Vec3::X,
269 Vec3::Y,
270 Vec3::new(translation.x, translation.y, 1.0),
271 )
272 }
273
274 #[inline]
280 #[must_use]
281 pub fn from_angle(angle: f32) -> Self {
282 let (sin, cos) = math::sin_cos(angle);
283 Self::from_cols(Vec3::new(cos, sin, 0.0), Vec3::new(-sin, cos, 0.0), Vec3::Z)
284 }
285
286 #[inline]
292 #[must_use]
293 pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
294 let (sin, cos) = math::sin_cos(angle);
295 Self::from_cols(
296 Vec3::new(cos * scale.x, sin * scale.x, 0.0),
297 Vec3::new(-sin * scale.y, cos * scale.y, 0.0),
298 Vec3::new(translation.x, translation.y, 1.0),
299 )
300 }
301
302 #[inline]
311 #[must_use]
312 pub fn from_scale(scale: Vec2) -> Self {
313 glam_assert!(scale.cmpne(Vec2::ZERO).any());
315
316 Self::from_cols(
317 Vec3::new(scale.x, 0.0, 0.0),
318 Vec3::new(0.0, scale.y, 0.0),
319 Vec3::Z,
320 )
321 }
322
323 #[inline]
328 pub fn from_mat2(m: Mat2) -> Self {
329 Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), Vec3::Z)
330 }
331
332 #[inline]
338 #[must_use]
339 pub const fn from_cols_slice(slice: &[f32]) -> Self {
340 Self::new(
341 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
342 slice[8],
343 )
344 }
345
346 #[inline]
352 pub fn write_cols_to_slice(self, slice: &mut [f32]) {
353 slice[0] = self.x_axis.x;
354 slice[1] = self.x_axis.y;
355 slice[2] = self.x_axis.z;
356 slice[3] = self.y_axis.x;
357 slice[4] = self.y_axis.y;
358 slice[5] = self.y_axis.z;
359 slice[6] = self.z_axis.x;
360 slice[7] = self.z_axis.y;
361 slice[8] = self.z_axis.z;
362 }
363
364 #[inline]
370 #[must_use]
371 pub fn col(&self, index: usize) -> Vec3 {
372 match index {
373 0 => self.x_axis,
374 1 => self.y_axis,
375 2 => self.z_axis,
376 _ => panic!("index out of bounds"),
377 }
378 }
379
380 #[inline]
386 pub fn col_mut(&mut self, index: usize) -> &mut Vec3 {
387 match index {
388 0 => &mut self.x_axis,
389 1 => &mut self.y_axis,
390 2 => &mut self.z_axis,
391 _ => panic!("index out of bounds"),
392 }
393 }
394
395 #[inline]
401 #[must_use]
402 pub fn row(&self, index: usize) -> Vec3 {
403 match index {
404 0 => Vec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
405 1 => Vec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
406 2 => Vec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
407 _ => panic!("index out of bounds"),
408 }
409 }
410
411 #[inline]
414 #[must_use]
415 pub fn is_finite(&self) -> bool {
416 self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
417 }
418
419 #[inline]
421 #[must_use]
422 pub fn is_nan(&self) -> bool {
423 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
424 }
425
426 #[inline]
428 #[must_use]
429 pub fn transpose(&self) -> Self {
430 Self {
431 x_axis: Vec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
432 y_axis: Vec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
433 z_axis: Vec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
434 }
435 }
436
437 #[inline]
439 #[must_use]
440 pub fn determinant(&self) -> f32 {
441 self.z_axis.dot(self.x_axis.cross(self.y_axis))
442 }
443
444 #[inline]
452 #[must_use]
453 pub fn inverse(&self) -> Self {
454 let tmp0 = self.y_axis.cross(self.z_axis);
455 let tmp1 = self.z_axis.cross(self.x_axis);
456 let tmp2 = self.x_axis.cross(self.y_axis);
457 let det = self.z_axis.dot(tmp2);
458 glam_assert!(det != 0.0);
459 let inv_det = Vec3::splat(det.recip());
460 Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose()
461 }
462
463 #[inline]
473 #[must_use]
474 pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
475 glam_assert!(self.row(2).abs_diff_eq(Vec3::Z, 1e-6));
476 Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
477 }
478
479 #[inline]
489 #[must_use]
490 pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
491 glam_assert!(self.row(2).abs_diff_eq(Vec3::Z, 1e-6));
492 Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
493 }
494
495 #[inline]
497 #[must_use]
498 pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 {
499 let mut res = self.x_axis.mul(rhs.x);
500 res = res.add(self.y_axis.mul(rhs.y));
501 res = res.add(self.z_axis.mul(rhs.z));
502 res
503 }
504
505 #[inline]
507 #[must_use]
508 pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A {
509 self.mul_vec3(rhs.into()).into()
510 }
511
512 #[inline]
514 #[must_use]
515 pub fn mul_mat3(&self, rhs: &Self) -> Self {
516 Self::from_cols(
517 self.mul(rhs.x_axis),
518 self.mul(rhs.y_axis),
519 self.mul(rhs.z_axis),
520 )
521 }
522
523 #[inline]
525 #[must_use]
526 pub fn add_mat3(&self, rhs: &Self) -> Self {
527 Self::from_cols(
528 self.x_axis.add(rhs.x_axis),
529 self.y_axis.add(rhs.y_axis),
530 self.z_axis.add(rhs.z_axis),
531 )
532 }
533
534 #[inline]
536 #[must_use]
537 pub fn sub_mat3(&self, rhs: &Self) -> Self {
538 Self::from_cols(
539 self.x_axis.sub(rhs.x_axis),
540 self.y_axis.sub(rhs.y_axis),
541 self.z_axis.sub(rhs.z_axis),
542 )
543 }
544
545 #[inline]
547 #[must_use]
548 pub fn mul_scalar(&self, rhs: f32) -> Self {
549 Self::from_cols(
550 self.x_axis.mul(rhs),
551 self.y_axis.mul(rhs),
552 self.z_axis.mul(rhs),
553 )
554 }
555
556 #[inline]
558 #[must_use]
559 pub fn div_scalar(&self, rhs: f32) -> Self {
560 let rhs = Vec3::splat(rhs);
561 Self::from_cols(
562 self.x_axis.div(rhs),
563 self.y_axis.div(rhs),
564 self.z_axis.div(rhs),
565 )
566 }
567
568 #[inline]
578 #[must_use]
579 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
580 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
581 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
582 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
583 }
584
585 #[inline]
587 #[must_use]
588 pub fn abs(&self) -> Self {
589 Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
590 }
591
592 #[inline]
593 pub fn as_dmat3(&self) -> DMat3 {
594 DMat3::from_cols(
595 self.x_axis.as_dvec3(),
596 self.y_axis.as_dvec3(),
597 self.z_axis.as_dvec3(),
598 )
599 }
600}
601
602impl Default for Mat3 {
603 #[inline]
604 fn default() -> Self {
605 Self::IDENTITY
606 }
607}
608
609impl Add<Mat3> for Mat3 {
610 type Output = Self;
611 #[inline]
612 fn add(self, rhs: Self) -> Self::Output {
613 self.add_mat3(&rhs)
614 }
615}
616
617impl AddAssign<Mat3> for Mat3 {
618 #[inline]
619 fn add_assign(&mut self, rhs: Self) {
620 *self = self.add_mat3(&rhs);
621 }
622}
623
624impl Sub<Mat3> for Mat3 {
625 type Output = Self;
626 #[inline]
627 fn sub(self, rhs: Self) -> Self::Output {
628 self.sub_mat3(&rhs)
629 }
630}
631
632impl SubAssign<Mat3> for Mat3 {
633 #[inline]
634 fn sub_assign(&mut self, rhs: Self) {
635 *self = self.sub_mat3(&rhs);
636 }
637}
638
639impl Neg for Mat3 {
640 type Output = Self;
641 #[inline]
642 fn neg(self) -> Self::Output {
643 Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
644 }
645}
646
647impl Mul<Mat3> for Mat3 {
648 type Output = Self;
649 #[inline]
650 fn mul(self, rhs: Self) -> Self::Output {
651 self.mul_mat3(&rhs)
652 }
653}
654
655impl MulAssign<Mat3> for Mat3 {
656 #[inline]
657 fn mul_assign(&mut self, rhs: Self) {
658 *self = self.mul_mat3(&rhs);
659 }
660}
661
662impl Mul<Vec3> for Mat3 {
663 type Output = Vec3;
664 #[inline]
665 fn mul(self, rhs: Vec3) -> Self::Output {
666 self.mul_vec3(rhs)
667 }
668}
669
670impl Mul<Mat3> for f32 {
671 type Output = Mat3;
672 #[inline]
673 fn mul(self, rhs: Mat3) -> Self::Output {
674 rhs.mul_scalar(self)
675 }
676}
677
678impl Mul<f32> for Mat3 {
679 type Output = Self;
680 #[inline]
681 fn mul(self, rhs: f32) -> Self::Output {
682 self.mul_scalar(rhs)
683 }
684}
685
686impl MulAssign<f32> for Mat3 {
687 #[inline]
688 fn mul_assign(&mut self, rhs: f32) {
689 *self = self.mul_scalar(rhs);
690 }
691}
692
693impl Div<Mat3> for f32 {
694 type Output = Mat3;
695 #[inline]
696 fn div(self, rhs: Mat3) -> Self::Output {
697 rhs.div_scalar(self)
698 }
699}
700
701impl Div<f32> for Mat3 {
702 type Output = Self;
703 #[inline]
704 fn div(self, rhs: f32) -> Self::Output {
705 self.div_scalar(rhs)
706 }
707}
708
709impl DivAssign<f32> for Mat3 {
710 #[inline]
711 fn div_assign(&mut self, rhs: f32) {
712 *self = self.div_scalar(rhs);
713 }
714}
715
716impl Mul<Vec3A> for Mat3 {
717 type Output = Vec3A;
718 #[inline]
719 fn mul(self, rhs: Vec3A) -> Vec3A {
720 self.mul_vec3a(rhs)
721 }
722}
723
724impl From<Mat3A> for Mat3 {
725 #[inline]
726 fn from(m: Mat3A) -> Self {
727 Self {
728 x_axis: m.x_axis.into(),
729 y_axis: m.y_axis.into(),
730 z_axis: m.z_axis.into(),
731 }
732 }
733}
734
735impl Sum<Self> for Mat3 {
736 fn sum<I>(iter: I) -> Self
737 where
738 I: Iterator<Item = Self>,
739 {
740 iter.fold(Self::ZERO, Self::add)
741 }
742}
743
744impl<'a> Sum<&'a Self> for Mat3 {
745 fn sum<I>(iter: I) -> Self
746 where
747 I: Iterator<Item = &'a Self>,
748 {
749 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
750 }
751}
752
753impl Product for Mat3 {
754 fn product<I>(iter: I) -> Self
755 where
756 I: Iterator<Item = Self>,
757 {
758 iter.fold(Self::IDENTITY, Self::mul)
759 }
760}
761
762impl<'a> Product<&'a Self> for Mat3 {
763 fn product<I>(iter: I) -> Self
764 where
765 I: Iterator<Item = &'a Self>,
766 {
767 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
768 }
769}
770
771impl PartialEq for Mat3 {
772 #[inline]
773 fn eq(&self, rhs: &Self) -> bool {
774 self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
775 }
776}
777
778#[cfg(not(target_arch = "spirv"))]
779impl AsRef<[f32; 9]> for Mat3 {
780 #[inline]
781 fn as_ref(&self) -> &[f32; 9] {
782 unsafe { &*(self as *const Self as *const [f32; 9]) }
783 }
784}
785
786#[cfg(not(target_arch = "spirv"))]
787impl AsMut<[f32; 9]> for Mat3 {
788 #[inline]
789 fn as_mut(&mut self) -> &mut [f32; 9] {
790 unsafe { &mut *(self as *mut Self as *mut [f32; 9]) }
791 }
792}
793
794#[cfg(not(target_arch = "spirv"))]
795impl fmt::Debug for Mat3 {
796 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
797 fmt.debug_struct(stringify!(Mat3))
798 .field("x_axis", &self.x_axis)
799 .field("y_axis", &self.y_axis)
800 .field("z_axis", &self.z_axis)
801 .finish()
802 }
803}
804
805#[cfg(not(target_arch = "spirv"))]
806impl fmt::Display for Mat3 {
807 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
808 if let Some(p) = f.precision() {
809 write!(
810 f,
811 "[{:.*}, {:.*}, {:.*}]",
812 p, self.x_axis, p, self.y_axis, p, self.z_axis
813 )
814 } else {
815 write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
816 }
817 }
818}