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