1use crate::{f64::math, swizzles::*, DMat3, DQuat, DVec3, DVec4, EulerRot, Mat4};
4#[cfg(not(target_arch = "spirv"))]
5use core::fmt;
6use core::iter::{Product, Sum};
7use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
8
9#[inline(always)]
11pub const fn dmat4(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> DMat4 {
12 DMat4::from_cols(x_axis, y_axis, z_axis, w_axis)
13}
14
15#[derive(Clone, Copy)]
45#[cfg_attr(feature = "cuda", repr(align(16)))]
46#[repr(C)]
47pub struct DMat4 {
48 pub x_axis: DVec4,
49 pub y_axis: DVec4,
50 pub z_axis: DVec4,
51 pub w_axis: DVec4,
52}
53
54impl DMat4 {
55 pub const ZERO: Self = Self::from_cols(DVec4::ZERO, DVec4::ZERO, DVec4::ZERO, DVec4::ZERO);
57
58 pub const IDENTITY: Self = Self::from_cols(DVec4::X, DVec4::Y, DVec4::Z, DVec4::W);
60
61 pub const NAN: Self = Self::from_cols(DVec4::NAN, DVec4::NAN, DVec4::NAN, DVec4::NAN);
63
64 #[allow(clippy::too_many_arguments)]
65 #[inline(always)]
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 pub const fn from_cols(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> Self {
95 Self {
96 x_axis,
97 y_axis,
98 z_axis,
99 w_axis,
100 }
101 }
102
103 #[inline]
107 pub const fn from_cols_array(m: &[f64; 16]) -> Self {
108 Self::new(
109 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],
110 m[14], m[15],
111 )
112 }
113
114 #[inline]
117 pub const fn to_cols_array(&self) -> [f64; 16] {
118 [
119 self.x_axis.x,
120 self.x_axis.y,
121 self.x_axis.z,
122 self.x_axis.w,
123 self.y_axis.x,
124 self.y_axis.y,
125 self.y_axis.z,
126 self.y_axis.w,
127 self.z_axis.x,
128 self.z_axis.y,
129 self.z_axis.z,
130 self.z_axis.w,
131 self.w_axis.x,
132 self.w_axis.y,
133 self.w_axis.z,
134 self.w_axis.w,
135 ]
136 }
137
138 #[inline]
142 pub const fn from_cols_array_2d(m: &[[f64; 4]; 4]) -> Self {
143 Self::from_cols(
144 DVec4::from_array(m[0]),
145 DVec4::from_array(m[1]),
146 DVec4::from_array(m[2]),
147 DVec4::from_array(m[3]),
148 )
149 }
150
151 #[inline]
154 pub const fn to_cols_array_2d(&self) -> [[f64; 4]; 4] {
155 [
156 self.x_axis.to_array(),
157 self.y_axis.to_array(),
158 self.z_axis.to_array(),
159 self.w_axis.to_array(),
160 ]
161 }
162
163 #[doc(alias = "scale")]
165 #[inline]
166 pub const fn from_diagonal(diagonal: DVec4) -> Self {
167 Self::new(
168 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,
169 0.0, 0.0, diagonal.w,
170 )
171 }
172
173 #[inline]
174 fn quat_to_axes(rotation: DQuat) -> (DVec4, DVec4, DVec4) {
175 glam_assert!(rotation.is_normalized());
176
177 let (x, y, z, w) = rotation.into();
178 let x2 = x + x;
179 let y2 = y + y;
180 let z2 = z + z;
181 let xx = x * x2;
182 let xy = x * y2;
183 let xz = x * z2;
184 let yy = y * y2;
185 let yz = y * z2;
186 let zz = z * z2;
187 let wx = w * x2;
188 let wy = w * y2;
189 let wz = w * z2;
190
191 let x_axis = DVec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
192 let y_axis = DVec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
193 let z_axis = DVec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
194 (x_axis, y_axis, z_axis)
195 }
196
197 #[inline]
207 pub fn from_scale_rotation_translation(
208 scale: DVec3,
209 rotation: DQuat,
210 translation: DVec3,
211 ) -> Self {
212 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
213 Self::from_cols(
214 x_axis.mul(scale.x),
215 y_axis.mul(scale.y),
216 z_axis.mul(scale.z),
217 DVec4::from((translation, 1.0)),
218 )
219 }
220
221 #[inline]
230 pub fn from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self {
231 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
232 Self::from_cols(x_axis, y_axis, z_axis, DVec4::from((translation, 1.0)))
233 }
234
235 #[inline]
243 pub fn to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3) {
244 let det = self.determinant();
245 glam_assert!(det != 0.0);
246
247 let scale = DVec3::new(
248 self.x_axis.length() * math::signum(det),
249 self.y_axis.length(),
250 self.z_axis.length(),
251 );
252
253 glam_assert!(scale.cmpne(DVec3::ZERO).all());
254
255 let inv_scale = scale.recip();
256
257 let rotation = DQuat::from_rotation_axes(
258 self.x_axis.mul(inv_scale.x).xyz(),
259 self.y_axis.mul(inv_scale.y).xyz(),
260 self.z_axis.mul(inv_scale.z).xyz(),
261 );
262
263 let translation = self.w_axis.xyz();
264
265 (scale, rotation, translation)
266 }
267
268 #[inline]
277 pub fn from_quat(rotation: DQuat) -> Self {
278 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
279 Self::from_cols(x_axis, y_axis, z_axis, DVec4::W)
280 }
281
282 #[inline]
288 pub fn from_mat3(m: DMat3) -> Self {
289 Self::from_cols(
290 DVec4::from((m.x_axis, 0.0)),
291 DVec4::from((m.y_axis, 0.0)),
292 DVec4::from((m.z_axis, 0.0)),
293 DVec4::W,
294 )
295 }
296
297 #[inline]
302 pub fn from_translation(translation: DVec3) -> Self {
303 Self::from_cols(
304 DVec4::X,
305 DVec4::Y,
306 DVec4::Z,
307 DVec4::new(translation.x, translation.y, translation.z, 1.0),
308 )
309 }
310
311 #[inline]
321 pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
322 glam_assert!(axis.is_normalized());
323
324 let (sin, cos) = math::sin_cos(angle);
325 let axis_sin = axis.mul(sin);
326 let axis_sq = axis.mul(axis);
327 let omc = 1.0 - cos;
328 let xyomc = axis.x * axis.y * omc;
329 let xzomc = axis.x * axis.z * omc;
330 let yzomc = axis.y * axis.z * omc;
331 Self::from_cols(
332 DVec4::new(
333 axis_sq.x * omc + cos,
334 xyomc + axis_sin.z,
335 xzomc - axis_sin.y,
336 0.0,
337 ),
338 DVec4::new(
339 xyomc - axis_sin.z,
340 axis_sq.y * omc + cos,
341 yzomc + axis_sin.x,
342 0.0,
343 ),
344 DVec4::new(
345 xzomc + axis_sin.y,
346 yzomc - axis_sin.x,
347 axis_sq.z * omc + cos,
348 0.0,
349 ),
350 DVec4::W,
351 )
352 }
353
354 #[inline]
355 pub fn from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self {
361 let quat = DQuat::from_euler(order, a, b, c);
362 Self::from_quat(quat)
363 }
364
365 #[inline]
371 pub fn from_rotation_x(angle: f64) -> Self {
372 let (sina, cosa) = math::sin_cos(angle);
373 Self::from_cols(
374 DVec4::X,
375 DVec4::new(0.0, cosa, sina, 0.0),
376 DVec4::new(0.0, -sina, cosa, 0.0),
377 DVec4::W,
378 )
379 }
380
381 #[inline]
387 pub fn from_rotation_y(angle: f64) -> Self {
388 let (sina, cosa) = math::sin_cos(angle);
389 Self::from_cols(
390 DVec4::new(cosa, 0.0, -sina, 0.0),
391 DVec4::Y,
392 DVec4::new(sina, 0.0, cosa, 0.0),
393 DVec4::W,
394 )
395 }
396
397 #[inline]
403 pub fn from_rotation_z(angle: f64) -> Self {
404 let (sina, cosa) = math::sin_cos(angle);
405 Self::from_cols(
406 DVec4::new(cosa, sina, 0.0, 0.0),
407 DVec4::new(-sina, cosa, 0.0, 0.0),
408 DVec4::Z,
409 DVec4::W,
410 )
411 }
412
413 #[inline]
422 pub fn from_scale(scale: DVec3) -> Self {
423 glam_assert!(scale.cmpne(DVec3::ZERO).any());
425
426 Self::from_cols(
427 DVec4::new(scale.x, 0.0, 0.0, 0.0),
428 DVec4::new(0.0, scale.y, 0.0, 0.0),
429 DVec4::new(0.0, 0.0, scale.z, 0.0),
430 DVec4::W,
431 )
432 }
433
434 #[inline]
440 pub const fn from_cols_slice(slice: &[f64]) -> Self {
441 Self::new(
442 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
443 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
444 )
445 }
446
447 #[inline]
453 pub fn write_cols_to_slice(self, slice: &mut [f64]) {
454 slice[0] = self.x_axis.x;
455 slice[1] = self.x_axis.y;
456 slice[2] = self.x_axis.z;
457 slice[3] = self.x_axis.w;
458 slice[4] = self.y_axis.x;
459 slice[5] = self.y_axis.y;
460 slice[6] = self.y_axis.z;
461 slice[7] = self.y_axis.w;
462 slice[8] = self.z_axis.x;
463 slice[9] = self.z_axis.y;
464 slice[10] = self.z_axis.z;
465 slice[11] = self.z_axis.w;
466 slice[12] = self.w_axis.x;
467 slice[13] = self.w_axis.y;
468 slice[14] = self.w_axis.z;
469 slice[15] = self.w_axis.w;
470 }
471
472 #[inline]
478 pub fn col(&self, index: usize) -> DVec4 {
479 match index {
480 0 => self.x_axis,
481 1 => self.y_axis,
482 2 => self.z_axis,
483 3 => self.w_axis,
484 _ => panic!("index out of bounds"),
485 }
486 }
487
488 #[inline]
494 pub fn col_mut(&mut self, index: usize) -> &mut DVec4 {
495 match index {
496 0 => &mut self.x_axis,
497 1 => &mut self.y_axis,
498 2 => &mut self.z_axis,
499 3 => &mut self.w_axis,
500 _ => panic!("index out of bounds"),
501 }
502 }
503
504 #[inline]
510 pub fn row(&self, index: usize) -> DVec4 {
511 match index {
512 0 => DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
513 1 => DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
514 2 => DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
515 3 => DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
516 _ => panic!("index out of bounds"),
517 }
518 }
519
520 #[inline]
523 pub fn is_finite(&self) -> bool {
524 self.x_axis.is_finite()
525 && self.y_axis.is_finite()
526 && self.z_axis.is_finite()
527 && self.w_axis.is_finite()
528 }
529
530 #[inline]
532 pub fn is_nan(&self) -> bool {
533 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
534 }
535
536 #[must_use]
538 #[inline]
539 pub fn transpose(&self) -> Self {
540 Self {
541 x_axis: DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
542 y_axis: DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
543 z_axis: DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
544 w_axis: DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
545 }
546 }
547
548 pub fn determinant(&self) -> f64 {
550 let (m00, m01, m02, m03) = self.x_axis.into();
551 let (m10, m11, m12, m13) = self.y_axis.into();
552 let (m20, m21, m22, m23) = self.z_axis.into();
553 let (m30, m31, m32, m33) = self.w_axis.into();
554
555 let a2323 = m22 * m33 - m23 * m32;
556 let a1323 = m21 * m33 - m23 * m31;
557 let a1223 = m21 * m32 - m22 * m31;
558 let a0323 = m20 * m33 - m23 * m30;
559 let a0223 = m20 * m32 - m22 * m30;
560 let a0123 = m20 * m31 - m21 * m30;
561
562 m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223)
563 - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223)
564 + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123)
565 - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123)
566 }
567
568 #[must_use]
576 pub fn inverse(&self) -> Self {
577 let (m00, m01, m02, m03) = self.x_axis.into();
578 let (m10, m11, m12, m13) = self.y_axis.into();
579 let (m20, m21, m22, m23) = self.z_axis.into();
580 let (m30, m31, m32, m33) = self.w_axis.into();
581
582 let coef00 = m22 * m33 - m32 * m23;
583 let coef02 = m12 * m33 - m32 * m13;
584 let coef03 = m12 * m23 - m22 * m13;
585
586 let coef04 = m21 * m33 - m31 * m23;
587 let coef06 = m11 * m33 - m31 * m13;
588 let coef07 = m11 * m23 - m21 * m13;
589
590 let coef08 = m21 * m32 - m31 * m22;
591 let coef10 = m11 * m32 - m31 * m12;
592 let coef11 = m11 * m22 - m21 * m12;
593
594 let coef12 = m20 * m33 - m30 * m23;
595 let coef14 = m10 * m33 - m30 * m13;
596 let coef15 = m10 * m23 - m20 * m13;
597
598 let coef16 = m20 * m32 - m30 * m22;
599 let coef18 = m10 * m32 - m30 * m12;
600 let coef19 = m10 * m22 - m20 * m12;
601
602 let coef20 = m20 * m31 - m30 * m21;
603 let coef22 = m10 * m31 - m30 * m11;
604 let coef23 = m10 * m21 - m20 * m11;
605
606 let fac0 = DVec4::new(coef00, coef00, coef02, coef03);
607 let fac1 = DVec4::new(coef04, coef04, coef06, coef07);
608 let fac2 = DVec4::new(coef08, coef08, coef10, coef11);
609 let fac3 = DVec4::new(coef12, coef12, coef14, coef15);
610 let fac4 = DVec4::new(coef16, coef16, coef18, coef19);
611 let fac5 = DVec4::new(coef20, coef20, coef22, coef23);
612
613 let vec0 = DVec4::new(m10, m00, m00, m00);
614 let vec1 = DVec4::new(m11, m01, m01, m01);
615 let vec2 = DVec4::new(m12, m02, m02, m02);
616 let vec3 = DVec4::new(m13, m03, m03, m03);
617
618 let inv0 = vec1.mul(fac0).sub(vec2.mul(fac1)).add(vec3.mul(fac2));
619 let inv1 = vec0.mul(fac0).sub(vec2.mul(fac3)).add(vec3.mul(fac4));
620 let inv2 = vec0.mul(fac1).sub(vec1.mul(fac3)).add(vec3.mul(fac5));
621 let inv3 = vec0.mul(fac2).sub(vec1.mul(fac4)).add(vec2.mul(fac5));
622
623 let sign_a = DVec4::new(1.0, -1.0, 1.0, -1.0);
624 let sign_b = DVec4::new(-1.0, 1.0, -1.0, 1.0);
625
626 let inverse = Self::from_cols(
627 inv0.mul(sign_a),
628 inv1.mul(sign_b),
629 inv2.mul(sign_a),
630 inv3.mul(sign_b),
631 );
632
633 let col0 = DVec4::new(
634 inverse.x_axis.x,
635 inverse.y_axis.x,
636 inverse.z_axis.x,
637 inverse.w_axis.x,
638 );
639
640 let dot0 = self.x_axis.mul(col0);
641 let dot1 = dot0.x + dot0.y + dot0.z + dot0.w;
642
643 glam_assert!(dot1 != 0.0);
644
645 let rcp_det = dot1.recip();
646 inverse.mul(rcp_det)
647 }
648
649 #[inline]
654 pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
655 Self::look_to_rh(eye, -dir, up)
656 }
657
658 #[inline]
663 pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
664 let f = dir.normalize();
665 let s = f.cross(up).normalize();
666 let u = s.cross(f);
667
668 Self::from_cols(
669 DVec4::new(s.x, u.x, -f.x, 0.0),
670 DVec4::new(s.y, u.y, -f.y, 0.0),
671 DVec4::new(s.z, u.z, -f.z, 0.0),
672 DVec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
673 )
674 }
675
676 #[inline]
684 pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
685 glam_assert!(up.is_normalized());
686 Self::look_to_lh(eye, center.sub(eye), up)
687 }
688
689 #[inline]
697 pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
698 glam_assert!(up.is_normalized());
699 Self::look_to_rh(eye, center.sub(eye), up)
700 }
701
702 #[inline]
706 pub fn perspective_rh_gl(
707 fov_y_radians: f64,
708 aspect_ratio: f64,
709 z_near: f64,
710 z_far: f64,
711 ) -> Self {
712 let inv_length = 1.0 / (z_near - z_far);
713 let f = 1.0 / math::tan(0.5 * fov_y_radians);
714 let a = f / aspect_ratio;
715 let b = (z_near + z_far) * inv_length;
716 let c = (2.0 * z_near * z_far) * inv_length;
717 Self::from_cols(
718 DVec4::new(a, 0.0, 0.0, 0.0),
719 DVec4::new(0.0, f, 0.0, 0.0),
720 DVec4::new(0.0, 0.0, b, -1.0),
721 DVec4::new(0.0, 0.0, c, 0.0),
722 )
723 }
724
725 #[inline]
732 pub fn perspective_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
733 glam_assert!(z_near > 0.0 && z_far > 0.0);
734 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
735 let h = cos_fov / sin_fov;
736 let w = h / aspect_ratio;
737 let r = z_far / (z_far - z_near);
738 Self::from_cols(
739 DVec4::new(w, 0.0, 0.0, 0.0),
740 DVec4::new(0.0, h, 0.0, 0.0),
741 DVec4::new(0.0, 0.0, r, 1.0),
742 DVec4::new(0.0, 0.0, -r * z_near, 0.0),
743 )
744 }
745
746 #[inline]
753 pub fn perspective_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
754 glam_assert!(z_near > 0.0 && z_far > 0.0);
755 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
756 let h = cos_fov / sin_fov;
757 let w = h / aspect_ratio;
758 let r = z_far / (z_near - z_far);
759 Self::from_cols(
760 DVec4::new(w, 0.0, 0.0, 0.0),
761 DVec4::new(0.0, h, 0.0, 0.0),
762 DVec4::new(0.0, 0.0, r, -1.0),
763 DVec4::new(0.0, 0.0, r * z_near, 0.0),
764 )
765 }
766
767 #[inline]
773 pub fn perspective_infinite_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
774 glam_assert!(z_near > 0.0);
775 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
776 let h = cos_fov / sin_fov;
777 let w = h / aspect_ratio;
778 Self::from_cols(
779 DVec4::new(w, 0.0, 0.0, 0.0),
780 DVec4::new(0.0, h, 0.0, 0.0),
781 DVec4::new(0.0, 0.0, 1.0, 1.0),
782 DVec4::new(0.0, 0.0, -z_near, 0.0),
783 )
784 }
785
786 #[inline]
792 pub fn perspective_infinite_reverse_lh(
793 fov_y_radians: f64,
794 aspect_ratio: f64,
795 z_near: f64,
796 ) -> Self {
797 glam_assert!(z_near > 0.0);
798 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
799 let h = cos_fov / sin_fov;
800 let w = h / aspect_ratio;
801 Self::from_cols(
802 DVec4::new(w, 0.0, 0.0, 0.0),
803 DVec4::new(0.0, h, 0.0, 0.0),
804 DVec4::new(0.0, 0.0, 0.0, 1.0),
805 DVec4::new(0.0, 0.0, z_near, 0.0),
806 )
807 }
808
809 #[inline]
812 pub fn perspective_infinite_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
813 glam_assert!(z_near > 0.0);
814 let f = 1.0 / math::tan(0.5 * fov_y_radians);
815 Self::from_cols(
816 DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
817 DVec4::new(0.0, f, 0.0, 0.0),
818 DVec4::new(0.0, 0.0, -1.0, -1.0),
819 DVec4::new(0.0, 0.0, -z_near, 0.0),
820 )
821 }
822
823 #[inline]
826 pub fn perspective_infinite_reverse_rh(
827 fov_y_radians: f64,
828 aspect_ratio: f64,
829 z_near: f64,
830 ) -> Self {
831 glam_assert!(z_near > 0.0);
832 let f = 1.0 / math::tan(0.5 * fov_y_radians);
833 Self::from_cols(
834 DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
835 DVec4::new(0.0, f, 0.0, 0.0),
836 DVec4::new(0.0, 0.0, 0.0, -1.0),
837 DVec4::new(0.0, 0.0, z_near, 0.0),
838 )
839 }
840
841 #[inline]
846 pub fn orthographic_rh_gl(
847 left: f64,
848 right: f64,
849 bottom: f64,
850 top: f64,
851 near: f64,
852 far: f64,
853 ) -> Self {
854 let a = 2.0 / (right - left);
855 let b = 2.0 / (top - bottom);
856 let c = -2.0 / (far - near);
857 let tx = -(right + left) / (right - left);
858 let ty = -(top + bottom) / (top - bottom);
859 let tz = -(far + near) / (far - near);
860
861 Self::from_cols(
862 DVec4::new(a, 0.0, 0.0, 0.0),
863 DVec4::new(0.0, b, 0.0, 0.0),
864 DVec4::new(0.0, 0.0, c, 0.0),
865 DVec4::new(tx, ty, tz, 1.0),
866 )
867 }
868
869 #[inline]
871 pub fn orthographic_lh(
872 left: f64,
873 right: f64,
874 bottom: f64,
875 top: f64,
876 near: f64,
877 far: f64,
878 ) -> Self {
879 let rcp_width = 1.0 / (right - left);
880 let rcp_height = 1.0 / (top - bottom);
881 let r = 1.0 / (far - near);
882 Self::from_cols(
883 DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
884 DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
885 DVec4::new(0.0, 0.0, r, 0.0),
886 DVec4::new(
887 -(left + right) * rcp_width,
888 -(top + bottom) * rcp_height,
889 -r * near,
890 1.0,
891 ),
892 )
893 }
894
895 #[inline]
897 pub fn orthographic_rh(
898 left: f64,
899 right: f64,
900 bottom: f64,
901 top: f64,
902 near: f64,
903 far: f64,
904 ) -> Self {
905 let rcp_width = 1.0 / (right - left);
906 let rcp_height = 1.0 / (top - bottom);
907 let r = 1.0 / (near - far);
908 Self::from_cols(
909 DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
910 DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
911 DVec4::new(0.0, 0.0, r, 0.0),
912 DVec4::new(
913 -(left + right) * rcp_width,
914 -(top + bottom) * rcp_height,
915 r * near,
916 1.0,
917 ),
918 )
919 }
920
921 #[inline]
928 pub fn project_point3(&self, rhs: DVec3) -> DVec3 {
929 let mut res = self.x_axis.mul(rhs.x);
930 res = self.y_axis.mul(rhs.y).add(res);
931 res = self.z_axis.mul(rhs.z).add(res);
932 res = self.w_axis.add(res);
933 res = res.mul(res.wwww().recip());
934 res.xyz()
935 }
936
937 #[inline]
950 pub fn transform_point3(&self, rhs: DVec3) -> DVec3 {
951 glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
952 let mut res = self.x_axis.mul(rhs.x);
953 res = self.y_axis.mul(rhs.y).add(res);
954 res = self.z_axis.mul(rhs.z).add(res);
955 res = self.w_axis.add(res);
956 res.xyz()
957 }
958
959 #[inline]
970 pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 {
971 glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
972 let mut res = self.x_axis.mul(rhs.x);
973 res = self.y_axis.mul(rhs.y).add(res);
974 res = self.z_axis.mul(rhs.z).add(res);
975 res.xyz()
976 }
977
978 #[inline]
980 pub fn mul_vec4(&self, rhs: DVec4) -> DVec4 {
981 let mut res = self.x_axis.mul(rhs.x);
982 res = res.add(self.y_axis.mul(rhs.y));
983 res = res.add(self.z_axis.mul(rhs.z));
984 res = res.add(self.w_axis.mul(rhs.w));
985 res
986 }
987
988 #[inline]
990 pub fn mul_mat4(&self, rhs: &Self) -> Self {
991 Self::from_cols(
992 self.mul(rhs.x_axis),
993 self.mul(rhs.y_axis),
994 self.mul(rhs.z_axis),
995 self.mul(rhs.w_axis),
996 )
997 }
998
999 #[inline]
1001 pub fn add_mat4(&self, rhs: &Self) -> Self {
1002 Self::from_cols(
1003 self.x_axis.add(rhs.x_axis),
1004 self.y_axis.add(rhs.y_axis),
1005 self.z_axis.add(rhs.z_axis),
1006 self.w_axis.add(rhs.w_axis),
1007 )
1008 }
1009
1010 #[inline]
1012 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1013 Self::from_cols(
1014 self.x_axis.sub(rhs.x_axis),
1015 self.y_axis.sub(rhs.y_axis),
1016 self.z_axis.sub(rhs.z_axis),
1017 self.w_axis.sub(rhs.w_axis),
1018 )
1019 }
1020
1021 #[inline]
1023 pub fn mul_scalar(&self, rhs: f64) -> Self {
1024 Self::from_cols(
1025 self.x_axis.mul(rhs),
1026 self.y_axis.mul(rhs),
1027 self.z_axis.mul(rhs),
1028 self.w_axis.mul(rhs),
1029 )
1030 }
1031
1032 #[inline]
1042 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
1043 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1044 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1045 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1046 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1047 }
1048
1049 #[inline]
1050 pub fn as_mat4(&self) -> Mat4 {
1051 Mat4::from_cols(
1052 self.x_axis.as_vec4(),
1053 self.y_axis.as_vec4(),
1054 self.z_axis.as_vec4(),
1055 self.w_axis.as_vec4(),
1056 )
1057 }
1058}
1059
1060impl Default for DMat4 {
1061 #[inline]
1062 fn default() -> Self {
1063 Self::IDENTITY
1064 }
1065}
1066
1067impl Add<DMat4> for DMat4 {
1068 type Output = Self;
1069 #[inline]
1070 fn add(self, rhs: Self) -> Self::Output {
1071 self.add_mat4(&rhs)
1072 }
1073}
1074
1075impl AddAssign<DMat4> for DMat4 {
1076 #[inline]
1077 fn add_assign(&mut self, rhs: Self) {
1078 *self = self.add_mat4(&rhs);
1079 }
1080}
1081
1082impl Sub<DMat4> for DMat4 {
1083 type Output = Self;
1084 #[inline]
1085 fn sub(self, rhs: Self) -> Self::Output {
1086 self.sub_mat4(&rhs)
1087 }
1088}
1089
1090impl SubAssign<DMat4> for DMat4 {
1091 #[inline]
1092 fn sub_assign(&mut self, rhs: Self) {
1093 *self = self.sub_mat4(&rhs);
1094 }
1095}
1096
1097impl Neg for DMat4 {
1098 type Output = Self;
1099 #[inline]
1100 fn neg(self) -> Self::Output {
1101 Self::from_cols(
1102 self.x_axis.neg(),
1103 self.y_axis.neg(),
1104 self.z_axis.neg(),
1105 self.w_axis.neg(),
1106 )
1107 }
1108}
1109
1110impl Mul<DMat4> for DMat4 {
1111 type Output = Self;
1112 #[inline]
1113 fn mul(self, rhs: Self) -> Self::Output {
1114 self.mul_mat4(&rhs)
1115 }
1116}
1117
1118impl MulAssign<DMat4> for DMat4 {
1119 #[inline]
1120 fn mul_assign(&mut self, rhs: Self) {
1121 *self = self.mul_mat4(&rhs);
1122 }
1123}
1124
1125impl Mul<DVec4> for DMat4 {
1126 type Output = DVec4;
1127 #[inline]
1128 fn mul(self, rhs: DVec4) -> Self::Output {
1129 self.mul_vec4(rhs)
1130 }
1131}
1132
1133impl Mul<DMat4> for f64 {
1134 type Output = DMat4;
1135 #[inline]
1136 fn mul(self, rhs: DMat4) -> Self::Output {
1137 rhs.mul_scalar(self)
1138 }
1139}
1140
1141impl Mul<f64> for DMat4 {
1142 type Output = Self;
1143 #[inline]
1144 fn mul(self, rhs: f64) -> Self::Output {
1145 self.mul_scalar(rhs)
1146 }
1147}
1148
1149impl MulAssign<f64> for DMat4 {
1150 #[inline]
1151 fn mul_assign(&mut self, rhs: f64) {
1152 *self = self.mul_scalar(rhs);
1153 }
1154}
1155
1156impl Sum<Self> for DMat4 {
1157 fn sum<I>(iter: I) -> Self
1158 where
1159 I: Iterator<Item = Self>,
1160 {
1161 iter.fold(Self::ZERO, Self::add)
1162 }
1163}
1164
1165impl<'a> Sum<&'a Self> for DMat4 {
1166 fn sum<I>(iter: I) -> Self
1167 where
1168 I: Iterator<Item = &'a Self>,
1169 {
1170 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1171 }
1172}
1173
1174impl Product for DMat4 {
1175 fn product<I>(iter: I) -> Self
1176 where
1177 I: Iterator<Item = Self>,
1178 {
1179 iter.fold(Self::IDENTITY, Self::mul)
1180 }
1181}
1182
1183impl<'a> Product<&'a Self> for DMat4 {
1184 fn product<I>(iter: I) -> Self
1185 where
1186 I: Iterator<Item = &'a Self>,
1187 {
1188 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1189 }
1190}
1191
1192impl PartialEq for DMat4 {
1193 #[inline]
1194 fn eq(&self, rhs: &Self) -> bool {
1195 self.x_axis.eq(&rhs.x_axis)
1196 && self.y_axis.eq(&rhs.y_axis)
1197 && self.z_axis.eq(&rhs.z_axis)
1198 && self.w_axis.eq(&rhs.w_axis)
1199 }
1200}
1201
1202#[cfg(not(target_arch = "spirv"))]
1203impl AsRef<[f64; 16]> for DMat4 {
1204 #[inline]
1205 fn as_ref(&self) -> &[f64; 16] {
1206 unsafe { &*(self as *const Self as *const [f64; 16]) }
1207 }
1208}
1209
1210#[cfg(not(target_arch = "spirv"))]
1211impl AsMut<[f64; 16]> for DMat4 {
1212 #[inline]
1213 fn as_mut(&mut self) -> &mut [f64; 16] {
1214 unsafe { &mut *(self as *mut Self as *mut [f64; 16]) }
1215 }
1216}
1217
1218#[cfg(not(target_arch = "spirv"))]
1219impl fmt::Debug for DMat4 {
1220 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1221 fmt.debug_struct(stringify!(DMat4))
1222 .field("x_axis", &self.x_axis)
1223 .field("y_axis", &self.y_axis)
1224 .field("z_axis", &self.z_axis)
1225 .field("w_axis", &self.w_axis)
1226 .finish()
1227 }
1228}
1229
1230#[cfg(not(target_arch = "spirv"))]
1231impl fmt::Display for DMat4 {
1232 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1233 write!(
1234 f,
1235 "[{}, {}, {}, {}]",
1236 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1237 )
1238 }
1239}