1use crate::{
4 euler::{FromEuler, ToEuler},
5 f64::math,
6 swizzles::*,
7 DMat3, DQuat, DVec3, DVec4, EulerRot, Mat4,
8};
9use core::fmt;
10use core::iter::{Product, Sum};
11use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
12
13#[cfg(feature = "zerocopy")]
14use zerocopy_derive::*;
15
16#[inline(always)]
18#[must_use]
19pub const fn dmat4(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> DMat4 {
20 DMat4::from_cols(x_axis, y_axis, z_axis, w_axis)
21}
22
23#[derive(Clone, Copy)]
53#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
54#[cfg_attr(
55 feature = "zerocopy",
56 derive(FromBytes, Immutable, IntoBytes, KnownLayout)
57)]
58#[cfg_attr(feature = "cuda", repr(align(16)))]
59#[repr(C)]
60pub struct DMat4 {
61 pub x_axis: DVec4,
62 pub y_axis: DVec4,
63 pub z_axis: DVec4,
64 pub w_axis: DVec4,
65}
66
67impl DMat4 {
68 pub const ZERO: Self = Self::from_cols(DVec4::ZERO, DVec4::ZERO, DVec4::ZERO, DVec4::ZERO);
70
71 pub const IDENTITY: Self = Self::from_cols(DVec4::X, DVec4::Y, DVec4::Z, DVec4::W);
73
74 pub const NAN: Self = Self::from_cols(DVec4::NAN, DVec4::NAN, DVec4::NAN, DVec4::NAN);
76
77 #[allow(clippy::too_many_arguments)]
78 #[inline(always)]
79 #[must_use]
80 const fn new(
81 m00: f64,
82 m01: f64,
83 m02: f64,
84 m03: f64,
85 m10: f64,
86 m11: f64,
87 m12: f64,
88 m13: f64,
89 m20: f64,
90 m21: f64,
91 m22: f64,
92 m23: f64,
93 m30: f64,
94 m31: f64,
95 m32: f64,
96 m33: f64,
97 ) -> Self {
98 Self {
99 x_axis: DVec4::new(m00, m01, m02, m03),
100 y_axis: DVec4::new(m10, m11, m12, m13),
101 z_axis: DVec4::new(m20, m21, m22, m23),
102 w_axis: DVec4::new(m30, m31, m32, m33),
103 }
104 }
105
106 #[inline(always)]
108 #[must_use]
109 pub const fn from_cols(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> Self {
110 Self {
111 x_axis,
112 y_axis,
113 z_axis,
114 w_axis,
115 }
116 }
117
118 #[inline]
122 #[must_use]
123 pub const fn from_cols_array(m: &[f64; 16]) -> Self {
124 Self::new(
125 m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13],
126 m[14], m[15],
127 )
128 }
129
130 #[inline]
133 #[must_use]
134 pub const fn to_cols_array(&self) -> [f64; 16] {
135 [
136 self.x_axis.x,
137 self.x_axis.y,
138 self.x_axis.z,
139 self.x_axis.w,
140 self.y_axis.x,
141 self.y_axis.y,
142 self.y_axis.z,
143 self.y_axis.w,
144 self.z_axis.x,
145 self.z_axis.y,
146 self.z_axis.z,
147 self.z_axis.w,
148 self.w_axis.x,
149 self.w_axis.y,
150 self.w_axis.z,
151 self.w_axis.w,
152 ]
153 }
154
155 #[inline]
159 #[must_use]
160 pub const fn from_cols_array_2d(m: &[[f64; 4]; 4]) -> Self {
161 Self::from_cols(
162 DVec4::from_array(m[0]),
163 DVec4::from_array(m[1]),
164 DVec4::from_array(m[2]),
165 DVec4::from_array(m[3]),
166 )
167 }
168
169 #[inline]
172 #[must_use]
173 pub const fn to_cols_array_2d(&self) -> [[f64; 4]; 4] {
174 [
175 self.x_axis.to_array(),
176 self.y_axis.to_array(),
177 self.z_axis.to_array(),
178 self.w_axis.to_array(),
179 ]
180 }
181
182 #[doc(alias = "scale")]
184 #[inline]
185 #[must_use]
186 pub const fn from_diagonal(diagonal: DVec4) -> Self {
187 Self::new(
188 diagonal.x, 0.0, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, 0.0, diagonal.z, 0.0, 0.0,
189 0.0, 0.0, diagonal.w,
190 )
191 }
192
193 #[inline]
194 #[must_use]
195 fn quat_to_axes(rotation: DQuat) -> (DVec4, DVec4, DVec4) {
196 glam_assert!(rotation.is_normalized());
197
198 let (x, y, z, w) = rotation.into();
199 let x2 = x + x;
200 let y2 = y + y;
201 let z2 = z + z;
202 let xx = x * x2;
203 let xy = x * y2;
204 let xz = x * z2;
205 let yy = y * y2;
206 let yz = y * z2;
207 let zz = z * z2;
208 let wx = w * x2;
209 let wy = w * y2;
210 let wz = w * z2;
211
212 let x_axis = DVec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
213 let y_axis = DVec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
214 let z_axis = DVec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
215 (x_axis, y_axis, z_axis)
216 }
217
218 #[inline]
228 #[must_use]
229 pub fn from_scale_rotation_translation(
230 scale: DVec3,
231 rotation: DQuat,
232 translation: DVec3,
233 ) -> Self {
234 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
235 Self::from_cols(
236 x_axis.mul(scale.x),
237 y_axis.mul(scale.y),
238 z_axis.mul(scale.z),
239 DVec4::from((translation, 1.0)),
240 )
241 }
242
243 #[inline]
252 #[must_use]
253 pub fn from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self {
254 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
255 Self::from_cols(x_axis, y_axis, z_axis, DVec4::from((translation, 1.0)))
256 }
257
258 #[inline]
266 #[must_use]
267 pub fn to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3) {
268 let det = self.determinant();
269 glam_assert!(det != 0.0);
270
271 let scale = DVec3::new(
272 self.x_axis.length() * math::signum(det),
273 self.y_axis.length(),
274 self.z_axis.length(),
275 );
276
277 glam_assert!(scale.cmpne(DVec3::ZERO).all());
278
279 let inv_scale = scale.recip();
280
281 let rotation = DQuat::from_rotation_axes(
282 self.x_axis.mul(inv_scale.x).xyz(),
283 self.y_axis.mul(inv_scale.y).xyz(),
284 self.z_axis.mul(inv_scale.z).xyz(),
285 );
286
287 let translation = self.w_axis.xyz();
288
289 (scale, rotation, translation)
290 }
291
292 #[inline]
301 #[must_use]
302 pub fn from_quat(rotation: DQuat) -> Self {
303 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
304 Self::from_cols(x_axis, y_axis, z_axis, DVec4::W)
305 }
306
307 #[inline]
313 #[must_use]
314 pub fn from_mat3(m: DMat3) -> Self {
315 Self::from_cols(
316 DVec4::from((m.x_axis, 0.0)),
317 DVec4::from((m.y_axis, 0.0)),
318 DVec4::from((m.z_axis, 0.0)),
319 DVec4::W,
320 )
321 }
322
323 #[inline]
328 #[must_use]
329 pub fn from_mat3_translation(mat3: DMat3, translation: DVec3) -> Self {
330 Self::from_cols(
331 DVec4::from((mat3.x_axis, 0.0)),
332 DVec4::from((mat3.y_axis, 0.0)),
333 DVec4::from((mat3.z_axis, 0.0)),
334 DVec4::from((translation, 1.0)),
335 )
336 }
337
338 #[inline]
343 #[must_use]
344 pub fn from_translation(translation: DVec3) -> Self {
345 Self::from_cols(
346 DVec4::X,
347 DVec4::Y,
348 DVec4::Z,
349 DVec4::new(translation.x, translation.y, translation.z, 1.0),
350 )
351 }
352
353 #[inline]
363 #[must_use]
364 pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
365 glam_assert!(axis.is_normalized());
366
367 let (sin, cos) = math::sin_cos(angle);
368 let axis_sin = axis.mul(sin);
369 let axis_sq = axis.mul(axis);
370 let omc = 1.0 - cos;
371 let xyomc = axis.x * axis.y * omc;
372 let xzomc = axis.x * axis.z * omc;
373 let yzomc = axis.y * axis.z * omc;
374 Self::from_cols(
375 DVec4::new(
376 axis_sq.x * omc + cos,
377 xyomc + axis_sin.z,
378 xzomc - axis_sin.y,
379 0.0,
380 ),
381 DVec4::new(
382 xyomc - axis_sin.z,
383 axis_sq.y * omc + cos,
384 yzomc + axis_sin.x,
385 0.0,
386 ),
387 DVec4::new(
388 xzomc + axis_sin.y,
389 yzomc - axis_sin.x,
390 axis_sq.z * omc + cos,
391 0.0,
392 ),
393 DVec4::W,
394 )
395 }
396
397 #[inline]
403 #[must_use]
404 pub fn from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self {
405 Self::from_euler_angles(order, a, b, c)
406 }
407
408 #[inline]
418 #[must_use]
419 pub fn to_euler(&self, order: EulerRot) -> (f64, f64, f64) {
420 glam_assert!(
421 self.x_axis.xyz().is_normalized()
422 && self.y_axis.xyz().is_normalized()
423 && self.z_axis.xyz().is_normalized()
424 );
425 self.to_euler_angles(order)
426 }
427
428 #[inline]
434 #[must_use]
435 pub fn from_rotation_x(angle: f64) -> Self {
436 let (sina, cosa) = math::sin_cos(angle);
437 Self::from_cols(
438 DVec4::X,
439 DVec4::new(0.0, cosa, sina, 0.0),
440 DVec4::new(0.0, -sina, cosa, 0.0),
441 DVec4::W,
442 )
443 }
444
445 #[inline]
451 #[must_use]
452 pub fn from_rotation_y(angle: f64) -> Self {
453 let (sina, cosa) = math::sin_cos(angle);
454 Self::from_cols(
455 DVec4::new(cosa, 0.0, -sina, 0.0),
456 DVec4::Y,
457 DVec4::new(sina, 0.0, cosa, 0.0),
458 DVec4::W,
459 )
460 }
461
462 #[inline]
468 #[must_use]
469 pub fn from_rotation_z(angle: f64) -> Self {
470 let (sina, cosa) = math::sin_cos(angle);
471 Self::from_cols(
472 DVec4::new(cosa, sina, 0.0, 0.0),
473 DVec4::new(-sina, cosa, 0.0, 0.0),
474 DVec4::Z,
475 DVec4::W,
476 )
477 }
478
479 #[inline]
488 #[must_use]
489 pub fn from_scale(scale: DVec3) -> Self {
490 glam_assert!(scale.cmpne(DVec3::ZERO).any());
492
493 Self::from_cols(
494 DVec4::new(scale.x, 0.0, 0.0, 0.0),
495 DVec4::new(0.0, scale.y, 0.0, 0.0),
496 DVec4::new(0.0, 0.0, scale.z, 0.0),
497 DVec4::W,
498 )
499 }
500
501 #[inline]
507 #[must_use]
508 pub const fn from_cols_slice(slice: &[f64]) -> Self {
509 Self::new(
510 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
511 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
512 )
513 }
514
515 #[inline]
521 pub fn write_cols_to_slice(&self, slice: &mut [f64]) {
522 slice[0] = self.x_axis.x;
523 slice[1] = self.x_axis.y;
524 slice[2] = self.x_axis.z;
525 slice[3] = self.x_axis.w;
526 slice[4] = self.y_axis.x;
527 slice[5] = self.y_axis.y;
528 slice[6] = self.y_axis.z;
529 slice[7] = self.y_axis.w;
530 slice[8] = self.z_axis.x;
531 slice[9] = self.z_axis.y;
532 slice[10] = self.z_axis.z;
533 slice[11] = self.z_axis.w;
534 slice[12] = self.w_axis.x;
535 slice[13] = self.w_axis.y;
536 slice[14] = self.w_axis.z;
537 slice[15] = self.w_axis.w;
538 }
539
540 #[inline]
546 #[must_use]
547 pub fn col(&self, index: usize) -> DVec4 {
548 match index {
549 0 => self.x_axis,
550 1 => self.y_axis,
551 2 => self.z_axis,
552 3 => self.w_axis,
553 _ => panic!("index out of bounds"),
554 }
555 }
556
557 #[inline]
563 pub fn col_mut(&mut self, index: usize) -> &mut DVec4 {
564 match index {
565 0 => &mut self.x_axis,
566 1 => &mut self.y_axis,
567 2 => &mut self.z_axis,
568 3 => &mut self.w_axis,
569 _ => panic!("index out of bounds"),
570 }
571 }
572
573 #[inline]
579 #[must_use]
580 pub fn row(&self, index: usize) -> DVec4 {
581 match index {
582 0 => DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
583 1 => DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
584 2 => DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
585 3 => DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
586 _ => panic!("index out of bounds"),
587 }
588 }
589
590 #[inline]
593 #[must_use]
594 pub fn is_finite(&self) -> bool {
595 self.x_axis.is_finite()
596 && self.y_axis.is_finite()
597 && self.z_axis.is_finite()
598 && self.w_axis.is_finite()
599 }
600
601 #[inline]
603 #[must_use]
604 pub fn is_nan(&self) -> bool {
605 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
606 }
607
608 #[inline]
610 #[must_use]
611 pub fn transpose(&self) -> Self {
612 Self {
613 x_axis: DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
614 y_axis: DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
615 z_axis: DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
616 w_axis: DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
617 }
618 }
619
620 #[inline]
622 #[must_use]
623 pub fn diagonal(&self) -> DVec4 {
624 DVec4::new(self.x_axis.x, self.y_axis.y, self.z_axis.z, self.w_axis.w)
625 }
626
627 #[must_use]
629 pub fn determinant(&self) -> f64 {
630 let (m00, m01, m02, m03) = self.x_axis.into();
631 let (m10, m11, m12, m13) = self.y_axis.into();
632 let (m20, m21, m22, m23) = self.z_axis.into();
633 let (m30, m31, m32, m33) = self.w_axis.into();
634
635 let a2323 = m22 * m33 - m23 * m32;
636 let a1323 = m21 * m33 - m23 * m31;
637 let a1223 = m21 * m32 - m22 * m31;
638 let a0323 = m20 * m33 - m23 * m30;
639 let a0223 = m20 * m32 - m22 * m30;
640 let a0123 = m20 * m31 - m21 * m30;
641
642 m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223)
643 - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223)
644 + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123)
645 - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123)
646 }
647
648 #[inline(always)]
660 #[must_use]
661 fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
662 let (m00, m01, m02, m03) = self.x_axis.into();
663 let (m10, m11, m12, m13) = self.y_axis.into();
664 let (m20, m21, m22, m23) = self.z_axis.into();
665 let (m30, m31, m32, m33) = self.w_axis.into();
666
667 let coef00 = m22 * m33 - m32 * m23;
668 let coef02 = m12 * m33 - m32 * m13;
669 let coef03 = m12 * m23 - m22 * m13;
670
671 let coef04 = m21 * m33 - m31 * m23;
672 let coef06 = m11 * m33 - m31 * m13;
673 let coef07 = m11 * m23 - m21 * m13;
674
675 let coef08 = m21 * m32 - m31 * m22;
676 let coef10 = m11 * m32 - m31 * m12;
677 let coef11 = m11 * m22 - m21 * m12;
678
679 let coef12 = m20 * m33 - m30 * m23;
680 let coef14 = m10 * m33 - m30 * m13;
681 let coef15 = m10 * m23 - m20 * m13;
682
683 let coef16 = m20 * m32 - m30 * m22;
684 let coef18 = m10 * m32 - m30 * m12;
685 let coef19 = m10 * m22 - m20 * m12;
686
687 let coef20 = m20 * m31 - m30 * m21;
688 let coef22 = m10 * m31 - m30 * m11;
689 let coef23 = m10 * m21 - m20 * m11;
690
691 let fac0 = DVec4::new(coef00, coef00, coef02, coef03);
692 let fac1 = DVec4::new(coef04, coef04, coef06, coef07);
693 let fac2 = DVec4::new(coef08, coef08, coef10, coef11);
694 let fac3 = DVec4::new(coef12, coef12, coef14, coef15);
695 let fac4 = DVec4::new(coef16, coef16, coef18, coef19);
696 let fac5 = DVec4::new(coef20, coef20, coef22, coef23);
697
698 let vec0 = DVec4::new(m10, m00, m00, m00);
699 let vec1 = DVec4::new(m11, m01, m01, m01);
700 let vec2 = DVec4::new(m12, m02, m02, m02);
701 let vec3 = DVec4::new(m13, m03, m03, m03);
702
703 let inv0 = vec1.mul(fac0).sub(vec2.mul(fac1)).add(vec3.mul(fac2));
704 let inv1 = vec0.mul(fac0).sub(vec2.mul(fac3)).add(vec3.mul(fac4));
705 let inv2 = vec0.mul(fac1).sub(vec1.mul(fac3)).add(vec3.mul(fac5));
706 let inv3 = vec0.mul(fac2).sub(vec1.mul(fac4)).add(vec2.mul(fac5));
707
708 let sign_a = DVec4::new(1.0, -1.0, 1.0, -1.0);
709 let sign_b = DVec4::new(-1.0, 1.0, -1.0, 1.0);
710
711 let inverse = Self::from_cols(
712 inv0.mul(sign_a),
713 inv1.mul(sign_b),
714 inv2.mul(sign_a),
715 inv3.mul(sign_b),
716 );
717
718 let col0 = DVec4::new(
719 inverse.x_axis.x,
720 inverse.y_axis.x,
721 inverse.z_axis.x,
722 inverse.w_axis.x,
723 );
724
725 let dot0 = self.x_axis.mul(col0);
726 let dot1 = dot0.x + dot0.y + dot0.z + dot0.w;
727
728 if CHECKED {
729 if dot1 == 0.0 {
730 return (Self::ZERO, false);
731 }
732 } else {
733 glam_assert!(dot1 != 0.0);
734 }
735
736 let rcp_det = dot1.recip();
737 (inverse.mul(rcp_det), true)
738 }
739
740 #[must_use]
748 pub fn inverse(&self) -> Self {
749 self.inverse_checked::<false>().0
750 }
751
752 #[must_use]
754 pub fn try_inverse(&self) -> Option<Self> {
755 let (m, is_valid) = self.inverse_checked::<true>();
756 if is_valid {
757 Some(m)
758 } else {
759 None
760 }
761 }
762
763 #[must_use]
765 pub fn inverse_or_zero(&self) -> Self {
766 self.inverse_checked::<true>().0
767 }
768
769 #[inline]
778 #[must_use]
779 pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
780 Self::look_to_rh(eye, -dir, up)
781 }
782
783 #[inline]
792 #[must_use]
793 pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
794 glam_assert!(dir.is_normalized());
795 glam_assert!(up.is_normalized());
796 let f = dir;
797 let s = f.cross(up).normalize();
798 let u = s.cross(f);
799
800 Self::from_cols(
801 DVec4::new(s.x, u.x, -f.x, 0.0),
802 DVec4::new(s.y, u.y, -f.y, 0.0),
803 DVec4::new(s.z, u.z, -f.z, 0.0),
804 DVec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
805 )
806 }
807
808 #[inline]
817 #[must_use]
818 pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
819 Self::look_to_lh(eye, center.sub(eye).normalize(), up)
820 }
821
822 #[inline]
831 pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
832 Self::look_to_rh(eye, center.sub(eye).normalize(), up)
833 }
834
835 #[inline]
841 #[must_use]
842 pub fn frustum_rh_gl(
843 left: f64,
844 right: f64,
845 bottom: f64,
846 top: f64,
847 z_near: f64,
848 z_far: f64,
849 ) -> Self {
850 let inv_width = 1.0 / (right - left);
851 let inv_height = 1.0 / (top - bottom);
852 let inv_depth = 1.0 / (z_far - z_near);
853 let a = (right + left) * inv_width;
854 let b = (top + bottom) * inv_height;
855 let c = -(z_far + z_near) * inv_depth;
856 let d = -(2.0 * z_far * z_near) * inv_depth;
857 let two_z_near = 2.0 * z_near;
858 Self::from_cols(
859 DVec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
860 DVec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
861 DVec4::new(a, b, c, -1.0),
862 DVec4::new(0.0, 0.0, d, 0.0),
863 )
864 }
865
866 #[inline]
873 #[must_use]
874 pub fn frustum_lh(
875 left: f64,
876 right: f64,
877 bottom: f64,
878 top: f64,
879 z_near: f64,
880 z_far: f64,
881 ) -> Self {
882 glam_assert!(z_near > 0.0 && z_far > 0.0);
883 let inv_width = 1.0 / (right - left);
884 let inv_height = 1.0 / (top - bottom);
885 let inv_depth = 1.0 / (z_far - z_near);
886 let a = (right + left) * inv_width;
887 let b = (top + bottom) * inv_height;
888 let c = z_far * inv_depth;
889 let d = -(z_far * z_near) * inv_depth;
890 let two_z_near = 2.0 * z_near;
891 Self::from_cols(
892 DVec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
893 DVec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
894 DVec4::new(a, b, c, 1.0),
895 DVec4::new(0.0, 0.0, d, 0.0),
896 )
897 }
898
899 #[inline]
906 #[must_use]
907 pub fn frustum_rh(
908 left: f64,
909 right: f64,
910 bottom: f64,
911 top: f64,
912 z_near: f64,
913 z_far: f64,
914 ) -> Self {
915 glam_assert!(z_near > 0.0 && z_far > 0.0);
916 let inv_width = 1.0 / (right - left);
917 let inv_height = 1.0 / (top - bottom);
918 let inv_depth = 1.0 / (z_far - z_near);
919 let a = (right + left) * inv_width;
920 let b = (top + bottom) * inv_height;
921 let c = -z_far * inv_depth;
922 let d = -(z_far * z_near) * inv_depth;
923 let two_z_near = 2.0 * z_near;
924 Self::from_cols(
925 DVec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
926 DVec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
927 DVec4::new(a, b, c, -1.0),
928 DVec4::new(0.0, 0.0, d, 0.0),
929 )
930 }
931
932 #[inline]
939 #[must_use]
940 pub fn perspective_rh_gl(
941 fov_y_radians: f64,
942 aspect_ratio: f64,
943 z_near: f64,
944 z_far: f64,
945 ) -> Self {
946 let inv_length = 1.0 / (z_near - z_far);
947 let f = 1.0 / math::tan(0.5 * fov_y_radians);
948 let a = f / aspect_ratio;
949 let b = (z_near + z_far) * inv_length;
950 let c = (2.0 * z_near * z_far) * inv_length;
951 Self::from_cols(
952 DVec4::new(a, 0.0, 0.0, 0.0),
953 DVec4::new(0.0, f, 0.0, 0.0),
954 DVec4::new(0.0, 0.0, b, -1.0),
955 DVec4::new(0.0, 0.0, c, 0.0),
956 )
957 }
958
959 #[inline]
968 #[must_use]
969 pub fn perspective_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
970 glam_assert!(z_near > 0.0 && z_far > 0.0);
971 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
972 let h = cos_fov / sin_fov;
973 let w = h / aspect_ratio;
974 let r = z_far / (z_far - z_near);
975 Self::from_cols(
976 DVec4::new(w, 0.0, 0.0, 0.0),
977 DVec4::new(0.0, h, 0.0, 0.0),
978 DVec4::new(0.0, 0.0, r, 1.0),
979 DVec4::new(0.0, 0.0, -r * z_near, 0.0),
980 )
981 }
982
983 #[inline]
992 #[must_use]
993 pub fn perspective_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
994 glam_assert!(z_near > 0.0 && z_far > 0.0);
995 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
996 let h = cos_fov / sin_fov;
997 let w = h / aspect_ratio;
998 let r = z_far / (z_near - z_far);
999 Self::from_cols(
1000 DVec4::new(w, 0.0, 0.0, 0.0),
1001 DVec4::new(0.0, h, 0.0, 0.0),
1002 DVec4::new(0.0, 0.0, r, -1.0),
1003 DVec4::new(0.0, 0.0, r * z_near, 0.0),
1004 )
1005 }
1006
1007 #[inline]
1017 #[must_use]
1018 pub fn perspective_infinite_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
1019 glam_assert!(z_near > 0.0);
1020 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1021 let h = cos_fov / sin_fov;
1022 let w = h / aspect_ratio;
1023 Self::from_cols(
1024 DVec4::new(w, 0.0, 0.0, 0.0),
1025 DVec4::new(0.0, h, 0.0, 0.0),
1026 DVec4::new(0.0, 0.0, 1.0, 1.0),
1027 DVec4::new(0.0, 0.0, -z_near, 0.0),
1028 )
1029 }
1030
1031 #[inline]
1039 #[must_use]
1040 pub fn perspective_infinite_reverse_lh(
1041 fov_y_radians: f64,
1042 aspect_ratio: f64,
1043 z_near: f64,
1044 ) -> Self {
1045 glam_assert!(z_near > 0.0);
1046 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1047 let h = cos_fov / sin_fov;
1048 let w = h / aspect_ratio;
1049 Self::from_cols(
1050 DVec4::new(w, 0.0, 0.0, 0.0),
1051 DVec4::new(0.0, h, 0.0, 0.0),
1052 DVec4::new(0.0, 0.0, 0.0, 1.0),
1053 DVec4::new(0.0, 0.0, z_near, 0.0),
1054 )
1055 }
1056
1057 #[inline]
1067 #[must_use]
1068 pub fn perspective_infinite_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
1069 glam_assert!(z_near > 0.0);
1070 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1071 Self::from_cols(
1072 DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1073 DVec4::new(0.0, f, 0.0, 0.0),
1074 DVec4::new(0.0, 0.0, -1.0, -1.0),
1075 DVec4::new(0.0, 0.0, -z_near, 0.0),
1076 )
1077 }
1078
1079 #[inline]
1087 #[must_use]
1088 pub fn perspective_infinite_reverse_rh(
1089 fov_y_radians: f64,
1090 aspect_ratio: f64,
1091 z_near: f64,
1092 ) -> Self {
1093 glam_assert!(z_near > 0.0);
1094 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1095 Self::from_cols(
1096 DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1097 DVec4::new(0.0, f, 0.0, 0.0),
1098 DVec4::new(0.0, 0.0, 0.0, -1.0),
1099 DVec4::new(0.0, 0.0, z_near, 0.0),
1100 )
1101 }
1102
1103 #[inline]
1110 #[must_use]
1111 pub fn orthographic_rh_gl(
1112 left: f64,
1113 right: f64,
1114 bottom: f64,
1115 top: f64,
1116 near: f64,
1117 far: f64,
1118 ) -> Self {
1119 let a = 2.0 / (right - left);
1120 let b = 2.0 / (top - bottom);
1121 let c = -2.0 / (far - near);
1122 let tx = -(right + left) / (right - left);
1123 let ty = -(top + bottom) / (top - bottom);
1124 let tz = -(far + near) / (far - near);
1125
1126 Self::from_cols(
1127 DVec4::new(a, 0.0, 0.0, 0.0),
1128 DVec4::new(0.0, b, 0.0, 0.0),
1129 DVec4::new(0.0, 0.0, c, 0.0),
1130 DVec4::new(tx, ty, tz, 1.0),
1131 )
1132 }
1133
1134 #[inline]
1138 #[must_use]
1139 pub fn orthographic_lh(
1140 left: f64,
1141 right: f64,
1142 bottom: f64,
1143 top: f64,
1144 near: f64,
1145 far: f64,
1146 ) -> Self {
1147 let rcp_width = 1.0 / (right - left);
1148 let rcp_height = 1.0 / (top - bottom);
1149 let r = 1.0 / (far - near);
1150 Self::from_cols(
1151 DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1152 DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1153 DVec4::new(0.0, 0.0, r, 0.0),
1154 DVec4::new(
1155 -(left + right) * rcp_width,
1156 -(top + bottom) * rcp_height,
1157 -r * near,
1158 1.0,
1159 ),
1160 )
1161 }
1162
1163 #[inline]
1167 #[must_use]
1168 pub fn orthographic_rh(
1169 left: f64,
1170 right: f64,
1171 bottom: f64,
1172 top: f64,
1173 near: f64,
1174 far: f64,
1175 ) -> Self {
1176 let rcp_width = 1.0 / (right - left);
1177 let rcp_height = 1.0 / (top - bottom);
1178 let r = 1.0 / (near - far);
1179 Self::from_cols(
1180 DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1181 DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1182 DVec4::new(0.0, 0.0, r, 0.0),
1183 DVec4::new(
1184 -(left + right) * rcp_width,
1185 -(top + bottom) * rcp_height,
1186 r * near,
1187 1.0,
1188 ),
1189 )
1190 }
1191
1192 #[inline]
1199 #[must_use]
1200 pub fn project_point3(&self, rhs: DVec3) -> DVec3 {
1201 let mut res = self.x_axis.mul(rhs.x);
1202 res = self.y_axis.mul(rhs.y).add(res);
1203 res = self.z_axis.mul(rhs.z).add(res);
1204 res = self.w_axis.add(res);
1205 res = res.div(res.w);
1206 res.xyz()
1207 }
1208
1209 #[inline]
1222 #[must_use]
1223 pub fn transform_point3(&self, rhs: DVec3) -> DVec3 {
1224 glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
1225 let mut res = self.x_axis.mul(rhs.x);
1226 res = self.y_axis.mul(rhs.y).add(res);
1227 res = self.z_axis.mul(rhs.z).add(res);
1228 res = self.w_axis.add(res);
1229 res.xyz()
1230 }
1231
1232 #[inline]
1243 #[must_use]
1244 pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 {
1245 glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
1246 let mut res = self.x_axis.mul(rhs.x);
1247 res = self.y_axis.mul(rhs.y).add(res);
1248 res = self.z_axis.mul(rhs.z).add(res);
1249 res.xyz()
1250 }
1251
1252 #[inline]
1254 #[must_use]
1255 pub fn mul_vec4(&self, rhs: DVec4) -> DVec4 {
1256 let mut res = self.x_axis.mul(rhs.x);
1257 res = res.add(self.y_axis.mul(rhs.y));
1258 res = res.add(self.z_axis.mul(rhs.z));
1259 res = res.add(self.w_axis.mul(rhs.w));
1260 res
1261 }
1262
1263 #[inline]
1265 #[must_use]
1266 pub fn mul_transpose_vec4(&self, rhs: DVec4) -> DVec4 {
1267 DVec4::new(
1268 self.x_axis.dot(rhs),
1269 self.y_axis.dot(rhs),
1270 self.z_axis.dot(rhs),
1271 self.w_axis.dot(rhs),
1272 )
1273 }
1274
1275 #[inline]
1277 #[must_use]
1278 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1279 self.mul(rhs)
1280 }
1281
1282 #[inline]
1284 #[must_use]
1285 pub fn add_mat4(&self, rhs: &Self) -> Self {
1286 self.add(rhs)
1287 }
1288
1289 #[inline]
1291 #[must_use]
1292 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1293 self.sub(rhs)
1294 }
1295
1296 #[inline]
1298 #[must_use]
1299 pub fn mul_scalar(&self, rhs: f64) -> Self {
1300 Self::from_cols(
1301 self.x_axis.mul(rhs),
1302 self.y_axis.mul(rhs),
1303 self.z_axis.mul(rhs),
1304 self.w_axis.mul(rhs),
1305 )
1306 }
1307
1308 #[inline]
1312 #[must_use]
1313 pub fn mul_diagonal_scale(&self, scale: DVec4) -> Self {
1314 Self::from_cols(
1315 self.x_axis * scale.x,
1316 self.y_axis * scale.y,
1317 self.z_axis * scale.z,
1318 self.w_axis * scale.w,
1319 )
1320 }
1321
1322 #[inline]
1324 #[must_use]
1325 pub fn div_scalar(&self, rhs: f64) -> Self {
1326 let rhs = DVec4::splat(rhs);
1327 Self::from_cols(
1328 self.x_axis.div(rhs),
1329 self.y_axis.div(rhs),
1330 self.z_axis.div(rhs),
1331 self.w_axis.div(rhs),
1332 )
1333 }
1334
1335 #[inline]
1345 #[must_use]
1346 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
1347 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1348 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1349 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1350 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1351 }
1352
1353 #[inline]
1355 #[must_use]
1356 pub fn abs(&self) -> Self {
1357 Self::from_cols(
1358 self.x_axis.abs(),
1359 self.y_axis.abs(),
1360 self.z_axis.abs(),
1361 self.w_axis.abs(),
1362 )
1363 }
1364
1365 #[inline]
1366 pub fn as_mat4(&self) -> Mat4 {
1367 Mat4::from_cols(
1368 self.x_axis.as_vec4(),
1369 self.y_axis.as_vec4(),
1370 self.z_axis.as_vec4(),
1371 self.w_axis.as_vec4(),
1372 )
1373 }
1374}
1375
1376impl Default for DMat4 {
1377 #[inline]
1378 fn default() -> Self {
1379 Self::IDENTITY
1380 }
1381}
1382
1383impl Add for DMat4 {
1384 type Output = Self;
1385 #[inline]
1386 fn add(self, rhs: Self) -> Self {
1387 Self::from_cols(
1388 self.x_axis.add(rhs.x_axis),
1389 self.y_axis.add(rhs.y_axis),
1390 self.z_axis.add(rhs.z_axis),
1391 self.w_axis.add(rhs.w_axis),
1392 )
1393 }
1394}
1395
1396impl Add<&Self> for DMat4 {
1397 type Output = Self;
1398 #[inline]
1399 fn add(self, rhs: &Self) -> Self {
1400 self.add(*rhs)
1401 }
1402}
1403
1404impl Add<&DMat4> for &DMat4 {
1405 type Output = DMat4;
1406 #[inline]
1407 fn add(self, rhs: &DMat4) -> DMat4 {
1408 (*self).add(*rhs)
1409 }
1410}
1411
1412impl Add<DMat4> for &DMat4 {
1413 type Output = DMat4;
1414 #[inline]
1415 fn add(self, rhs: DMat4) -> DMat4 {
1416 (*self).add(rhs)
1417 }
1418}
1419
1420impl AddAssign for DMat4 {
1421 #[inline]
1422 fn add_assign(&mut self, rhs: Self) {
1423 *self = self.add(rhs);
1424 }
1425}
1426
1427impl AddAssign<&Self> for DMat4 {
1428 #[inline]
1429 fn add_assign(&mut self, rhs: &Self) {
1430 self.add_assign(*rhs);
1431 }
1432}
1433
1434impl Sub for DMat4 {
1435 type Output = Self;
1436 #[inline]
1437 fn sub(self, rhs: Self) -> Self {
1438 Self::from_cols(
1439 self.x_axis.sub(rhs.x_axis),
1440 self.y_axis.sub(rhs.y_axis),
1441 self.z_axis.sub(rhs.z_axis),
1442 self.w_axis.sub(rhs.w_axis),
1443 )
1444 }
1445}
1446
1447impl Sub<&Self> for DMat4 {
1448 type Output = Self;
1449 #[inline]
1450 fn sub(self, rhs: &Self) -> Self {
1451 self.sub(*rhs)
1452 }
1453}
1454
1455impl Sub<&DMat4> for &DMat4 {
1456 type Output = DMat4;
1457 #[inline]
1458 fn sub(self, rhs: &DMat4) -> DMat4 {
1459 (*self).sub(*rhs)
1460 }
1461}
1462
1463impl Sub<DMat4> for &DMat4 {
1464 type Output = DMat4;
1465 #[inline]
1466 fn sub(self, rhs: DMat4) -> DMat4 {
1467 (*self).sub(rhs)
1468 }
1469}
1470
1471impl SubAssign for DMat4 {
1472 #[inline]
1473 fn sub_assign(&mut self, rhs: Self) {
1474 *self = self.sub(rhs);
1475 }
1476}
1477
1478impl SubAssign<&Self> for DMat4 {
1479 #[inline]
1480 fn sub_assign(&mut self, rhs: &Self) {
1481 self.sub_assign(*rhs);
1482 }
1483}
1484
1485impl Neg for DMat4 {
1486 type Output = Self;
1487 #[inline]
1488 fn neg(self) -> Self::Output {
1489 Self::from_cols(
1490 self.x_axis.neg(),
1491 self.y_axis.neg(),
1492 self.z_axis.neg(),
1493 self.w_axis.neg(),
1494 )
1495 }
1496}
1497
1498impl Neg for &DMat4 {
1499 type Output = DMat4;
1500 #[inline]
1501 fn neg(self) -> DMat4 {
1502 (*self).neg()
1503 }
1504}
1505
1506impl Mul for DMat4 {
1507 type Output = Self;
1508 #[inline]
1509 fn mul(self, rhs: Self) -> Self {
1510 Self::from_cols(
1511 self.mul(rhs.x_axis),
1512 self.mul(rhs.y_axis),
1513 self.mul(rhs.z_axis),
1514 self.mul(rhs.w_axis),
1515 )
1516 }
1517}
1518
1519impl Mul<&Self> for DMat4 {
1520 type Output = Self;
1521 #[inline]
1522 fn mul(self, rhs: &Self) -> Self {
1523 self.mul(*rhs)
1524 }
1525}
1526
1527impl Mul<&DMat4> for &DMat4 {
1528 type Output = DMat4;
1529 #[inline]
1530 fn mul(self, rhs: &DMat4) -> DMat4 {
1531 (*self).mul(*rhs)
1532 }
1533}
1534
1535impl Mul<DMat4> for &DMat4 {
1536 type Output = DMat4;
1537 #[inline]
1538 fn mul(self, rhs: DMat4) -> DMat4 {
1539 (*self).mul(rhs)
1540 }
1541}
1542
1543impl MulAssign for DMat4 {
1544 #[inline]
1545 fn mul_assign(&mut self, rhs: Self) {
1546 *self = self.mul(rhs);
1547 }
1548}
1549
1550impl MulAssign<&Self> for DMat4 {
1551 #[inline]
1552 fn mul_assign(&mut self, rhs: &Self) {
1553 self.mul_assign(*rhs);
1554 }
1555}
1556
1557impl Mul<DVec4> for DMat4 {
1558 type Output = DVec4;
1559 #[inline]
1560 fn mul(self, rhs: DVec4) -> Self::Output {
1561 self.mul_vec4(rhs)
1562 }
1563}
1564
1565impl Mul<&DVec4> for DMat4 {
1566 type Output = DVec4;
1567 #[inline]
1568 fn mul(self, rhs: &DVec4) -> DVec4 {
1569 self.mul(*rhs)
1570 }
1571}
1572
1573impl Mul<&DVec4> for &DMat4 {
1574 type Output = DVec4;
1575 #[inline]
1576 fn mul(self, rhs: &DVec4) -> DVec4 {
1577 (*self).mul(*rhs)
1578 }
1579}
1580
1581impl Mul<DVec4> for &DMat4 {
1582 type Output = DVec4;
1583 #[inline]
1584 fn mul(self, rhs: DVec4) -> DVec4 {
1585 (*self).mul(rhs)
1586 }
1587}
1588
1589impl Mul<DMat4> for f64 {
1590 type Output = DMat4;
1591 #[inline]
1592 fn mul(self, rhs: DMat4) -> Self::Output {
1593 rhs.mul_scalar(self)
1594 }
1595}
1596
1597impl Mul<&DMat4> for f64 {
1598 type Output = DMat4;
1599 #[inline]
1600 fn mul(self, rhs: &DMat4) -> DMat4 {
1601 self.mul(*rhs)
1602 }
1603}
1604
1605impl Mul<&DMat4> for &f64 {
1606 type Output = DMat4;
1607 #[inline]
1608 fn mul(self, rhs: &DMat4) -> DMat4 {
1609 (*self).mul(*rhs)
1610 }
1611}
1612
1613impl Mul<DMat4> for &f64 {
1614 type Output = DMat4;
1615 #[inline]
1616 fn mul(self, rhs: DMat4) -> DMat4 {
1617 (*self).mul(rhs)
1618 }
1619}
1620
1621impl Mul<f64> for DMat4 {
1622 type Output = Self;
1623 #[inline]
1624 fn mul(self, rhs: f64) -> Self {
1625 self.mul_scalar(rhs)
1626 }
1627}
1628
1629impl Mul<&f64> for DMat4 {
1630 type Output = Self;
1631 #[inline]
1632 fn mul(self, rhs: &f64) -> Self {
1633 self.mul(*rhs)
1634 }
1635}
1636
1637impl Mul<&f64> for &DMat4 {
1638 type Output = DMat4;
1639 #[inline]
1640 fn mul(self, rhs: &f64) -> DMat4 {
1641 (*self).mul(*rhs)
1642 }
1643}
1644
1645impl Mul<f64> for &DMat4 {
1646 type Output = DMat4;
1647 #[inline]
1648 fn mul(self, rhs: f64) -> DMat4 {
1649 (*self).mul(rhs)
1650 }
1651}
1652
1653impl MulAssign<f64> for DMat4 {
1654 #[inline]
1655 fn mul_assign(&mut self, rhs: f64) {
1656 *self = self.mul(rhs);
1657 }
1658}
1659
1660impl MulAssign<&f64> for DMat4 {
1661 #[inline]
1662 fn mul_assign(&mut self, rhs: &f64) {
1663 self.mul_assign(*rhs);
1664 }
1665}
1666
1667impl Div<DMat4> for f64 {
1668 type Output = DMat4;
1669 #[inline]
1670 fn div(self, rhs: DMat4) -> Self::Output {
1671 rhs.div_scalar(self)
1672 }
1673}
1674
1675impl Div<&DMat4> for f64 {
1676 type Output = DMat4;
1677 #[inline]
1678 fn div(self, rhs: &DMat4) -> DMat4 {
1679 self.div(*rhs)
1680 }
1681}
1682
1683impl Div<&DMat4> for &f64 {
1684 type Output = DMat4;
1685 #[inline]
1686 fn div(self, rhs: &DMat4) -> DMat4 {
1687 (*self).div(*rhs)
1688 }
1689}
1690
1691impl Div<DMat4> for &f64 {
1692 type Output = DMat4;
1693 #[inline]
1694 fn div(self, rhs: DMat4) -> DMat4 {
1695 (*self).div(rhs)
1696 }
1697}
1698
1699impl Div<f64> for DMat4 {
1700 type Output = Self;
1701 #[inline]
1702 fn div(self, rhs: f64) -> Self {
1703 self.div_scalar(rhs)
1704 }
1705}
1706
1707impl Div<&f64> for DMat4 {
1708 type Output = Self;
1709 #[inline]
1710 fn div(self, rhs: &f64) -> Self {
1711 self.div(*rhs)
1712 }
1713}
1714
1715impl Div<&f64> for &DMat4 {
1716 type Output = DMat4;
1717 #[inline]
1718 fn div(self, rhs: &f64) -> DMat4 {
1719 (*self).div(*rhs)
1720 }
1721}
1722
1723impl Div<f64> for &DMat4 {
1724 type Output = DMat4;
1725 #[inline]
1726 fn div(self, rhs: f64) -> DMat4 {
1727 (*self).div(rhs)
1728 }
1729}
1730
1731impl DivAssign<f64> for DMat4 {
1732 #[inline]
1733 fn div_assign(&mut self, rhs: f64) {
1734 *self = self.div(rhs);
1735 }
1736}
1737
1738impl DivAssign<&f64> for DMat4 {
1739 #[inline]
1740 fn div_assign(&mut self, rhs: &f64) {
1741 self.div_assign(*rhs);
1742 }
1743}
1744
1745impl Sum<Self> for DMat4 {
1746 fn sum<I>(iter: I) -> Self
1747 where
1748 I: Iterator<Item = Self>,
1749 {
1750 iter.fold(Self::ZERO, Self::add)
1751 }
1752}
1753
1754impl<'a> Sum<&'a Self> for DMat4 {
1755 fn sum<I>(iter: I) -> Self
1756 where
1757 I: Iterator<Item = &'a Self>,
1758 {
1759 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1760 }
1761}
1762
1763impl Product for DMat4 {
1764 fn product<I>(iter: I) -> Self
1765 where
1766 I: Iterator<Item = Self>,
1767 {
1768 iter.fold(Self::IDENTITY, Self::mul)
1769 }
1770}
1771
1772impl<'a> Product<&'a Self> for DMat4 {
1773 fn product<I>(iter: I) -> Self
1774 where
1775 I: Iterator<Item = &'a Self>,
1776 {
1777 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1778 }
1779}
1780
1781impl PartialEq for DMat4 {
1782 #[inline]
1783 fn eq(&self, rhs: &Self) -> bool {
1784 self.x_axis.eq(&rhs.x_axis)
1785 && self.y_axis.eq(&rhs.y_axis)
1786 && self.z_axis.eq(&rhs.z_axis)
1787 && self.w_axis.eq(&rhs.w_axis)
1788 }
1789}
1790
1791impl AsRef<[f64; 16]> for DMat4 {
1792 #[inline]
1793 fn as_ref(&self) -> &[f64; 16] {
1794 unsafe { &*(self as *const Self as *const [f64; 16]) }
1795 }
1796}
1797
1798impl AsMut<[f64; 16]> for DMat4 {
1799 #[inline]
1800 fn as_mut(&mut self) -> &mut [f64; 16] {
1801 unsafe { &mut *(self as *mut Self as *mut [f64; 16]) }
1802 }
1803}
1804
1805impl fmt::Debug for DMat4 {
1806 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1807 fmt.debug_struct(stringify!(DMat4))
1808 .field("x_axis", &self.x_axis)
1809 .field("y_axis", &self.y_axis)
1810 .field("z_axis", &self.z_axis)
1811 .field("w_axis", &self.w_axis)
1812 .finish()
1813 }
1814}
1815
1816impl fmt::Display for DMat4 {
1817 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1818 if let Some(p) = f.precision() {
1819 write!(
1820 f,
1821 "[{:.*}, {:.*}, {:.*}, {:.*}]",
1822 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
1823 )
1824 } else {
1825 write!(
1826 f,
1827 "[{}, {}, {}, {}]",
1828 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1829 )
1830 }
1831 }
1832}