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 #[must_use]
622 pub fn determinant(&self) -> f64 {
623 let (m00, m01, m02, m03) = self.x_axis.into();
624 let (m10, m11, m12, m13) = self.y_axis.into();
625 let (m20, m21, m22, m23) = self.z_axis.into();
626 let (m30, m31, m32, m33) = self.w_axis.into();
627
628 let a2323 = m22 * m33 - m23 * m32;
629 let a1323 = m21 * m33 - m23 * m31;
630 let a1223 = m21 * m32 - m22 * m31;
631 let a0323 = m20 * m33 - m23 * m30;
632 let a0223 = m20 * m32 - m22 * m30;
633 let a0123 = m20 * m31 - m21 * m30;
634
635 m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223)
636 - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223)
637 + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123)
638 - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123)
639 }
640
641 #[must_use]
649 pub fn inverse(&self) -> Self {
650 let (m00, m01, m02, m03) = self.x_axis.into();
651 let (m10, m11, m12, m13) = self.y_axis.into();
652 let (m20, m21, m22, m23) = self.z_axis.into();
653 let (m30, m31, m32, m33) = self.w_axis.into();
654
655 let coef00 = m22 * m33 - m32 * m23;
656 let coef02 = m12 * m33 - m32 * m13;
657 let coef03 = m12 * m23 - m22 * m13;
658
659 let coef04 = m21 * m33 - m31 * m23;
660 let coef06 = m11 * m33 - m31 * m13;
661 let coef07 = m11 * m23 - m21 * m13;
662
663 let coef08 = m21 * m32 - m31 * m22;
664 let coef10 = m11 * m32 - m31 * m12;
665 let coef11 = m11 * m22 - m21 * m12;
666
667 let coef12 = m20 * m33 - m30 * m23;
668 let coef14 = m10 * m33 - m30 * m13;
669 let coef15 = m10 * m23 - m20 * m13;
670
671 let coef16 = m20 * m32 - m30 * m22;
672 let coef18 = m10 * m32 - m30 * m12;
673 let coef19 = m10 * m22 - m20 * m12;
674
675 let coef20 = m20 * m31 - m30 * m21;
676 let coef22 = m10 * m31 - m30 * m11;
677 let coef23 = m10 * m21 - m20 * m11;
678
679 let fac0 = DVec4::new(coef00, coef00, coef02, coef03);
680 let fac1 = DVec4::new(coef04, coef04, coef06, coef07);
681 let fac2 = DVec4::new(coef08, coef08, coef10, coef11);
682 let fac3 = DVec4::new(coef12, coef12, coef14, coef15);
683 let fac4 = DVec4::new(coef16, coef16, coef18, coef19);
684 let fac5 = DVec4::new(coef20, coef20, coef22, coef23);
685
686 let vec0 = DVec4::new(m10, m00, m00, m00);
687 let vec1 = DVec4::new(m11, m01, m01, m01);
688 let vec2 = DVec4::new(m12, m02, m02, m02);
689 let vec3 = DVec4::new(m13, m03, m03, m03);
690
691 let inv0 = vec1.mul(fac0).sub(vec2.mul(fac1)).add(vec3.mul(fac2));
692 let inv1 = vec0.mul(fac0).sub(vec2.mul(fac3)).add(vec3.mul(fac4));
693 let inv2 = vec0.mul(fac1).sub(vec1.mul(fac3)).add(vec3.mul(fac5));
694 let inv3 = vec0.mul(fac2).sub(vec1.mul(fac4)).add(vec2.mul(fac5));
695
696 let sign_a = DVec4::new(1.0, -1.0, 1.0, -1.0);
697 let sign_b = DVec4::new(-1.0, 1.0, -1.0, 1.0);
698
699 let inverse = Self::from_cols(
700 inv0.mul(sign_a),
701 inv1.mul(sign_b),
702 inv2.mul(sign_a),
703 inv3.mul(sign_b),
704 );
705
706 let col0 = DVec4::new(
707 inverse.x_axis.x,
708 inverse.y_axis.x,
709 inverse.z_axis.x,
710 inverse.w_axis.x,
711 );
712
713 let dot0 = self.x_axis.mul(col0);
714 let dot1 = dot0.x + dot0.y + dot0.z + dot0.w;
715
716 glam_assert!(dot1 != 0.0);
717
718 let rcp_det = dot1.recip();
719 inverse.mul(rcp_det)
720 }
721
722 #[inline]
731 #[must_use]
732 pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
733 Self::look_to_rh(eye, -dir, up)
734 }
735
736 #[inline]
745 #[must_use]
746 pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
747 glam_assert!(dir.is_normalized());
748 glam_assert!(up.is_normalized());
749 let f = dir;
750 let s = f.cross(up).normalize();
751 let u = s.cross(f);
752
753 Self::from_cols(
754 DVec4::new(s.x, u.x, -f.x, 0.0),
755 DVec4::new(s.y, u.y, -f.y, 0.0),
756 DVec4::new(s.z, u.z, -f.z, 0.0),
757 DVec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
758 )
759 }
760
761 #[inline]
770 #[must_use]
771 pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
772 Self::look_to_lh(eye, center.sub(eye).normalize(), up)
773 }
774
775 #[inline]
784 pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
785 Self::look_to_rh(eye, center.sub(eye).normalize(), up)
786 }
787
788 #[inline]
794 #[must_use]
795 pub fn frustum_rh_gl(
796 left: f64,
797 right: f64,
798 bottom: f64,
799 top: f64,
800 z_near: f64,
801 z_far: f64,
802 ) -> Self {
803 let inv_width = 1.0 / (right - left);
804 let inv_height = 1.0 / (top - bottom);
805 let inv_depth = 1.0 / (z_far - z_near);
806 let a = (right + left) * inv_width;
807 let b = (top + bottom) * inv_height;
808 let c = -(z_far + z_near) * inv_depth;
809 let d = -(2.0 * z_far * z_near) * inv_depth;
810 let two_z_near = 2.0 * z_near;
811 Self::from_cols(
812 DVec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
813 DVec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
814 DVec4::new(a, b, c, -1.0),
815 DVec4::new(0.0, 0.0, d, 0.0),
816 )
817 }
818
819 #[inline]
826 #[must_use]
827 pub fn frustum_lh(
828 left: f64,
829 right: f64,
830 bottom: f64,
831 top: f64,
832 z_near: f64,
833 z_far: f64,
834 ) -> Self {
835 glam_assert!(z_near > 0.0 && z_far > 0.0);
836 let inv_width = 1.0 / (right - left);
837 let inv_height = 1.0 / (top - bottom);
838 let inv_depth = 1.0 / (z_far - z_near);
839 let a = (right + left) * inv_width;
840 let b = (top + bottom) * inv_height;
841 let c = z_far * inv_depth;
842 let d = -(z_far * z_near) * inv_depth;
843 let two_z_near = 2.0 * z_near;
844 Self::from_cols(
845 DVec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
846 DVec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
847 DVec4::new(a, b, c, 1.0),
848 DVec4::new(0.0, 0.0, d, 0.0),
849 )
850 }
851
852 #[inline]
859 #[must_use]
860 pub fn frustum_rh(
861 left: f64,
862 right: f64,
863 bottom: f64,
864 top: f64,
865 z_near: f64,
866 z_far: f64,
867 ) -> Self {
868 glam_assert!(z_near > 0.0 && z_far > 0.0);
869 let inv_width = 1.0 / (right - left);
870 let inv_height = 1.0 / (top - bottom);
871 let inv_depth = 1.0 / (z_far - z_near);
872 let a = (right + left) * inv_width;
873 let b = (top + bottom) * inv_height;
874 let c = -z_far * inv_depth;
875 let d = -(z_far * z_near) * inv_depth;
876 let two_z_near = 2.0 * z_near;
877 Self::from_cols(
878 DVec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
879 DVec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
880 DVec4::new(a, b, c, -1.0),
881 DVec4::new(0.0, 0.0, d, 0.0),
882 )
883 }
884
885 #[inline]
892 #[must_use]
893 pub fn perspective_rh_gl(
894 fov_y_radians: f64,
895 aspect_ratio: f64,
896 z_near: f64,
897 z_far: f64,
898 ) -> Self {
899 let inv_length = 1.0 / (z_near - z_far);
900 let f = 1.0 / math::tan(0.5 * fov_y_radians);
901 let a = f / aspect_ratio;
902 let b = (z_near + z_far) * inv_length;
903 let c = (2.0 * z_near * z_far) * inv_length;
904 Self::from_cols(
905 DVec4::new(a, 0.0, 0.0, 0.0),
906 DVec4::new(0.0, f, 0.0, 0.0),
907 DVec4::new(0.0, 0.0, b, -1.0),
908 DVec4::new(0.0, 0.0, c, 0.0),
909 )
910 }
911
912 #[inline]
921 #[must_use]
922 pub fn perspective_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
923 glam_assert!(z_near > 0.0 && z_far > 0.0);
924 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
925 let h = cos_fov / sin_fov;
926 let w = h / aspect_ratio;
927 let r = z_far / (z_far - z_near);
928 Self::from_cols(
929 DVec4::new(w, 0.0, 0.0, 0.0),
930 DVec4::new(0.0, h, 0.0, 0.0),
931 DVec4::new(0.0, 0.0, r, 1.0),
932 DVec4::new(0.0, 0.0, -r * z_near, 0.0),
933 )
934 }
935
936 #[inline]
945 #[must_use]
946 pub fn perspective_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
947 glam_assert!(z_near > 0.0 && z_far > 0.0);
948 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
949 let h = cos_fov / sin_fov;
950 let w = h / aspect_ratio;
951 let r = z_far / (z_near - z_far);
952 Self::from_cols(
953 DVec4::new(w, 0.0, 0.0, 0.0),
954 DVec4::new(0.0, h, 0.0, 0.0),
955 DVec4::new(0.0, 0.0, r, -1.0),
956 DVec4::new(0.0, 0.0, r * z_near, 0.0),
957 )
958 }
959
960 #[inline]
970 #[must_use]
971 pub fn perspective_infinite_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
972 glam_assert!(z_near > 0.0);
973 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
974 let h = cos_fov / sin_fov;
975 let w = h / aspect_ratio;
976 Self::from_cols(
977 DVec4::new(w, 0.0, 0.0, 0.0),
978 DVec4::new(0.0, h, 0.0, 0.0),
979 DVec4::new(0.0, 0.0, 1.0, 1.0),
980 DVec4::new(0.0, 0.0, -z_near, 0.0),
981 )
982 }
983
984 #[inline]
992 #[must_use]
993 pub fn perspective_infinite_reverse_lh(
994 fov_y_radians: f64,
995 aspect_ratio: f64,
996 z_near: f64,
997 ) -> Self {
998 glam_assert!(z_near > 0.0);
999 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1000 let h = cos_fov / sin_fov;
1001 let w = h / aspect_ratio;
1002 Self::from_cols(
1003 DVec4::new(w, 0.0, 0.0, 0.0),
1004 DVec4::new(0.0, h, 0.0, 0.0),
1005 DVec4::new(0.0, 0.0, 0.0, 1.0),
1006 DVec4::new(0.0, 0.0, z_near, 0.0),
1007 )
1008 }
1009
1010 #[inline]
1020 #[must_use]
1021 pub fn perspective_infinite_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
1022 glam_assert!(z_near > 0.0);
1023 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1024 Self::from_cols(
1025 DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1026 DVec4::new(0.0, f, 0.0, 0.0),
1027 DVec4::new(0.0, 0.0, -1.0, -1.0),
1028 DVec4::new(0.0, 0.0, -z_near, 0.0),
1029 )
1030 }
1031
1032 #[inline]
1040 #[must_use]
1041 pub fn perspective_infinite_reverse_rh(
1042 fov_y_radians: f64,
1043 aspect_ratio: f64,
1044 z_near: f64,
1045 ) -> Self {
1046 glam_assert!(z_near > 0.0);
1047 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1048 Self::from_cols(
1049 DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1050 DVec4::new(0.0, f, 0.0, 0.0),
1051 DVec4::new(0.0, 0.0, 0.0, -1.0),
1052 DVec4::new(0.0, 0.0, z_near, 0.0),
1053 )
1054 }
1055
1056 #[inline]
1063 #[must_use]
1064 pub fn orthographic_rh_gl(
1065 left: f64,
1066 right: f64,
1067 bottom: f64,
1068 top: f64,
1069 near: f64,
1070 far: f64,
1071 ) -> Self {
1072 let a = 2.0 / (right - left);
1073 let b = 2.0 / (top - bottom);
1074 let c = -2.0 / (far - near);
1075 let tx = -(right + left) / (right - left);
1076 let ty = -(top + bottom) / (top - bottom);
1077 let tz = -(far + near) / (far - near);
1078
1079 Self::from_cols(
1080 DVec4::new(a, 0.0, 0.0, 0.0),
1081 DVec4::new(0.0, b, 0.0, 0.0),
1082 DVec4::new(0.0, 0.0, c, 0.0),
1083 DVec4::new(tx, ty, tz, 1.0),
1084 )
1085 }
1086
1087 #[inline]
1091 #[must_use]
1092 pub fn orthographic_lh(
1093 left: f64,
1094 right: f64,
1095 bottom: f64,
1096 top: f64,
1097 near: f64,
1098 far: f64,
1099 ) -> Self {
1100 let rcp_width = 1.0 / (right - left);
1101 let rcp_height = 1.0 / (top - bottom);
1102 let r = 1.0 / (far - near);
1103 Self::from_cols(
1104 DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1105 DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1106 DVec4::new(0.0, 0.0, r, 0.0),
1107 DVec4::new(
1108 -(left + right) * rcp_width,
1109 -(top + bottom) * rcp_height,
1110 -r * near,
1111 1.0,
1112 ),
1113 )
1114 }
1115
1116 #[inline]
1120 #[must_use]
1121 pub fn orthographic_rh(
1122 left: f64,
1123 right: f64,
1124 bottom: f64,
1125 top: f64,
1126 near: f64,
1127 far: f64,
1128 ) -> Self {
1129 let rcp_width = 1.0 / (right - left);
1130 let rcp_height = 1.0 / (top - bottom);
1131 let r = 1.0 / (near - far);
1132 Self::from_cols(
1133 DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1134 DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1135 DVec4::new(0.0, 0.0, r, 0.0),
1136 DVec4::new(
1137 -(left + right) * rcp_width,
1138 -(top + bottom) * rcp_height,
1139 r * near,
1140 1.0,
1141 ),
1142 )
1143 }
1144
1145 #[inline]
1152 #[must_use]
1153 pub fn project_point3(&self, rhs: DVec3) -> DVec3 {
1154 let mut res = self.x_axis.mul(rhs.x);
1155 res = self.y_axis.mul(rhs.y).add(res);
1156 res = self.z_axis.mul(rhs.z).add(res);
1157 res = self.w_axis.add(res);
1158 res = res.div(res.w);
1159 res.xyz()
1160 }
1161
1162 #[inline]
1175 #[must_use]
1176 pub fn transform_point3(&self, rhs: DVec3) -> DVec3 {
1177 glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
1178 let mut res = self.x_axis.mul(rhs.x);
1179 res = self.y_axis.mul(rhs.y).add(res);
1180 res = self.z_axis.mul(rhs.z).add(res);
1181 res = self.w_axis.add(res);
1182 res.xyz()
1183 }
1184
1185 #[inline]
1196 #[must_use]
1197 pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 {
1198 glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
1199 let mut res = self.x_axis.mul(rhs.x);
1200 res = self.y_axis.mul(rhs.y).add(res);
1201 res = self.z_axis.mul(rhs.z).add(res);
1202 res.xyz()
1203 }
1204
1205 #[inline]
1207 #[must_use]
1208 pub fn mul_vec4(&self, rhs: DVec4) -> DVec4 {
1209 let mut res = self.x_axis.mul(rhs.x);
1210 res = res.add(self.y_axis.mul(rhs.y));
1211 res = res.add(self.z_axis.mul(rhs.z));
1212 res = res.add(self.w_axis.mul(rhs.w));
1213 res
1214 }
1215
1216 #[inline]
1218 #[must_use]
1219 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1220 self.mul(rhs)
1221 }
1222
1223 #[inline]
1225 #[must_use]
1226 pub fn add_mat4(&self, rhs: &Self) -> Self {
1227 self.add(rhs)
1228 }
1229
1230 #[inline]
1232 #[must_use]
1233 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1234 self.sub(rhs)
1235 }
1236
1237 #[inline]
1239 #[must_use]
1240 pub fn mul_scalar(&self, rhs: f64) -> Self {
1241 Self::from_cols(
1242 self.x_axis.mul(rhs),
1243 self.y_axis.mul(rhs),
1244 self.z_axis.mul(rhs),
1245 self.w_axis.mul(rhs),
1246 )
1247 }
1248
1249 #[inline]
1251 #[must_use]
1252 pub fn div_scalar(&self, rhs: f64) -> Self {
1253 let rhs = DVec4::splat(rhs);
1254 Self::from_cols(
1255 self.x_axis.div(rhs),
1256 self.y_axis.div(rhs),
1257 self.z_axis.div(rhs),
1258 self.w_axis.div(rhs),
1259 )
1260 }
1261
1262 #[inline]
1272 #[must_use]
1273 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
1274 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1275 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1276 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1277 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1278 }
1279
1280 #[inline]
1282 #[must_use]
1283 pub fn abs(&self) -> Self {
1284 Self::from_cols(
1285 self.x_axis.abs(),
1286 self.y_axis.abs(),
1287 self.z_axis.abs(),
1288 self.w_axis.abs(),
1289 )
1290 }
1291
1292 #[inline]
1293 pub fn as_mat4(&self) -> Mat4 {
1294 Mat4::from_cols(
1295 self.x_axis.as_vec4(),
1296 self.y_axis.as_vec4(),
1297 self.z_axis.as_vec4(),
1298 self.w_axis.as_vec4(),
1299 )
1300 }
1301}
1302
1303impl Default for DMat4 {
1304 #[inline]
1305 fn default() -> Self {
1306 Self::IDENTITY
1307 }
1308}
1309
1310impl Add for DMat4 {
1311 type Output = Self;
1312 #[inline]
1313 fn add(self, rhs: Self) -> Self {
1314 Self::from_cols(
1315 self.x_axis.add(rhs.x_axis),
1316 self.y_axis.add(rhs.y_axis),
1317 self.z_axis.add(rhs.z_axis),
1318 self.w_axis.add(rhs.w_axis),
1319 )
1320 }
1321}
1322
1323impl Add<&Self> for DMat4 {
1324 type Output = Self;
1325 #[inline]
1326 fn add(self, rhs: &Self) -> Self {
1327 self.add(*rhs)
1328 }
1329}
1330
1331impl Add<&DMat4> for &DMat4 {
1332 type Output = DMat4;
1333 #[inline]
1334 fn add(self, rhs: &DMat4) -> DMat4 {
1335 (*self).add(*rhs)
1336 }
1337}
1338
1339impl Add<DMat4> for &DMat4 {
1340 type Output = DMat4;
1341 #[inline]
1342 fn add(self, rhs: DMat4) -> DMat4 {
1343 (*self).add(rhs)
1344 }
1345}
1346
1347impl AddAssign for DMat4 {
1348 #[inline]
1349 fn add_assign(&mut self, rhs: Self) {
1350 *self = self.add(rhs);
1351 }
1352}
1353
1354impl AddAssign<&Self> for DMat4 {
1355 #[inline]
1356 fn add_assign(&mut self, rhs: &Self) {
1357 self.add_assign(*rhs);
1358 }
1359}
1360
1361impl Sub for DMat4 {
1362 type Output = Self;
1363 #[inline]
1364 fn sub(self, rhs: Self) -> Self {
1365 Self::from_cols(
1366 self.x_axis.sub(rhs.x_axis),
1367 self.y_axis.sub(rhs.y_axis),
1368 self.z_axis.sub(rhs.z_axis),
1369 self.w_axis.sub(rhs.w_axis),
1370 )
1371 }
1372}
1373
1374impl Sub<&Self> for DMat4 {
1375 type Output = Self;
1376 #[inline]
1377 fn sub(self, rhs: &Self) -> Self {
1378 self.sub(*rhs)
1379 }
1380}
1381
1382impl Sub<&DMat4> for &DMat4 {
1383 type Output = DMat4;
1384 #[inline]
1385 fn sub(self, rhs: &DMat4) -> DMat4 {
1386 (*self).sub(*rhs)
1387 }
1388}
1389
1390impl Sub<DMat4> for &DMat4 {
1391 type Output = DMat4;
1392 #[inline]
1393 fn sub(self, rhs: DMat4) -> DMat4 {
1394 (*self).sub(rhs)
1395 }
1396}
1397
1398impl SubAssign for DMat4 {
1399 #[inline]
1400 fn sub_assign(&mut self, rhs: Self) {
1401 *self = self.sub(rhs);
1402 }
1403}
1404
1405impl SubAssign<&Self> for DMat4 {
1406 #[inline]
1407 fn sub_assign(&mut self, rhs: &Self) {
1408 self.sub_assign(*rhs);
1409 }
1410}
1411
1412impl Neg for DMat4 {
1413 type Output = Self;
1414 #[inline]
1415 fn neg(self) -> Self::Output {
1416 Self::from_cols(
1417 self.x_axis.neg(),
1418 self.y_axis.neg(),
1419 self.z_axis.neg(),
1420 self.w_axis.neg(),
1421 )
1422 }
1423}
1424
1425impl Neg for &DMat4 {
1426 type Output = DMat4;
1427 #[inline]
1428 fn neg(self) -> DMat4 {
1429 (*self).neg()
1430 }
1431}
1432
1433impl Mul for DMat4 {
1434 type Output = Self;
1435 #[inline]
1436 fn mul(self, rhs: Self) -> Self {
1437 Self::from_cols(
1438 self.mul(rhs.x_axis),
1439 self.mul(rhs.y_axis),
1440 self.mul(rhs.z_axis),
1441 self.mul(rhs.w_axis),
1442 )
1443 }
1444}
1445
1446impl Mul<&Self> for DMat4 {
1447 type Output = Self;
1448 #[inline]
1449 fn mul(self, rhs: &Self) -> Self {
1450 self.mul(*rhs)
1451 }
1452}
1453
1454impl Mul<&DMat4> for &DMat4 {
1455 type Output = DMat4;
1456 #[inline]
1457 fn mul(self, rhs: &DMat4) -> DMat4 {
1458 (*self).mul(*rhs)
1459 }
1460}
1461
1462impl Mul<DMat4> for &DMat4 {
1463 type Output = DMat4;
1464 #[inline]
1465 fn mul(self, rhs: DMat4) -> DMat4 {
1466 (*self).mul(rhs)
1467 }
1468}
1469
1470impl MulAssign for DMat4 {
1471 #[inline]
1472 fn mul_assign(&mut self, rhs: Self) {
1473 *self = self.mul(rhs);
1474 }
1475}
1476
1477impl MulAssign<&Self> for DMat4 {
1478 #[inline]
1479 fn mul_assign(&mut self, rhs: &Self) {
1480 self.mul_assign(*rhs);
1481 }
1482}
1483
1484impl Mul<DVec4> for DMat4 {
1485 type Output = DVec4;
1486 #[inline]
1487 fn mul(self, rhs: DVec4) -> Self::Output {
1488 self.mul_vec4(rhs)
1489 }
1490}
1491
1492impl Mul<&DVec4> for DMat4 {
1493 type Output = DVec4;
1494 #[inline]
1495 fn mul(self, rhs: &DVec4) -> DVec4 {
1496 self.mul(*rhs)
1497 }
1498}
1499
1500impl Mul<&DVec4> for &DMat4 {
1501 type Output = DVec4;
1502 #[inline]
1503 fn mul(self, rhs: &DVec4) -> DVec4 {
1504 (*self).mul(*rhs)
1505 }
1506}
1507
1508impl Mul<DVec4> for &DMat4 {
1509 type Output = DVec4;
1510 #[inline]
1511 fn mul(self, rhs: DVec4) -> DVec4 {
1512 (*self).mul(rhs)
1513 }
1514}
1515
1516impl Mul<DMat4> for f64 {
1517 type Output = DMat4;
1518 #[inline]
1519 fn mul(self, rhs: DMat4) -> Self::Output {
1520 rhs.mul_scalar(self)
1521 }
1522}
1523
1524impl Mul<&DMat4> for f64 {
1525 type Output = DMat4;
1526 #[inline]
1527 fn mul(self, rhs: &DMat4) -> DMat4 {
1528 self.mul(*rhs)
1529 }
1530}
1531
1532impl Mul<&DMat4> for &f64 {
1533 type Output = DMat4;
1534 #[inline]
1535 fn mul(self, rhs: &DMat4) -> DMat4 {
1536 (*self).mul(*rhs)
1537 }
1538}
1539
1540impl Mul<DMat4> for &f64 {
1541 type Output = DMat4;
1542 #[inline]
1543 fn mul(self, rhs: DMat4) -> DMat4 {
1544 (*self).mul(rhs)
1545 }
1546}
1547
1548impl Mul<f64> for DMat4 {
1549 type Output = Self;
1550 #[inline]
1551 fn mul(self, rhs: f64) -> Self {
1552 self.mul_scalar(rhs)
1553 }
1554}
1555
1556impl Mul<&f64> for DMat4 {
1557 type Output = Self;
1558 #[inline]
1559 fn mul(self, rhs: &f64) -> Self {
1560 self.mul(*rhs)
1561 }
1562}
1563
1564impl Mul<&f64> for &DMat4 {
1565 type Output = DMat4;
1566 #[inline]
1567 fn mul(self, rhs: &f64) -> DMat4 {
1568 (*self).mul(*rhs)
1569 }
1570}
1571
1572impl Mul<f64> for &DMat4 {
1573 type Output = DMat4;
1574 #[inline]
1575 fn mul(self, rhs: f64) -> DMat4 {
1576 (*self).mul(rhs)
1577 }
1578}
1579
1580impl MulAssign<f64> for DMat4 {
1581 #[inline]
1582 fn mul_assign(&mut self, rhs: f64) {
1583 *self = self.mul(rhs);
1584 }
1585}
1586
1587impl MulAssign<&f64> for DMat4 {
1588 #[inline]
1589 fn mul_assign(&mut self, rhs: &f64) {
1590 self.mul_assign(*rhs);
1591 }
1592}
1593
1594impl Div<DMat4> for f64 {
1595 type Output = DMat4;
1596 #[inline]
1597 fn div(self, rhs: DMat4) -> Self::Output {
1598 rhs.div_scalar(self)
1599 }
1600}
1601
1602impl Div<&DMat4> for f64 {
1603 type Output = DMat4;
1604 #[inline]
1605 fn div(self, rhs: &DMat4) -> DMat4 {
1606 self.div(*rhs)
1607 }
1608}
1609
1610impl Div<&DMat4> for &f64 {
1611 type Output = DMat4;
1612 #[inline]
1613 fn div(self, rhs: &DMat4) -> DMat4 {
1614 (*self).div(*rhs)
1615 }
1616}
1617
1618impl Div<DMat4> for &f64 {
1619 type Output = DMat4;
1620 #[inline]
1621 fn div(self, rhs: DMat4) -> DMat4 {
1622 (*self).div(rhs)
1623 }
1624}
1625
1626impl Div<f64> for DMat4 {
1627 type Output = Self;
1628 #[inline]
1629 fn div(self, rhs: f64) -> Self {
1630 self.div_scalar(rhs)
1631 }
1632}
1633
1634impl Div<&f64> for DMat4 {
1635 type Output = Self;
1636 #[inline]
1637 fn div(self, rhs: &f64) -> Self {
1638 self.div(*rhs)
1639 }
1640}
1641
1642impl Div<&f64> for &DMat4 {
1643 type Output = DMat4;
1644 #[inline]
1645 fn div(self, rhs: &f64) -> DMat4 {
1646 (*self).div(*rhs)
1647 }
1648}
1649
1650impl Div<f64> for &DMat4 {
1651 type Output = DMat4;
1652 #[inline]
1653 fn div(self, rhs: f64) -> DMat4 {
1654 (*self).div(rhs)
1655 }
1656}
1657
1658impl DivAssign<f64> for DMat4 {
1659 #[inline]
1660 fn div_assign(&mut self, rhs: f64) {
1661 *self = self.div(rhs);
1662 }
1663}
1664
1665impl DivAssign<&f64> for DMat4 {
1666 #[inline]
1667 fn div_assign(&mut self, rhs: &f64) {
1668 self.div_assign(*rhs);
1669 }
1670}
1671
1672impl Sum<Self> for DMat4 {
1673 fn sum<I>(iter: I) -> Self
1674 where
1675 I: Iterator<Item = Self>,
1676 {
1677 iter.fold(Self::ZERO, Self::add)
1678 }
1679}
1680
1681impl<'a> Sum<&'a Self> for DMat4 {
1682 fn sum<I>(iter: I) -> Self
1683 where
1684 I: Iterator<Item = &'a Self>,
1685 {
1686 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1687 }
1688}
1689
1690impl Product for DMat4 {
1691 fn product<I>(iter: I) -> Self
1692 where
1693 I: Iterator<Item = Self>,
1694 {
1695 iter.fold(Self::IDENTITY, Self::mul)
1696 }
1697}
1698
1699impl<'a> Product<&'a Self> for DMat4 {
1700 fn product<I>(iter: I) -> Self
1701 where
1702 I: Iterator<Item = &'a Self>,
1703 {
1704 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1705 }
1706}
1707
1708impl PartialEq for DMat4 {
1709 #[inline]
1710 fn eq(&self, rhs: &Self) -> bool {
1711 self.x_axis.eq(&rhs.x_axis)
1712 && self.y_axis.eq(&rhs.y_axis)
1713 && self.z_axis.eq(&rhs.z_axis)
1714 && self.w_axis.eq(&rhs.w_axis)
1715 }
1716}
1717
1718impl AsRef<[f64; 16]> for DMat4 {
1719 #[inline]
1720 fn as_ref(&self) -> &[f64; 16] {
1721 unsafe { &*(self as *const Self as *const [f64; 16]) }
1722 }
1723}
1724
1725impl AsMut<[f64; 16]> for DMat4 {
1726 #[inline]
1727 fn as_mut(&mut self) -> &mut [f64; 16] {
1728 unsafe { &mut *(self as *mut Self as *mut [f64; 16]) }
1729 }
1730}
1731
1732impl fmt::Debug for DMat4 {
1733 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1734 fmt.debug_struct(stringify!(DMat4))
1735 .field("x_axis", &self.x_axis)
1736 .field("y_axis", &self.y_axis)
1737 .field("z_axis", &self.z_axis)
1738 .field("w_axis", &self.w_axis)
1739 .finish()
1740 }
1741}
1742
1743impl fmt::Display for DMat4 {
1744 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1745 if let Some(p) = f.precision() {
1746 write!(
1747 f,
1748 "[{:.*}, {:.*}, {:.*}, {:.*}]",
1749 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
1750 )
1751 } else {
1752 write!(
1753 f,
1754 "[{}, {}, {}, {}]",
1755 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1756 )
1757 }
1758 }
1759}