1use crate::{f32::math, swizzles::*, DMat3, EulerRot, Mat2, Mat3, 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#[cfg(target_arch = "x86")]
10use core::arch::x86::*;
11#[cfg(target_arch = "x86_64")]
12use core::arch::x86_64::*;
13
14#[inline(always)]
16pub const fn mat3a(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Mat3A {
17 Mat3A::from_cols(x_axis, y_axis, z_axis)
18}
19
20#[derive(Clone, Copy)]
45#[repr(C)]
46pub struct Mat3A {
47 pub x_axis: Vec3A,
48 pub y_axis: Vec3A,
49 pub z_axis: Vec3A,
50}
51
52impl Mat3A {
53 pub const ZERO: Self = Self::from_cols(Vec3A::ZERO, Vec3A::ZERO, Vec3A::ZERO);
55
56 pub const IDENTITY: Self = Self::from_cols(Vec3A::X, Vec3A::Y, Vec3A::Z);
58
59 pub const NAN: Self = Self::from_cols(Vec3A::NAN, Vec3A::NAN, Vec3A::NAN);
61
62 #[allow(clippy::too_many_arguments)]
63 #[inline(always)]
64 const fn new(
65 m00: f32,
66 m01: f32,
67 m02: f32,
68 m10: f32,
69 m11: f32,
70 m12: f32,
71 m20: f32,
72 m21: f32,
73 m22: f32,
74 ) -> Self {
75 Self {
76 x_axis: Vec3A::new(m00, m01, m02),
77 y_axis: Vec3A::new(m10, m11, m12),
78 z_axis: Vec3A::new(m20, m21, m22),
79 }
80 }
81
82 #[inline(always)]
84 pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Self {
85 Self {
86 x_axis,
87 y_axis,
88 z_axis,
89 }
90 }
91
92 #[inline]
96 pub const fn from_cols_array(m: &[f32; 9]) -> Self {
97 Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
98 }
99
100 #[inline]
103 pub const fn to_cols_array(&self) -> [f32; 9] {
104 let [x_axis_x, x_axis_y, x_axis_z] = self.x_axis.to_array();
105 let [y_axis_x, y_axis_y, y_axis_z] = self.y_axis.to_array();
106 let [z_axis_x, z_axis_y, z_axis_z] = self.z_axis.to_array();
107
108 [
109 x_axis_x, x_axis_y, x_axis_z, y_axis_x, y_axis_y, y_axis_z, z_axis_x, z_axis_y,
110 z_axis_z,
111 ]
112 }
113
114 #[inline]
118 pub const fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self {
119 Self::from_cols(
120 Vec3A::from_array(m[0]),
121 Vec3A::from_array(m[1]),
122 Vec3A::from_array(m[2]),
123 )
124 }
125
126 #[inline]
129 pub const fn to_cols_array_2d(&self) -> [[f32; 3]; 3] {
130 [
131 self.x_axis.to_array(),
132 self.y_axis.to_array(),
133 self.z_axis.to_array(),
134 ]
135 }
136
137 #[doc(alias = "scale")]
139 #[inline]
140 pub const fn from_diagonal(diagonal: Vec3) -> Self {
141 Self::new(
142 diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
143 )
144 }
145
146 pub fn from_mat4(m: Mat4) -> Self {
148 Self::from_cols(m.x_axis.into(), m.y_axis.into(), m.z_axis.into())
149 }
150
151 #[inline]
157 pub fn from_quat(rotation: Quat) -> Self {
158 glam_assert!(rotation.is_normalized());
159
160 let x2 = rotation.x + rotation.x;
161 let y2 = rotation.y + rotation.y;
162 let z2 = rotation.z + rotation.z;
163 let xx = rotation.x * x2;
164 let xy = rotation.x * y2;
165 let xz = rotation.x * z2;
166 let yy = rotation.y * y2;
167 let yz = rotation.y * z2;
168 let zz = rotation.z * z2;
169 let wx = rotation.w * x2;
170 let wy = rotation.w * y2;
171 let wz = rotation.w * z2;
172
173 Self::from_cols(
174 Vec3A::new(1.0 - (yy + zz), xy + wz, xz - wy),
175 Vec3A::new(xy - wz, 1.0 - (xx + zz), yz + wx),
176 Vec3A::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
177 )
178 }
179
180 #[inline]
187 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
188 glam_assert!(axis.is_normalized());
189
190 let (sin, cos) = math::sin_cos(angle);
191 let (xsin, ysin, zsin) = axis.mul(sin).into();
192 let (x, y, z) = axis.into();
193 let (x2, y2, z2) = axis.mul(axis).into();
194 let omc = 1.0 - cos;
195 let xyomc = x * y * omc;
196 let xzomc = x * z * omc;
197 let yzomc = y * z * omc;
198 Self::from_cols(
199 Vec3A::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
200 Vec3A::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
201 Vec3A::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
202 )
203 }
204
205 #[inline]
206 pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
209 let quat = Quat::from_euler(order, a, b, c);
210 Self::from_quat(quat)
211 }
212
213 #[inline]
215 pub fn from_rotation_x(angle: f32) -> Self {
216 let (sina, cosa) = math::sin_cos(angle);
217 Self::from_cols(
218 Vec3A::X,
219 Vec3A::new(0.0, cosa, sina),
220 Vec3A::new(0.0, -sina, cosa),
221 )
222 }
223
224 #[inline]
226 pub fn from_rotation_y(angle: f32) -> Self {
227 let (sina, cosa) = math::sin_cos(angle);
228 Self::from_cols(
229 Vec3A::new(cosa, 0.0, -sina),
230 Vec3A::Y,
231 Vec3A::new(sina, 0.0, cosa),
232 )
233 }
234
235 #[inline]
237 pub fn from_rotation_z(angle: f32) -> Self {
238 let (sina, cosa) = math::sin_cos(angle);
239 Self::from_cols(
240 Vec3A::new(cosa, sina, 0.0),
241 Vec3A::new(-sina, cosa, 0.0),
242 Vec3A::Z,
243 )
244 }
245
246 #[inline]
251 pub fn from_translation(translation: Vec2) -> Self {
252 Self::from_cols(
253 Vec3A::X,
254 Vec3A::Y,
255 Vec3A::new(translation.x, translation.y, 1.0),
256 )
257 }
258
259 #[inline]
265 pub fn from_angle(angle: f32) -> Self {
266 let (sin, cos) = math::sin_cos(angle);
267 Self::from_cols(
268 Vec3A::new(cos, sin, 0.0),
269 Vec3A::new(-sin, cos, 0.0),
270 Vec3A::Z,
271 )
272 }
273
274 #[inline]
280 pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
281 let (sin, cos) = math::sin_cos(angle);
282 Self::from_cols(
283 Vec3A::new(cos * scale.x, sin * scale.x, 0.0),
284 Vec3A::new(-sin * scale.y, cos * scale.y, 0.0),
285 Vec3A::new(translation.x, translation.y, 1.0),
286 )
287 }
288
289 #[inline]
298 pub fn from_scale(scale: Vec2) -> Self {
299 glam_assert!(scale.cmpne(Vec2::ZERO).any());
301
302 Self::from_cols(
303 Vec3A::new(scale.x, 0.0, 0.0),
304 Vec3A::new(0.0, scale.y, 0.0),
305 Vec3A::Z,
306 )
307 }
308
309 #[inline]
314 pub fn from_mat2(m: Mat2) -> Self {
315 Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), Vec3A::Z)
316 }
317
318 #[inline]
324 pub const fn from_cols_slice(slice: &[f32]) -> Self {
325 Self::new(
326 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
327 slice[8],
328 )
329 }
330
331 #[inline]
337 pub fn write_cols_to_slice(self, slice: &mut [f32]) {
338 slice[0] = self.x_axis.x;
339 slice[1] = self.x_axis.y;
340 slice[2] = self.x_axis.z;
341 slice[3] = self.y_axis.x;
342 slice[4] = self.y_axis.y;
343 slice[5] = self.y_axis.z;
344 slice[6] = self.z_axis.x;
345 slice[7] = self.z_axis.y;
346 slice[8] = self.z_axis.z;
347 }
348
349 #[inline]
355 pub fn col(&self, index: usize) -> Vec3A {
356 match index {
357 0 => self.x_axis,
358 1 => self.y_axis,
359 2 => self.z_axis,
360 _ => panic!("index out of bounds"),
361 }
362 }
363
364 #[inline]
370 pub fn col_mut(&mut self, index: usize) -> &mut Vec3A {
371 match index {
372 0 => &mut self.x_axis,
373 1 => &mut self.y_axis,
374 2 => &mut self.z_axis,
375 _ => panic!("index out of bounds"),
376 }
377 }
378
379 #[inline]
385 pub fn row(&self, index: usize) -> Vec3A {
386 match index {
387 0 => Vec3A::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
388 1 => Vec3A::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
389 2 => Vec3A::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
390 _ => panic!("index out of bounds"),
391 }
392 }
393
394 #[inline]
397 pub fn is_finite(&self) -> bool {
398 self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
399 }
400
401 #[inline]
403 pub fn is_nan(&self) -> bool {
404 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
405 }
406
407 #[must_use]
409 #[inline]
410 pub fn transpose(&self) -> Self {
411 unsafe {
412 let tmp0 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b01_00_01_00);
413 let tmp1 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b11_10_11_10);
414
415 Self {
416 x_axis: Vec3A(_mm_shuffle_ps(tmp0, self.z_axis.0, 0b00_00_10_00)),
417 y_axis: Vec3A(_mm_shuffle_ps(tmp0, self.z_axis.0, 0b01_01_11_01)),
418 z_axis: Vec3A(_mm_shuffle_ps(tmp1, self.z_axis.0, 0b10_10_10_00)),
419 }
420 }
421 }
422
423 #[inline]
425 pub fn determinant(&self) -> f32 {
426 self.z_axis.dot(self.x_axis.cross(self.y_axis))
427 }
428
429 #[must_use]
437 #[inline]
438 pub fn inverse(&self) -> Self {
439 let tmp0 = self.y_axis.cross(self.z_axis);
440 let tmp1 = self.z_axis.cross(self.x_axis);
441 let tmp2 = self.x_axis.cross(self.y_axis);
442 let det = self.z_axis.dot(tmp2);
443 glam_assert!(det != 0.0);
444 let inv_det = Vec3A::splat(det.recip());
445 Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose()
446 }
447
448 #[inline]
458 pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
459 glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
460 Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
461 }
462
463 #[inline]
473 pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
474 glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
475 Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
476 }
477
478 #[inline]
480 pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 {
481 self.mul_vec3a(rhs.into()).into()
482 }
483
484 #[inline]
486 pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A {
487 let mut res = self.x_axis.mul(rhs.xxx());
488 res = res.add(self.y_axis.mul(rhs.yyy()));
489 res = res.add(self.z_axis.mul(rhs.zzz()));
490 res
491 }
492
493 #[inline]
495 pub fn mul_mat3(&self, rhs: &Self) -> Self {
496 Self::from_cols(
497 self.mul(rhs.x_axis),
498 self.mul(rhs.y_axis),
499 self.mul(rhs.z_axis),
500 )
501 }
502
503 #[inline]
505 pub fn add_mat3(&self, rhs: &Self) -> Self {
506 Self::from_cols(
507 self.x_axis.add(rhs.x_axis),
508 self.y_axis.add(rhs.y_axis),
509 self.z_axis.add(rhs.z_axis),
510 )
511 }
512
513 #[inline]
515 pub fn sub_mat3(&self, rhs: &Self) -> Self {
516 Self::from_cols(
517 self.x_axis.sub(rhs.x_axis),
518 self.y_axis.sub(rhs.y_axis),
519 self.z_axis.sub(rhs.z_axis),
520 )
521 }
522
523 #[inline]
525 pub fn mul_scalar(&self, rhs: f32) -> Self {
526 Self::from_cols(
527 self.x_axis.mul(rhs),
528 self.y_axis.mul(rhs),
529 self.z_axis.mul(rhs),
530 )
531 }
532
533 #[inline]
543 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
544 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
545 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
546 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
547 }
548
549 #[inline]
550 pub fn as_dmat3(&self) -> DMat3 {
551 DMat3::from_cols(
552 self.x_axis.as_dvec3(),
553 self.y_axis.as_dvec3(),
554 self.z_axis.as_dvec3(),
555 )
556 }
557}
558
559impl Default for Mat3A {
560 #[inline]
561 fn default() -> Self {
562 Self::IDENTITY
563 }
564}
565
566impl Add<Mat3A> for Mat3A {
567 type Output = Self;
568 #[inline]
569 fn add(self, rhs: Self) -> Self::Output {
570 self.add_mat3(&rhs)
571 }
572}
573
574impl AddAssign<Mat3A> for Mat3A {
575 #[inline]
576 fn add_assign(&mut self, rhs: Self) {
577 *self = self.add_mat3(&rhs);
578 }
579}
580
581impl Sub<Mat3A> for Mat3A {
582 type Output = Self;
583 #[inline]
584 fn sub(self, rhs: Self) -> Self::Output {
585 self.sub_mat3(&rhs)
586 }
587}
588
589impl SubAssign<Mat3A> for Mat3A {
590 #[inline]
591 fn sub_assign(&mut self, rhs: Self) {
592 *self = self.sub_mat3(&rhs);
593 }
594}
595
596impl Neg for Mat3A {
597 type Output = Self;
598 #[inline]
599 fn neg(self) -> Self::Output {
600 Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
601 }
602}
603
604impl Mul<Mat3A> for Mat3A {
605 type Output = Self;
606 #[inline]
607 fn mul(self, rhs: Self) -> Self::Output {
608 self.mul_mat3(&rhs)
609 }
610}
611
612impl MulAssign<Mat3A> for Mat3A {
613 #[inline]
614 fn mul_assign(&mut self, rhs: Self) {
615 *self = self.mul_mat3(&rhs);
616 }
617}
618
619impl Mul<Vec3A> for Mat3A {
620 type Output = Vec3A;
621 #[inline]
622 fn mul(self, rhs: Vec3A) -> Self::Output {
623 self.mul_vec3a(rhs)
624 }
625}
626
627impl Mul<Mat3A> for f32 {
628 type Output = Mat3A;
629 #[inline]
630 fn mul(self, rhs: Mat3A) -> Self::Output {
631 rhs.mul_scalar(self)
632 }
633}
634
635impl Mul<f32> for Mat3A {
636 type Output = Self;
637 #[inline]
638 fn mul(self, rhs: f32) -> Self::Output {
639 self.mul_scalar(rhs)
640 }
641}
642
643impl MulAssign<f32> for Mat3A {
644 #[inline]
645 fn mul_assign(&mut self, rhs: f32) {
646 *self = self.mul_scalar(rhs);
647 }
648}
649
650impl Mul<Vec3> for Mat3A {
651 type Output = Vec3;
652 #[inline]
653 fn mul(self, rhs: Vec3) -> Vec3 {
654 self.mul_vec3a(rhs.into()).into()
655 }
656}
657
658impl From<Mat3> for Mat3A {
659 #[inline]
660 fn from(m: Mat3) -> Self {
661 Self {
662 x_axis: m.x_axis.into(),
663 y_axis: m.y_axis.into(),
664 z_axis: m.z_axis.into(),
665 }
666 }
667}
668
669impl Sum<Self> for Mat3A {
670 fn sum<I>(iter: I) -> Self
671 where
672 I: Iterator<Item = Self>,
673 {
674 iter.fold(Self::ZERO, Self::add)
675 }
676}
677
678impl<'a> Sum<&'a Self> for Mat3A {
679 fn sum<I>(iter: I) -> Self
680 where
681 I: Iterator<Item = &'a Self>,
682 {
683 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
684 }
685}
686
687impl Product for Mat3A {
688 fn product<I>(iter: I) -> Self
689 where
690 I: Iterator<Item = Self>,
691 {
692 iter.fold(Self::IDENTITY, Self::mul)
693 }
694}
695
696impl<'a> Product<&'a Self> for Mat3A {
697 fn product<I>(iter: I) -> Self
698 where
699 I: Iterator<Item = &'a Self>,
700 {
701 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
702 }
703}
704
705impl PartialEq for Mat3A {
706 #[inline]
707 fn eq(&self, rhs: &Self) -> bool {
708 self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
709 }
710}
711
712#[cfg(not(target_arch = "spirv"))]
713impl fmt::Debug for Mat3A {
714 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
715 fmt.debug_struct(stringify!(Mat3A))
716 .field("x_axis", &self.x_axis)
717 .field("y_axis", &self.y_axis)
718 .field("z_axis", &self.z_axis)
719 .finish()
720 }
721}
722
723#[cfg(not(target_arch = "spirv"))]
724impl fmt::Display for Mat3A {
725 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
726 write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
727 }
728}