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#[inline(always)]
15#[must_use]
16pub const fn dmat4(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> DMat4 {
17 DMat4::from_cols(x_axis, y_axis, z_axis, w_axis)
18}
19
20#[derive(Clone, Copy)]
50#[cfg_attr(
51 all(feature = "bytemuck", not(target_arch = "spirv")),
52 derive(bytemuck::Pod, bytemuck::Zeroable)
53)]
54#[cfg_attr(feature = "cuda", repr(align(16)))]
55#[repr(C)]
56pub struct DMat4 {
57 pub x_axis: DVec4,
58 pub y_axis: DVec4,
59 pub z_axis: DVec4,
60 pub w_axis: DVec4,
61}
62
63impl DMat4 {
64 pub const ZERO: Self = Self::from_cols(DVec4::ZERO, DVec4::ZERO, DVec4::ZERO, DVec4::ZERO);
66
67 pub const IDENTITY: Self = Self::from_cols(DVec4::X, DVec4::Y, DVec4::Z, DVec4::W);
69
70 pub const NAN: Self = Self::from_cols(DVec4::NAN, DVec4::NAN, DVec4::NAN, DVec4::NAN);
72
73 #[allow(clippy::too_many_arguments)]
74 #[inline(always)]
75 #[must_use]
76 const fn new(
77 m00: f64,
78 m01: f64,
79 m02: f64,
80 m03: f64,
81 m10: f64,
82 m11: f64,
83 m12: f64,
84 m13: f64,
85 m20: f64,
86 m21: f64,
87 m22: f64,
88 m23: f64,
89 m30: f64,
90 m31: f64,
91 m32: f64,
92 m33: f64,
93 ) -> Self {
94 Self {
95 x_axis: DVec4::new(m00, m01, m02, m03),
96 y_axis: DVec4::new(m10, m11, m12, m13),
97 z_axis: DVec4::new(m20, m21, m22, m23),
98 w_axis: DVec4::new(m30, m31, m32, m33),
99 }
100 }
101
102 #[inline(always)]
104 #[must_use]
105 pub const fn from_cols(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> Self {
106 Self {
107 x_axis,
108 y_axis,
109 z_axis,
110 w_axis,
111 }
112 }
113
114 #[inline]
118 #[must_use]
119 pub const fn from_cols_array(m: &[f64; 16]) -> Self {
120 Self::new(
121 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],
122 m[14], m[15],
123 )
124 }
125
126 #[inline]
129 #[must_use]
130 pub const fn to_cols_array(&self) -> [f64; 16] {
131 [
132 self.x_axis.x,
133 self.x_axis.y,
134 self.x_axis.z,
135 self.x_axis.w,
136 self.y_axis.x,
137 self.y_axis.y,
138 self.y_axis.z,
139 self.y_axis.w,
140 self.z_axis.x,
141 self.z_axis.y,
142 self.z_axis.z,
143 self.z_axis.w,
144 self.w_axis.x,
145 self.w_axis.y,
146 self.w_axis.z,
147 self.w_axis.w,
148 ]
149 }
150
151 #[inline]
155 #[must_use]
156 pub const fn from_cols_array_2d(m: &[[f64; 4]; 4]) -> Self {
157 Self::from_cols(
158 DVec4::from_array(m[0]),
159 DVec4::from_array(m[1]),
160 DVec4::from_array(m[2]),
161 DVec4::from_array(m[3]),
162 )
163 }
164
165 #[inline]
168 #[must_use]
169 pub const fn to_cols_array_2d(&self) -> [[f64; 4]; 4] {
170 [
171 self.x_axis.to_array(),
172 self.y_axis.to_array(),
173 self.z_axis.to_array(),
174 self.w_axis.to_array(),
175 ]
176 }
177
178 #[doc(alias = "scale")]
180 #[inline]
181 #[must_use]
182 pub const fn from_diagonal(diagonal: DVec4) -> Self {
183 Self::new(
184 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,
185 0.0, 0.0, diagonal.w,
186 )
187 }
188
189 #[inline]
190 #[must_use]
191 fn quat_to_axes(rotation: DQuat) -> (DVec4, DVec4, DVec4) {
192 glam_assert!(rotation.is_normalized());
193
194 let (x, y, z, w) = rotation.into();
195 let x2 = x + x;
196 let y2 = y + y;
197 let z2 = z + z;
198 let xx = x * x2;
199 let xy = x * y2;
200 let xz = x * z2;
201 let yy = y * y2;
202 let yz = y * z2;
203 let zz = z * z2;
204 let wx = w * x2;
205 let wy = w * y2;
206 let wz = w * z2;
207
208 let x_axis = DVec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
209 let y_axis = DVec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
210 let z_axis = DVec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
211 (x_axis, y_axis, z_axis)
212 }
213
214 #[inline]
224 #[must_use]
225 pub fn from_scale_rotation_translation(
226 scale: DVec3,
227 rotation: DQuat,
228 translation: DVec3,
229 ) -> Self {
230 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
231 Self::from_cols(
232 x_axis.mul(scale.x),
233 y_axis.mul(scale.y),
234 z_axis.mul(scale.z),
235 DVec4::from((translation, 1.0)),
236 )
237 }
238
239 #[inline]
248 #[must_use]
249 pub fn from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self {
250 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
251 Self::from_cols(x_axis, y_axis, z_axis, DVec4::from((translation, 1.0)))
252 }
253
254 #[inline]
262 #[must_use]
263 pub fn to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3) {
264 let det = self.determinant();
265 glam_assert!(det != 0.0);
266
267 let scale = DVec3::new(
268 self.x_axis.length() * math::signum(det),
269 self.y_axis.length(),
270 self.z_axis.length(),
271 );
272
273 glam_assert!(scale.cmpne(DVec3::ZERO).all());
274
275 let inv_scale = scale.recip();
276
277 let rotation = DQuat::from_rotation_axes(
278 self.x_axis.mul(inv_scale.x).xyz(),
279 self.y_axis.mul(inv_scale.y).xyz(),
280 self.z_axis.mul(inv_scale.z).xyz(),
281 );
282
283 let translation = self.w_axis.xyz();
284
285 (scale, rotation, translation)
286 }
287
288 #[inline]
297 #[must_use]
298 pub fn from_quat(rotation: DQuat) -> Self {
299 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
300 Self::from_cols(x_axis, y_axis, z_axis, DVec4::W)
301 }
302
303 #[inline]
309 #[must_use]
310 pub fn from_mat3(m: DMat3) -> Self {
311 Self::from_cols(
312 DVec4::from((m.x_axis, 0.0)),
313 DVec4::from((m.y_axis, 0.0)),
314 DVec4::from((m.z_axis, 0.0)),
315 DVec4::W,
316 )
317 }
318
319 #[inline]
324 #[must_use]
325 pub fn from_mat3_translation(mat3: DMat3, translation: DVec3) -> Self {
326 Self::from_cols(
327 DVec4::from((mat3.x_axis, 0.0)),
328 DVec4::from((mat3.y_axis, 0.0)),
329 DVec4::from((mat3.z_axis, 0.0)),
330 DVec4::from((translation, 1.0)),
331 )
332 }
333
334 #[inline]
339 #[must_use]
340 pub fn from_translation(translation: DVec3) -> Self {
341 Self::from_cols(
342 DVec4::X,
343 DVec4::Y,
344 DVec4::Z,
345 DVec4::new(translation.x, translation.y, translation.z, 1.0),
346 )
347 }
348
349 #[inline]
359 #[must_use]
360 pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
361 glam_assert!(axis.is_normalized());
362
363 let (sin, cos) = math::sin_cos(angle);
364 let axis_sin = axis.mul(sin);
365 let axis_sq = axis.mul(axis);
366 let omc = 1.0 - cos;
367 let xyomc = axis.x * axis.y * omc;
368 let xzomc = axis.x * axis.z * omc;
369 let yzomc = axis.y * axis.z * omc;
370 Self::from_cols(
371 DVec4::new(
372 axis_sq.x * omc + cos,
373 xyomc + axis_sin.z,
374 xzomc - axis_sin.y,
375 0.0,
376 ),
377 DVec4::new(
378 xyomc - axis_sin.z,
379 axis_sq.y * omc + cos,
380 yzomc + axis_sin.x,
381 0.0,
382 ),
383 DVec4::new(
384 xzomc + axis_sin.y,
385 yzomc - axis_sin.x,
386 axis_sq.z * omc + cos,
387 0.0,
388 ),
389 DVec4::W,
390 )
391 }
392
393 #[inline]
399 #[must_use]
400 pub fn from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self {
401 Self::from_euler_angles(order, a, b, c)
402 }
403
404 #[inline]
414 #[must_use]
415 pub fn to_euler(&self, order: EulerRot) -> (f64, f64, f64) {
416 glam_assert!(
417 self.x_axis.xyz().is_normalized()
418 && self.y_axis.xyz().is_normalized()
419 && self.z_axis.xyz().is_normalized()
420 );
421 self.to_euler_angles(order)
422 }
423
424 #[inline]
430 #[must_use]
431 pub fn from_rotation_x(angle: f64) -> Self {
432 let (sina, cosa) = math::sin_cos(angle);
433 Self::from_cols(
434 DVec4::X,
435 DVec4::new(0.0, cosa, sina, 0.0),
436 DVec4::new(0.0, -sina, cosa, 0.0),
437 DVec4::W,
438 )
439 }
440
441 #[inline]
447 #[must_use]
448 pub fn from_rotation_y(angle: f64) -> Self {
449 let (sina, cosa) = math::sin_cos(angle);
450 Self::from_cols(
451 DVec4::new(cosa, 0.0, -sina, 0.0),
452 DVec4::Y,
453 DVec4::new(sina, 0.0, cosa, 0.0),
454 DVec4::W,
455 )
456 }
457
458 #[inline]
464 #[must_use]
465 pub fn from_rotation_z(angle: f64) -> Self {
466 let (sina, cosa) = math::sin_cos(angle);
467 Self::from_cols(
468 DVec4::new(cosa, sina, 0.0, 0.0),
469 DVec4::new(-sina, cosa, 0.0, 0.0),
470 DVec4::Z,
471 DVec4::W,
472 )
473 }
474
475 #[inline]
484 #[must_use]
485 pub fn from_scale(scale: DVec3) -> Self {
486 glam_assert!(scale.cmpne(DVec3::ZERO).any());
488
489 Self::from_cols(
490 DVec4::new(scale.x, 0.0, 0.0, 0.0),
491 DVec4::new(0.0, scale.y, 0.0, 0.0),
492 DVec4::new(0.0, 0.0, scale.z, 0.0),
493 DVec4::W,
494 )
495 }
496
497 #[inline]
503 #[must_use]
504 pub const fn from_cols_slice(slice: &[f64]) -> Self {
505 Self::new(
506 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
507 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
508 )
509 }
510
511 #[inline]
517 pub fn write_cols_to_slice(self, slice: &mut [f64]) {
518 slice[0] = self.x_axis.x;
519 slice[1] = self.x_axis.y;
520 slice[2] = self.x_axis.z;
521 slice[3] = self.x_axis.w;
522 slice[4] = self.y_axis.x;
523 slice[5] = self.y_axis.y;
524 slice[6] = self.y_axis.z;
525 slice[7] = self.y_axis.w;
526 slice[8] = self.z_axis.x;
527 slice[9] = self.z_axis.y;
528 slice[10] = self.z_axis.z;
529 slice[11] = self.z_axis.w;
530 slice[12] = self.w_axis.x;
531 slice[13] = self.w_axis.y;
532 slice[14] = self.w_axis.z;
533 slice[15] = self.w_axis.w;
534 }
535
536 #[inline]
542 #[must_use]
543 pub fn col(&self, index: usize) -> DVec4 {
544 match index {
545 0 => self.x_axis,
546 1 => self.y_axis,
547 2 => self.z_axis,
548 3 => self.w_axis,
549 _ => panic!("index out of bounds"),
550 }
551 }
552
553 #[inline]
559 pub fn col_mut(&mut self, index: usize) -> &mut DVec4 {
560 match index {
561 0 => &mut self.x_axis,
562 1 => &mut self.y_axis,
563 2 => &mut self.z_axis,
564 3 => &mut self.w_axis,
565 _ => panic!("index out of bounds"),
566 }
567 }
568
569 #[inline]
575 #[must_use]
576 pub fn row(&self, index: usize) -> DVec4 {
577 match index {
578 0 => DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
579 1 => DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
580 2 => DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
581 3 => DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
582 _ => panic!("index out of bounds"),
583 }
584 }
585
586 #[inline]
589 #[must_use]
590 pub fn is_finite(&self) -> bool {
591 self.x_axis.is_finite()
592 && self.y_axis.is_finite()
593 && self.z_axis.is_finite()
594 && self.w_axis.is_finite()
595 }
596
597 #[inline]
599 #[must_use]
600 pub fn is_nan(&self) -> bool {
601 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
602 }
603
604 #[inline]
606 #[must_use]
607 pub fn transpose(&self) -> Self {
608 Self {
609 x_axis: DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
610 y_axis: DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
611 z_axis: DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
612 w_axis: DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
613 }
614 }
615
616 #[must_use]
618 pub fn determinant(&self) -> f64 {
619 let (m00, m01, m02, m03) = self.x_axis.into();
620 let (m10, m11, m12, m13) = self.y_axis.into();
621 let (m20, m21, m22, m23) = self.z_axis.into();
622 let (m30, m31, m32, m33) = self.w_axis.into();
623
624 let a2323 = m22 * m33 - m23 * m32;
625 let a1323 = m21 * m33 - m23 * m31;
626 let a1223 = m21 * m32 - m22 * m31;
627 let a0323 = m20 * m33 - m23 * m30;
628 let a0223 = m20 * m32 - m22 * m30;
629 let a0123 = m20 * m31 - m21 * m30;
630
631 m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223)
632 - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223)
633 + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123)
634 - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123)
635 }
636
637 #[must_use]
645 pub fn inverse(&self) -> Self {
646 let (m00, m01, m02, m03) = self.x_axis.into();
647 let (m10, m11, m12, m13) = self.y_axis.into();
648 let (m20, m21, m22, m23) = self.z_axis.into();
649 let (m30, m31, m32, m33) = self.w_axis.into();
650
651 let coef00 = m22 * m33 - m32 * m23;
652 let coef02 = m12 * m33 - m32 * m13;
653 let coef03 = m12 * m23 - m22 * m13;
654
655 let coef04 = m21 * m33 - m31 * m23;
656 let coef06 = m11 * m33 - m31 * m13;
657 let coef07 = m11 * m23 - m21 * m13;
658
659 let coef08 = m21 * m32 - m31 * m22;
660 let coef10 = m11 * m32 - m31 * m12;
661 let coef11 = m11 * m22 - m21 * m12;
662
663 let coef12 = m20 * m33 - m30 * m23;
664 let coef14 = m10 * m33 - m30 * m13;
665 let coef15 = m10 * m23 - m20 * m13;
666
667 let coef16 = m20 * m32 - m30 * m22;
668 let coef18 = m10 * m32 - m30 * m12;
669 let coef19 = m10 * m22 - m20 * m12;
670
671 let coef20 = m20 * m31 - m30 * m21;
672 let coef22 = m10 * m31 - m30 * m11;
673 let coef23 = m10 * m21 - m20 * m11;
674
675 let fac0 = DVec4::new(coef00, coef00, coef02, coef03);
676 let fac1 = DVec4::new(coef04, coef04, coef06, coef07);
677 let fac2 = DVec4::new(coef08, coef08, coef10, coef11);
678 let fac3 = DVec4::new(coef12, coef12, coef14, coef15);
679 let fac4 = DVec4::new(coef16, coef16, coef18, coef19);
680 let fac5 = DVec4::new(coef20, coef20, coef22, coef23);
681
682 let vec0 = DVec4::new(m10, m00, m00, m00);
683 let vec1 = DVec4::new(m11, m01, m01, m01);
684 let vec2 = DVec4::new(m12, m02, m02, m02);
685 let vec3 = DVec4::new(m13, m03, m03, m03);
686
687 let inv0 = vec1.mul(fac0).sub(vec2.mul(fac1)).add(vec3.mul(fac2));
688 let inv1 = vec0.mul(fac0).sub(vec2.mul(fac3)).add(vec3.mul(fac4));
689 let inv2 = vec0.mul(fac1).sub(vec1.mul(fac3)).add(vec3.mul(fac5));
690 let inv3 = vec0.mul(fac2).sub(vec1.mul(fac4)).add(vec2.mul(fac5));
691
692 let sign_a = DVec4::new(1.0, -1.0, 1.0, -1.0);
693 let sign_b = DVec4::new(-1.0, 1.0, -1.0, 1.0);
694
695 let inverse = Self::from_cols(
696 inv0.mul(sign_a),
697 inv1.mul(sign_b),
698 inv2.mul(sign_a),
699 inv3.mul(sign_b),
700 );
701
702 let col0 = DVec4::new(
703 inverse.x_axis.x,
704 inverse.y_axis.x,
705 inverse.z_axis.x,
706 inverse.w_axis.x,
707 );
708
709 let dot0 = self.x_axis.mul(col0);
710 let dot1 = dot0.x + dot0.y + dot0.z + dot0.w;
711
712 glam_assert!(dot1 != 0.0);
713
714 let rcp_det = dot1.recip();
715 inverse.mul(rcp_det)
716 }
717
718 #[inline]
727 #[must_use]
728 pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
729 Self::look_to_rh(eye, -dir, up)
730 }
731
732 #[inline]
741 #[must_use]
742 pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
743 glam_assert!(dir.is_normalized());
744 glam_assert!(up.is_normalized());
745 let f = dir;
746 let s = f.cross(up).normalize();
747 let u = s.cross(f);
748
749 Self::from_cols(
750 DVec4::new(s.x, u.x, -f.x, 0.0),
751 DVec4::new(s.y, u.y, -f.y, 0.0),
752 DVec4::new(s.z, u.z, -f.z, 0.0),
753 DVec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
754 )
755 }
756
757 #[inline]
766 #[must_use]
767 pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
768 Self::look_to_lh(eye, center.sub(eye).normalize(), up)
769 }
770
771 #[inline]
780 pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
781 Self::look_to_rh(eye, center.sub(eye).normalize(), up)
782 }
783
784 #[inline]
790 #[must_use]
791 pub fn frustum_rh_gl(
792 left: f64,
793 right: f64,
794 bottom: f64,
795 top: f64,
796 z_near: f64,
797 z_far: f64,
798 ) -> Self {
799 let inv_width = 1.0 / (right - left);
800 let inv_height = 1.0 / (top - bottom);
801 let inv_depth = 1.0 / (z_far - z_near);
802 let a = (right + left) * inv_width;
803 let b = (top + bottom) * inv_height;
804 let c = -(z_far + z_near) * inv_depth;
805 let d = -(2.0 * z_far * z_near) * inv_depth;
806 let two_z_near = 2.0 * z_near;
807 Self::from_cols(
808 DVec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
809 DVec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
810 DVec4::new(a, b, c, -1.0),
811 DVec4::new(0.0, 0.0, d, 0.0),
812 )
813 }
814
815 #[inline]
822 #[must_use]
823 pub fn frustum_lh(
824 left: f64,
825 right: f64,
826 bottom: f64,
827 top: f64,
828 z_near: f64,
829 z_far: f64,
830 ) -> Self {
831 glam_assert!(z_near > 0.0 && z_far > 0.0);
832 let inv_width = 1.0 / (right - left);
833 let inv_height = 1.0 / (top - bottom);
834 let inv_depth = 1.0 / (z_far - z_near);
835 let a = (right + left) * inv_width;
836 let b = (top + bottom) * inv_height;
837 let c = z_far * inv_depth;
838 let d = -(z_far * z_near) * inv_depth;
839 let two_z_near = 2.0 * z_near;
840 Self::from_cols(
841 DVec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
842 DVec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
843 DVec4::new(a, b, c, 1.0),
844 DVec4::new(0.0, 0.0, d, 0.0),
845 )
846 }
847
848 #[inline]
855 #[must_use]
856 pub fn frustum_rh(
857 left: f64,
858 right: f64,
859 bottom: f64,
860 top: f64,
861 z_near: f64,
862 z_far: f64,
863 ) -> Self {
864 glam_assert!(z_near > 0.0 && z_far > 0.0);
865 let inv_width = 1.0 / (right - left);
866 let inv_height = 1.0 / (top - bottom);
867 let inv_depth = 1.0 / (z_far - z_near);
868 let a = (right + left) * inv_width;
869 let b = (top + bottom) * inv_height;
870 let c = -z_far * inv_depth;
871 let d = -(z_far * z_near) * inv_depth;
872 let two_z_near = 2.0 * z_near;
873 Self::from_cols(
874 DVec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
875 DVec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
876 DVec4::new(a, b, c, -1.0),
877 DVec4::new(0.0, 0.0, d, 0.0),
878 )
879 }
880
881 #[inline]
888 #[must_use]
889 pub fn perspective_rh_gl(
890 fov_y_radians: f64,
891 aspect_ratio: f64,
892 z_near: f64,
893 z_far: f64,
894 ) -> Self {
895 let inv_length = 1.0 / (z_near - z_far);
896 let f = 1.0 / math::tan(0.5 * fov_y_radians);
897 let a = f / aspect_ratio;
898 let b = (z_near + z_far) * inv_length;
899 let c = (2.0 * z_near * z_far) * inv_length;
900 Self::from_cols(
901 DVec4::new(a, 0.0, 0.0, 0.0),
902 DVec4::new(0.0, f, 0.0, 0.0),
903 DVec4::new(0.0, 0.0, b, -1.0),
904 DVec4::new(0.0, 0.0, c, 0.0),
905 )
906 }
907
908 #[inline]
917 #[must_use]
918 pub fn perspective_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
919 glam_assert!(z_near > 0.0 && z_far > 0.0);
920 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
921 let h = cos_fov / sin_fov;
922 let w = h / aspect_ratio;
923 let r = z_far / (z_far - z_near);
924 Self::from_cols(
925 DVec4::new(w, 0.0, 0.0, 0.0),
926 DVec4::new(0.0, h, 0.0, 0.0),
927 DVec4::new(0.0, 0.0, r, 1.0),
928 DVec4::new(0.0, 0.0, -r * z_near, 0.0),
929 )
930 }
931
932 #[inline]
941 #[must_use]
942 pub fn perspective_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
943 glam_assert!(z_near > 0.0 && z_far > 0.0);
944 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
945 let h = cos_fov / sin_fov;
946 let w = h / aspect_ratio;
947 let r = z_far / (z_near - z_far);
948 Self::from_cols(
949 DVec4::new(w, 0.0, 0.0, 0.0),
950 DVec4::new(0.0, h, 0.0, 0.0),
951 DVec4::new(0.0, 0.0, r, -1.0),
952 DVec4::new(0.0, 0.0, r * z_near, 0.0),
953 )
954 }
955
956 #[inline]
966 #[must_use]
967 pub fn perspective_infinite_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
968 glam_assert!(z_near > 0.0);
969 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
970 let h = cos_fov / sin_fov;
971 let w = h / aspect_ratio;
972 Self::from_cols(
973 DVec4::new(w, 0.0, 0.0, 0.0),
974 DVec4::new(0.0, h, 0.0, 0.0),
975 DVec4::new(0.0, 0.0, 1.0, 1.0),
976 DVec4::new(0.0, 0.0, -z_near, 0.0),
977 )
978 }
979
980 #[inline]
988 #[must_use]
989 pub fn perspective_infinite_reverse_lh(
990 fov_y_radians: f64,
991 aspect_ratio: f64,
992 z_near: f64,
993 ) -> Self {
994 glam_assert!(z_near > 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 Self::from_cols(
999 DVec4::new(w, 0.0, 0.0, 0.0),
1000 DVec4::new(0.0, h, 0.0, 0.0),
1001 DVec4::new(0.0, 0.0, 0.0, 1.0),
1002 DVec4::new(0.0, 0.0, z_near, 0.0),
1003 )
1004 }
1005
1006 #[inline]
1016 #[must_use]
1017 pub fn perspective_infinite_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
1018 glam_assert!(z_near > 0.0);
1019 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1020 Self::from_cols(
1021 DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1022 DVec4::new(0.0, f, 0.0, 0.0),
1023 DVec4::new(0.0, 0.0, -1.0, -1.0),
1024 DVec4::new(0.0, 0.0, -z_near, 0.0),
1025 )
1026 }
1027
1028 #[inline]
1036 #[must_use]
1037 pub fn perspective_infinite_reverse_rh(
1038 fov_y_radians: f64,
1039 aspect_ratio: f64,
1040 z_near: f64,
1041 ) -> Self {
1042 glam_assert!(z_near > 0.0);
1043 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1044 Self::from_cols(
1045 DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1046 DVec4::new(0.0, f, 0.0, 0.0),
1047 DVec4::new(0.0, 0.0, 0.0, -1.0),
1048 DVec4::new(0.0, 0.0, z_near, 0.0),
1049 )
1050 }
1051
1052 #[inline]
1059 #[must_use]
1060 pub fn orthographic_rh_gl(
1061 left: f64,
1062 right: f64,
1063 bottom: f64,
1064 top: f64,
1065 near: f64,
1066 far: f64,
1067 ) -> Self {
1068 let a = 2.0 / (right - left);
1069 let b = 2.0 / (top - bottom);
1070 let c = -2.0 / (far - near);
1071 let tx = -(right + left) / (right - left);
1072 let ty = -(top + bottom) / (top - bottom);
1073 let tz = -(far + near) / (far - near);
1074
1075 Self::from_cols(
1076 DVec4::new(a, 0.0, 0.0, 0.0),
1077 DVec4::new(0.0, b, 0.0, 0.0),
1078 DVec4::new(0.0, 0.0, c, 0.0),
1079 DVec4::new(tx, ty, tz, 1.0),
1080 )
1081 }
1082
1083 #[inline]
1087 #[must_use]
1088 pub fn orthographic_lh(
1089 left: f64,
1090 right: f64,
1091 bottom: f64,
1092 top: f64,
1093 near: f64,
1094 far: f64,
1095 ) -> Self {
1096 let rcp_width = 1.0 / (right - left);
1097 let rcp_height = 1.0 / (top - bottom);
1098 let r = 1.0 / (far - near);
1099 Self::from_cols(
1100 DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1101 DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1102 DVec4::new(0.0, 0.0, r, 0.0),
1103 DVec4::new(
1104 -(left + right) * rcp_width,
1105 -(top + bottom) * rcp_height,
1106 -r * near,
1107 1.0,
1108 ),
1109 )
1110 }
1111
1112 #[inline]
1116 #[must_use]
1117 pub fn orthographic_rh(
1118 left: f64,
1119 right: f64,
1120 bottom: f64,
1121 top: f64,
1122 near: f64,
1123 far: f64,
1124 ) -> Self {
1125 let rcp_width = 1.0 / (right - left);
1126 let rcp_height = 1.0 / (top - bottom);
1127 let r = 1.0 / (near - far);
1128 Self::from_cols(
1129 DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1130 DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1131 DVec4::new(0.0, 0.0, r, 0.0),
1132 DVec4::new(
1133 -(left + right) * rcp_width,
1134 -(top + bottom) * rcp_height,
1135 r * near,
1136 1.0,
1137 ),
1138 )
1139 }
1140
1141 #[inline]
1148 #[must_use]
1149 pub fn project_point3(&self, rhs: DVec3) -> DVec3 {
1150 let mut res = self.x_axis.mul(rhs.x);
1151 res = self.y_axis.mul(rhs.y).add(res);
1152 res = self.z_axis.mul(rhs.z).add(res);
1153 res = self.w_axis.add(res);
1154 res = res.div(res.w);
1155 res.xyz()
1156 }
1157
1158 #[inline]
1171 #[must_use]
1172 pub fn transform_point3(&self, rhs: DVec3) -> DVec3 {
1173 glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
1174 let mut res = self.x_axis.mul(rhs.x);
1175 res = self.y_axis.mul(rhs.y).add(res);
1176 res = self.z_axis.mul(rhs.z).add(res);
1177 res = self.w_axis.add(res);
1178 res.xyz()
1179 }
1180
1181 #[inline]
1192 #[must_use]
1193 pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 {
1194 glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
1195 let mut res = self.x_axis.mul(rhs.x);
1196 res = self.y_axis.mul(rhs.y).add(res);
1197 res = self.z_axis.mul(rhs.z).add(res);
1198 res.xyz()
1199 }
1200
1201 #[inline]
1203 #[must_use]
1204 pub fn mul_vec4(&self, rhs: DVec4) -> DVec4 {
1205 let mut res = self.x_axis.mul(rhs.x);
1206 res = res.add(self.y_axis.mul(rhs.y));
1207 res = res.add(self.z_axis.mul(rhs.z));
1208 res = res.add(self.w_axis.mul(rhs.w));
1209 res
1210 }
1211
1212 #[inline]
1214 #[must_use]
1215 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1216 self.mul(rhs)
1217 }
1218
1219 #[inline]
1221 #[must_use]
1222 pub fn add_mat4(&self, rhs: &Self) -> Self {
1223 self.add(rhs)
1224 }
1225
1226 #[inline]
1228 #[must_use]
1229 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1230 self.sub(rhs)
1231 }
1232
1233 #[inline]
1235 #[must_use]
1236 pub fn mul_scalar(&self, rhs: f64) -> Self {
1237 Self::from_cols(
1238 self.x_axis.mul(rhs),
1239 self.y_axis.mul(rhs),
1240 self.z_axis.mul(rhs),
1241 self.w_axis.mul(rhs),
1242 )
1243 }
1244
1245 #[inline]
1247 #[must_use]
1248 pub fn div_scalar(&self, rhs: f64) -> Self {
1249 let rhs = DVec4::splat(rhs);
1250 Self::from_cols(
1251 self.x_axis.div(rhs),
1252 self.y_axis.div(rhs),
1253 self.z_axis.div(rhs),
1254 self.w_axis.div(rhs),
1255 )
1256 }
1257
1258 #[inline]
1268 #[must_use]
1269 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
1270 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1271 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1272 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1273 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1274 }
1275
1276 #[inline]
1278 #[must_use]
1279 pub fn abs(&self) -> Self {
1280 Self::from_cols(
1281 self.x_axis.abs(),
1282 self.y_axis.abs(),
1283 self.z_axis.abs(),
1284 self.w_axis.abs(),
1285 )
1286 }
1287
1288 #[inline]
1289 pub fn as_mat4(&self) -> Mat4 {
1290 Mat4::from_cols(
1291 self.x_axis.as_vec4(),
1292 self.y_axis.as_vec4(),
1293 self.z_axis.as_vec4(),
1294 self.w_axis.as_vec4(),
1295 )
1296 }
1297}
1298
1299impl Default for DMat4 {
1300 #[inline]
1301 fn default() -> Self {
1302 Self::IDENTITY
1303 }
1304}
1305
1306impl Add for DMat4 {
1307 type Output = Self;
1308 #[inline]
1309 fn add(self, rhs: Self) -> Self {
1310 Self::from_cols(
1311 self.x_axis.add(rhs.x_axis),
1312 self.y_axis.add(rhs.y_axis),
1313 self.z_axis.add(rhs.z_axis),
1314 self.w_axis.add(rhs.w_axis),
1315 )
1316 }
1317}
1318
1319impl Add<&Self> for DMat4 {
1320 type Output = Self;
1321 #[inline]
1322 fn add(self, rhs: &Self) -> Self {
1323 self.add(*rhs)
1324 }
1325}
1326
1327impl Add<&DMat4> for &DMat4 {
1328 type Output = DMat4;
1329 #[inline]
1330 fn add(self, rhs: &DMat4) -> DMat4 {
1331 (*self).add(*rhs)
1332 }
1333}
1334
1335impl Add<DMat4> for &DMat4 {
1336 type Output = DMat4;
1337 #[inline]
1338 fn add(self, rhs: DMat4) -> DMat4 {
1339 (*self).add(rhs)
1340 }
1341}
1342
1343impl AddAssign for DMat4 {
1344 #[inline]
1345 fn add_assign(&mut self, rhs: Self) {
1346 *self = self.add(rhs);
1347 }
1348}
1349
1350impl AddAssign<&Self> for DMat4 {
1351 #[inline]
1352 fn add_assign(&mut self, rhs: &Self) {
1353 self.add_assign(*rhs);
1354 }
1355}
1356
1357impl Sub for DMat4 {
1358 type Output = Self;
1359 #[inline]
1360 fn sub(self, rhs: Self) -> Self {
1361 Self::from_cols(
1362 self.x_axis.sub(rhs.x_axis),
1363 self.y_axis.sub(rhs.y_axis),
1364 self.z_axis.sub(rhs.z_axis),
1365 self.w_axis.sub(rhs.w_axis),
1366 )
1367 }
1368}
1369
1370impl Sub<&Self> for DMat4 {
1371 type Output = Self;
1372 #[inline]
1373 fn sub(self, rhs: &Self) -> Self {
1374 self.sub(*rhs)
1375 }
1376}
1377
1378impl Sub<&DMat4> for &DMat4 {
1379 type Output = DMat4;
1380 #[inline]
1381 fn sub(self, rhs: &DMat4) -> DMat4 {
1382 (*self).sub(*rhs)
1383 }
1384}
1385
1386impl Sub<DMat4> for &DMat4 {
1387 type Output = DMat4;
1388 #[inline]
1389 fn sub(self, rhs: DMat4) -> DMat4 {
1390 (*self).sub(rhs)
1391 }
1392}
1393
1394impl SubAssign for DMat4 {
1395 #[inline]
1396 fn sub_assign(&mut self, rhs: Self) {
1397 *self = self.sub(rhs);
1398 }
1399}
1400
1401impl SubAssign<&Self> for DMat4 {
1402 #[inline]
1403 fn sub_assign(&mut self, rhs: &Self) {
1404 self.sub_assign(*rhs);
1405 }
1406}
1407
1408impl Neg for DMat4 {
1409 type Output = Self;
1410 #[inline]
1411 fn neg(self) -> Self::Output {
1412 Self::from_cols(
1413 self.x_axis.neg(),
1414 self.y_axis.neg(),
1415 self.z_axis.neg(),
1416 self.w_axis.neg(),
1417 )
1418 }
1419}
1420
1421impl Neg for &DMat4 {
1422 type Output = DMat4;
1423 #[inline]
1424 fn neg(self) -> DMat4 {
1425 (*self).neg()
1426 }
1427}
1428
1429impl Mul for DMat4 {
1430 type Output = Self;
1431 #[inline]
1432 fn mul(self, rhs: Self) -> Self {
1433 Self::from_cols(
1434 self.mul(rhs.x_axis),
1435 self.mul(rhs.y_axis),
1436 self.mul(rhs.z_axis),
1437 self.mul(rhs.w_axis),
1438 )
1439 }
1440}
1441
1442impl Mul<&Self> for DMat4 {
1443 type Output = Self;
1444 #[inline]
1445 fn mul(self, rhs: &Self) -> Self {
1446 self.mul(*rhs)
1447 }
1448}
1449
1450impl Mul<&DMat4> for &DMat4 {
1451 type Output = DMat4;
1452 #[inline]
1453 fn mul(self, rhs: &DMat4) -> DMat4 {
1454 (*self).mul(*rhs)
1455 }
1456}
1457
1458impl Mul<DMat4> for &DMat4 {
1459 type Output = DMat4;
1460 #[inline]
1461 fn mul(self, rhs: DMat4) -> DMat4 {
1462 (*self).mul(rhs)
1463 }
1464}
1465
1466impl MulAssign for DMat4 {
1467 #[inline]
1468 fn mul_assign(&mut self, rhs: Self) {
1469 *self = self.mul(rhs);
1470 }
1471}
1472
1473impl MulAssign<&Self> for DMat4 {
1474 #[inline]
1475 fn mul_assign(&mut self, rhs: &Self) {
1476 self.mul_assign(*rhs);
1477 }
1478}
1479
1480impl Mul<DVec4> for DMat4 {
1481 type Output = DVec4;
1482 #[inline]
1483 fn mul(self, rhs: DVec4) -> Self::Output {
1484 self.mul_vec4(rhs)
1485 }
1486}
1487
1488impl Mul<&DVec4> for DMat4 {
1489 type Output = DVec4;
1490 #[inline]
1491 fn mul(self, rhs: &DVec4) -> DVec4 {
1492 self.mul(*rhs)
1493 }
1494}
1495
1496impl Mul<&DVec4> for &DMat4 {
1497 type Output = DVec4;
1498 #[inline]
1499 fn mul(self, rhs: &DVec4) -> DVec4 {
1500 (*self).mul(*rhs)
1501 }
1502}
1503
1504impl Mul<DVec4> for &DMat4 {
1505 type Output = DVec4;
1506 #[inline]
1507 fn mul(self, rhs: DVec4) -> DVec4 {
1508 (*self).mul(rhs)
1509 }
1510}
1511
1512impl Mul<DMat4> for f64 {
1513 type Output = DMat4;
1514 #[inline]
1515 fn mul(self, rhs: DMat4) -> Self::Output {
1516 rhs.mul_scalar(self)
1517 }
1518}
1519
1520impl Mul<&DMat4> for f64 {
1521 type Output = DMat4;
1522 #[inline]
1523 fn mul(self, rhs: &DMat4) -> DMat4 {
1524 self.mul(*rhs)
1525 }
1526}
1527
1528impl Mul<&DMat4> for &f64 {
1529 type Output = DMat4;
1530 #[inline]
1531 fn mul(self, rhs: &DMat4) -> DMat4 {
1532 (*self).mul(*rhs)
1533 }
1534}
1535
1536impl Mul<DMat4> for &f64 {
1537 type Output = DMat4;
1538 #[inline]
1539 fn mul(self, rhs: DMat4) -> DMat4 {
1540 (*self).mul(rhs)
1541 }
1542}
1543
1544impl Mul<f64> for DMat4 {
1545 type Output = Self;
1546 #[inline]
1547 fn mul(self, rhs: f64) -> Self {
1548 self.mul_scalar(rhs)
1549 }
1550}
1551
1552impl Mul<&f64> for DMat4 {
1553 type Output = Self;
1554 #[inline]
1555 fn mul(self, rhs: &f64) -> Self {
1556 self.mul(*rhs)
1557 }
1558}
1559
1560impl Mul<&f64> for &DMat4 {
1561 type Output = DMat4;
1562 #[inline]
1563 fn mul(self, rhs: &f64) -> DMat4 {
1564 (*self).mul(*rhs)
1565 }
1566}
1567
1568impl Mul<f64> for &DMat4 {
1569 type Output = DMat4;
1570 #[inline]
1571 fn mul(self, rhs: f64) -> DMat4 {
1572 (*self).mul(rhs)
1573 }
1574}
1575
1576impl MulAssign<f64> for DMat4 {
1577 #[inline]
1578 fn mul_assign(&mut self, rhs: f64) {
1579 *self = self.mul(rhs);
1580 }
1581}
1582
1583impl MulAssign<&f64> for DMat4 {
1584 #[inline]
1585 fn mul_assign(&mut self, rhs: &f64) {
1586 self.mul_assign(*rhs);
1587 }
1588}
1589
1590impl Div<DMat4> for f64 {
1591 type Output = DMat4;
1592 #[inline]
1593 fn div(self, rhs: DMat4) -> Self::Output {
1594 rhs.div_scalar(self)
1595 }
1596}
1597
1598impl Div<&DMat4> for f64 {
1599 type Output = DMat4;
1600 #[inline]
1601 fn div(self, rhs: &DMat4) -> DMat4 {
1602 self.div(*rhs)
1603 }
1604}
1605
1606impl Div<&DMat4> for &f64 {
1607 type Output = DMat4;
1608 #[inline]
1609 fn div(self, rhs: &DMat4) -> DMat4 {
1610 (*self).div(*rhs)
1611 }
1612}
1613
1614impl Div<DMat4> for &f64 {
1615 type Output = DMat4;
1616 #[inline]
1617 fn div(self, rhs: DMat4) -> DMat4 {
1618 (*self).div(rhs)
1619 }
1620}
1621
1622impl Div<f64> for DMat4 {
1623 type Output = Self;
1624 #[inline]
1625 fn div(self, rhs: f64) -> Self {
1626 self.div_scalar(rhs)
1627 }
1628}
1629
1630impl Div<&f64> for DMat4 {
1631 type Output = Self;
1632 #[inline]
1633 fn div(self, rhs: &f64) -> Self {
1634 self.div(*rhs)
1635 }
1636}
1637
1638impl Div<&f64> for &DMat4 {
1639 type Output = DMat4;
1640 #[inline]
1641 fn div(self, rhs: &f64) -> DMat4 {
1642 (*self).div(*rhs)
1643 }
1644}
1645
1646impl Div<f64> for &DMat4 {
1647 type Output = DMat4;
1648 #[inline]
1649 fn div(self, rhs: f64) -> DMat4 {
1650 (*self).div(rhs)
1651 }
1652}
1653
1654impl DivAssign<f64> for DMat4 {
1655 #[inline]
1656 fn div_assign(&mut self, rhs: f64) {
1657 *self = self.div(rhs);
1658 }
1659}
1660
1661impl DivAssign<&f64> for DMat4 {
1662 #[inline]
1663 fn div_assign(&mut self, rhs: &f64) {
1664 self.div_assign(*rhs);
1665 }
1666}
1667
1668impl Sum<Self> for DMat4 {
1669 fn sum<I>(iter: I) -> Self
1670 where
1671 I: Iterator<Item = Self>,
1672 {
1673 iter.fold(Self::ZERO, Self::add)
1674 }
1675}
1676
1677impl<'a> Sum<&'a Self> for DMat4 {
1678 fn sum<I>(iter: I) -> Self
1679 where
1680 I: Iterator<Item = &'a Self>,
1681 {
1682 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1683 }
1684}
1685
1686impl Product for DMat4 {
1687 fn product<I>(iter: I) -> Self
1688 where
1689 I: Iterator<Item = Self>,
1690 {
1691 iter.fold(Self::IDENTITY, Self::mul)
1692 }
1693}
1694
1695impl<'a> Product<&'a Self> for DMat4 {
1696 fn product<I>(iter: I) -> Self
1697 where
1698 I: Iterator<Item = &'a Self>,
1699 {
1700 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1701 }
1702}
1703
1704impl PartialEq for DMat4 {
1705 #[inline]
1706 fn eq(&self, rhs: &Self) -> bool {
1707 self.x_axis.eq(&rhs.x_axis)
1708 && self.y_axis.eq(&rhs.y_axis)
1709 && self.z_axis.eq(&rhs.z_axis)
1710 && self.w_axis.eq(&rhs.w_axis)
1711 }
1712}
1713
1714#[cfg(not(target_arch = "spirv"))]
1715impl AsRef<[f64; 16]> for DMat4 {
1716 #[inline]
1717 fn as_ref(&self) -> &[f64; 16] {
1718 unsafe { &*(self as *const Self as *const [f64; 16]) }
1719 }
1720}
1721
1722#[cfg(not(target_arch = "spirv"))]
1723impl AsMut<[f64; 16]> for DMat4 {
1724 #[inline]
1725 fn as_mut(&mut self) -> &mut [f64; 16] {
1726 unsafe { &mut *(self as *mut Self as *mut [f64; 16]) }
1727 }
1728}
1729
1730impl fmt::Debug for DMat4 {
1731 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1732 fmt.debug_struct(stringify!(DMat4))
1733 .field("x_axis", &self.x_axis)
1734 .field("y_axis", &self.y_axis)
1735 .field("z_axis", &self.z_axis)
1736 .field("w_axis", &self.w_axis)
1737 .finish()
1738 }
1739}
1740
1741impl fmt::Display for DMat4 {
1742 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1743 if let Some(p) = f.precision() {
1744 write!(
1745 f,
1746 "[{:.*}, {:.*}, {:.*}, {:.*}]",
1747 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
1748 )
1749 } else {
1750 write!(
1751 f,
1752 "[{}, {}, {}, {}]",
1753 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1754 )
1755 }
1756 }
1757}