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