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 = "cuda", repr(align(16)))]
51#[repr(C)]
52pub struct DMat4 {
53 pub x_axis: DVec4,
54 pub y_axis: DVec4,
55 pub z_axis: DVec4,
56 pub w_axis: DVec4,
57}
58
59impl DMat4 {
60 pub const ZERO: Self = Self::from_cols(DVec4::ZERO, DVec4::ZERO, DVec4::ZERO, DVec4::ZERO);
62
63 pub const IDENTITY: Self = Self::from_cols(DVec4::X, DVec4::Y, DVec4::Z, DVec4::W);
65
66 pub const NAN: Self = Self::from_cols(DVec4::NAN, DVec4::NAN, DVec4::NAN, DVec4::NAN);
68
69 #[allow(clippy::too_many_arguments)]
70 #[inline(always)]
71 #[must_use]
72 const fn new(
73 m00: f64,
74 m01: f64,
75 m02: f64,
76 m03: f64,
77 m10: f64,
78 m11: f64,
79 m12: f64,
80 m13: f64,
81 m20: f64,
82 m21: f64,
83 m22: f64,
84 m23: f64,
85 m30: f64,
86 m31: f64,
87 m32: f64,
88 m33: f64,
89 ) -> Self {
90 Self {
91 x_axis: DVec4::new(m00, m01, m02, m03),
92 y_axis: DVec4::new(m10, m11, m12, m13),
93 z_axis: DVec4::new(m20, m21, m22, m23),
94 w_axis: DVec4::new(m30, m31, m32, m33),
95 }
96 }
97
98 #[inline(always)]
100 #[must_use]
101 pub const fn from_cols(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> Self {
102 Self {
103 x_axis,
104 y_axis,
105 z_axis,
106 w_axis,
107 }
108 }
109
110 #[inline]
114 #[must_use]
115 pub const fn from_cols_array(m: &[f64; 16]) -> Self {
116 Self::new(
117 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],
118 m[14], m[15],
119 )
120 }
121
122 #[inline]
125 #[must_use]
126 pub const fn to_cols_array(&self) -> [f64; 16] {
127 [
128 self.x_axis.x,
129 self.x_axis.y,
130 self.x_axis.z,
131 self.x_axis.w,
132 self.y_axis.x,
133 self.y_axis.y,
134 self.y_axis.z,
135 self.y_axis.w,
136 self.z_axis.x,
137 self.z_axis.y,
138 self.z_axis.z,
139 self.z_axis.w,
140 self.w_axis.x,
141 self.w_axis.y,
142 self.w_axis.z,
143 self.w_axis.w,
144 ]
145 }
146
147 #[inline]
151 #[must_use]
152 pub const fn from_cols_array_2d(m: &[[f64; 4]; 4]) -> Self {
153 Self::from_cols(
154 DVec4::from_array(m[0]),
155 DVec4::from_array(m[1]),
156 DVec4::from_array(m[2]),
157 DVec4::from_array(m[3]),
158 )
159 }
160
161 #[inline]
164 #[must_use]
165 pub const fn to_cols_array_2d(&self) -> [[f64; 4]; 4] {
166 [
167 self.x_axis.to_array(),
168 self.y_axis.to_array(),
169 self.z_axis.to_array(),
170 self.w_axis.to_array(),
171 ]
172 }
173
174 #[doc(alias = "scale")]
176 #[inline]
177 #[must_use]
178 pub const fn from_diagonal(diagonal: DVec4) -> Self {
179 Self::new(
180 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,
181 0.0, 0.0, diagonal.w,
182 )
183 }
184
185 #[inline]
186 #[must_use]
187 fn quat_to_axes(rotation: DQuat) -> (DVec4, DVec4, DVec4) {
188 glam_assert!(rotation.is_normalized());
189
190 let (x, y, z, w) = rotation.into();
191 let x2 = x + x;
192 let y2 = y + y;
193 let z2 = z + z;
194 let xx = x * x2;
195 let xy = x * y2;
196 let xz = x * z2;
197 let yy = y * y2;
198 let yz = y * z2;
199 let zz = z * z2;
200 let wx = w * x2;
201 let wy = w * y2;
202 let wz = w * z2;
203
204 let x_axis = DVec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
205 let y_axis = DVec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
206 let z_axis = DVec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
207 (x_axis, y_axis, z_axis)
208 }
209
210 #[inline]
220 #[must_use]
221 pub fn from_scale_rotation_translation(
222 scale: DVec3,
223 rotation: DQuat,
224 translation: DVec3,
225 ) -> Self {
226 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
227 Self::from_cols(
228 x_axis.mul(scale.x),
229 y_axis.mul(scale.y),
230 z_axis.mul(scale.z),
231 DVec4::from((translation, 1.0)),
232 )
233 }
234
235 #[inline]
244 #[must_use]
245 pub fn from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self {
246 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
247 Self::from_cols(x_axis, y_axis, z_axis, DVec4::from((translation, 1.0)))
248 }
249
250 #[inline]
258 #[must_use]
259 pub fn to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3) {
260 let det = self.determinant();
261 glam_assert!(det != 0.0);
262
263 let scale = DVec3::new(
264 self.x_axis.length() * math::signum(det),
265 self.y_axis.length(),
266 self.z_axis.length(),
267 );
268
269 glam_assert!(scale.cmpne(DVec3::ZERO).all());
270
271 let inv_scale = scale.recip();
272
273 let rotation = DQuat::from_rotation_axes(
274 self.x_axis.mul(inv_scale.x).xyz(),
275 self.y_axis.mul(inv_scale.y).xyz(),
276 self.z_axis.mul(inv_scale.z).xyz(),
277 );
278
279 let translation = self.w_axis.xyz();
280
281 (scale, rotation, translation)
282 }
283
284 #[inline]
293 #[must_use]
294 pub fn from_quat(rotation: DQuat) -> Self {
295 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
296 Self::from_cols(x_axis, y_axis, z_axis, DVec4::W)
297 }
298
299 #[inline]
305 #[must_use]
306 pub fn from_mat3(m: DMat3) -> Self {
307 Self::from_cols(
308 DVec4::from((m.x_axis, 0.0)),
309 DVec4::from((m.y_axis, 0.0)),
310 DVec4::from((m.z_axis, 0.0)),
311 DVec4::W,
312 )
313 }
314
315 #[inline]
320 #[must_use]
321 pub fn from_translation(translation: DVec3) -> Self {
322 Self::from_cols(
323 DVec4::X,
324 DVec4::Y,
325 DVec4::Z,
326 DVec4::new(translation.x, translation.y, translation.z, 1.0),
327 )
328 }
329
330 #[inline]
340 #[must_use]
341 pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
342 glam_assert!(axis.is_normalized());
343
344 let (sin, cos) = math::sin_cos(angle);
345 let axis_sin = axis.mul(sin);
346 let axis_sq = axis.mul(axis);
347 let omc = 1.0 - cos;
348 let xyomc = axis.x * axis.y * omc;
349 let xzomc = axis.x * axis.z * omc;
350 let yzomc = axis.y * axis.z * omc;
351 Self::from_cols(
352 DVec4::new(
353 axis_sq.x * omc + cos,
354 xyomc + axis_sin.z,
355 xzomc - axis_sin.y,
356 0.0,
357 ),
358 DVec4::new(
359 xyomc - axis_sin.z,
360 axis_sq.y * omc + cos,
361 yzomc + axis_sin.x,
362 0.0,
363 ),
364 DVec4::new(
365 xzomc + axis_sin.y,
366 yzomc - axis_sin.x,
367 axis_sq.z * omc + cos,
368 0.0,
369 ),
370 DVec4::W,
371 )
372 }
373
374 #[inline]
380 #[must_use]
381 pub fn from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self {
382 Self::from_euler_angles(order, a, b, c)
383 }
384
385 #[inline]
395 #[must_use]
396 pub fn to_euler(&self, order: EulerRot) -> (f64, f64, f64) {
397 glam_assert!(
398 self.x_axis.xyz().is_normalized()
399 && self.y_axis.xyz().is_normalized()
400 && self.z_axis.xyz().is_normalized()
401 );
402 self.to_euler_angles(order)
403 }
404
405 #[inline]
411 #[must_use]
412 pub fn from_rotation_x(angle: f64) -> Self {
413 let (sina, cosa) = math::sin_cos(angle);
414 Self::from_cols(
415 DVec4::X,
416 DVec4::new(0.0, cosa, sina, 0.0),
417 DVec4::new(0.0, -sina, cosa, 0.0),
418 DVec4::W,
419 )
420 }
421
422 #[inline]
428 #[must_use]
429 pub fn from_rotation_y(angle: f64) -> Self {
430 let (sina, cosa) = math::sin_cos(angle);
431 Self::from_cols(
432 DVec4::new(cosa, 0.0, -sina, 0.0),
433 DVec4::Y,
434 DVec4::new(sina, 0.0, cosa, 0.0),
435 DVec4::W,
436 )
437 }
438
439 #[inline]
445 #[must_use]
446 pub fn from_rotation_z(angle: f64) -> Self {
447 let (sina, cosa) = math::sin_cos(angle);
448 Self::from_cols(
449 DVec4::new(cosa, sina, 0.0, 0.0),
450 DVec4::new(-sina, cosa, 0.0, 0.0),
451 DVec4::Z,
452 DVec4::W,
453 )
454 }
455
456 #[inline]
465 #[must_use]
466 pub fn from_scale(scale: DVec3) -> Self {
467 glam_assert!(scale.cmpne(DVec3::ZERO).any());
469
470 Self::from_cols(
471 DVec4::new(scale.x, 0.0, 0.0, 0.0),
472 DVec4::new(0.0, scale.y, 0.0, 0.0),
473 DVec4::new(0.0, 0.0, scale.z, 0.0),
474 DVec4::W,
475 )
476 }
477
478 #[inline]
484 #[must_use]
485 pub const fn from_cols_slice(slice: &[f64]) -> Self {
486 Self::new(
487 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
488 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
489 )
490 }
491
492 #[inline]
498 pub fn write_cols_to_slice(self, slice: &mut [f64]) {
499 slice[0] = self.x_axis.x;
500 slice[1] = self.x_axis.y;
501 slice[2] = self.x_axis.z;
502 slice[3] = self.x_axis.w;
503 slice[4] = self.y_axis.x;
504 slice[5] = self.y_axis.y;
505 slice[6] = self.y_axis.z;
506 slice[7] = self.y_axis.w;
507 slice[8] = self.z_axis.x;
508 slice[9] = self.z_axis.y;
509 slice[10] = self.z_axis.z;
510 slice[11] = self.z_axis.w;
511 slice[12] = self.w_axis.x;
512 slice[13] = self.w_axis.y;
513 slice[14] = self.w_axis.z;
514 slice[15] = self.w_axis.w;
515 }
516
517 #[inline]
523 #[must_use]
524 pub fn col(&self, index: usize) -> DVec4 {
525 match index {
526 0 => self.x_axis,
527 1 => self.y_axis,
528 2 => self.z_axis,
529 3 => self.w_axis,
530 _ => panic!("index out of bounds"),
531 }
532 }
533
534 #[inline]
540 pub fn col_mut(&mut self, index: usize) -> &mut DVec4 {
541 match index {
542 0 => &mut self.x_axis,
543 1 => &mut self.y_axis,
544 2 => &mut self.z_axis,
545 3 => &mut self.w_axis,
546 _ => panic!("index out of bounds"),
547 }
548 }
549
550 #[inline]
556 #[must_use]
557 pub fn row(&self, index: usize) -> DVec4 {
558 match index {
559 0 => DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
560 1 => DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
561 2 => DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
562 3 => DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
563 _ => panic!("index out of bounds"),
564 }
565 }
566
567 #[inline]
570 #[must_use]
571 pub fn is_finite(&self) -> bool {
572 self.x_axis.is_finite()
573 && self.y_axis.is_finite()
574 && self.z_axis.is_finite()
575 && self.w_axis.is_finite()
576 }
577
578 #[inline]
580 #[must_use]
581 pub fn is_nan(&self) -> bool {
582 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
583 }
584
585 #[inline]
587 #[must_use]
588 pub fn transpose(&self) -> Self {
589 Self {
590 x_axis: DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
591 y_axis: DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
592 z_axis: DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
593 w_axis: DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
594 }
595 }
596
597 #[must_use]
599 pub fn determinant(&self) -> f64 {
600 let (m00, m01, m02, m03) = self.x_axis.into();
601 let (m10, m11, m12, m13) = self.y_axis.into();
602 let (m20, m21, m22, m23) = self.z_axis.into();
603 let (m30, m31, m32, m33) = self.w_axis.into();
604
605 let a2323 = m22 * m33 - m23 * m32;
606 let a1323 = m21 * m33 - m23 * m31;
607 let a1223 = m21 * m32 - m22 * m31;
608 let a0323 = m20 * m33 - m23 * m30;
609 let a0223 = m20 * m32 - m22 * m30;
610 let a0123 = m20 * m31 - m21 * m30;
611
612 m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223)
613 - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223)
614 + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123)
615 - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123)
616 }
617
618 #[must_use]
626 pub fn inverse(&self) -> Self {
627 let (m00, m01, m02, m03) = self.x_axis.into();
628 let (m10, m11, m12, m13) = self.y_axis.into();
629 let (m20, m21, m22, m23) = self.z_axis.into();
630 let (m30, m31, m32, m33) = self.w_axis.into();
631
632 let coef00 = m22 * m33 - m32 * m23;
633 let coef02 = m12 * m33 - m32 * m13;
634 let coef03 = m12 * m23 - m22 * m13;
635
636 let coef04 = m21 * m33 - m31 * m23;
637 let coef06 = m11 * m33 - m31 * m13;
638 let coef07 = m11 * m23 - m21 * m13;
639
640 let coef08 = m21 * m32 - m31 * m22;
641 let coef10 = m11 * m32 - m31 * m12;
642 let coef11 = m11 * m22 - m21 * m12;
643
644 let coef12 = m20 * m33 - m30 * m23;
645 let coef14 = m10 * m33 - m30 * m13;
646 let coef15 = m10 * m23 - m20 * m13;
647
648 let coef16 = m20 * m32 - m30 * m22;
649 let coef18 = m10 * m32 - m30 * m12;
650 let coef19 = m10 * m22 - m20 * m12;
651
652 let coef20 = m20 * m31 - m30 * m21;
653 let coef22 = m10 * m31 - m30 * m11;
654 let coef23 = m10 * m21 - m20 * m11;
655
656 let fac0 = DVec4::new(coef00, coef00, coef02, coef03);
657 let fac1 = DVec4::new(coef04, coef04, coef06, coef07);
658 let fac2 = DVec4::new(coef08, coef08, coef10, coef11);
659 let fac3 = DVec4::new(coef12, coef12, coef14, coef15);
660 let fac4 = DVec4::new(coef16, coef16, coef18, coef19);
661 let fac5 = DVec4::new(coef20, coef20, coef22, coef23);
662
663 let vec0 = DVec4::new(m10, m00, m00, m00);
664 let vec1 = DVec4::new(m11, m01, m01, m01);
665 let vec2 = DVec4::new(m12, m02, m02, m02);
666 let vec3 = DVec4::new(m13, m03, m03, m03);
667
668 let inv0 = vec1.mul(fac0).sub(vec2.mul(fac1)).add(vec3.mul(fac2));
669 let inv1 = vec0.mul(fac0).sub(vec2.mul(fac3)).add(vec3.mul(fac4));
670 let inv2 = vec0.mul(fac1).sub(vec1.mul(fac3)).add(vec3.mul(fac5));
671 let inv3 = vec0.mul(fac2).sub(vec1.mul(fac4)).add(vec2.mul(fac5));
672
673 let sign_a = DVec4::new(1.0, -1.0, 1.0, -1.0);
674 let sign_b = DVec4::new(-1.0, 1.0, -1.0, 1.0);
675
676 let inverse = Self::from_cols(
677 inv0.mul(sign_a),
678 inv1.mul(sign_b),
679 inv2.mul(sign_a),
680 inv3.mul(sign_b),
681 );
682
683 let col0 = DVec4::new(
684 inverse.x_axis.x,
685 inverse.y_axis.x,
686 inverse.z_axis.x,
687 inverse.w_axis.x,
688 );
689
690 let dot0 = self.x_axis.mul(col0);
691 let dot1 = dot0.x + dot0.y + dot0.z + dot0.w;
692
693 glam_assert!(dot1 != 0.0);
694
695 let rcp_det = dot1.recip();
696 inverse.mul(rcp_det)
697 }
698
699 #[inline]
704 #[must_use]
705 pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
706 Self::look_to_rh(eye, -dir, up)
707 }
708
709 #[inline]
714 #[must_use]
715 pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
716 let f = dir.normalize();
717 let s = f.cross(up).normalize();
718 let u = s.cross(f);
719
720 Self::from_cols(
721 DVec4::new(s.x, u.x, -f.x, 0.0),
722 DVec4::new(s.y, u.y, -f.y, 0.0),
723 DVec4::new(s.z, u.z, -f.z, 0.0),
724 DVec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
725 )
726 }
727
728 #[inline]
736 #[must_use]
737 pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
738 glam_assert!(up.is_normalized());
739 Self::look_to_lh(eye, center.sub(eye), up)
740 }
741
742 #[inline]
750 pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
751 glam_assert!(up.is_normalized());
752 Self::look_to_rh(eye, center.sub(eye), up)
753 }
754
755 #[inline]
762 #[must_use]
763 pub fn perspective_rh_gl(
764 fov_y_radians: f64,
765 aspect_ratio: f64,
766 z_near: f64,
767 z_far: f64,
768 ) -> Self {
769 let inv_length = 1.0 / (z_near - z_far);
770 let f = 1.0 / math::tan(0.5 * fov_y_radians);
771 let a = f / aspect_ratio;
772 let b = (z_near + z_far) * inv_length;
773 let c = (2.0 * z_near * z_far) * inv_length;
774 Self::from_cols(
775 DVec4::new(a, 0.0, 0.0, 0.0),
776 DVec4::new(0.0, f, 0.0, 0.0),
777 DVec4::new(0.0, 0.0, b, -1.0),
778 DVec4::new(0.0, 0.0, c, 0.0),
779 )
780 }
781
782 #[inline]
791 #[must_use]
792 pub fn perspective_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
793 glam_assert!(z_near > 0.0 && z_far > 0.0);
794 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
795 let h = cos_fov / sin_fov;
796 let w = h / aspect_ratio;
797 let r = z_far / (z_far - z_near);
798 Self::from_cols(
799 DVec4::new(w, 0.0, 0.0, 0.0),
800 DVec4::new(0.0, h, 0.0, 0.0),
801 DVec4::new(0.0, 0.0, r, 1.0),
802 DVec4::new(0.0, 0.0, -r * z_near, 0.0),
803 )
804 }
805
806 #[inline]
815 #[must_use]
816 pub fn perspective_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
817 glam_assert!(z_near > 0.0 && z_far > 0.0);
818 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
819 let h = cos_fov / sin_fov;
820 let w = h / aspect_ratio;
821 let r = z_far / (z_near - z_far);
822 Self::from_cols(
823 DVec4::new(w, 0.0, 0.0, 0.0),
824 DVec4::new(0.0, h, 0.0, 0.0),
825 DVec4::new(0.0, 0.0, r, -1.0),
826 DVec4::new(0.0, 0.0, r * z_near, 0.0),
827 )
828 }
829
830 #[inline]
840 #[must_use]
841 pub fn perspective_infinite_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
842 glam_assert!(z_near > 0.0);
843 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
844 let h = cos_fov / sin_fov;
845 let w = h / aspect_ratio;
846 Self::from_cols(
847 DVec4::new(w, 0.0, 0.0, 0.0),
848 DVec4::new(0.0, h, 0.0, 0.0),
849 DVec4::new(0.0, 0.0, 1.0, 1.0),
850 DVec4::new(0.0, 0.0, -z_near, 0.0),
851 )
852 }
853
854 #[inline]
862 #[must_use]
863 pub fn perspective_infinite_reverse_lh(
864 fov_y_radians: f64,
865 aspect_ratio: f64,
866 z_near: f64,
867 ) -> Self {
868 glam_assert!(z_near > 0.0);
869 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
870 let h = cos_fov / sin_fov;
871 let w = h / aspect_ratio;
872 Self::from_cols(
873 DVec4::new(w, 0.0, 0.0, 0.0),
874 DVec4::new(0.0, h, 0.0, 0.0),
875 DVec4::new(0.0, 0.0, 0.0, 1.0),
876 DVec4::new(0.0, 0.0, z_near, 0.0),
877 )
878 }
879
880 #[inline]
890 #[must_use]
891 pub fn perspective_infinite_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
892 glam_assert!(z_near > 0.0);
893 let f = 1.0 / math::tan(0.5 * fov_y_radians);
894 Self::from_cols(
895 DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
896 DVec4::new(0.0, f, 0.0, 0.0),
897 DVec4::new(0.0, 0.0, -1.0, -1.0),
898 DVec4::new(0.0, 0.0, -z_near, 0.0),
899 )
900 }
901
902 #[inline]
910 #[must_use]
911 pub fn perspective_infinite_reverse_rh(
912 fov_y_radians: f64,
913 aspect_ratio: f64,
914 z_near: f64,
915 ) -> Self {
916 glam_assert!(z_near > 0.0);
917 let f = 1.0 / math::tan(0.5 * fov_y_radians);
918 Self::from_cols(
919 DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
920 DVec4::new(0.0, f, 0.0, 0.0),
921 DVec4::new(0.0, 0.0, 0.0, -1.0),
922 DVec4::new(0.0, 0.0, z_near, 0.0),
923 )
924 }
925
926 #[inline]
933 #[must_use]
934 pub fn orthographic_rh_gl(
935 left: f64,
936 right: f64,
937 bottom: f64,
938 top: f64,
939 near: f64,
940 far: f64,
941 ) -> Self {
942 let a = 2.0 / (right - left);
943 let b = 2.0 / (top - bottom);
944 let c = -2.0 / (far - near);
945 let tx = -(right + left) / (right - left);
946 let ty = -(top + bottom) / (top - bottom);
947 let tz = -(far + near) / (far - near);
948
949 Self::from_cols(
950 DVec4::new(a, 0.0, 0.0, 0.0),
951 DVec4::new(0.0, b, 0.0, 0.0),
952 DVec4::new(0.0, 0.0, c, 0.0),
953 DVec4::new(tx, ty, tz, 1.0),
954 )
955 }
956
957 #[inline]
961 #[must_use]
962 pub fn orthographic_lh(
963 left: f64,
964 right: f64,
965 bottom: f64,
966 top: f64,
967 near: f64,
968 far: f64,
969 ) -> Self {
970 let rcp_width = 1.0 / (right - left);
971 let rcp_height = 1.0 / (top - bottom);
972 let r = 1.0 / (far - near);
973 Self::from_cols(
974 DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
975 DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
976 DVec4::new(0.0, 0.0, r, 0.0),
977 DVec4::new(
978 -(left + right) * rcp_width,
979 -(top + bottom) * rcp_height,
980 -r * near,
981 1.0,
982 ),
983 )
984 }
985
986 #[inline]
990 #[must_use]
991 pub fn orthographic_rh(
992 left: f64,
993 right: f64,
994 bottom: f64,
995 top: f64,
996 near: f64,
997 far: f64,
998 ) -> Self {
999 let rcp_width = 1.0 / (right - left);
1000 let rcp_height = 1.0 / (top - bottom);
1001 let r = 1.0 / (near - far);
1002 Self::from_cols(
1003 DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1004 DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1005 DVec4::new(0.0, 0.0, r, 0.0),
1006 DVec4::new(
1007 -(left + right) * rcp_width,
1008 -(top + bottom) * rcp_height,
1009 r * near,
1010 1.0,
1011 ),
1012 )
1013 }
1014
1015 #[inline]
1022 #[must_use]
1023 pub fn project_point3(&self, rhs: DVec3) -> DVec3 {
1024 let mut res = self.x_axis.mul(rhs.x);
1025 res = self.y_axis.mul(rhs.y).add(res);
1026 res = self.z_axis.mul(rhs.z).add(res);
1027 res = self.w_axis.add(res);
1028 res = res.div(res.w);
1029 res.xyz()
1030 }
1031
1032 #[inline]
1045 #[must_use]
1046 pub fn transform_point3(&self, rhs: DVec3) -> DVec3 {
1047 glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
1048 let mut res = self.x_axis.mul(rhs.x);
1049 res = self.y_axis.mul(rhs.y).add(res);
1050 res = self.z_axis.mul(rhs.z).add(res);
1051 res = self.w_axis.add(res);
1052 res.xyz()
1053 }
1054
1055 #[inline]
1066 #[must_use]
1067 pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 {
1068 glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
1069 let mut res = self.x_axis.mul(rhs.x);
1070 res = self.y_axis.mul(rhs.y).add(res);
1071 res = self.z_axis.mul(rhs.z).add(res);
1072 res.xyz()
1073 }
1074
1075 #[inline]
1077 #[must_use]
1078 pub fn mul_vec4(&self, rhs: DVec4) -> DVec4 {
1079 let mut res = self.x_axis.mul(rhs.x);
1080 res = res.add(self.y_axis.mul(rhs.y));
1081 res = res.add(self.z_axis.mul(rhs.z));
1082 res = res.add(self.w_axis.mul(rhs.w));
1083 res
1084 }
1085
1086 #[inline]
1088 #[must_use]
1089 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1090 Self::from_cols(
1091 self.mul(rhs.x_axis),
1092 self.mul(rhs.y_axis),
1093 self.mul(rhs.z_axis),
1094 self.mul(rhs.w_axis),
1095 )
1096 }
1097
1098 #[inline]
1100 #[must_use]
1101 pub fn add_mat4(&self, rhs: &Self) -> Self {
1102 Self::from_cols(
1103 self.x_axis.add(rhs.x_axis),
1104 self.y_axis.add(rhs.y_axis),
1105 self.z_axis.add(rhs.z_axis),
1106 self.w_axis.add(rhs.w_axis),
1107 )
1108 }
1109
1110 #[inline]
1112 #[must_use]
1113 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1114 Self::from_cols(
1115 self.x_axis.sub(rhs.x_axis),
1116 self.y_axis.sub(rhs.y_axis),
1117 self.z_axis.sub(rhs.z_axis),
1118 self.w_axis.sub(rhs.w_axis),
1119 )
1120 }
1121
1122 #[inline]
1124 #[must_use]
1125 pub fn mul_scalar(&self, rhs: f64) -> Self {
1126 Self::from_cols(
1127 self.x_axis.mul(rhs),
1128 self.y_axis.mul(rhs),
1129 self.z_axis.mul(rhs),
1130 self.w_axis.mul(rhs),
1131 )
1132 }
1133
1134 #[inline]
1136 #[must_use]
1137 pub fn div_scalar(&self, rhs: f64) -> Self {
1138 let rhs = DVec4::splat(rhs);
1139 Self::from_cols(
1140 self.x_axis.div(rhs),
1141 self.y_axis.div(rhs),
1142 self.z_axis.div(rhs),
1143 self.w_axis.div(rhs),
1144 )
1145 }
1146
1147 #[inline]
1157 #[must_use]
1158 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
1159 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1160 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1161 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1162 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1163 }
1164
1165 #[inline]
1167 #[must_use]
1168 pub fn abs(&self) -> Self {
1169 Self::from_cols(
1170 self.x_axis.abs(),
1171 self.y_axis.abs(),
1172 self.z_axis.abs(),
1173 self.w_axis.abs(),
1174 )
1175 }
1176
1177 #[inline]
1178 pub fn as_mat4(&self) -> Mat4 {
1179 Mat4::from_cols(
1180 self.x_axis.as_vec4(),
1181 self.y_axis.as_vec4(),
1182 self.z_axis.as_vec4(),
1183 self.w_axis.as_vec4(),
1184 )
1185 }
1186}
1187
1188impl Default for DMat4 {
1189 #[inline]
1190 fn default() -> Self {
1191 Self::IDENTITY
1192 }
1193}
1194
1195impl Add<DMat4> for DMat4 {
1196 type Output = Self;
1197 #[inline]
1198 fn add(self, rhs: Self) -> Self::Output {
1199 self.add_mat4(&rhs)
1200 }
1201}
1202
1203impl AddAssign<DMat4> for DMat4 {
1204 #[inline]
1205 fn add_assign(&mut self, rhs: Self) {
1206 *self = self.add_mat4(&rhs);
1207 }
1208}
1209
1210impl Sub<DMat4> for DMat4 {
1211 type Output = Self;
1212 #[inline]
1213 fn sub(self, rhs: Self) -> Self::Output {
1214 self.sub_mat4(&rhs)
1215 }
1216}
1217
1218impl SubAssign<DMat4> for DMat4 {
1219 #[inline]
1220 fn sub_assign(&mut self, rhs: Self) {
1221 *self = self.sub_mat4(&rhs);
1222 }
1223}
1224
1225impl Neg for DMat4 {
1226 type Output = Self;
1227 #[inline]
1228 fn neg(self) -> Self::Output {
1229 Self::from_cols(
1230 self.x_axis.neg(),
1231 self.y_axis.neg(),
1232 self.z_axis.neg(),
1233 self.w_axis.neg(),
1234 )
1235 }
1236}
1237
1238impl Mul<DMat4> for DMat4 {
1239 type Output = Self;
1240 #[inline]
1241 fn mul(self, rhs: Self) -> Self::Output {
1242 self.mul_mat4(&rhs)
1243 }
1244}
1245
1246impl MulAssign<DMat4> for DMat4 {
1247 #[inline]
1248 fn mul_assign(&mut self, rhs: Self) {
1249 *self = self.mul_mat4(&rhs);
1250 }
1251}
1252
1253impl Mul<DVec4> for DMat4 {
1254 type Output = DVec4;
1255 #[inline]
1256 fn mul(self, rhs: DVec4) -> Self::Output {
1257 self.mul_vec4(rhs)
1258 }
1259}
1260
1261impl Mul<DMat4> for f64 {
1262 type Output = DMat4;
1263 #[inline]
1264 fn mul(self, rhs: DMat4) -> Self::Output {
1265 rhs.mul_scalar(self)
1266 }
1267}
1268
1269impl Mul<f64> for DMat4 {
1270 type Output = Self;
1271 #[inline]
1272 fn mul(self, rhs: f64) -> Self::Output {
1273 self.mul_scalar(rhs)
1274 }
1275}
1276
1277impl MulAssign<f64> for DMat4 {
1278 #[inline]
1279 fn mul_assign(&mut self, rhs: f64) {
1280 *self = self.mul_scalar(rhs);
1281 }
1282}
1283
1284impl Div<DMat4> for f64 {
1285 type Output = DMat4;
1286 #[inline]
1287 fn div(self, rhs: DMat4) -> Self::Output {
1288 rhs.div_scalar(self)
1289 }
1290}
1291
1292impl Div<f64> for DMat4 {
1293 type Output = Self;
1294 #[inline]
1295 fn div(self, rhs: f64) -> Self::Output {
1296 self.div_scalar(rhs)
1297 }
1298}
1299
1300impl DivAssign<f64> for DMat4 {
1301 #[inline]
1302 fn div_assign(&mut self, rhs: f64) {
1303 *self = self.div_scalar(rhs);
1304 }
1305}
1306
1307impl Sum<Self> for DMat4 {
1308 fn sum<I>(iter: I) -> Self
1309 where
1310 I: Iterator<Item = Self>,
1311 {
1312 iter.fold(Self::ZERO, Self::add)
1313 }
1314}
1315
1316impl<'a> Sum<&'a Self> for DMat4 {
1317 fn sum<I>(iter: I) -> Self
1318 where
1319 I: Iterator<Item = &'a Self>,
1320 {
1321 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1322 }
1323}
1324
1325impl Product for DMat4 {
1326 fn product<I>(iter: I) -> Self
1327 where
1328 I: Iterator<Item = Self>,
1329 {
1330 iter.fold(Self::IDENTITY, Self::mul)
1331 }
1332}
1333
1334impl<'a> Product<&'a Self> for DMat4 {
1335 fn product<I>(iter: I) -> Self
1336 where
1337 I: Iterator<Item = &'a Self>,
1338 {
1339 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1340 }
1341}
1342
1343impl PartialEq for DMat4 {
1344 #[inline]
1345 fn eq(&self, rhs: &Self) -> bool {
1346 self.x_axis.eq(&rhs.x_axis)
1347 && self.y_axis.eq(&rhs.y_axis)
1348 && self.z_axis.eq(&rhs.z_axis)
1349 && self.w_axis.eq(&rhs.w_axis)
1350 }
1351}
1352
1353#[cfg(not(target_arch = "spirv"))]
1354impl AsRef<[f64; 16]> for DMat4 {
1355 #[inline]
1356 fn as_ref(&self) -> &[f64; 16] {
1357 unsafe { &*(self as *const Self as *const [f64; 16]) }
1358 }
1359}
1360
1361#[cfg(not(target_arch = "spirv"))]
1362impl AsMut<[f64; 16]> for DMat4 {
1363 #[inline]
1364 fn as_mut(&mut self) -> &mut [f64; 16] {
1365 unsafe { &mut *(self as *mut Self as *mut [f64; 16]) }
1366 }
1367}
1368
1369impl fmt::Debug for DMat4 {
1370 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1371 fmt.debug_struct(stringify!(DMat4))
1372 .field("x_axis", &self.x_axis)
1373 .field("y_axis", &self.y_axis)
1374 .field("z_axis", &self.z_axis)
1375 .field("w_axis", &self.w_axis)
1376 .finish()
1377 }
1378}
1379
1380impl fmt::Display for DMat4 {
1381 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1382 if let Some(p) = f.precision() {
1383 write!(
1384 f,
1385 "[{:.*}, {:.*}, {:.*}, {:.*}]",
1386 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
1387 )
1388 } else {
1389 write!(
1390 f,
1391 "[{}, {}, {}, {}]",
1392 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1393 )
1394 }
1395 }
1396}