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, 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]
566 #[must_use]
567 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
568 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
569 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
570 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
571 }
572
573 #[inline]
574 pub fn as_dmat3(&self) -> DMat3 {
575 DMat3::from_cols(
576 self.x_axis.as_dvec3(),
577 self.y_axis.as_dvec3(),
578 self.z_axis.as_dvec3(),
579 )
580 }
581}
582
583impl Default for Mat3 {
584 #[inline]
585 fn default() -> Self {
586 Self::IDENTITY
587 }
588}
589
590impl Add<Mat3> for Mat3 {
591 type Output = Self;
592 #[inline]
593 fn add(self, rhs: Self) -> Self::Output {
594 self.add_mat3(&rhs)
595 }
596}
597
598impl AddAssign<Mat3> for Mat3 {
599 #[inline]
600 fn add_assign(&mut self, rhs: Self) {
601 *self = self.add_mat3(&rhs);
602 }
603}
604
605impl Sub<Mat3> for Mat3 {
606 type Output = Self;
607 #[inline]
608 fn sub(self, rhs: Self) -> Self::Output {
609 self.sub_mat3(&rhs)
610 }
611}
612
613impl SubAssign<Mat3> for Mat3 {
614 #[inline]
615 fn sub_assign(&mut self, rhs: Self) {
616 *self = self.sub_mat3(&rhs);
617 }
618}
619
620impl Neg for Mat3 {
621 type Output = Self;
622 #[inline]
623 fn neg(self) -> Self::Output {
624 Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
625 }
626}
627
628impl Mul<Mat3> for Mat3 {
629 type Output = Self;
630 #[inline]
631 fn mul(self, rhs: Self) -> Self::Output {
632 self.mul_mat3(&rhs)
633 }
634}
635
636impl MulAssign<Mat3> for Mat3 {
637 #[inline]
638 fn mul_assign(&mut self, rhs: Self) {
639 *self = self.mul_mat3(&rhs);
640 }
641}
642
643impl Mul<Vec3> for Mat3 {
644 type Output = Vec3;
645 #[inline]
646 fn mul(self, rhs: Vec3) -> Self::Output {
647 self.mul_vec3(rhs)
648 }
649}
650
651impl Mul<Mat3> for f32 {
652 type Output = Mat3;
653 #[inline]
654 fn mul(self, rhs: Mat3) -> Self::Output {
655 rhs.mul_scalar(self)
656 }
657}
658
659impl Mul<f32> for Mat3 {
660 type Output = Self;
661 #[inline]
662 fn mul(self, rhs: f32) -> Self::Output {
663 self.mul_scalar(rhs)
664 }
665}
666
667impl MulAssign<f32> for Mat3 {
668 #[inline]
669 fn mul_assign(&mut self, rhs: f32) {
670 *self = self.mul_scalar(rhs);
671 }
672}
673
674impl Mul<Vec3A> for Mat3 {
675 type Output = Vec3A;
676 #[inline]
677 fn mul(self, rhs: Vec3A) -> Vec3A {
678 self.mul_vec3a(rhs)
679 }
680}
681
682impl From<Mat3A> for Mat3 {
683 #[inline]
684 fn from(m: Mat3A) -> Self {
685 Self {
686 x_axis: m.x_axis.into(),
687 y_axis: m.y_axis.into(),
688 z_axis: m.z_axis.into(),
689 }
690 }
691}
692
693impl Sum<Self> for Mat3 {
694 fn sum<I>(iter: I) -> Self
695 where
696 I: Iterator<Item = Self>,
697 {
698 iter.fold(Self::ZERO, Self::add)
699 }
700}
701
702impl<'a> Sum<&'a Self> for Mat3 {
703 fn sum<I>(iter: I) -> Self
704 where
705 I: Iterator<Item = &'a Self>,
706 {
707 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
708 }
709}
710
711impl Product for Mat3 {
712 fn product<I>(iter: I) -> Self
713 where
714 I: Iterator<Item = Self>,
715 {
716 iter.fold(Self::IDENTITY, Self::mul)
717 }
718}
719
720impl<'a> Product<&'a Self> for Mat3 {
721 fn product<I>(iter: I) -> Self
722 where
723 I: Iterator<Item = &'a Self>,
724 {
725 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
726 }
727}
728
729impl PartialEq for Mat3 {
730 #[inline]
731 fn eq(&self, rhs: &Self) -> bool {
732 self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
733 }
734}
735
736#[cfg(not(target_arch = "spirv"))]
737impl AsRef<[f32; 9]> for Mat3 {
738 #[inline]
739 fn as_ref(&self) -> &[f32; 9] {
740 unsafe { &*(self as *const Self as *const [f32; 9]) }
741 }
742}
743
744#[cfg(not(target_arch = "spirv"))]
745impl AsMut<[f32; 9]> for Mat3 {
746 #[inline]
747 fn as_mut(&mut self) -> &mut [f32; 9] {
748 unsafe { &mut *(self as *mut Self as *mut [f32; 9]) }
749 }
750}
751
752#[cfg(not(target_arch = "spirv"))]
753impl fmt::Debug for Mat3 {
754 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
755 fmt.debug_struct(stringify!(Mat3))
756 .field("x_axis", &self.x_axis)
757 .field("y_axis", &self.y_axis)
758 .field("z_axis", &self.z_axis)
759 .finish()
760 }
761}
762
763#[cfg(not(target_arch = "spirv"))]
764impl fmt::Display for Mat3 {
765 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
766 write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
767 }
768}