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)]
11pub const fn dmat3(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> DMat3 {
12 DMat3::from_cols(x_axis, y_axis, z_axis)
13}
14
15#[derive(Clone, Copy)]
40#[repr(C)]
41pub struct DMat3 {
42 pub x_axis: DVec3,
43 pub y_axis: DVec3,
44 pub z_axis: DVec3,
45}
46
47impl DMat3 {
48 pub const ZERO: Self = Self::from_cols(DVec3::ZERO, DVec3::ZERO, DVec3::ZERO);
50
51 pub const IDENTITY: Self = Self::from_cols(DVec3::X, DVec3::Y, DVec3::Z);
53
54 pub const NAN: Self = Self::from_cols(DVec3::NAN, DVec3::NAN, DVec3::NAN);
56
57 #[allow(clippy::too_many_arguments)]
58 #[inline(always)]
59 const fn new(
60 m00: f64,
61 m01: f64,
62 m02: f64,
63 m10: f64,
64 m11: f64,
65 m12: f64,
66 m20: f64,
67 m21: f64,
68 m22: f64,
69 ) -> Self {
70 Self {
71 x_axis: DVec3::new(m00, m01, m02),
72 y_axis: DVec3::new(m10, m11, m12),
73 z_axis: DVec3::new(m20, m21, m22),
74 }
75 }
76
77 #[inline(always)]
79 pub const fn from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> Self {
80 Self {
81 x_axis,
82 y_axis,
83 z_axis,
84 }
85 }
86
87 #[inline]
91 pub const fn from_cols_array(m: &[f64; 9]) -> Self {
92 Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
93 }
94
95 #[inline]
98 pub const fn to_cols_array(&self) -> [f64; 9] {
99 [
100 self.x_axis.x,
101 self.x_axis.y,
102 self.x_axis.z,
103 self.y_axis.x,
104 self.y_axis.y,
105 self.y_axis.z,
106 self.z_axis.x,
107 self.z_axis.y,
108 self.z_axis.z,
109 ]
110 }
111
112 #[inline]
116 pub const fn from_cols_array_2d(m: &[[f64; 3]; 3]) -> Self {
117 Self::from_cols(
118 DVec3::from_array(m[0]),
119 DVec3::from_array(m[1]),
120 DVec3::from_array(m[2]),
121 )
122 }
123
124 #[inline]
127 pub const fn to_cols_array_2d(&self) -> [[f64; 3]; 3] {
128 [
129 self.x_axis.to_array(),
130 self.y_axis.to_array(),
131 self.z_axis.to_array(),
132 ]
133 }
134
135 #[doc(alias = "scale")]
137 #[inline]
138 pub const fn from_diagonal(diagonal: DVec3) -> Self {
139 Self::new(
140 diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
141 )
142 }
143
144 pub fn from_mat4(m: DMat4) -> Self {
146 Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.z_axis.xyz())
147 }
148
149 #[inline]
155 pub fn from_quat(rotation: DQuat) -> Self {
156 glam_assert!(rotation.is_normalized());
157
158 let x2 = rotation.x + rotation.x;
159 let y2 = rotation.y + rotation.y;
160 let z2 = rotation.z + rotation.z;
161 let xx = rotation.x * x2;
162 let xy = rotation.x * y2;
163 let xz = rotation.x * z2;
164 let yy = rotation.y * y2;
165 let yz = rotation.y * z2;
166 let zz = rotation.z * z2;
167 let wx = rotation.w * x2;
168 let wy = rotation.w * y2;
169 let wz = rotation.w * z2;
170
171 Self::from_cols(
172 DVec3::new(1.0 - (yy + zz), xy + wz, xz - wy),
173 DVec3::new(xy - wz, 1.0 - (xx + zz), yz + wx),
174 DVec3::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
175 )
176 }
177
178 #[inline]
185 pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
186 glam_assert!(axis.is_normalized());
187
188 let (sin, cos) = math::sin_cos(angle);
189 let (xsin, ysin, zsin) = axis.mul(sin).into();
190 let (x, y, z) = axis.into();
191 let (x2, y2, z2) = axis.mul(axis).into();
192 let omc = 1.0 - cos;
193 let xyomc = x * y * omc;
194 let xzomc = x * z * omc;
195 let yzomc = y * z * omc;
196 Self::from_cols(
197 DVec3::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
198 DVec3::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
199 DVec3::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
200 )
201 }
202
203 #[inline]
204 pub fn from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self {
207 let quat = DQuat::from_euler(order, a, b, c);
208 Self::from_quat(quat)
209 }
210
211 #[inline]
213 pub fn from_rotation_x(angle: f64) -> Self {
214 let (sina, cosa) = math::sin_cos(angle);
215 Self::from_cols(
216 DVec3::X,
217 DVec3::new(0.0, cosa, sina),
218 DVec3::new(0.0, -sina, cosa),
219 )
220 }
221
222 #[inline]
224 pub fn from_rotation_y(angle: f64) -> Self {
225 let (sina, cosa) = math::sin_cos(angle);
226 Self::from_cols(
227 DVec3::new(cosa, 0.0, -sina),
228 DVec3::Y,
229 DVec3::new(sina, 0.0, cosa),
230 )
231 }
232
233 #[inline]
235 pub fn from_rotation_z(angle: f64) -> Self {
236 let (sina, cosa) = math::sin_cos(angle);
237 Self::from_cols(
238 DVec3::new(cosa, sina, 0.0),
239 DVec3::new(-sina, cosa, 0.0),
240 DVec3::Z,
241 )
242 }
243
244 #[inline]
249 pub fn from_translation(translation: DVec2) -> Self {
250 Self::from_cols(
251 DVec3::X,
252 DVec3::Y,
253 DVec3::new(translation.x, translation.y, 1.0),
254 )
255 }
256
257 #[inline]
263 pub fn from_angle(angle: f64) -> Self {
264 let (sin, cos) = math::sin_cos(angle);
265 Self::from_cols(
266 DVec3::new(cos, sin, 0.0),
267 DVec3::new(-sin, cos, 0.0),
268 DVec3::Z,
269 )
270 }
271
272 #[inline]
278 pub fn from_scale_angle_translation(scale: DVec2, angle: f64, translation: DVec2) -> Self {
279 let (sin, cos) = math::sin_cos(angle);
280 Self::from_cols(
281 DVec3::new(cos * scale.x, sin * scale.x, 0.0),
282 DVec3::new(-sin * scale.y, cos * scale.y, 0.0),
283 DVec3::new(translation.x, translation.y, 1.0),
284 )
285 }
286
287 #[inline]
296 pub fn from_scale(scale: DVec2) -> Self {
297 glam_assert!(scale.cmpne(DVec2::ZERO).any());
299
300 Self::from_cols(
301 DVec3::new(scale.x, 0.0, 0.0),
302 DVec3::new(0.0, scale.y, 0.0),
303 DVec3::Z,
304 )
305 }
306
307 #[inline]
312 pub fn from_mat2(m: DMat2) -> Self {
313 Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), DVec3::Z)
314 }
315
316 #[inline]
322 pub const fn from_cols_slice(slice: &[f64]) -> Self {
323 Self::new(
324 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
325 slice[8],
326 )
327 }
328
329 #[inline]
335 pub fn write_cols_to_slice(self, slice: &mut [f64]) {
336 slice[0] = self.x_axis.x;
337 slice[1] = self.x_axis.y;
338 slice[2] = self.x_axis.z;
339 slice[3] = self.y_axis.x;
340 slice[4] = self.y_axis.y;
341 slice[5] = self.y_axis.z;
342 slice[6] = self.z_axis.x;
343 slice[7] = self.z_axis.y;
344 slice[8] = self.z_axis.z;
345 }
346
347 #[inline]
353 pub fn col(&self, index: usize) -> DVec3 {
354 match index {
355 0 => self.x_axis,
356 1 => self.y_axis,
357 2 => self.z_axis,
358 _ => panic!("index out of bounds"),
359 }
360 }
361
362 #[inline]
368 pub fn col_mut(&mut self, index: usize) -> &mut DVec3 {
369 match index {
370 0 => &mut self.x_axis,
371 1 => &mut self.y_axis,
372 2 => &mut self.z_axis,
373 _ => panic!("index out of bounds"),
374 }
375 }
376
377 #[inline]
383 pub fn row(&self, index: usize) -> DVec3 {
384 match index {
385 0 => DVec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
386 1 => DVec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
387 2 => DVec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
388 _ => panic!("index out of bounds"),
389 }
390 }
391
392 #[inline]
395 pub fn is_finite(&self) -> bool {
396 self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
397 }
398
399 #[inline]
401 pub fn is_nan(&self) -> bool {
402 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
403 }
404
405 #[must_use]
407 #[inline]
408 pub fn transpose(&self) -> Self {
409 Self {
410 x_axis: DVec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
411 y_axis: DVec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
412 z_axis: DVec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
413 }
414 }
415
416 #[inline]
418 pub fn determinant(&self) -> f64 {
419 self.z_axis.dot(self.x_axis.cross(self.y_axis))
420 }
421
422 #[must_use]
430 #[inline]
431 pub fn inverse(&self) -> Self {
432 let tmp0 = self.y_axis.cross(self.z_axis);
433 let tmp1 = self.z_axis.cross(self.x_axis);
434 let tmp2 = self.x_axis.cross(self.y_axis);
435 let det = self.z_axis.dot(tmp2);
436 glam_assert!(det != 0.0);
437 let inv_det = DVec3::splat(det.recip());
438 Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose()
439 }
440
441 #[inline]
451 pub fn transform_point2(&self, rhs: DVec2) -> DVec2 {
452 glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
453 DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
454 }
455
456 #[inline]
466 pub fn transform_vector2(&self, rhs: DVec2) -> DVec2 {
467 glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
468 DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
469 }
470
471 #[inline]
473 pub fn mul_vec3(&self, rhs: DVec3) -> DVec3 {
474 let mut res = self.x_axis.mul(rhs.x);
475 res = res.add(self.y_axis.mul(rhs.y));
476 res = res.add(self.z_axis.mul(rhs.z));
477 res
478 }
479
480 #[inline]
482 pub fn mul_mat3(&self, rhs: &Self) -> Self {
483 Self::from_cols(
484 self.mul(rhs.x_axis),
485 self.mul(rhs.y_axis),
486 self.mul(rhs.z_axis),
487 )
488 }
489
490 #[inline]
492 pub fn add_mat3(&self, rhs: &Self) -> Self {
493 Self::from_cols(
494 self.x_axis.add(rhs.x_axis),
495 self.y_axis.add(rhs.y_axis),
496 self.z_axis.add(rhs.z_axis),
497 )
498 }
499
500 #[inline]
502 pub fn sub_mat3(&self, rhs: &Self) -> Self {
503 Self::from_cols(
504 self.x_axis.sub(rhs.x_axis),
505 self.y_axis.sub(rhs.y_axis),
506 self.z_axis.sub(rhs.z_axis),
507 )
508 }
509
510 #[inline]
512 pub fn mul_scalar(&self, rhs: f64) -> Self {
513 Self::from_cols(
514 self.x_axis.mul(rhs),
515 self.y_axis.mul(rhs),
516 self.z_axis.mul(rhs),
517 )
518 }
519
520 #[inline]
530 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
531 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
532 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
533 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
534 }
535
536 #[inline]
537 pub fn as_mat3(&self) -> Mat3 {
538 Mat3::from_cols(
539 self.x_axis.as_vec3(),
540 self.y_axis.as_vec3(),
541 self.z_axis.as_vec3(),
542 )
543 }
544}
545
546impl Default for DMat3 {
547 #[inline]
548 fn default() -> Self {
549 Self::IDENTITY
550 }
551}
552
553impl Add<DMat3> for DMat3 {
554 type Output = Self;
555 #[inline]
556 fn add(self, rhs: Self) -> Self::Output {
557 self.add_mat3(&rhs)
558 }
559}
560
561impl AddAssign<DMat3> for DMat3 {
562 #[inline]
563 fn add_assign(&mut self, rhs: Self) {
564 *self = self.add_mat3(&rhs);
565 }
566}
567
568impl Sub<DMat3> for DMat3 {
569 type Output = Self;
570 #[inline]
571 fn sub(self, rhs: Self) -> Self::Output {
572 self.sub_mat3(&rhs)
573 }
574}
575
576impl SubAssign<DMat3> for DMat3 {
577 #[inline]
578 fn sub_assign(&mut self, rhs: Self) {
579 *self = self.sub_mat3(&rhs);
580 }
581}
582
583impl Neg for DMat3 {
584 type Output = Self;
585 #[inline]
586 fn neg(self) -> Self::Output {
587 Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
588 }
589}
590
591impl Mul<DMat3> for DMat3 {
592 type Output = Self;
593 #[inline]
594 fn mul(self, rhs: Self) -> Self::Output {
595 self.mul_mat3(&rhs)
596 }
597}
598
599impl MulAssign<DMat3> for DMat3 {
600 #[inline]
601 fn mul_assign(&mut self, rhs: Self) {
602 *self = self.mul_mat3(&rhs);
603 }
604}
605
606impl Mul<DVec3> for DMat3 {
607 type Output = DVec3;
608 #[inline]
609 fn mul(self, rhs: DVec3) -> Self::Output {
610 self.mul_vec3(rhs)
611 }
612}
613
614impl Mul<DMat3> for f64 {
615 type Output = DMat3;
616 #[inline]
617 fn mul(self, rhs: DMat3) -> Self::Output {
618 rhs.mul_scalar(self)
619 }
620}
621
622impl Mul<f64> for DMat3 {
623 type Output = Self;
624 #[inline]
625 fn mul(self, rhs: f64) -> Self::Output {
626 self.mul_scalar(rhs)
627 }
628}
629
630impl MulAssign<f64> for DMat3 {
631 #[inline]
632 fn mul_assign(&mut self, rhs: f64) {
633 *self = self.mul_scalar(rhs);
634 }
635}
636
637impl Sum<Self> for DMat3 {
638 fn sum<I>(iter: I) -> Self
639 where
640 I: Iterator<Item = Self>,
641 {
642 iter.fold(Self::ZERO, Self::add)
643 }
644}
645
646impl<'a> Sum<&'a Self> for DMat3 {
647 fn sum<I>(iter: I) -> Self
648 where
649 I: Iterator<Item = &'a Self>,
650 {
651 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
652 }
653}
654
655impl Product for DMat3 {
656 fn product<I>(iter: I) -> Self
657 where
658 I: Iterator<Item = Self>,
659 {
660 iter.fold(Self::IDENTITY, Self::mul)
661 }
662}
663
664impl<'a> Product<&'a Self> for DMat3 {
665 fn product<I>(iter: I) -> Self
666 where
667 I: Iterator<Item = &'a Self>,
668 {
669 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
670 }
671}
672
673impl PartialEq for DMat3 {
674 #[inline]
675 fn eq(&self, rhs: &Self) -> bool {
676 self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
677 }
678}
679
680#[cfg(not(target_arch = "spirv"))]
681impl AsRef<[f64; 9]> for DMat3 {
682 #[inline]
683 fn as_ref(&self) -> &[f64; 9] {
684 unsafe { &*(self as *const Self as *const [f64; 9]) }
685 }
686}
687
688#[cfg(not(target_arch = "spirv"))]
689impl AsMut<[f64; 9]> for DMat3 {
690 #[inline]
691 fn as_mut(&mut self) -> &mut [f64; 9] {
692 unsafe { &mut *(self as *mut Self as *mut [f64; 9]) }
693 }
694}
695
696#[cfg(not(target_arch = "spirv"))]
697impl fmt::Debug for DMat3 {
698 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
699 fmt.debug_struct(stringify!(DMat3))
700 .field("x_axis", &self.x_axis)
701 .field("y_axis", &self.y_axis)
702 .field("z_axis", &self.z_axis)
703 .finish()
704 }
705}
706
707#[cfg(not(target_arch = "spirv"))]
708impl fmt::Display for DMat3 {
709 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
710 write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
711 }
712}