1use crate::{
4 euler::{FromEuler, ToEuler},
5 f64::math,
6 swizzles::*,
7 DMat3, DQuat, DVec3, DVec4, EulerRot, Mat4,
8};
9use core::fmt;
10use core::iter::{Product, Sum};
11use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
12
13#[cfg(feature = "zerocopy")]
14use zerocopy_derive::*;
15
16#[inline(always)]
18#[must_use]
19pub const fn dmat4(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> DMat4 {
20 DMat4::from_cols(x_axis, y_axis, z_axis, w_axis)
21}
22
23#[derive(Clone, Copy)]
39#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
40#[cfg_attr(
41 feature = "zerocopy",
42 derive(FromBytes, Immutable, IntoBytes, KnownLayout)
43)]
44#[cfg_attr(feature = "cuda", repr(align(16)))]
45#[repr(C)]
46pub struct DMat4 {
47 pub x_axis: DVec4,
48 pub y_axis: DVec4,
49 pub z_axis: DVec4,
50 pub w_axis: DVec4,
51}
52
53impl DMat4 {
54 pub const ZERO: Self = Self::from_cols(DVec4::ZERO, DVec4::ZERO, DVec4::ZERO, DVec4::ZERO);
56
57 pub const IDENTITY: Self = Self::from_cols(DVec4::X, DVec4::Y, DVec4::Z, DVec4::W);
59
60 pub const NAN: Self = Self::from_cols(DVec4::NAN, DVec4::NAN, DVec4::NAN, DVec4::NAN);
62
63 #[allow(clippy::too_many_arguments)]
64 #[inline(always)]
65 #[must_use]
66 const fn new(
67 m00: f64,
68 m01: f64,
69 m02: f64,
70 m03: f64,
71 m10: f64,
72 m11: f64,
73 m12: f64,
74 m13: f64,
75 m20: f64,
76 m21: f64,
77 m22: f64,
78 m23: f64,
79 m30: f64,
80 m31: f64,
81 m32: f64,
82 m33: f64,
83 ) -> Self {
84 Self {
85 x_axis: DVec4::new(m00, m01, m02, m03),
86 y_axis: DVec4::new(m10, m11, m12, m13),
87 z_axis: DVec4::new(m20, m21, m22, m23),
88 w_axis: DVec4::new(m30, m31, m32, m33),
89 }
90 }
91
92 #[inline(always)]
94 #[must_use]
95 pub const fn from_cols(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> Self {
96 Self {
97 x_axis,
98 y_axis,
99 z_axis,
100 w_axis,
101 }
102 }
103
104 #[inline]
108 #[must_use]
109 pub const fn from_cols_array(m: &[f64; 16]) -> Self {
110 Self::new(
111 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],
112 m[14], m[15],
113 )
114 }
115
116 #[inline]
119 #[must_use]
120 pub const fn to_cols_array(&self) -> [f64; 16] {
121 [
122 self.x_axis.x,
123 self.x_axis.y,
124 self.x_axis.z,
125 self.x_axis.w,
126 self.y_axis.x,
127 self.y_axis.y,
128 self.y_axis.z,
129 self.y_axis.w,
130 self.z_axis.x,
131 self.z_axis.y,
132 self.z_axis.z,
133 self.z_axis.w,
134 self.w_axis.x,
135 self.w_axis.y,
136 self.w_axis.z,
137 self.w_axis.w,
138 ]
139 }
140
141 #[inline]
145 #[must_use]
146 pub const fn from_cols_array_2d(m: &[[f64; 4]; 4]) -> Self {
147 Self::from_cols(
148 DVec4::from_array(m[0]),
149 DVec4::from_array(m[1]),
150 DVec4::from_array(m[2]),
151 DVec4::from_array(m[3]),
152 )
153 }
154
155 #[inline]
158 #[must_use]
159 pub const fn to_cols_array_2d(&self) -> [[f64; 4]; 4] {
160 [
161 self.x_axis.to_array(),
162 self.y_axis.to_array(),
163 self.z_axis.to_array(),
164 self.w_axis.to_array(),
165 ]
166 }
167
168 #[doc(alias = "scale")]
170 #[inline]
171 #[must_use]
172 pub const fn from_diagonal(diagonal: DVec4) -> Self {
173 Self::new(
174 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,
175 0.0, 0.0, diagonal.w,
176 )
177 }
178
179 #[inline]
180 #[must_use]
181 fn quat_to_axes(rotation: DQuat) -> (DVec4, DVec4, DVec4) {
182 glam_assert!(rotation.is_normalized());
183
184 let (x, y, z, w) = rotation.into();
185 let x2 = x + x;
186 let y2 = y + y;
187 let z2 = z + z;
188 let xx = x * x2;
189 let xy = x * y2;
190 let xz = x * z2;
191 let yy = y * y2;
192 let yz = y * z2;
193 let zz = z * z2;
194 let wx = w * x2;
195 let wy = w * y2;
196 let wz = w * z2;
197
198 let x_axis = DVec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
199 let y_axis = DVec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
200 let z_axis = DVec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
201 (x_axis, y_axis, z_axis)
202 }
203
204 #[inline]
214 #[must_use]
215 pub fn from_scale_rotation_translation(
216 scale: DVec3,
217 rotation: DQuat,
218 translation: DVec3,
219 ) -> Self {
220 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
221 Self::from_cols(
222 x_axis.mul(scale.x),
223 y_axis.mul(scale.y),
224 z_axis.mul(scale.z),
225 DVec4::from((translation, 1.0)),
226 )
227 }
228
229 #[inline]
238 #[must_use]
239 pub fn from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self {
240 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
241 Self::from_cols(x_axis, y_axis, z_axis, DVec4::from((translation, 1.0)))
242 }
243
244 #[inline]
252 #[must_use]
253 pub fn to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3) {
254 let det = self.determinant();
255 glam_assert!(det != 0.0);
256
257 let scale = DVec3::new(
258 self.x_axis.length() * math::signum(det),
259 self.y_axis.length(),
260 self.z_axis.length(),
261 );
262
263 glam_assert!(scale.cmpne(DVec3::ZERO).all());
264
265 let inv_scale = scale.recip();
266
267 let rotation = DQuat::from_rotation_axes(
268 self.x_axis.mul(inv_scale.x).xyz(),
269 self.y_axis.mul(inv_scale.y).xyz(),
270 self.z_axis.mul(inv_scale.z).xyz(),
271 );
272
273 let translation = self.w_axis.xyz();
274
275 (scale, rotation, translation)
276 }
277
278 #[inline]
287 #[must_use]
288 pub fn from_quat(rotation: DQuat) -> Self {
289 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
290 Self::from_cols(x_axis, y_axis, z_axis, DVec4::W)
291 }
292
293 #[inline]
299 #[must_use]
300 pub fn from_mat3(m: DMat3) -> Self {
301 Self::from_cols(
302 DVec4::from((m.x_axis, 0.0)),
303 DVec4::from((m.y_axis, 0.0)),
304 DVec4::from((m.z_axis, 0.0)),
305 DVec4::W,
306 )
307 }
308
309 #[inline]
314 #[must_use]
315 pub fn from_mat3_translation(mat3: DMat3, translation: DVec3) -> Self {
316 Self::from_cols(
317 DVec4::from((mat3.x_axis, 0.0)),
318 DVec4::from((mat3.y_axis, 0.0)),
319 DVec4::from((mat3.z_axis, 0.0)),
320 DVec4::from((translation, 1.0)),
321 )
322 }
323
324 #[inline]
329 #[must_use]
330 pub fn from_translation(translation: DVec3) -> Self {
331 Self::from_cols(
332 DVec4::X,
333 DVec4::Y,
334 DVec4::Z,
335 DVec4::new(translation.x, translation.y, translation.z, 1.0),
336 )
337 }
338
339 #[inline]
349 #[must_use]
350 pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
351 glam_assert!(axis.is_normalized());
352
353 let (sin, cos) = math::sin_cos(angle);
354 let axis_sin = axis.mul(sin);
355 let axis_sq = axis.mul(axis);
356 let omc = 1.0 - cos;
357 let xyomc = axis.x * axis.y * omc;
358 let xzomc = axis.x * axis.z * omc;
359 let yzomc = axis.y * axis.z * omc;
360 Self::from_cols(
361 DVec4::new(
362 axis_sq.x * omc + cos,
363 xyomc + axis_sin.z,
364 xzomc - axis_sin.y,
365 0.0,
366 ),
367 DVec4::new(
368 xyomc - axis_sin.z,
369 axis_sq.y * omc + cos,
370 yzomc + axis_sin.x,
371 0.0,
372 ),
373 DVec4::new(
374 xzomc + axis_sin.y,
375 yzomc - axis_sin.x,
376 axis_sq.z * omc + cos,
377 0.0,
378 ),
379 DVec4::W,
380 )
381 }
382
383 #[inline]
389 #[must_use]
390 pub fn from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self {
391 Self::from_euler_angles(order, a, b, c)
392 }
393
394 #[inline]
404 #[must_use]
405 pub fn to_euler(&self, order: EulerRot) -> (f64, f64, f64) {
406 glam_assert!(
407 self.x_axis.xyz().is_normalized()
408 && self.y_axis.xyz().is_normalized()
409 && self.z_axis.xyz().is_normalized()
410 );
411 self.to_euler_angles(order)
412 }
413
414 #[inline]
420 #[must_use]
421 pub fn from_rotation_x(angle: f64) -> Self {
422 let (sina, cosa) = math::sin_cos(angle);
423 Self::from_cols(
424 DVec4::X,
425 DVec4::new(0.0, cosa, sina, 0.0),
426 DVec4::new(0.0, -sina, cosa, 0.0),
427 DVec4::W,
428 )
429 }
430
431 #[inline]
437 #[must_use]
438 pub fn from_rotation_y(angle: f64) -> Self {
439 let (sina, cosa) = math::sin_cos(angle);
440 Self::from_cols(
441 DVec4::new(cosa, 0.0, -sina, 0.0),
442 DVec4::Y,
443 DVec4::new(sina, 0.0, cosa, 0.0),
444 DVec4::W,
445 )
446 }
447
448 #[inline]
454 #[must_use]
455 pub fn from_rotation_z(angle: f64) -> Self {
456 let (sina, cosa) = math::sin_cos(angle);
457 Self::from_cols(
458 DVec4::new(cosa, sina, 0.0, 0.0),
459 DVec4::new(-sina, cosa, 0.0, 0.0),
460 DVec4::Z,
461 DVec4::W,
462 )
463 }
464
465 #[inline]
474 #[must_use]
475 pub fn from_scale(scale: DVec3) -> Self {
476 glam_assert!(scale.cmpne(DVec3::ZERO).any());
478
479 Self::from_cols(
480 DVec4::new(scale.x, 0.0, 0.0, 0.0),
481 DVec4::new(0.0, scale.y, 0.0, 0.0),
482 DVec4::new(0.0, 0.0, scale.z, 0.0),
483 DVec4::W,
484 )
485 }
486
487 #[inline]
493 #[must_use]
494 pub const fn from_cols_slice(slice: &[f64]) -> Self {
495 Self::new(
496 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
497 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
498 )
499 }
500
501 #[inline]
507 pub fn write_cols_to_slice(&self, slice: &mut [f64]) {
508 slice[0] = self.x_axis.x;
509 slice[1] = self.x_axis.y;
510 slice[2] = self.x_axis.z;
511 slice[3] = self.x_axis.w;
512 slice[4] = self.y_axis.x;
513 slice[5] = self.y_axis.y;
514 slice[6] = self.y_axis.z;
515 slice[7] = self.y_axis.w;
516 slice[8] = self.z_axis.x;
517 slice[9] = self.z_axis.y;
518 slice[10] = self.z_axis.z;
519 slice[11] = self.z_axis.w;
520 slice[12] = self.w_axis.x;
521 slice[13] = self.w_axis.y;
522 slice[14] = self.w_axis.z;
523 slice[15] = self.w_axis.w;
524 }
525
526 #[inline]
532 #[must_use]
533 pub fn col(&self, index: usize) -> DVec4 {
534 match index {
535 0 => self.x_axis,
536 1 => self.y_axis,
537 2 => self.z_axis,
538 3 => self.w_axis,
539 _ => panic!("index out of bounds"),
540 }
541 }
542
543 #[inline]
549 pub fn col_mut(&mut self, index: usize) -> &mut DVec4 {
550 match index {
551 0 => &mut self.x_axis,
552 1 => &mut self.y_axis,
553 2 => &mut self.z_axis,
554 3 => &mut self.w_axis,
555 _ => panic!("index out of bounds"),
556 }
557 }
558
559 #[inline]
565 #[must_use]
566 pub fn row(&self, index: usize) -> DVec4 {
567 match index {
568 0 => DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
569 1 => DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
570 2 => DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
571 3 => DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
572 _ => panic!("index out of bounds"),
573 }
574 }
575
576 #[inline]
579 #[must_use]
580 pub fn is_finite(&self) -> bool {
581 self.x_axis.is_finite()
582 && self.y_axis.is_finite()
583 && self.z_axis.is_finite()
584 && self.w_axis.is_finite()
585 }
586
587 #[inline]
589 #[must_use]
590 pub fn is_nan(&self) -> bool {
591 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
592 }
593
594 #[inline]
596 #[must_use]
597 pub fn transpose(&self) -> Self {
598 Self {
599 x_axis: DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
600 y_axis: DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
601 z_axis: DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
602 w_axis: DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
603 }
604 }
605
606 #[inline]
608 #[must_use]
609 pub fn diagonal(&self) -> DVec4 {
610 DVec4::new(self.x_axis.x, self.y_axis.y, self.z_axis.z, self.w_axis.w)
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 #[inline(always)]
646 #[must_use]
647 fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
648 let (m00, m01, m02, m03) = self.x_axis.into();
649 let (m10, m11, m12, m13) = self.y_axis.into();
650 let (m20, m21, m22, m23) = self.z_axis.into();
651 let (m30, m31, m32, m33) = self.w_axis.into();
652
653 let coef00 = m22 * m33 - m32 * m23;
654 let coef02 = m12 * m33 - m32 * m13;
655 let coef03 = m12 * m23 - m22 * m13;
656
657 let coef04 = m21 * m33 - m31 * m23;
658 let coef06 = m11 * m33 - m31 * m13;
659 let coef07 = m11 * m23 - m21 * m13;
660
661 let coef08 = m21 * m32 - m31 * m22;
662 let coef10 = m11 * m32 - m31 * m12;
663 let coef11 = m11 * m22 - m21 * m12;
664
665 let coef12 = m20 * m33 - m30 * m23;
666 let coef14 = m10 * m33 - m30 * m13;
667 let coef15 = m10 * m23 - m20 * m13;
668
669 let coef16 = m20 * m32 - m30 * m22;
670 let coef18 = m10 * m32 - m30 * m12;
671 let coef19 = m10 * m22 - m20 * m12;
672
673 let coef20 = m20 * m31 - m30 * m21;
674 let coef22 = m10 * m31 - m30 * m11;
675 let coef23 = m10 * m21 - m20 * m11;
676
677 let fac0 = DVec4::new(coef00, coef00, coef02, coef03);
678 let fac1 = DVec4::new(coef04, coef04, coef06, coef07);
679 let fac2 = DVec4::new(coef08, coef08, coef10, coef11);
680 let fac3 = DVec4::new(coef12, coef12, coef14, coef15);
681 let fac4 = DVec4::new(coef16, coef16, coef18, coef19);
682 let fac5 = DVec4::new(coef20, coef20, coef22, coef23);
683
684 let vec0 = DVec4::new(m10, m00, m00, m00);
685 let vec1 = DVec4::new(m11, m01, m01, m01);
686 let vec2 = DVec4::new(m12, m02, m02, m02);
687 let vec3 = DVec4::new(m13, m03, m03, m03);
688
689 let inv0 = vec1.mul(fac0).sub(vec2.mul(fac1)).add(vec3.mul(fac2));
690 let inv1 = vec0.mul(fac0).sub(vec2.mul(fac3)).add(vec3.mul(fac4));
691 let inv2 = vec0.mul(fac1).sub(vec1.mul(fac3)).add(vec3.mul(fac5));
692 let inv3 = vec0.mul(fac2).sub(vec1.mul(fac4)).add(vec2.mul(fac5));
693
694 let sign_a = DVec4::new(1.0, -1.0, 1.0, -1.0);
695 let sign_b = DVec4::new(-1.0, 1.0, -1.0, 1.0);
696
697 let inverse = Self::from_cols(
698 inv0.mul(sign_a),
699 inv1.mul(sign_b),
700 inv2.mul(sign_a),
701 inv3.mul(sign_b),
702 );
703
704 let col0 = DVec4::new(
705 inverse.x_axis.x,
706 inverse.y_axis.x,
707 inverse.z_axis.x,
708 inverse.w_axis.x,
709 );
710
711 let dot0 = self.x_axis.mul(col0);
712 let dot1 = dot0.x + dot0.y + dot0.z + dot0.w;
713
714 if CHECKED {
715 if dot1 == 0.0 {
716 return (Self::ZERO, false);
717 }
718 } else {
719 glam_assert!(dot1 != 0.0);
720 }
721
722 let rcp_det = dot1.recip();
723 (inverse.mul(rcp_det), true)
724 }
725
726 #[must_use]
734 pub fn inverse(&self) -> Self {
735 self.inverse_checked::<false>().0
736 }
737
738 #[must_use]
740 pub fn try_inverse(&self) -> Option<Self> {
741 let (m, is_valid) = self.inverse_checked::<true>();
742 if is_valid {
743 Some(m)
744 } else {
745 None
746 }
747 }
748
749 #[must_use]
751 pub fn inverse_or_zero(&self) -> Self {
752 self.inverse_checked::<true>().0
753 }
754
755 #[deprecated(
764 since = "0.33.1",
765 note = "use the `glam::dcamera::lh::view::look_to_mat4` function instead"
766 )]
767 #[inline]
768 #[must_use]
769 pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
770 #[allow(deprecated)]
771 Self::look_to_rh(eye, -dir, up)
772 }
773
774 #[deprecated(
783 since = "0.33.1",
784 note = "use the `glam::dcamera::rh::view::look_to_mat4` function instead"
785 )]
786 #[inline]
787 #[must_use]
788 pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
789 glam_assert!(dir.is_normalized());
790 glam_assert!(up.is_normalized());
791 let f = dir;
792 let s = f.cross(up).normalize();
793 let u = s.cross(f);
794
795 Self::from_cols(
796 DVec4::new(s.x, u.x, -f.x, 0.0),
797 DVec4::new(s.y, u.y, -f.y, 0.0),
798 DVec4::new(s.z, u.z, -f.z, 0.0),
799 DVec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
800 )
801 }
802
803 #[deprecated(
812 since = "0.33.1",
813 note = "use the `glam::dcamera::lh::view::look_at_mat4` function instead"
814 )]
815 #[inline]
816 #[must_use]
817 pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
818 #[allow(deprecated)]
819 Self::look_to_lh(eye, center.sub(eye).normalize(), up)
820 }
821
822 #[deprecated(
831 since = "0.33.1",
832 note = "use the `glam::dcamera::rh::view::look_at_mat4` function instead"
833 )]
834 #[inline]
835 pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
836 #[allow(deprecated)]
837 Self::look_to_rh(eye, center.sub(eye).normalize(), up)
838 }
839
840 #[deprecated(
846 since = "0.33.1",
847 note = "use the `glam::dcamera::rh::proj::opengl::frustum` function instead"
848 )]
849 #[inline]
850 #[must_use]
851 pub fn frustum_rh_gl(
852 left: f64,
853 right: f64,
854 bottom: f64,
855 top: f64,
856 z_near: f64,
857 z_far: f64,
858 ) -> Self {
859 let inv_width = 1.0 / (right - left);
860 let inv_height = 1.0 / (top - bottom);
861 let inv_depth = 1.0 / (z_far - z_near);
862 let a = (right + left) * inv_width;
863 let b = (top + bottom) * inv_height;
864 let c = -(z_far + z_near) * inv_depth;
865 let d = -(2.0 * z_far * z_near) * inv_depth;
866 let two_z_near = 2.0 * z_near;
867 Self::from_cols(
868 DVec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
869 DVec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
870 DVec4::new(a, b, c, -1.0),
871 DVec4::new(0.0, 0.0, d, 0.0),
872 )
873 }
874
875 #[deprecated(
882 since = "0.33.1",
883 note = "use the `glam::dcamera::lh::proj::directx::frustum` function instead"
884 )]
885 #[inline]
886 #[must_use]
887 pub fn frustum_lh(
888 left: f64,
889 right: f64,
890 bottom: f64,
891 top: f64,
892 z_near: f64,
893 z_far: f64,
894 ) -> Self {
895 glam_assert!(z_near > 0.0 && z_far > 0.0);
896 let inv_width = 1.0 / (right - left);
897 let inv_height = 1.0 / (top - bottom);
898 let inv_depth = 1.0 / (z_far - z_near);
899 let a = (right + left) * inv_width;
900 let b = (top + bottom) * inv_height;
901 let c = z_far * inv_depth;
902 let d = -(z_far * z_near) * inv_depth;
903 let two_z_near = 2.0 * z_near;
904 Self::from_cols(
905 DVec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
906 DVec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
907 DVec4::new(a, b, c, 1.0),
908 DVec4::new(0.0, 0.0, d, 0.0),
909 )
910 }
911
912 #[deprecated(
919 since = "0.33.1",
920 note = "use the `glam::dcamera::rh::proj::directx::frustum` function instead"
921 )]
922 #[inline]
923 #[must_use]
924 pub fn frustum_rh(
925 left: f64,
926 right: f64,
927 bottom: f64,
928 top: f64,
929 z_near: f64,
930 z_far: f64,
931 ) -> Self {
932 glam_assert!(z_near > 0.0 && z_far > 0.0);
933 let inv_width = 1.0 / (right - left);
934 let inv_height = 1.0 / (top - bottom);
935 let inv_depth = 1.0 / (z_far - z_near);
936 let a = (right + left) * inv_width;
937 let b = (top + bottom) * inv_height;
938 let c = -z_far * inv_depth;
939 let d = -(z_far * z_near) * inv_depth;
940 let two_z_near = 2.0 * z_near;
941 Self::from_cols(
942 DVec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
943 DVec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
944 DVec4::new(a, b, c, -1.0),
945 DVec4::new(0.0, 0.0, d, 0.0),
946 )
947 }
948
949 #[deprecated(
956 since = "0.33.1",
957 note = "use the `glam::dcamera::rh::proj::opengl::perspective` function instead"
958 )]
959 #[inline]
960 #[must_use]
961 pub fn perspective_rh_gl(
962 fov_y_radians: f64,
963 aspect_ratio: f64,
964 z_near: f64,
965 z_far: f64,
966 ) -> Self {
967 let inv_length = 1.0 / (z_near - z_far);
968 let f = 1.0 / math::tan(0.5 * fov_y_radians);
969 let a = f / aspect_ratio;
970 let b = (z_near + z_far) * inv_length;
971 let c = (2.0 * z_near * z_far) * inv_length;
972 Self::from_cols(
973 DVec4::new(a, 0.0, 0.0, 0.0),
974 DVec4::new(0.0, f, 0.0, 0.0),
975 DVec4::new(0.0, 0.0, b, -1.0),
976 DVec4::new(0.0, 0.0, c, 0.0),
977 )
978 }
979
980 #[deprecated(
989 since = "0.33.1",
990 note = "use the `glam::dcamera::lh::proj::directx::perspective` function instead"
991 )]
992 #[inline]
993 #[must_use]
994 pub fn perspective_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
995 glam_assert!(z_near > 0.0 && z_far > 0.0);
996 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
997 let h = cos_fov / sin_fov;
998 let w = h / aspect_ratio;
999 let r = z_far / (z_far - z_near);
1000 Self::from_cols(
1001 DVec4::new(w, 0.0, 0.0, 0.0),
1002 DVec4::new(0.0, h, 0.0, 0.0),
1003 DVec4::new(0.0, 0.0, r, 1.0),
1004 DVec4::new(0.0, 0.0, -r * z_near, 0.0),
1005 )
1006 }
1007
1008 #[deprecated(
1017 since = "0.33.1",
1018 note = "use the `glam::dcamera::rh::proj::directx::perspective` function instead"
1019 )]
1020 #[inline]
1021 #[must_use]
1022 pub fn perspective_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
1023 glam_assert!(z_near > 0.0 && z_far > 0.0);
1024 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1025 let h = cos_fov / sin_fov;
1026 let w = h / aspect_ratio;
1027 let r = z_far / (z_near - z_far);
1028 Self::from_cols(
1029 DVec4::new(w, 0.0, 0.0, 0.0),
1030 DVec4::new(0.0, h, 0.0, 0.0),
1031 DVec4::new(0.0, 0.0, r, -1.0),
1032 DVec4::new(0.0, 0.0, r * z_near, 0.0),
1033 )
1034 }
1035
1036 #[deprecated(
1046 since = "0.33.1",
1047 note = "use the `glam::dcamera::lh::proj::directx::perspective_infinite` function instead"
1048 )]
1049 #[inline]
1050 #[must_use]
1051 pub fn perspective_infinite_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
1052 glam_assert!(z_near > 0.0);
1053 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1054 let h = cos_fov / sin_fov;
1055 let w = h / aspect_ratio;
1056 Self::from_cols(
1057 DVec4::new(w, 0.0, 0.0, 0.0),
1058 DVec4::new(0.0, h, 0.0, 0.0),
1059 DVec4::new(0.0, 0.0, 1.0, 1.0),
1060 DVec4::new(0.0, 0.0, -z_near, 0.0),
1061 )
1062 }
1063
1064 #[deprecated(
1072 since = "0.33.1",
1073 note = "use the `glam::dcamera::lh::proj::directx::perspective_infinite_reverse` function instead"
1074 )]
1075 #[inline]
1076 #[must_use]
1077 pub fn perspective_infinite_reverse_lh(
1078 fov_y_radians: f64,
1079 aspect_ratio: f64,
1080 z_near: f64,
1081 ) -> Self {
1082 glam_assert!(z_near > 0.0);
1083 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1084 let h = cos_fov / sin_fov;
1085 let w = h / aspect_ratio;
1086 Self::from_cols(
1087 DVec4::new(w, 0.0, 0.0, 0.0),
1088 DVec4::new(0.0, h, 0.0, 0.0),
1089 DVec4::new(0.0, 0.0, 0.0, 1.0),
1090 DVec4::new(0.0, 0.0, z_near, 0.0),
1091 )
1092 }
1093
1094 #[deprecated(
1104 since = "0.33.1",
1105 note = "use the `glam::dcamera::rh::proj::directx::perspective_infinite` function instead"
1106 )]
1107 #[inline]
1108 #[must_use]
1109 pub fn perspective_infinite_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
1110 glam_assert!(z_near > 0.0);
1111 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1112 Self::from_cols(
1113 DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1114 DVec4::new(0.0, f, 0.0, 0.0),
1115 DVec4::new(0.0, 0.0, -1.0, -1.0),
1116 DVec4::new(0.0, 0.0, -z_near, 0.0),
1117 )
1118 }
1119
1120 #[deprecated(
1128 since = "0.33.1",
1129 note = "use the `glam::dcamera::rh::proj::directx::perspective_infinite_reverse` function instead"
1130 )]
1131 #[inline]
1132 #[must_use]
1133 pub fn perspective_infinite_reverse_rh(
1134 fov_y_radians: f64,
1135 aspect_ratio: f64,
1136 z_near: f64,
1137 ) -> Self {
1138 glam_assert!(z_near > 0.0);
1139 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1140 Self::from_cols(
1141 DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1142 DVec4::new(0.0, f, 0.0, 0.0),
1143 DVec4::new(0.0, 0.0, 0.0, -1.0),
1144 DVec4::new(0.0, 0.0, z_near, 0.0),
1145 )
1146 }
1147
1148 #[deprecated(
1155 since = "0.33.1",
1156 note = "use the `glam::dcamera::rh::proj::opengl::orthographic` function instead"
1157 )]
1158 #[inline]
1159 #[must_use]
1160 pub fn orthographic_rh_gl(
1161 left: f64,
1162 right: f64,
1163 bottom: f64,
1164 top: f64,
1165 near: f64,
1166 far: f64,
1167 ) -> Self {
1168 let a = 2.0 / (right - left);
1169 let b = 2.0 / (top - bottom);
1170 let c = 2.0 / (near - far);
1171 let tx = -(right + left) / (right - left);
1172 let ty = -(top + bottom) / (top - bottom);
1173 let tz = -(far + near) / (far - near);
1174
1175 Self::from_cols(
1176 DVec4::new(a, 0.0, 0.0, 0.0),
1177 DVec4::new(0.0, b, 0.0, 0.0),
1178 DVec4::new(0.0, 0.0, c, 0.0),
1179 DVec4::new(tx, ty, tz, 1.0),
1180 )
1181 }
1182
1183 #[deprecated(
1187 since = "0.33.1",
1188 note = "use the `glam::dcamera::lh::proj::directx::orthographic` function instead"
1189 )]
1190 #[inline]
1191 #[must_use]
1192 pub fn orthographic_lh(
1193 left: f64,
1194 right: f64,
1195 bottom: f64,
1196 top: f64,
1197 near: f64,
1198 far: f64,
1199 ) -> Self {
1200 let rcp_width = 1.0 / (right - left);
1201 let rcp_height = 1.0 / (top - bottom);
1202 let r = 1.0 / (far - near);
1203 Self::from_cols(
1204 DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1205 DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1206 DVec4::new(0.0, 0.0, r, 0.0),
1207 DVec4::new(
1208 -(left + right) * rcp_width,
1209 -(top + bottom) * rcp_height,
1210 -r * near,
1211 1.0,
1212 ),
1213 )
1214 }
1215
1216 #[deprecated(
1220 since = "0.33.1",
1221 note = "use the `glam::dcamera::rh::proj::directx::orthographic` function instead"
1222 )]
1223 #[inline]
1224 #[must_use]
1225 pub fn orthographic_rh(
1226 left: f64,
1227 right: f64,
1228 bottom: f64,
1229 top: f64,
1230 near: f64,
1231 far: f64,
1232 ) -> Self {
1233 let rcp_width = 1.0 / (right - left);
1234 let rcp_height = 1.0 / (top - bottom);
1235 let r = 1.0 / (near - far);
1236 Self::from_cols(
1237 DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1238 DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1239 DVec4::new(0.0, 0.0, r, 0.0),
1240 DVec4::new(
1241 -(left + right) * rcp_width,
1242 -(top + bottom) * rcp_height,
1243 r * near,
1244 1.0,
1245 ),
1246 )
1247 }
1248
1249 #[inline]
1256 #[must_use]
1257 pub fn project_point3(&self, rhs: DVec3) -> DVec3 {
1258 let mut res = self.x_axis.mul(rhs.x);
1259 res = self.y_axis.mul(rhs.y).add(res);
1260 res = self.z_axis.mul(rhs.z).add(res);
1261 res = self.w_axis.add(res);
1262 res = res.div(res.w);
1263 res.xyz()
1264 }
1265
1266 #[inline]
1279 #[must_use]
1280 pub fn transform_point3(&self, rhs: DVec3) -> DVec3 {
1281 glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
1282 let mut res = self.x_axis.mul(rhs.x);
1283 res = self.y_axis.mul(rhs.y).add(res);
1284 res = self.z_axis.mul(rhs.z).add(res);
1285 res = self.w_axis.add(res);
1286 res.xyz()
1287 }
1288
1289 #[inline]
1300 #[must_use]
1301 pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 {
1302 glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
1303 let mut res = self.x_axis.mul(rhs.x);
1304 res = self.y_axis.mul(rhs.y).add(res);
1305 res = self.z_axis.mul(rhs.z).add(res);
1306 res.xyz()
1307 }
1308
1309 #[inline]
1311 #[must_use]
1312 pub fn mul_vec4(&self, rhs: DVec4) -> DVec4 {
1313 let mut res = self.x_axis.mul(rhs.x);
1314 res = res.add(self.y_axis.mul(rhs.y));
1315 res = res.add(self.z_axis.mul(rhs.z));
1316 res = res.add(self.w_axis.mul(rhs.w));
1317 res
1318 }
1319
1320 #[inline]
1322 #[must_use]
1323 pub fn mul_transpose_vec4(&self, rhs: DVec4) -> DVec4 {
1324 DVec4::new(
1325 self.x_axis.dot(rhs),
1326 self.y_axis.dot(rhs),
1327 self.z_axis.dot(rhs),
1328 self.w_axis.dot(rhs),
1329 )
1330 }
1331
1332 #[inline]
1334 #[must_use]
1335 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1336 self.mul(rhs)
1337 }
1338
1339 #[inline]
1341 #[must_use]
1342 pub fn add_mat4(&self, rhs: &Self) -> Self {
1343 self.add(rhs)
1344 }
1345
1346 #[inline]
1348 #[must_use]
1349 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1350 self.sub(rhs)
1351 }
1352
1353 #[inline]
1355 #[must_use]
1356 pub fn mul_scalar(&self, rhs: f64) -> Self {
1357 Self::from_cols(
1358 self.x_axis.mul(rhs),
1359 self.y_axis.mul(rhs),
1360 self.z_axis.mul(rhs),
1361 self.w_axis.mul(rhs),
1362 )
1363 }
1364
1365 #[inline]
1369 #[must_use]
1370 pub fn mul_diagonal_scale(&self, scale: DVec4) -> Self {
1371 Self::from_cols(
1372 self.x_axis * scale.x,
1373 self.y_axis * scale.y,
1374 self.z_axis * scale.z,
1375 self.w_axis * scale.w,
1376 )
1377 }
1378
1379 #[inline]
1381 #[must_use]
1382 pub fn div_scalar(&self, rhs: f64) -> Self {
1383 let rhs = DVec4::splat(rhs);
1384 Self::from_cols(
1385 self.x_axis.div(rhs),
1386 self.y_axis.div(rhs),
1387 self.z_axis.div(rhs),
1388 self.w_axis.div(rhs),
1389 )
1390 }
1391
1392 #[inline]
1394 #[must_use]
1395 pub fn recip(&self) -> Self {
1396 Self::from_cols(
1397 self.x_axis.recip(),
1398 self.y_axis.recip(),
1399 self.z_axis.recip(),
1400 self.w_axis.recip(),
1401 )
1402 }
1403
1404 #[inline]
1414 #[must_use]
1415 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
1416 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1417 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1418 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1419 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1420 }
1421
1422 #[inline]
1424 #[must_use]
1425 pub fn abs(&self) -> Self {
1426 Self::from_cols(
1427 self.x_axis.abs(),
1428 self.y_axis.abs(),
1429 self.z_axis.abs(),
1430 self.w_axis.abs(),
1431 )
1432 }
1433
1434 #[cfg(feature = "f64")]
1435 #[inline]
1436 #[must_use]
1437 pub fn as_mat4(&self) -> Mat4 {
1438 Mat4::from_cols(
1439 self.x_axis.as_vec4(),
1440 self.y_axis.as_vec4(),
1441 self.z_axis.as_vec4(),
1442 self.w_axis.as_vec4(),
1443 )
1444 }
1445}
1446
1447impl Default for DMat4 {
1448 #[inline]
1449 fn default() -> Self {
1450 Self::IDENTITY
1451 }
1452}
1453
1454impl Add for DMat4 {
1455 type Output = Self;
1456 #[inline]
1457 fn add(self, rhs: Self) -> Self {
1458 Self::from_cols(
1459 self.x_axis.add(rhs.x_axis),
1460 self.y_axis.add(rhs.y_axis),
1461 self.z_axis.add(rhs.z_axis),
1462 self.w_axis.add(rhs.w_axis),
1463 )
1464 }
1465}
1466
1467impl Add<&Self> for DMat4 {
1468 type Output = Self;
1469 #[inline]
1470 fn add(self, rhs: &Self) -> Self {
1471 self.add(*rhs)
1472 }
1473}
1474
1475impl Add<&DMat4> for &DMat4 {
1476 type Output = DMat4;
1477 #[inline]
1478 fn add(self, rhs: &DMat4) -> DMat4 {
1479 (*self).add(*rhs)
1480 }
1481}
1482
1483impl Add<DMat4> for &DMat4 {
1484 type Output = DMat4;
1485 #[inline]
1486 fn add(self, rhs: DMat4) -> DMat4 {
1487 (*self).add(rhs)
1488 }
1489}
1490
1491impl AddAssign for DMat4 {
1492 #[inline]
1493 fn add_assign(&mut self, rhs: Self) {
1494 *self = self.add(rhs);
1495 }
1496}
1497
1498impl AddAssign<&Self> for DMat4 {
1499 #[inline]
1500 fn add_assign(&mut self, rhs: &Self) {
1501 self.add_assign(*rhs);
1502 }
1503}
1504
1505impl Sub for DMat4 {
1506 type Output = Self;
1507 #[inline]
1508 fn sub(self, rhs: Self) -> Self {
1509 Self::from_cols(
1510 self.x_axis.sub(rhs.x_axis),
1511 self.y_axis.sub(rhs.y_axis),
1512 self.z_axis.sub(rhs.z_axis),
1513 self.w_axis.sub(rhs.w_axis),
1514 )
1515 }
1516}
1517
1518impl Sub<&Self> for DMat4 {
1519 type Output = Self;
1520 #[inline]
1521 fn sub(self, rhs: &Self) -> Self {
1522 self.sub(*rhs)
1523 }
1524}
1525
1526impl Sub<&DMat4> for &DMat4 {
1527 type Output = DMat4;
1528 #[inline]
1529 fn sub(self, rhs: &DMat4) -> DMat4 {
1530 (*self).sub(*rhs)
1531 }
1532}
1533
1534impl Sub<DMat4> for &DMat4 {
1535 type Output = DMat4;
1536 #[inline]
1537 fn sub(self, rhs: DMat4) -> DMat4 {
1538 (*self).sub(rhs)
1539 }
1540}
1541
1542impl SubAssign for DMat4 {
1543 #[inline]
1544 fn sub_assign(&mut self, rhs: Self) {
1545 *self = self.sub(rhs);
1546 }
1547}
1548
1549impl SubAssign<&Self> for DMat4 {
1550 #[inline]
1551 fn sub_assign(&mut self, rhs: &Self) {
1552 self.sub_assign(*rhs);
1553 }
1554}
1555
1556impl Neg for DMat4 {
1557 type Output = Self;
1558 #[inline]
1559 fn neg(self) -> Self::Output {
1560 Self::from_cols(
1561 self.x_axis.neg(),
1562 self.y_axis.neg(),
1563 self.z_axis.neg(),
1564 self.w_axis.neg(),
1565 )
1566 }
1567}
1568
1569impl Neg for &DMat4 {
1570 type Output = DMat4;
1571 #[inline]
1572 fn neg(self) -> DMat4 {
1573 (*self).neg()
1574 }
1575}
1576
1577impl Mul for DMat4 {
1578 type Output = Self;
1579 #[inline]
1580 fn mul(self, rhs: Self) -> Self {
1581 Self::from_cols(
1582 self.mul(rhs.x_axis),
1583 self.mul(rhs.y_axis),
1584 self.mul(rhs.z_axis),
1585 self.mul(rhs.w_axis),
1586 )
1587 }
1588}
1589
1590impl Mul<&Self> for DMat4 {
1591 type Output = Self;
1592 #[inline]
1593 fn mul(self, rhs: &Self) -> Self {
1594 self.mul(*rhs)
1595 }
1596}
1597
1598impl Mul<&DMat4> for &DMat4 {
1599 type Output = DMat4;
1600 #[inline]
1601 fn mul(self, rhs: &DMat4) -> DMat4 {
1602 (*self).mul(*rhs)
1603 }
1604}
1605
1606impl Mul<DMat4> for &DMat4 {
1607 type Output = DMat4;
1608 #[inline]
1609 fn mul(self, rhs: DMat4) -> DMat4 {
1610 (*self).mul(rhs)
1611 }
1612}
1613
1614impl MulAssign for DMat4 {
1615 #[inline]
1616 fn mul_assign(&mut self, rhs: Self) {
1617 *self = self.mul(rhs);
1618 }
1619}
1620
1621impl MulAssign<&Self> for DMat4 {
1622 #[inline]
1623 fn mul_assign(&mut self, rhs: &Self) {
1624 self.mul_assign(*rhs);
1625 }
1626}
1627
1628impl Mul<DVec4> for DMat4 {
1629 type Output = DVec4;
1630 #[inline]
1631 fn mul(self, rhs: DVec4) -> Self::Output {
1632 self.mul_vec4(rhs)
1633 }
1634}
1635
1636impl Mul<&DVec4> for DMat4 {
1637 type Output = DVec4;
1638 #[inline]
1639 fn mul(self, rhs: &DVec4) -> DVec4 {
1640 self.mul(*rhs)
1641 }
1642}
1643
1644impl Mul<&DVec4> for &DMat4 {
1645 type Output = DVec4;
1646 #[inline]
1647 fn mul(self, rhs: &DVec4) -> DVec4 {
1648 (*self).mul(*rhs)
1649 }
1650}
1651
1652impl Mul<DVec4> for &DMat4 {
1653 type Output = DVec4;
1654 #[inline]
1655 fn mul(self, rhs: DVec4) -> DVec4 {
1656 (*self).mul(rhs)
1657 }
1658}
1659
1660impl Mul<DMat4> for f64 {
1661 type Output = DMat4;
1662 #[inline]
1663 fn mul(self, rhs: DMat4) -> Self::Output {
1664 rhs.mul_scalar(self)
1665 }
1666}
1667
1668impl Mul<&DMat4> for f64 {
1669 type Output = DMat4;
1670 #[inline]
1671 fn mul(self, rhs: &DMat4) -> DMat4 {
1672 self.mul(*rhs)
1673 }
1674}
1675
1676impl Mul<&DMat4> for &f64 {
1677 type Output = DMat4;
1678 #[inline]
1679 fn mul(self, rhs: &DMat4) -> DMat4 {
1680 (*self).mul(*rhs)
1681 }
1682}
1683
1684impl Mul<DMat4> for &f64 {
1685 type Output = DMat4;
1686 #[inline]
1687 fn mul(self, rhs: DMat4) -> DMat4 {
1688 (*self).mul(rhs)
1689 }
1690}
1691
1692impl Mul<f64> for DMat4 {
1693 type Output = Self;
1694 #[inline]
1695 fn mul(self, rhs: f64) -> Self {
1696 self.mul_scalar(rhs)
1697 }
1698}
1699
1700impl Mul<&f64> for DMat4 {
1701 type Output = Self;
1702 #[inline]
1703 fn mul(self, rhs: &f64) -> Self {
1704 self.mul(*rhs)
1705 }
1706}
1707
1708impl Mul<&f64> for &DMat4 {
1709 type Output = DMat4;
1710 #[inline]
1711 fn mul(self, rhs: &f64) -> DMat4 {
1712 (*self).mul(*rhs)
1713 }
1714}
1715
1716impl Mul<f64> for &DMat4 {
1717 type Output = DMat4;
1718 #[inline]
1719 fn mul(self, rhs: f64) -> DMat4 {
1720 (*self).mul(rhs)
1721 }
1722}
1723
1724impl MulAssign<f64> for DMat4 {
1725 #[inline]
1726 fn mul_assign(&mut self, rhs: f64) {
1727 *self = self.mul(rhs);
1728 }
1729}
1730
1731impl MulAssign<&f64> for DMat4 {
1732 #[inline]
1733 fn mul_assign(&mut self, rhs: &f64) {
1734 self.mul_assign(*rhs);
1735 }
1736}
1737
1738impl Div<DMat4> for f64 {
1739 type Output = DMat4;
1740 #[inline]
1741 fn div(self, rhs: DMat4) -> Self::Output {
1742 DMat4::from_cols(
1743 self.div(rhs.x_axis),
1744 self.div(rhs.y_axis),
1745 self.div(rhs.z_axis),
1746 self.div(rhs.w_axis),
1747 )
1748 }
1749}
1750
1751impl Div<&DMat4> for f64 {
1752 type Output = DMat4;
1753 #[inline]
1754 fn div(self, rhs: &DMat4) -> DMat4 {
1755 self.div(*rhs)
1756 }
1757}
1758
1759impl Div<&DMat4> for &f64 {
1760 type Output = DMat4;
1761 #[inline]
1762 fn div(self, rhs: &DMat4) -> DMat4 {
1763 (*self).div(*rhs)
1764 }
1765}
1766
1767impl Div<DMat4> for &f64 {
1768 type Output = DMat4;
1769 #[inline]
1770 fn div(self, rhs: DMat4) -> DMat4 {
1771 (*self).div(rhs)
1772 }
1773}
1774
1775impl Div<f64> for DMat4 {
1776 type Output = Self;
1777 #[inline]
1778 fn div(self, rhs: f64) -> Self {
1779 self.div_scalar(rhs)
1780 }
1781}
1782
1783impl Div<&f64> for DMat4 {
1784 type Output = Self;
1785 #[inline]
1786 fn div(self, rhs: &f64) -> Self {
1787 self.div(*rhs)
1788 }
1789}
1790
1791impl Div<&f64> for &DMat4 {
1792 type Output = DMat4;
1793 #[inline]
1794 fn div(self, rhs: &f64) -> DMat4 {
1795 (*self).div(*rhs)
1796 }
1797}
1798
1799impl Div<f64> for &DMat4 {
1800 type Output = DMat4;
1801 #[inline]
1802 fn div(self, rhs: f64) -> DMat4 {
1803 (*self).div(rhs)
1804 }
1805}
1806
1807impl DivAssign<f64> for DMat4 {
1808 #[inline]
1809 fn div_assign(&mut self, rhs: f64) {
1810 *self = self.div(rhs);
1811 }
1812}
1813
1814impl DivAssign<&f64> for DMat4 {
1815 #[inline]
1816 fn div_assign(&mut self, rhs: &f64) {
1817 self.div_assign(*rhs);
1818 }
1819}
1820
1821impl Sum<Self> for DMat4 {
1822 fn sum<I>(iter: I) -> Self
1823 where
1824 I: Iterator<Item = Self>,
1825 {
1826 iter.fold(Self::ZERO, Self::add)
1827 }
1828}
1829
1830impl<'a> Sum<&'a Self> for DMat4 {
1831 fn sum<I>(iter: I) -> Self
1832 where
1833 I: Iterator<Item = &'a Self>,
1834 {
1835 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1836 }
1837}
1838
1839impl Product for DMat4 {
1840 fn product<I>(iter: I) -> Self
1841 where
1842 I: Iterator<Item = Self>,
1843 {
1844 iter.fold(Self::IDENTITY, Self::mul)
1845 }
1846}
1847
1848impl<'a> Product<&'a Self> for DMat4 {
1849 fn product<I>(iter: I) -> Self
1850 where
1851 I: Iterator<Item = &'a Self>,
1852 {
1853 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1854 }
1855}
1856
1857impl PartialEq for DMat4 {
1858 #[inline]
1859 fn eq(&self, rhs: &Self) -> bool {
1860 self.x_axis.eq(&rhs.x_axis)
1861 && self.y_axis.eq(&rhs.y_axis)
1862 && self.z_axis.eq(&rhs.z_axis)
1863 && self.w_axis.eq(&rhs.w_axis)
1864 }
1865}
1866
1867impl AsRef<[f64; 16]> for DMat4 {
1868 #[inline]
1869 fn as_ref(&self) -> &[f64; 16] {
1870 unsafe { &*(self as *const Self as *const [f64; 16]) }
1871 }
1872}
1873
1874impl AsMut<[f64; 16]> for DMat4 {
1875 #[inline]
1876 fn as_mut(&mut self) -> &mut [f64; 16] {
1877 unsafe { &mut *(self as *mut Self as *mut [f64; 16]) }
1878 }
1879}
1880
1881impl fmt::Debug for DMat4 {
1882 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1883 fmt.debug_struct(stringify!(DMat4))
1884 .field("x_axis", &self.x_axis)
1885 .field("y_axis", &self.y_axis)
1886 .field("z_axis", &self.z_axis)
1887 .field("w_axis", &self.w_axis)
1888 .finish()
1889 }
1890}
1891
1892impl fmt::Display for DMat4 {
1893 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1894 if let Some(p) = f.precision() {
1895 write!(
1896 f,
1897 "[{:.*}, {:.*}, {:.*}, {:.*}]",
1898 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
1899 )
1900 } else {
1901 write!(
1902 f,
1903 "[{}, {}, {}, {}]",
1904 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1905 )
1906 }
1907 }
1908}