1use crate::{f64::math, swizzles::*, DMat2, DMat4, DQuat, DVec2, DVec3, EulerRot, Mat3};
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 dmat3(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> DMat3 {
13 DMat3::from_cols(x_axis, y_axis, z_axis)
14}
15
16#[derive(Clone, Copy)]
41#[repr(C)]
42pub struct DMat3 {
43 pub x_axis: DVec3,
44 pub y_axis: DVec3,
45 pub z_axis: DVec3,
46}
47
48impl DMat3 {
49 pub const ZERO: Self = Self::from_cols(DVec3::ZERO, DVec3::ZERO, DVec3::ZERO);
51
52 pub const IDENTITY: Self = Self::from_cols(DVec3::X, DVec3::Y, DVec3::Z);
54
55 pub const NAN: Self = Self::from_cols(DVec3::NAN, DVec3::NAN, DVec3::NAN);
57
58 #[allow(clippy::too_many_arguments)]
59 #[inline(always)]
60 #[must_use]
61 const fn new(
62 m00: f64,
63 m01: f64,
64 m02: f64,
65 m10: f64,
66 m11: f64,
67 m12: f64,
68 m20: f64,
69 m21: f64,
70 m22: f64,
71 ) -> Self {
72 Self {
73 x_axis: DVec3::new(m00, m01, m02),
74 y_axis: DVec3::new(m10, m11, m12),
75 z_axis: DVec3::new(m20, m21, m22),
76 }
77 }
78
79 #[inline(always)]
81 #[must_use]
82 pub const fn from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> 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: &[f64; 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) -> [f64; 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: &[[f64; 3]; 3]) -> Self {
123 Self::from_cols(
124 DVec3::from_array(m[0]),
125 DVec3::from_array(m[1]),
126 DVec3::from_array(m[2]),
127 )
128 }
129
130 #[inline]
133 #[must_use]
134 pub const fn to_cols_array_2d(&self) -> [[f64; 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: DVec3) -> 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: DMat4) -> 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: DQuat) -> 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 DVec3::new(1.0 - (yy + zz), xy + wz, xz - wy),
184 DVec3::new(xy - wz, 1.0 - (xx + zz), yz + wx),
185 DVec3::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
186 )
187 }
188
189 #[inline]
196 #[must_use]
197 pub fn from_axis_angle(axis: DVec3, angle: f64) -> 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 DVec3::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
210 DVec3::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
211 DVec3::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
212 )
213 }
214
215 #[inline]
218 #[must_use]
219 pub fn from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self {
220 let quat = DQuat::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: f64) -> Self {
228 let (sina, cosa) = math::sin_cos(angle);
229 Self::from_cols(
230 DVec3::X,
231 DVec3::new(0.0, cosa, sina),
232 DVec3::new(0.0, -sina, cosa),
233 )
234 }
235
236 #[inline]
238 #[must_use]
239 pub fn from_rotation_y(angle: f64) -> Self {
240 let (sina, cosa) = math::sin_cos(angle);
241 Self::from_cols(
242 DVec3::new(cosa, 0.0, -sina),
243 DVec3::Y,
244 DVec3::new(sina, 0.0, cosa),
245 )
246 }
247
248 #[inline]
250 #[must_use]
251 pub fn from_rotation_z(angle: f64) -> Self {
252 let (sina, cosa) = math::sin_cos(angle);
253 Self::from_cols(
254 DVec3::new(cosa, sina, 0.0),
255 DVec3::new(-sina, cosa, 0.0),
256 DVec3::Z,
257 )
258 }
259
260 #[inline]
265 #[must_use]
266 pub fn from_translation(translation: DVec2) -> Self {
267 Self::from_cols(
268 DVec3::X,
269 DVec3::Y,
270 DVec3::new(translation.x, translation.y, 1.0),
271 )
272 }
273
274 #[inline]
280 #[must_use]
281 pub fn from_angle(angle: f64) -> Self {
282 let (sin, cos) = math::sin_cos(angle);
283 Self::from_cols(
284 DVec3::new(cos, sin, 0.0),
285 DVec3::new(-sin, cos, 0.0),
286 DVec3::Z,
287 )
288 }
289
290 #[inline]
296 #[must_use]
297 pub fn from_scale_angle_translation(scale: DVec2, angle: f64, translation: DVec2) -> Self {
298 let (sin, cos) = math::sin_cos(angle);
299 Self::from_cols(
300 DVec3::new(cos * scale.x, sin * scale.x, 0.0),
301 DVec3::new(-sin * scale.y, cos * scale.y, 0.0),
302 DVec3::new(translation.x, translation.y, 1.0),
303 )
304 }
305
306 #[inline]
315 #[must_use]
316 pub fn from_scale(scale: DVec2) -> Self {
317 glam_assert!(scale.cmpne(DVec2::ZERO).any());
319
320 Self::from_cols(
321 DVec3::new(scale.x, 0.0, 0.0),
322 DVec3::new(0.0, scale.y, 0.0),
323 DVec3::Z,
324 )
325 }
326
327 #[inline]
332 pub fn from_mat2(m: DMat2) -> Self {
333 Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), DVec3::Z)
334 }
335
336 #[inline]
342 #[must_use]
343 pub const fn from_cols_slice(slice: &[f64]) -> Self {
344 Self::new(
345 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
346 slice[8],
347 )
348 }
349
350 #[inline]
356 pub fn write_cols_to_slice(self, slice: &mut [f64]) {
357 slice[0] = self.x_axis.x;
358 slice[1] = self.x_axis.y;
359 slice[2] = self.x_axis.z;
360 slice[3] = self.y_axis.x;
361 slice[4] = self.y_axis.y;
362 slice[5] = self.y_axis.z;
363 slice[6] = self.z_axis.x;
364 slice[7] = self.z_axis.y;
365 slice[8] = self.z_axis.z;
366 }
367
368 #[inline]
374 #[must_use]
375 pub fn col(&self, index: usize) -> DVec3 {
376 match index {
377 0 => self.x_axis,
378 1 => self.y_axis,
379 2 => self.z_axis,
380 _ => panic!("index out of bounds"),
381 }
382 }
383
384 #[inline]
390 pub fn col_mut(&mut self, index: usize) -> &mut DVec3 {
391 match index {
392 0 => &mut self.x_axis,
393 1 => &mut self.y_axis,
394 2 => &mut self.z_axis,
395 _ => panic!("index out of bounds"),
396 }
397 }
398
399 #[inline]
405 #[must_use]
406 pub fn row(&self, index: usize) -> DVec3 {
407 match index {
408 0 => DVec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
409 1 => DVec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
410 2 => DVec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
411 _ => panic!("index out of bounds"),
412 }
413 }
414
415 #[inline]
418 #[must_use]
419 pub fn is_finite(&self) -> bool {
420 self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
421 }
422
423 #[inline]
425 #[must_use]
426 pub fn is_nan(&self) -> bool {
427 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
428 }
429
430 #[inline]
432 #[must_use]
433 pub fn transpose(&self) -> Self {
434 Self {
435 x_axis: DVec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
436 y_axis: DVec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
437 z_axis: DVec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
438 }
439 }
440
441 #[inline]
443 #[must_use]
444 pub fn determinant(&self) -> f64 {
445 self.z_axis.dot(self.x_axis.cross(self.y_axis))
446 }
447
448 #[inline]
456 #[must_use]
457 pub fn inverse(&self) -> Self {
458 let tmp0 = self.y_axis.cross(self.z_axis);
459 let tmp1 = self.z_axis.cross(self.x_axis);
460 let tmp2 = self.x_axis.cross(self.y_axis);
461 let det = self.z_axis.dot(tmp2);
462 glam_assert!(det != 0.0);
463 let inv_det = DVec3::splat(det.recip());
464 Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose()
465 }
466
467 #[inline]
477 #[must_use]
478 pub fn transform_point2(&self, rhs: DVec2) -> DVec2 {
479 glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
480 DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
481 }
482
483 #[inline]
493 #[must_use]
494 pub fn transform_vector2(&self, rhs: DVec2) -> DVec2 {
495 glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
496 DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
497 }
498
499 #[inline]
501 #[must_use]
502 pub fn mul_vec3(&self, rhs: DVec3) -> DVec3 {
503 let mut res = self.x_axis.mul(rhs.x);
504 res = res.add(self.y_axis.mul(rhs.y));
505 res = res.add(self.z_axis.mul(rhs.z));
506 res
507 }
508
509 #[inline]
511 #[must_use]
512 pub fn mul_mat3(&self, rhs: &Self) -> Self {
513 Self::from_cols(
514 self.mul(rhs.x_axis),
515 self.mul(rhs.y_axis),
516 self.mul(rhs.z_axis),
517 )
518 }
519
520 #[inline]
522 #[must_use]
523 pub fn add_mat3(&self, rhs: &Self) -> Self {
524 Self::from_cols(
525 self.x_axis.add(rhs.x_axis),
526 self.y_axis.add(rhs.y_axis),
527 self.z_axis.add(rhs.z_axis),
528 )
529 }
530
531 #[inline]
533 #[must_use]
534 pub fn sub_mat3(&self, rhs: &Self) -> Self {
535 Self::from_cols(
536 self.x_axis.sub(rhs.x_axis),
537 self.y_axis.sub(rhs.y_axis),
538 self.z_axis.sub(rhs.z_axis),
539 )
540 }
541
542 #[inline]
544 #[must_use]
545 pub fn mul_scalar(&self, rhs: f64) -> Self {
546 Self::from_cols(
547 self.x_axis.mul(rhs),
548 self.y_axis.mul(rhs),
549 self.z_axis.mul(rhs),
550 )
551 }
552
553 #[inline]
555 #[must_use]
556 pub fn div_scalar(&self, rhs: f64) -> Self {
557 let rhs = DVec3::splat(rhs);
558 Self::from_cols(
559 self.x_axis.div(rhs),
560 self.y_axis.div(rhs),
561 self.z_axis.div(rhs),
562 )
563 }
564
565 #[inline]
575 #[must_use]
576 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
577 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
578 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
579 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
580 }
581
582 #[inline]
584 #[must_use]
585 pub fn abs(&self) -> Self {
586 Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
587 }
588
589 #[inline]
590 pub fn as_mat3(&self) -> Mat3 {
591 Mat3::from_cols(
592 self.x_axis.as_vec3(),
593 self.y_axis.as_vec3(),
594 self.z_axis.as_vec3(),
595 )
596 }
597}
598
599impl Default for DMat3 {
600 #[inline]
601 fn default() -> Self {
602 Self::IDENTITY
603 }
604}
605
606impl Add<DMat3> for DMat3 {
607 type Output = Self;
608 #[inline]
609 fn add(self, rhs: Self) -> Self::Output {
610 self.add_mat3(&rhs)
611 }
612}
613
614impl AddAssign<DMat3> for DMat3 {
615 #[inline]
616 fn add_assign(&mut self, rhs: Self) {
617 *self = self.add_mat3(&rhs);
618 }
619}
620
621impl Sub<DMat3> for DMat3 {
622 type Output = Self;
623 #[inline]
624 fn sub(self, rhs: Self) -> Self::Output {
625 self.sub_mat3(&rhs)
626 }
627}
628
629impl SubAssign<DMat3> for DMat3 {
630 #[inline]
631 fn sub_assign(&mut self, rhs: Self) {
632 *self = self.sub_mat3(&rhs);
633 }
634}
635
636impl Neg for DMat3 {
637 type Output = Self;
638 #[inline]
639 fn neg(self) -> Self::Output {
640 Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
641 }
642}
643
644impl Mul<DMat3> for DMat3 {
645 type Output = Self;
646 #[inline]
647 fn mul(self, rhs: Self) -> Self::Output {
648 self.mul_mat3(&rhs)
649 }
650}
651
652impl MulAssign<DMat3> for DMat3 {
653 #[inline]
654 fn mul_assign(&mut self, rhs: Self) {
655 *self = self.mul_mat3(&rhs);
656 }
657}
658
659impl Mul<DVec3> for DMat3 {
660 type Output = DVec3;
661 #[inline]
662 fn mul(self, rhs: DVec3) -> Self::Output {
663 self.mul_vec3(rhs)
664 }
665}
666
667impl Mul<DMat3> for f64 {
668 type Output = DMat3;
669 #[inline]
670 fn mul(self, rhs: DMat3) -> Self::Output {
671 rhs.mul_scalar(self)
672 }
673}
674
675impl Mul<f64> for DMat3 {
676 type Output = Self;
677 #[inline]
678 fn mul(self, rhs: f64) -> Self::Output {
679 self.mul_scalar(rhs)
680 }
681}
682
683impl MulAssign<f64> for DMat3 {
684 #[inline]
685 fn mul_assign(&mut self, rhs: f64) {
686 *self = self.mul_scalar(rhs);
687 }
688}
689
690impl Div<DMat3> for f64 {
691 type Output = DMat3;
692 #[inline]
693 fn div(self, rhs: DMat3) -> Self::Output {
694 rhs.div_scalar(self)
695 }
696}
697
698impl Div<f64> for DMat3 {
699 type Output = Self;
700 #[inline]
701 fn div(self, rhs: f64) -> Self::Output {
702 self.div_scalar(rhs)
703 }
704}
705
706impl DivAssign<f64> for DMat3 {
707 #[inline]
708 fn div_assign(&mut self, rhs: f64) {
709 *self = self.div_scalar(rhs);
710 }
711}
712
713impl Sum<Self> for DMat3 {
714 fn sum<I>(iter: I) -> Self
715 where
716 I: Iterator<Item = Self>,
717 {
718 iter.fold(Self::ZERO, Self::add)
719 }
720}
721
722impl<'a> Sum<&'a Self> for DMat3 {
723 fn sum<I>(iter: I) -> Self
724 where
725 I: Iterator<Item = &'a Self>,
726 {
727 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
728 }
729}
730
731impl Product for DMat3 {
732 fn product<I>(iter: I) -> Self
733 where
734 I: Iterator<Item = Self>,
735 {
736 iter.fold(Self::IDENTITY, Self::mul)
737 }
738}
739
740impl<'a> Product<&'a Self> for DMat3 {
741 fn product<I>(iter: I) -> Self
742 where
743 I: Iterator<Item = &'a Self>,
744 {
745 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
746 }
747}
748
749impl PartialEq for DMat3 {
750 #[inline]
751 fn eq(&self, rhs: &Self) -> bool {
752 self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
753 }
754}
755
756#[cfg(not(target_arch = "spirv"))]
757impl AsRef<[f64; 9]> for DMat3 {
758 #[inline]
759 fn as_ref(&self) -> &[f64; 9] {
760 unsafe { &*(self as *const Self as *const [f64; 9]) }
761 }
762}
763
764#[cfg(not(target_arch = "spirv"))]
765impl AsMut<[f64; 9]> for DMat3 {
766 #[inline]
767 fn as_mut(&mut self) -> &mut [f64; 9] {
768 unsafe { &mut *(self as *mut Self as *mut [f64; 9]) }
769 }
770}
771
772#[cfg(not(target_arch = "spirv"))]
773impl fmt::Debug for DMat3 {
774 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
775 fmt.debug_struct(stringify!(DMat3))
776 .field("x_axis", &self.x_axis)
777 .field("y_axis", &self.y_axis)
778 .field("z_axis", &self.z_axis)
779 .finish()
780 }
781}
782
783#[cfg(not(target_arch = "spirv"))]
784impl fmt::Display for DMat3 {
785 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
786 if let Some(p) = f.precision() {
787 write!(
788 f,
789 "[{:.*}, {:.*}, {:.*}]",
790 p, self.x_axis, p, self.y_axis, p, self.z_axis
791 )
792 } else {
793 write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
794 }
795 }
796}