1#[cfg(feature = "f64")]
4use crate::DMat4;
5
6use crate::{
7 euler::{FromEuler, ToEuler},
8 f32::math,
9 sse2::*,
10 swizzles::*,
11 EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4,
12};
13use core::fmt;
14use core::iter::{Product, Sum};
15use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
16
17#[cfg(target_arch = "x86")]
18use core::arch::x86::*;
19#[cfg(target_arch = "x86_64")]
20use core::arch::x86_64::*;
21
22#[cfg(feature = "zerocopy-08")]
23use zerocopy_derive_08::*;
24
25#[inline(always)]
27#[must_use]
28pub const fn mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat4 {
29 Mat4::from_cols(x_axis, y_axis, z_axis, w_axis)
30}
31
32#[derive(Clone, Copy)]
52#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
53#[cfg_attr(
54 feature = "zerocopy-08",
55 derive(FromBytes, Immutable, IntoBytes, KnownLayout)
56)]
57#[repr(C)]
58pub struct Mat4 {
59 pub x_axis: Vec4,
60 pub y_axis: Vec4,
61 pub z_axis: Vec4,
62 pub w_axis: Vec4,
63}
64
65impl Mat4 {
66 pub const ZERO: Self = Self::from_cols(Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO);
68
69 pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W);
71
72 pub const NAN: Self = Self::from_cols(Vec4::NAN, Vec4::NAN, Vec4::NAN, Vec4::NAN);
74
75 #[allow(clippy::too_many_arguments)]
76 #[inline(always)]
77 #[must_use]
78 const fn new(
79 m00: f32,
80 m01: f32,
81 m02: f32,
82 m03: f32,
83 m10: f32,
84 m11: f32,
85 m12: f32,
86 m13: f32,
87 m20: f32,
88 m21: f32,
89 m22: f32,
90 m23: f32,
91 m30: f32,
92 m31: f32,
93 m32: f32,
94 m33: f32,
95 ) -> Self {
96 Self {
97 x_axis: Vec4::new(m00, m01, m02, m03),
98 y_axis: Vec4::new(m10, m11, m12, m13),
99 z_axis: Vec4::new(m20, m21, m22, m23),
100 w_axis: Vec4::new(m30, m31, m32, m33),
101 }
102 }
103
104 #[inline(always)]
108 #[must_use]
109 pub const fn from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self {
110 Self {
111 x_axis,
112 y_axis,
113 z_axis,
114 w_axis,
115 }
116 }
117
118 #[inline(always)]
124 #[must_use]
125 pub const fn from_rows(row0: Vec4, row1: Vec4, row2: Vec4, row3: Vec4) -> Self {
126 let [m00, m01, m02, m03] = row0.to_array();
127 let [m10, m11, m12, m13] = row1.to_array();
128 let [m20, m21, m22, m23] = row2.to_array();
129 let [m30, m31, m32, m33] = row3.to_array();
130 Self::new(
131 m00, m10, m20, m30, m01, m11, m21, m31, m02, m12, m22, m32, m03, m13, m23, m33,
132 )
133 }
134
135 #[inline]
139 #[must_use]
140 pub const fn from_cols_array(m: &[f32; 16]) -> Self {
141 Self::new(
142 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],
143 m[14], m[15],
144 )
145 }
146
147 #[inline]
151 #[must_use]
152 pub const fn to_cols_array(&self) -> [f32; 16] {
153 let [x_axis_x, x_axis_y, x_axis_z, x_axis_w] = self.x_axis.to_array();
154 let [y_axis_x, y_axis_y, y_axis_z, y_axis_w] = self.y_axis.to_array();
155 let [z_axis_x, z_axis_y, z_axis_z, z_axis_w] = self.z_axis.to_array();
156 let [w_axis_x, w_axis_y, w_axis_z, w_axis_w] = self.w_axis.to_array();
157
158 [
159 x_axis_x, x_axis_y, x_axis_z, x_axis_w, y_axis_x, y_axis_y, y_axis_z, y_axis_w,
160 z_axis_x, z_axis_y, z_axis_z, z_axis_w, w_axis_x, w_axis_y, w_axis_z, w_axis_w,
161 ]
162 }
163
164 #[inline]
168 #[must_use]
169 pub const fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self {
170 Self::from_cols(
171 Vec4::from_array(m[0]),
172 Vec4::from_array(m[1]),
173 Vec4::from_array(m[2]),
174 Vec4::from_array(m[3]),
175 )
176 }
177
178 #[inline]
182 #[must_use]
183 pub const fn to_cols_array_2d(&self) -> [[f32; 4]; 4] {
184 [
185 self.x_axis.to_array(),
186 self.y_axis.to_array(),
187 self.z_axis.to_array(),
188 self.w_axis.to_array(),
189 ]
190 }
191
192 #[inline]
198 #[must_use]
199 pub const fn from_rows_array(m: &[f32; 16]) -> Self {
200 Self::new(
201 m[0], m[4], m[8], m[12], m[1], m[5], m[9], m[13], m[2], m[6], m[10], m[14], m[3], m[7],
202 m[11], m[15],
203 )
204 }
205
206 #[inline]
212 #[must_use]
213 pub const fn to_rows_array(&self) -> [f32; 16] {
214 let m = self.to_cols_array();
215 [
216 m[0], m[4], m[8], m[12], m[1], m[5], m[9], m[13], m[2], m[6], m[10], m[14], m[3], m[7],
217 m[11], m[15],
218 ]
219 }
220
221 #[doc(alias = "scale")]
223 #[inline]
224 #[must_use]
225 pub const fn from_diagonal(diagonal: Vec4) -> Self {
226 let [x, y, z, w] = diagonal.to_array();
228 Self::new(
229 x, 0.0, 0.0, 0.0, 0.0, y, 0.0, 0.0, 0.0, 0.0, z, 0.0, 0.0, 0.0, 0.0, w,
230 )
231 }
232
233 #[inline]
234 #[must_use]
235 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
236 fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) {
237 glam_assert!(rotation.is_normalized());
238
239 let (x, y, z, w) = rotation.into();
240 let x2 = x + x;
241 let y2 = y + y;
242 let z2 = z + z;
243 let xx = x * x2;
244 let xy = x * y2;
245 let xz = x * z2;
246 let yy = y * y2;
247 let yz = y * z2;
248 let zz = z * z2;
249 let wx = w * x2;
250 let wy = w * y2;
251 let wz = w * z2;
252
253 let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
254 let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
255 let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
256 (x_axis, y_axis, z_axis)
257 }
258
259 #[inline]
269 #[must_use]
270 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
271 pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
272 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
273 Self::from_cols(
274 x_axis.mul(scale.x),
275 y_axis.mul(scale.y),
276 z_axis.mul(scale.z),
277 Vec4::from((translation, 1.0)),
278 )
279 }
280
281 #[inline]
290 #[must_use]
291 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
292 pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
293 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
294 Self::from_cols(x_axis, y_axis, z_axis, Vec4::from((translation, 1.0)))
295 }
296
297 #[inline]
305 #[must_use]
306 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
307 pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
308 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
309
310 let r = Mat3A::from_mat4(*self);
311
312 let det = r.determinant();
313
314 glam_assert!(det != 0.0);
315
316 let scale = Vec3::new(
317 r.x_axis.length() * math::signum(det),
318 r.y_axis.length(),
319 r.z_axis.length(),
320 );
321
322 glam_assert!(scale.cmpne(Vec3::ZERO).all());
323
324 let inv_scale = scale.recip();
325
326 let rotation = Quat::from_mat3a(&Mat3A::from_cols(
327 r.x_axis.mul(inv_scale.x),
328 r.y_axis.mul(inv_scale.y),
329 r.z_axis.mul(inv_scale.z),
330 ));
331
332 let translation = self.w_axis.xyz();
333
334 (scale, rotation, translation)
335 }
336
337 #[inline]
346 #[must_use]
347 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
348 pub fn from_quat(rotation: Quat) -> Self {
349 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
350 Self::from_cols(x_axis, y_axis, z_axis, Vec4::W)
351 }
352
353 #[inline]
359 #[must_use]
360 pub fn from_mat3(m: Mat3) -> Self {
361 Self::from_cols(
362 Vec4::from((m.x_axis, 0.0)),
363 Vec4::from((m.y_axis, 0.0)),
364 Vec4::from((m.z_axis, 0.0)),
365 Vec4::W,
366 )
367 }
368
369 #[inline]
374 #[must_use]
375 pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
376 Self::from_cols(
377 Vec4::from((mat3.x_axis, 0.0)),
378 Vec4::from((mat3.y_axis, 0.0)),
379 Vec4::from((mat3.z_axis, 0.0)),
380 Vec4::from((translation, 1.0)),
381 )
382 }
383
384 #[inline]
390 #[must_use]
391 pub fn from_mat3a(m: Mat3A) -> Self {
392 Self::from_cols(
393 Vec4::from((m.x_axis, 0.0)),
394 Vec4::from((m.y_axis, 0.0)),
395 Vec4::from((m.z_axis, 0.0)),
396 Vec4::W,
397 )
398 }
399
400 #[inline]
405 #[must_use]
406 pub fn from_translation(translation: Vec3) -> Self {
407 Self::from_cols(
408 Vec4::X,
409 Vec4::Y,
410 Vec4::Z,
411 Vec4::new(translation.x, translation.y, translation.z, 1.0),
412 )
413 }
414
415 #[inline]
425 #[must_use]
426 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
427 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
428 glam_assert!(axis.is_normalized());
429
430 let (sin, cos) = math::sin_cos(angle);
431 let axis_sin = axis.mul(sin);
432 let axis_sq = axis.mul(axis);
433 let omc = 1.0 - cos;
434 let xyomc = axis.x * axis.y * omc;
435 let xzomc = axis.x * axis.z * omc;
436 let yzomc = axis.y * axis.z * omc;
437 Self::from_cols(
438 Vec4::new(
439 axis_sq.x * omc + cos,
440 xyomc + axis_sin.z,
441 xzomc - axis_sin.y,
442 0.0,
443 ),
444 Vec4::new(
445 xyomc - axis_sin.z,
446 axis_sq.y * omc + cos,
447 yzomc + axis_sin.x,
448 0.0,
449 ),
450 Vec4::new(
451 xzomc + axis_sin.y,
452 yzomc - axis_sin.x,
453 axis_sq.z * omc + cos,
454 0.0,
455 ),
456 Vec4::W,
457 )
458 }
459
460 #[inline]
466 #[must_use]
467 pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
468 Self::from_euler_angles(order, a, b, c)
469 }
470
471 #[inline]
481 #[must_use]
482 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
483 pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
484 glam_assert!(
485 self.x_axis.xyz().is_normalized()
486 && self.y_axis.xyz().is_normalized()
487 && self.z_axis.xyz().is_normalized()
488 );
489 Mat3::from_mat4(*self).to_euler_angles(order)
490 }
491
492 #[inline]
498 #[must_use]
499 pub fn from_rotation_x(angle: f32) -> Self {
500 let (sina, cosa) = math::sin_cos(angle);
501 Self::from_cols(
502 Vec4::X,
503 Vec4::new(0.0, cosa, sina, 0.0),
504 Vec4::new(0.0, -sina, cosa, 0.0),
505 Vec4::W,
506 )
507 }
508
509 #[inline]
515 #[must_use]
516 pub fn from_rotation_y(angle: f32) -> Self {
517 let (sina, cosa) = math::sin_cos(angle);
518 Self::from_cols(
519 Vec4::new(cosa, 0.0, -sina, 0.0),
520 Vec4::Y,
521 Vec4::new(sina, 0.0, cosa, 0.0),
522 Vec4::W,
523 )
524 }
525
526 #[inline]
532 #[must_use]
533 pub fn from_rotation_z(angle: f32) -> Self {
534 let (sina, cosa) = math::sin_cos(angle);
535 Self::from_cols(
536 Vec4::new(cosa, sina, 0.0, 0.0),
537 Vec4::new(-sina, cosa, 0.0, 0.0),
538 Vec4::Z,
539 Vec4::W,
540 )
541 }
542
543 #[inline]
552 #[must_use]
553 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
554 pub fn from_scale(scale: Vec3) -> Self {
555 glam_assert!(scale.cmpne(Vec3::ZERO).any());
557
558 Self::from_cols(
559 Vec4::new(scale.x, 0.0, 0.0, 0.0),
560 Vec4::new(0.0, scale.y, 0.0, 0.0),
561 Vec4::new(0.0, 0.0, scale.z, 0.0),
562 Vec4::W,
563 )
564 }
565
566 #[inline]
574 #[must_use]
575 #[track_caller]
576 pub const fn from_cols_slice(slice: &[f32]) -> Self {
577 Self::new(
578 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
579 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
580 )
581 }
582
583 #[inline]
589 #[track_caller]
590 pub fn write_cols_to_slice(&self, slice: &mut [f32]) {
591 slice[0] = self.x_axis.x;
592 slice[1] = self.x_axis.y;
593 slice[2] = self.x_axis.z;
594 slice[3] = self.x_axis.w;
595 slice[4] = self.y_axis.x;
596 slice[5] = self.y_axis.y;
597 slice[6] = self.y_axis.z;
598 slice[7] = self.y_axis.w;
599 slice[8] = self.z_axis.x;
600 slice[9] = self.z_axis.y;
601 slice[10] = self.z_axis.z;
602 slice[11] = self.z_axis.w;
603 slice[12] = self.w_axis.x;
604 slice[13] = self.w_axis.y;
605 slice[14] = self.w_axis.z;
606 slice[15] = self.w_axis.w;
607 }
608
609 #[inline]
620 #[must_use]
621 #[track_caller]
622 pub const fn from_rows_slice(slice: &[f32]) -> Self {
623 Self::new(
624 slice[0], slice[4], slice[8], slice[12], slice[1], slice[5], slice[9], slice[13],
625 slice[2], slice[6], slice[10], slice[14], slice[3], slice[7], slice[11], slice[15],
626 )
627 }
628
629 #[inline]
635 #[must_use]
636 #[track_caller]
637 pub fn col(&self, index: usize) -> Vec4 {
638 match index {
639 0 => self.x_axis,
640 1 => self.y_axis,
641 2 => self.z_axis,
642 3 => self.w_axis,
643 _ => panic!("index out of bounds"),
644 }
645 }
646
647 #[inline]
653 #[track_caller]
654 pub fn col_mut(&mut self, index: usize) -> &mut Vec4 {
655 match index {
656 0 => &mut self.x_axis,
657 1 => &mut self.y_axis,
658 2 => &mut self.z_axis,
659 3 => &mut self.w_axis,
660 _ => panic!("index out of bounds"),
661 }
662 }
663
664 #[inline]
672 #[must_use]
673 #[track_caller]
674 pub fn row(&self, index: usize) -> Vec4 {
675 match index {
676 0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
677 1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
678 2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
679 3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
680 _ => panic!("index out of bounds"),
681 }
682 }
683
684 #[inline]
694 #[track_caller]
695 pub fn set_row(&mut self, index: usize, row: Vec4) {
696 match index {
697 0 => {
698 self.x_axis.x = row.x;
699 self.y_axis.x = row.y;
700 self.z_axis.x = row.z;
701 self.w_axis.x = row.w;
702 }
703 1 => {
704 self.x_axis.y = row.x;
705 self.y_axis.y = row.y;
706 self.z_axis.y = row.z;
707 self.w_axis.y = row.w;
708 }
709 2 => {
710 self.x_axis.z = row.x;
711 self.y_axis.z = row.y;
712 self.z_axis.z = row.z;
713 self.w_axis.z = row.w;
714 }
715 3 => {
716 self.x_axis.w = row.x;
717 self.y_axis.w = row.y;
718 self.z_axis.w = row.z;
719 self.w_axis.w = row.w;
720 }
721 _ => panic!("index out of bounds"),
722 }
723 }
724
725 #[inline]
728 #[must_use]
729 pub fn is_finite(&self) -> bool {
730 self.x_axis.is_finite()
731 && self.y_axis.is_finite()
732 && self.z_axis.is_finite()
733 && self.w_axis.is_finite()
734 }
735
736 #[inline]
738 #[must_use]
739 pub fn is_nan(&self) -> bool {
740 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
741 }
742
743 #[inline]
745 #[must_use]
746 pub fn transpose(&self) -> Self {
747 unsafe {
748 let tmp0 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b01_00_01_00);
750 let tmp1 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b11_10_11_10);
751 let tmp2 = _mm_shuffle_ps(self.z_axis.0, self.w_axis.0, 0b01_00_01_00);
752 let tmp3 = _mm_shuffle_ps(self.z_axis.0, self.w_axis.0, 0b11_10_11_10);
753
754 Self {
755 x_axis: Vec4(_mm_shuffle_ps(tmp0, tmp2, 0b10_00_10_00)),
756 y_axis: Vec4(_mm_shuffle_ps(tmp0, tmp2, 0b11_01_11_01)),
757 z_axis: Vec4(_mm_shuffle_ps(tmp1, tmp3, 0b10_00_10_00)),
758 w_axis: Vec4(_mm_shuffle_ps(tmp1, tmp3, 0b11_01_11_01)),
759 }
760 }
761 }
762
763 #[inline]
765 #[must_use]
766 pub fn diagonal(&self) -> Vec4 {
767 Vec4::new(self.x_axis.x, self.y_axis.y, self.z_axis.z, self.w_axis.w)
768 }
769
770 #[must_use]
772 pub fn determinant(&self) -> f32 {
773 unsafe {
774 let swp2a = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_01_01_10);
776 let swp3a = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b11_10_11_11);
777 let swp2b = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b11_10_11_11);
778 let swp3b = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b00_01_01_10);
779 let swp2c = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_00_01_10);
780 let swp3c = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b01_10_00_00);
781
782 let mula = _mm_mul_ps(swp2a, swp3a);
783 let mulb = _mm_mul_ps(swp2b, swp3b);
784 let mulc = _mm_mul_ps(swp2c, swp3c);
785 let sube = _mm_sub_ps(mula, mulb);
786 let subf = _mm_sub_ps(_mm_movehl_ps(mulc, mulc), mulc);
787
788 let subfaca = _mm_shuffle_ps(sube, sube, 0b10_01_00_00);
789 let swpfaca = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b00_00_00_01);
790 let mulfaca = _mm_mul_ps(swpfaca, subfaca);
791
792 let subtmpb = _mm_shuffle_ps(sube, subf, 0b00_00_11_01);
793 let subfacb = _mm_shuffle_ps(subtmpb, subtmpb, 0b11_01_01_00);
794 let swpfacb = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b01_01_10_10);
795 let mulfacb = _mm_mul_ps(swpfacb, subfacb);
796
797 let subres = _mm_sub_ps(mulfaca, mulfacb);
798 let subtmpc = _mm_shuffle_ps(sube, subf, 0b01_00_10_10);
799 let subfacc = _mm_shuffle_ps(subtmpc, subtmpc, 0b11_11_10_00);
800 let swpfacc = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b10_11_11_11);
801 let mulfacc = _mm_mul_ps(swpfacc, subfacc);
802
803 let addres = _mm_add_ps(subres, mulfacc);
804 let detcof = _mm_mul_ps(addres, _mm_setr_ps(1.0, -1.0, 1.0, -1.0));
805
806 dot4(self.x_axis.0, detcof)
807 }
808 }
809
810 #[inline(always)]
822 #[must_use]
823 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
824 fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
825 unsafe {
826 let fac0 = {
828 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
829 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
830
831 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
832 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
833 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
834 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
835
836 let mul00 = _mm_mul_ps(swp00, swp01);
837 let mul01 = _mm_mul_ps(swp02, swp03);
838 _mm_sub_ps(mul00, mul01)
839 };
840 let fac1 = {
841 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
842 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
843
844 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
845 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
846 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
847 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
848
849 let mul00 = _mm_mul_ps(swp00, swp01);
850 let mul01 = _mm_mul_ps(swp02, swp03);
851 _mm_sub_ps(mul00, mul01)
852 };
853 let fac2 = {
854 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
855 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
856
857 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
858 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
859 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
860 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
861
862 let mul00 = _mm_mul_ps(swp00, swp01);
863 let mul01 = _mm_mul_ps(swp02, swp03);
864 _mm_sub_ps(mul00, mul01)
865 };
866 let fac3 = {
867 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
868 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
869
870 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
871 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
872 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
873 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
874
875 let mul00 = _mm_mul_ps(swp00, swp01);
876 let mul01 = _mm_mul_ps(swp02, swp03);
877 _mm_sub_ps(mul00, mul01)
878 };
879 let fac4 = {
880 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
881 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
882
883 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
884 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
885 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
886 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
887
888 let mul00 = _mm_mul_ps(swp00, swp01);
889 let mul01 = _mm_mul_ps(swp02, swp03);
890 _mm_sub_ps(mul00, mul01)
891 };
892 let fac5 = {
893 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
894 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
895
896 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
897 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
898 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
899 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
900
901 let mul00 = _mm_mul_ps(swp00, swp01);
902 let mul01 = _mm_mul_ps(swp02, swp03);
903 _mm_sub_ps(mul00, mul01)
904 };
905 let sign_a = _mm_set_ps(1.0, -1.0, 1.0, -1.0);
906 let sign_b = _mm_set_ps(-1.0, 1.0, -1.0, 1.0);
907
908 let temp0 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b00_00_00_00);
909 let vec0 = _mm_shuffle_ps(temp0, temp0, 0b10_10_10_00);
910
911 let temp1 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b01_01_01_01);
912 let vec1 = _mm_shuffle_ps(temp1, temp1, 0b10_10_10_00);
913
914 let temp2 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b10_10_10_10);
915 let vec2 = _mm_shuffle_ps(temp2, temp2, 0b10_10_10_00);
916
917 let temp3 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b11_11_11_11);
918 let vec3 = _mm_shuffle_ps(temp3, temp3, 0b10_10_10_00);
919
920 let mul00 = _mm_mul_ps(vec1, fac0);
921 let mul01 = _mm_mul_ps(vec2, fac1);
922 let mul02 = _mm_mul_ps(vec3, fac2);
923 let sub00 = _mm_sub_ps(mul00, mul01);
924 let add00 = _mm_add_ps(sub00, mul02);
925 let inv0 = _mm_mul_ps(sign_b, add00);
926
927 let mul03 = _mm_mul_ps(vec0, fac0);
928 let mul04 = _mm_mul_ps(vec2, fac3);
929 let mul05 = _mm_mul_ps(vec3, fac4);
930 let sub01 = _mm_sub_ps(mul03, mul04);
931 let add01 = _mm_add_ps(sub01, mul05);
932 let inv1 = _mm_mul_ps(sign_a, add01);
933
934 let mul06 = _mm_mul_ps(vec0, fac1);
935 let mul07 = _mm_mul_ps(vec1, fac3);
936 let mul08 = _mm_mul_ps(vec3, fac5);
937 let sub02 = _mm_sub_ps(mul06, mul07);
938 let add02 = _mm_add_ps(sub02, mul08);
939 let inv2 = _mm_mul_ps(sign_b, add02);
940
941 let mul09 = _mm_mul_ps(vec0, fac2);
942 let mul10 = _mm_mul_ps(vec1, fac4);
943 let mul11 = _mm_mul_ps(vec2, fac5);
944 let sub03 = _mm_sub_ps(mul09, mul10);
945 let add03 = _mm_add_ps(sub03, mul11);
946 let inv3 = _mm_mul_ps(sign_a, add03);
947
948 let row0 = _mm_shuffle_ps(inv0, inv1, 0b00_00_00_00);
949 let row1 = _mm_shuffle_ps(inv2, inv3, 0b00_00_00_00);
950 let row2 = _mm_shuffle_ps(row0, row1, 0b10_00_10_00);
951
952 let dot0 = dot4(self.x_axis.0, row2);
953
954 let rcp0 = _mm_set1_ps(dot0.recip());
955 let m = Self {
956 x_axis: Vec4(_mm_mul_ps(inv0, rcp0)),
957 y_axis: Vec4(_mm_mul_ps(inv1, rcp0)),
958 z_axis: Vec4(_mm_mul_ps(inv2, rcp0)),
959 w_axis: Vec4(_mm_mul_ps(inv3, rcp0)),
960 };
961 if CHECKED {
962 if !m.is_finite() {
963 return (Self::ZERO, false);
964 }
965 } else {
966 glam_assert!(m.is_finite());
967 }
968 (m, true)
969 }
970 }
971
972 #[must_use]
984 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
985 pub fn inverse(&self) -> Self {
986 self.inverse_checked::<false>().0
987 }
988
989 #[must_use]
992 pub fn try_inverse(&self) -> Option<Self> {
993 let (m, is_valid) = self.inverse_checked::<true>();
994 if is_valid {
995 Some(m)
996 } else {
997 None
998 }
999 }
1000
1001 #[must_use]
1004 pub fn inverse_or_zero(&self) -> Self {
1005 self.inverse_checked::<true>().0
1006 }
1007
1008 #[deprecated(
1018 since = "0.33.1",
1019 note = "use the `glam::camera::lh::view::look_to_mat4` function instead"
1020 )]
1021 #[inline]
1022 #[must_use]
1023 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1024 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
1025 #[allow(deprecated)]
1026 Self::look_to_rh(eye, -dir, up)
1027 }
1028
1029 #[deprecated(
1039 since = "0.33.1",
1040 note = "use the `glam::camera::rh::view::look_to_mat4` function instead"
1041 )]
1042 #[inline]
1043 #[must_use]
1044 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1045 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
1046 glam_assert!(dir.is_normalized());
1047 glam_assert!(up.is_normalized());
1048 let f = dir;
1049 let s = f.cross(up).normalize();
1050 let u = s.cross(f);
1051
1052 Self::from_cols(
1053 Vec4::new(s.x, u.x, -f.x, 0.0),
1054 Vec4::new(s.y, u.y, -f.y, 0.0),
1055 Vec4::new(s.z, u.z, -f.z, 0.0),
1056 Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
1057 )
1058 }
1059
1060 #[deprecated(
1070 since = "0.33.1",
1071 note = "use the `glam::camera::lh::view::look_at_mat4` function instead"
1072 )]
1073 #[inline]
1074 #[must_use]
1075 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1076 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
1077 #[allow(deprecated)]
1078 Self::look_to_lh(eye, center.sub(eye).normalize(), up)
1079 }
1080
1081 #[deprecated(
1091 since = "0.33.1",
1092 note = "use the `glam::camera::rh::view::look_at_mat4` function instead"
1093 )]
1094 #[inline]
1095 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1096 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
1097 #[allow(deprecated)]
1098 Self::look_to_rh(eye, center.sub(eye).normalize(), up)
1099 }
1100
1101 #[deprecated(
1107 since = "0.33.1",
1108 note = "use the `glam::camera::rh::proj::opengl::frustum` function instead"
1109 )]
1110 #[inline]
1111 #[must_use]
1112 pub fn frustum_rh_gl(
1113 left: f32,
1114 right: f32,
1115 bottom: f32,
1116 top: f32,
1117 z_near: f32,
1118 z_far: f32,
1119 ) -> Self {
1120 let inv_width = 1.0 / (right - left);
1121 let inv_height = 1.0 / (top - bottom);
1122 let inv_depth = 1.0 / (z_far - z_near);
1123 let a = (right + left) * inv_width;
1124 let b = (top + bottom) * inv_height;
1125 let c = -(z_far + z_near) * inv_depth;
1126 let d = -(2.0 * z_far * z_near) * inv_depth;
1127 let two_z_near = 2.0 * z_near;
1128 Self::from_cols(
1129 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
1130 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
1131 Vec4::new(a, b, c, -1.0),
1132 Vec4::new(0.0, 0.0, d, 0.0),
1133 )
1134 }
1135
1136 #[deprecated(
1143 since = "0.33.1",
1144 note = "use the `glam::camera::lh::proj::directx::frustum` function instead"
1145 )]
1146 #[inline]
1147 #[must_use]
1148 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1149 pub fn frustum_lh(
1150 left: f32,
1151 right: f32,
1152 bottom: f32,
1153 top: f32,
1154 z_near: f32,
1155 z_far: f32,
1156 ) -> Self {
1157 glam_assert!(left != right && bottom != top);
1158 glam_assert!(z_near > 0.0 && z_far > 0.0 && z_near != z_far);
1159 let inv_width = 1.0 / (right - left);
1160 let inv_height = 1.0 / (top - bottom);
1161 let inv_depth = 1.0 / (z_far - z_near);
1162 let a = (right + left) * inv_width;
1163 let b = (top + bottom) * inv_height;
1164 let c = z_far * inv_depth;
1165 let d = -(z_far * z_near) * inv_depth;
1166 let two_z_near = 2.0 * z_near;
1167 Self::from_cols(
1168 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
1169 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
1170 Vec4::new(a, b, c, 1.0),
1171 Vec4::new(0.0, 0.0, d, 0.0),
1172 )
1173 }
1174
1175 #[deprecated(
1182 since = "0.33.1",
1183 note = "use the `glam::camera::rh::proj::directx::frustum` function instead"
1184 )]
1185 #[inline]
1186 #[must_use]
1187 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1188 pub fn frustum_rh(
1189 left: f32,
1190 right: f32,
1191 bottom: f32,
1192 top: f32,
1193 z_near: f32,
1194 z_far: f32,
1195 ) -> Self {
1196 glam_assert!(left != right && bottom != top);
1197 glam_assert!(z_near > 0.0 && z_far > 0.0 && z_near != z_far);
1198 let inv_width = 1.0 / (right - left);
1199 let inv_height = 1.0 / (top - bottom);
1200 let inv_depth = 1.0 / (z_far - z_near);
1201 let a = (right + left) * inv_width;
1202 let b = (top + bottom) * inv_height;
1203 let c = -z_far * inv_depth;
1204 let d = -(z_far * z_near) * inv_depth;
1205 let two_z_near = 2.0 * z_near;
1206 Self::from_cols(
1207 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
1208 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
1209 Vec4::new(a, b, c, -1.0),
1210 Vec4::new(0.0, 0.0, d, 0.0),
1211 )
1212 }
1213
1214 #[deprecated(
1221 since = "0.33.1",
1222 note = "use the `glam::camera::rh::proj::opengl::perspective` function instead"
1223 )]
1224 #[inline]
1225 #[must_use]
1226 pub fn perspective_rh_gl(
1227 fov_y_radians: f32,
1228 aspect_ratio: f32,
1229 z_near: f32,
1230 z_far: f32,
1231 ) -> Self {
1232 let inv_length = 1.0 / (z_near - z_far);
1233 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1234 let a = f / aspect_ratio;
1235 let b = (z_near + z_far) * inv_length;
1236 let c = (2.0 * z_near * z_far) * inv_length;
1237 Self::from_cols(
1238 Vec4::new(a, 0.0, 0.0, 0.0),
1239 Vec4::new(0.0, f, 0.0, 0.0),
1240 Vec4::new(0.0, 0.0, b, -1.0),
1241 Vec4::new(0.0, 0.0, c, 0.0),
1242 )
1243 }
1244
1245 #[deprecated(
1255 since = "0.33.1",
1256 note = "use the `glam::camera::lh::proj::directx::perspective` function instead"
1257 )]
1258 #[inline]
1259 #[must_use]
1260 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1261 pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
1262 glam_assert!(fov_y_radians > 0.0 && fov_y_radians < core::f32::consts::PI);
1263 glam_assert!(aspect_ratio != 0.0);
1264 glam_assert!(z_near > 0.0 && z_far > 0.0 && z_near != z_far);
1265 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1266 let h = cos_fov / sin_fov;
1267 let w = h / aspect_ratio;
1268 let r = z_far / (z_far - z_near);
1269 Self::from_cols(
1270 Vec4::new(w, 0.0, 0.0, 0.0),
1271 Vec4::new(0.0, h, 0.0, 0.0),
1272 Vec4::new(0.0, 0.0, r, 1.0),
1273 Vec4::new(0.0, 0.0, -r * z_near, 0.0),
1274 )
1275 }
1276
1277 #[deprecated(
1287 since = "0.33.1",
1288 note = "use the `glam::camera::rh::proj::directx::perspective` function instead"
1289 )]
1290 #[inline]
1291 #[must_use]
1292 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1293 pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
1294 glam_assert!(fov_y_radians > 0.0 && fov_y_radians < core::f32::consts::PI);
1295 glam_assert!(aspect_ratio != 0.0);
1296 glam_assert!(z_near > 0.0 && z_far > 0.0 && z_near != z_far);
1297 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1298 let h = cos_fov / sin_fov;
1299 let w = h / aspect_ratio;
1300 let r = z_far / (z_near - z_far);
1301 Self::from_cols(
1302 Vec4::new(w, 0.0, 0.0, 0.0),
1303 Vec4::new(0.0, h, 0.0, 0.0),
1304 Vec4::new(0.0, 0.0, r, -1.0),
1305 Vec4::new(0.0, 0.0, r * z_near, 0.0),
1306 )
1307 }
1308
1309 #[deprecated(
1319 since = "0.33.1",
1320 note = "use the `glam::camera::lh::proj::directx::perspective_infinite` function instead"
1321 )]
1322 #[inline]
1323 #[must_use]
1324 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1325 pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1326 glam_assert!(fov_y_radians > 0.0 && fov_y_radians < core::f32::consts::PI);
1327 glam_assert!(aspect_ratio != 0.0);
1328 glam_assert!(z_near > 0.0);
1329 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1330 let h = cos_fov / sin_fov;
1331 let w = h / aspect_ratio;
1332 Self::from_cols(
1333 Vec4::new(w, 0.0, 0.0, 0.0),
1334 Vec4::new(0.0, h, 0.0, 0.0),
1335 Vec4::new(0.0, 0.0, 1.0, 1.0),
1336 Vec4::new(0.0, 0.0, -z_near, 0.0),
1337 )
1338 }
1339
1340 #[deprecated(
1349 since = "0.33.1",
1350 note = "use the `glam::camera::lh::proj::directx::perspective_infinite_reverse` function instead"
1351 )]
1352 #[inline]
1353 #[must_use]
1354 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1355 pub fn perspective_infinite_reverse_lh(
1356 fov_y_radians: f32,
1357 aspect_ratio: f32,
1358 z_near: f32,
1359 ) -> Self {
1360 glam_assert!(fov_y_radians > 0.0 && fov_y_radians < core::f32::consts::PI);
1361 glam_assert!(aspect_ratio != 0.0);
1362 glam_assert!(z_near > 0.0);
1363 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1364 let h = cos_fov / sin_fov;
1365 let w = h / aspect_ratio;
1366 Self::from_cols(
1367 Vec4::new(w, 0.0, 0.0, 0.0),
1368 Vec4::new(0.0, h, 0.0, 0.0),
1369 Vec4::new(0.0, 0.0, 0.0, 1.0),
1370 Vec4::new(0.0, 0.0, z_near, 0.0),
1371 )
1372 }
1373
1374 #[deprecated(
1384 since = "0.33.1",
1385 note = "use the `glam::camera::rh::proj::directx::perspective_infinite` function instead"
1386 )]
1387 #[inline]
1388 #[must_use]
1389 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1390 pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1391 glam_assert!(fov_y_radians > 0.0 && fov_y_radians < core::f32::consts::PI);
1392 glam_assert!(aspect_ratio != 0.0);
1393 glam_assert!(z_near > 0.0);
1394 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1395 Self::from_cols(
1396 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1397 Vec4::new(0.0, f, 0.0, 0.0),
1398 Vec4::new(0.0, 0.0, -1.0, -1.0),
1399 Vec4::new(0.0, 0.0, -z_near, 0.0),
1400 )
1401 }
1402
1403 #[deprecated(
1412 since = "0.33.1",
1413 note = "use the `glam::camera::rh::proj::directx::perspective_infinite_reverse` function instead"
1414 )]
1415 #[inline]
1416 #[must_use]
1417 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1418 pub fn perspective_infinite_reverse_rh(
1419 fov_y_radians: f32,
1420 aspect_ratio: f32,
1421 z_near: f32,
1422 ) -> Self {
1423 glam_assert!(fov_y_radians > 0.0 && fov_y_radians < core::f32::consts::PI);
1424 glam_assert!(aspect_ratio != 0.0);
1425 glam_assert!(z_near > 0.0);
1426 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1427 Self::from_cols(
1428 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1429 Vec4::new(0.0, f, 0.0, 0.0),
1430 Vec4::new(0.0, 0.0, 0.0, -1.0),
1431 Vec4::new(0.0, 0.0, z_near, 0.0),
1432 )
1433 }
1434
1435 #[deprecated(
1442 since = "0.33.1",
1443 note = "use the `glam::camera::rh::proj::opengl::orthographic` function instead"
1444 )]
1445 #[inline]
1446 #[must_use]
1447 pub fn orthographic_rh_gl(
1448 left: f32,
1449 right: f32,
1450 bottom: f32,
1451 top: f32,
1452 near: f32,
1453 far: f32,
1454 ) -> Self {
1455 let a = 2.0 / (right - left);
1456 let b = 2.0 / (top - bottom);
1457 let c = 2.0 / (near - far);
1458 let tx = -(right + left) / (right - left);
1459 let ty = -(top + bottom) / (top - bottom);
1460 let tz = -(far + near) / (far - near);
1461
1462 Self::from_cols(
1463 Vec4::new(a, 0.0, 0.0, 0.0),
1464 Vec4::new(0.0, b, 0.0, 0.0),
1465 Vec4::new(0.0, 0.0, c, 0.0),
1466 Vec4::new(tx, ty, tz, 1.0),
1467 )
1468 }
1469
1470 #[deprecated(
1474 since = "0.33.1",
1475 note = "use the `glam::camera::lh::proj::directx::orthographic` function instead"
1476 )]
1477 #[inline]
1478 #[must_use]
1479 pub fn orthographic_lh(
1480 left: f32,
1481 right: f32,
1482 bottom: f32,
1483 top: f32,
1484 near: f32,
1485 far: f32,
1486 ) -> Self {
1487 let rcp_width = 1.0 / (right - left);
1488 let rcp_height = 1.0 / (top - bottom);
1489 let r = 1.0 / (far - near);
1490 Self::from_cols(
1491 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1492 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1493 Vec4::new(0.0, 0.0, r, 0.0),
1494 Vec4::new(
1495 -(left + right) * rcp_width,
1496 -(top + bottom) * rcp_height,
1497 -r * near,
1498 1.0,
1499 ),
1500 )
1501 }
1502
1503 #[deprecated(
1507 since = "0.33.1",
1508 note = "use the `glam::camera::rh::proj::directx::orthographic` function instead"
1509 )]
1510 #[inline]
1511 #[must_use]
1512 pub fn orthographic_rh(
1513 left: f32,
1514 right: f32,
1515 bottom: f32,
1516 top: f32,
1517 near: f32,
1518 far: f32,
1519 ) -> Self {
1520 let rcp_width = 1.0 / (right - left);
1521 let rcp_height = 1.0 / (top - bottom);
1522 let r = 1.0 / (near - far);
1523 Self::from_cols(
1524 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1525 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1526 Vec4::new(0.0, 0.0, r, 0.0),
1527 Vec4::new(
1528 -(left + right) * rcp_width,
1529 -(top + bottom) * rcp_height,
1530 r * near,
1531 1.0,
1532 ),
1533 )
1534 }
1535
1536 #[inline]
1543 #[must_use]
1544 pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
1545 let mut res = self.x_axis.mul(rhs.x);
1546 res = self.y_axis.mul(rhs.y).add(res);
1547 res = self.z_axis.mul(rhs.z).add(res);
1548 res = self.w_axis.add(res);
1549 res = res.div(res.w);
1550 res.xyz()
1551 }
1552
1553 #[inline]
1566 #[must_use]
1567 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1568 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1569 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1570 let mut res = self.x_axis.mul(rhs.x);
1571 res = self.y_axis.mul(rhs.y).add(res);
1572 res = self.z_axis.mul(rhs.z).add(res);
1573 res = self.w_axis.add(res);
1574 res.xyz()
1575 }
1576
1577 #[inline]
1588 #[must_use]
1589 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1590 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1591 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1592 let mut res = self.x_axis.mul(rhs.x);
1593 res = self.y_axis.mul(rhs.y).add(res);
1594 res = self.z_axis.mul(rhs.z).add(res);
1595 res.xyz()
1596 }
1597
1598 #[inline]
1605 #[must_use]
1606 pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
1607 let mut res = self.x_axis.mul(rhs.xxxx());
1608 res = self.y_axis.mul(rhs.yyyy()).add(res);
1609 res = self.z_axis.mul(rhs.zzzz()).add(res);
1610 res = self.w_axis.add(res);
1611 res = res.div(res.wwww());
1612 Vec3A::from_vec4(res)
1613 }
1614
1615 #[inline]
1627 #[must_use]
1628 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1629 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1630 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1631 let mut res = self.x_axis.mul(rhs.xxxx());
1632 res = self.y_axis.mul(rhs.yyyy()).add(res);
1633 res = self.z_axis.mul(rhs.zzzz()).add(res);
1634 res = self.w_axis.add(res);
1635 Vec3A::from_vec4(res)
1636 }
1637
1638 #[inline]
1648 #[must_use]
1649 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1650 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1651 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1652 let mut res = self.x_axis.mul(rhs.xxxx());
1653 res = self.y_axis.mul(rhs.yyyy()).add(res);
1654 res = self.z_axis.mul(rhs.zzzz()).add(res);
1655 Vec3A::from_vec4(res)
1656 }
1657
1658 #[inline]
1660 #[must_use]
1661 pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1662 let mut res = self.x_axis.mul(rhs.xxxx());
1663 res = res.add(self.y_axis.mul(rhs.yyyy()));
1664 res = res.add(self.z_axis.mul(rhs.zzzz()));
1665 res = res.add(self.w_axis.mul(rhs.wwww()));
1666 res
1667 }
1668
1669 #[inline]
1671 #[must_use]
1672 pub fn mul_transpose_vec4(&self, rhs: Vec4) -> Vec4 {
1673 Vec4::new(
1674 self.x_axis.dot(rhs),
1675 self.y_axis.dot(rhs),
1676 self.z_axis.dot(rhs),
1677 self.w_axis.dot(rhs),
1678 )
1679 }
1680
1681 #[inline]
1683 #[must_use]
1684 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1685 self.mul(rhs)
1686 }
1687
1688 #[inline]
1690 #[must_use]
1691 pub fn add_mat4(&self, rhs: &Self) -> Self {
1692 self.add(rhs)
1693 }
1694
1695 #[inline]
1697 #[must_use]
1698 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1699 self.sub(rhs)
1700 }
1701
1702 #[inline]
1704 #[must_use]
1705 pub fn mul_scalar(&self, rhs: f32) -> Self {
1706 Self::from_cols(
1707 self.x_axis.mul(rhs),
1708 self.y_axis.mul(rhs),
1709 self.z_axis.mul(rhs),
1710 self.w_axis.mul(rhs),
1711 )
1712 }
1713
1714 #[inline]
1718 #[must_use]
1719 pub fn mul_diagonal_scale(&self, scale: Vec4) -> Self {
1720 Self::from_cols(
1721 self.x_axis * scale.x,
1722 self.y_axis * scale.y,
1723 self.z_axis * scale.z,
1724 self.w_axis * scale.w,
1725 )
1726 }
1727
1728 #[inline]
1730 #[must_use]
1731 pub fn div_scalar(&self, rhs: f32) -> Self {
1732 let rhs = Vec4::splat(rhs);
1733 Self::from_cols(
1734 self.x_axis.div(rhs),
1735 self.y_axis.div(rhs),
1736 self.z_axis.div(rhs),
1737 self.w_axis.div(rhs),
1738 )
1739 }
1740
1741 #[inline]
1743 #[must_use]
1744 pub fn recip(&self) -> Self {
1745 Self::from_cols(
1746 self.x_axis.recip(),
1747 self.y_axis.recip(),
1748 self.z_axis.recip(),
1749 self.w_axis.recip(),
1750 )
1751 }
1752
1753 #[inline]
1763 #[must_use]
1764 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1765 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1766 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1767 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1768 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1769 }
1770
1771 #[inline]
1773 #[must_use]
1774 pub fn abs(&self) -> Self {
1775 Self::from_cols(
1776 self.x_axis.abs(),
1777 self.y_axis.abs(),
1778 self.z_axis.abs(),
1779 self.w_axis.abs(),
1780 )
1781 }
1782
1783 #[cfg(feature = "f64")]
1784 #[inline]
1785 #[must_use]
1786 pub fn as_dmat4(&self) -> DMat4 {
1787 DMat4::from_cols(
1788 self.x_axis.as_dvec4(),
1789 self.y_axis.as_dvec4(),
1790 self.z_axis.as_dvec4(),
1791 self.w_axis.as_dvec4(),
1792 )
1793 }
1794}
1795
1796impl Default for Mat4 {
1797 #[inline]
1798 fn default() -> Self {
1799 Self::IDENTITY
1800 }
1801}
1802
1803impl Add for Mat4 {
1804 type Output = Self;
1805 #[inline]
1806 fn add(self, rhs: Self) -> Self {
1807 Self::from_cols(
1808 self.x_axis.add(rhs.x_axis),
1809 self.y_axis.add(rhs.y_axis),
1810 self.z_axis.add(rhs.z_axis),
1811 self.w_axis.add(rhs.w_axis),
1812 )
1813 }
1814}
1815
1816impl Add<&Self> for Mat4 {
1817 type Output = Self;
1818 #[inline]
1819 fn add(self, rhs: &Self) -> Self {
1820 self.add(*rhs)
1821 }
1822}
1823
1824impl Add<&Mat4> for &Mat4 {
1825 type Output = Mat4;
1826 #[inline]
1827 fn add(self, rhs: &Mat4) -> Mat4 {
1828 (*self).add(*rhs)
1829 }
1830}
1831
1832impl Add<Mat4> for &Mat4 {
1833 type Output = Mat4;
1834 #[inline]
1835 fn add(self, rhs: Mat4) -> Mat4 {
1836 (*self).add(rhs)
1837 }
1838}
1839
1840impl AddAssign for Mat4 {
1841 #[inline]
1842 fn add_assign(&mut self, rhs: Self) {
1843 *self = self.add(rhs);
1844 }
1845}
1846
1847impl AddAssign<&Self> for Mat4 {
1848 #[inline]
1849 fn add_assign(&mut self, rhs: &Self) {
1850 self.add_assign(*rhs);
1851 }
1852}
1853
1854impl Sub for Mat4 {
1855 type Output = Self;
1856 #[inline]
1857 fn sub(self, rhs: Self) -> Self {
1858 Self::from_cols(
1859 self.x_axis.sub(rhs.x_axis),
1860 self.y_axis.sub(rhs.y_axis),
1861 self.z_axis.sub(rhs.z_axis),
1862 self.w_axis.sub(rhs.w_axis),
1863 )
1864 }
1865}
1866
1867impl Sub<&Self> for Mat4 {
1868 type Output = Self;
1869 #[inline]
1870 fn sub(self, rhs: &Self) -> Self {
1871 self.sub(*rhs)
1872 }
1873}
1874
1875impl Sub<&Mat4> for &Mat4 {
1876 type Output = Mat4;
1877 #[inline]
1878 fn sub(self, rhs: &Mat4) -> Mat4 {
1879 (*self).sub(*rhs)
1880 }
1881}
1882
1883impl Sub<Mat4> for &Mat4 {
1884 type Output = Mat4;
1885 #[inline]
1886 fn sub(self, rhs: Mat4) -> Mat4 {
1887 (*self).sub(rhs)
1888 }
1889}
1890
1891impl SubAssign for Mat4 {
1892 #[inline]
1893 fn sub_assign(&mut self, rhs: Self) {
1894 *self = self.sub(rhs);
1895 }
1896}
1897
1898impl SubAssign<&Self> for Mat4 {
1899 #[inline]
1900 fn sub_assign(&mut self, rhs: &Self) {
1901 self.sub_assign(*rhs);
1902 }
1903}
1904
1905impl Neg for Mat4 {
1906 type Output = Self;
1907 #[inline]
1908 fn neg(self) -> Self::Output {
1909 Self::from_cols(
1910 self.x_axis.neg(),
1911 self.y_axis.neg(),
1912 self.z_axis.neg(),
1913 self.w_axis.neg(),
1914 )
1915 }
1916}
1917
1918impl Neg for &Mat4 {
1919 type Output = Mat4;
1920 #[inline]
1921 fn neg(self) -> Mat4 {
1922 (*self).neg()
1923 }
1924}
1925
1926impl Mul for Mat4 {
1927 type Output = Self;
1928 #[inline]
1929 fn mul(self, rhs: Self) -> Self {
1930 Self::from_cols(
1931 self.mul(rhs.x_axis),
1932 self.mul(rhs.y_axis),
1933 self.mul(rhs.z_axis),
1934 self.mul(rhs.w_axis),
1935 )
1936 }
1937}
1938
1939impl Mul<&Self> for Mat4 {
1940 type Output = Self;
1941 #[inline]
1942 fn mul(self, rhs: &Self) -> Self {
1943 self.mul(*rhs)
1944 }
1945}
1946
1947impl Mul<&Mat4> for &Mat4 {
1948 type Output = Mat4;
1949 #[inline]
1950 fn mul(self, rhs: &Mat4) -> Mat4 {
1951 (*self).mul(*rhs)
1952 }
1953}
1954
1955impl Mul<Mat4> for &Mat4 {
1956 type Output = Mat4;
1957 #[inline]
1958 fn mul(self, rhs: Mat4) -> Mat4 {
1959 (*self).mul(rhs)
1960 }
1961}
1962
1963impl MulAssign for Mat4 {
1964 #[inline]
1965 fn mul_assign(&mut self, rhs: Self) {
1966 *self = self.mul(rhs);
1967 }
1968}
1969
1970impl MulAssign<&Self> for Mat4 {
1971 #[inline]
1972 fn mul_assign(&mut self, rhs: &Self) {
1973 self.mul_assign(*rhs);
1974 }
1975}
1976
1977impl Mul<Vec4> for Mat4 {
1978 type Output = Vec4;
1979 #[inline]
1980 fn mul(self, rhs: Vec4) -> Self::Output {
1981 self.mul_vec4(rhs)
1982 }
1983}
1984
1985impl Mul<&Vec4> for Mat4 {
1986 type Output = Vec4;
1987 #[inline]
1988 fn mul(self, rhs: &Vec4) -> Vec4 {
1989 self.mul(*rhs)
1990 }
1991}
1992
1993impl Mul<&Vec4> for &Mat4 {
1994 type Output = Vec4;
1995 #[inline]
1996 fn mul(self, rhs: &Vec4) -> Vec4 {
1997 (*self).mul(*rhs)
1998 }
1999}
2000
2001impl Mul<Vec4> for &Mat4 {
2002 type Output = Vec4;
2003 #[inline]
2004 fn mul(self, rhs: Vec4) -> Vec4 {
2005 (*self).mul(rhs)
2006 }
2007}
2008
2009impl Mul<Mat4> for f32 {
2010 type Output = Mat4;
2011 #[inline]
2012 fn mul(self, rhs: Mat4) -> Self::Output {
2013 rhs.mul_scalar(self)
2014 }
2015}
2016
2017impl Mul<&Mat4> for f32 {
2018 type Output = Mat4;
2019 #[inline]
2020 fn mul(self, rhs: &Mat4) -> Mat4 {
2021 self.mul(*rhs)
2022 }
2023}
2024
2025impl Mul<&Mat4> for &f32 {
2026 type Output = Mat4;
2027 #[inline]
2028 fn mul(self, rhs: &Mat4) -> Mat4 {
2029 (*self).mul(*rhs)
2030 }
2031}
2032
2033impl Mul<Mat4> for &f32 {
2034 type Output = Mat4;
2035 #[inline]
2036 fn mul(self, rhs: Mat4) -> Mat4 {
2037 (*self).mul(rhs)
2038 }
2039}
2040
2041impl Mul<f32> for Mat4 {
2042 type Output = Self;
2043 #[inline]
2044 fn mul(self, rhs: f32) -> Self {
2045 self.mul_scalar(rhs)
2046 }
2047}
2048
2049impl Mul<&f32> for Mat4 {
2050 type Output = Self;
2051 #[inline]
2052 fn mul(self, rhs: &f32) -> Self {
2053 self.mul(*rhs)
2054 }
2055}
2056
2057impl Mul<&f32> for &Mat4 {
2058 type Output = Mat4;
2059 #[inline]
2060 fn mul(self, rhs: &f32) -> Mat4 {
2061 (*self).mul(*rhs)
2062 }
2063}
2064
2065impl Mul<f32> for &Mat4 {
2066 type Output = Mat4;
2067 #[inline]
2068 fn mul(self, rhs: f32) -> Mat4 {
2069 (*self).mul(rhs)
2070 }
2071}
2072
2073impl MulAssign<f32> for Mat4 {
2074 #[inline]
2075 fn mul_assign(&mut self, rhs: f32) {
2076 *self = self.mul(rhs);
2077 }
2078}
2079
2080impl MulAssign<&f32> for Mat4 {
2081 #[inline]
2082 fn mul_assign(&mut self, rhs: &f32) {
2083 self.mul_assign(*rhs);
2084 }
2085}
2086
2087impl Div<Mat4> for f32 {
2088 type Output = Mat4;
2089 #[inline]
2090 fn div(self, rhs: Mat4) -> Self::Output {
2091 Mat4::from_cols(
2092 self.div(rhs.x_axis),
2093 self.div(rhs.y_axis),
2094 self.div(rhs.z_axis),
2095 self.div(rhs.w_axis),
2096 )
2097 }
2098}
2099
2100impl Div<&Mat4> for f32 {
2101 type Output = Mat4;
2102 #[inline]
2103 fn div(self, rhs: &Mat4) -> Mat4 {
2104 self.div(*rhs)
2105 }
2106}
2107
2108impl Div<&Mat4> for &f32 {
2109 type Output = Mat4;
2110 #[inline]
2111 fn div(self, rhs: &Mat4) -> Mat4 {
2112 (*self).div(*rhs)
2113 }
2114}
2115
2116impl Div<Mat4> for &f32 {
2117 type Output = Mat4;
2118 #[inline]
2119 fn div(self, rhs: Mat4) -> Mat4 {
2120 (*self).div(rhs)
2121 }
2122}
2123
2124impl Div<f32> for Mat4 {
2125 type Output = Self;
2126 #[inline]
2127 fn div(self, rhs: f32) -> Self {
2128 self.div_scalar(rhs)
2129 }
2130}
2131
2132impl Div<&f32> for Mat4 {
2133 type Output = Self;
2134 #[inline]
2135 fn div(self, rhs: &f32) -> Self {
2136 self.div(*rhs)
2137 }
2138}
2139
2140impl Div<&f32> for &Mat4 {
2141 type Output = Mat4;
2142 #[inline]
2143 fn div(self, rhs: &f32) -> Mat4 {
2144 (*self).div(*rhs)
2145 }
2146}
2147
2148impl Div<f32> for &Mat4 {
2149 type Output = Mat4;
2150 #[inline]
2151 fn div(self, rhs: f32) -> Mat4 {
2152 (*self).div(rhs)
2153 }
2154}
2155
2156impl DivAssign<f32> for Mat4 {
2157 #[inline]
2158 fn div_assign(&mut self, rhs: f32) {
2159 *self = self.div(rhs);
2160 }
2161}
2162
2163impl DivAssign<&f32> for Mat4 {
2164 #[inline]
2165 fn div_assign(&mut self, rhs: &f32) {
2166 self.div_assign(*rhs);
2167 }
2168}
2169
2170impl Sum<Self> for Mat4 {
2171 fn sum<I>(iter: I) -> Self
2172 where
2173 I: Iterator<Item = Self>,
2174 {
2175 iter.fold(Self::ZERO, Self::add)
2176 }
2177}
2178
2179impl<'a> Sum<&'a Self> for Mat4 {
2180 fn sum<I>(iter: I) -> Self
2181 where
2182 I: Iterator<Item = &'a Self>,
2183 {
2184 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
2185 }
2186}
2187
2188impl Product for Mat4 {
2189 fn product<I>(iter: I) -> Self
2190 where
2191 I: Iterator<Item = Self>,
2192 {
2193 iter.fold(Self::IDENTITY, Self::mul)
2194 }
2195}
2196
2197impl<'a> Product<&'a Self> for Mat4 {
2198 fn product<I>(iter: I) -> Self
2199 where
2200 I: Iterator<Item = &'a Self>,
2201 {
2202 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
2203 }
2204}
2205
2206impl PartialEq for Mat4 {
2207 #[inline]
2208 fn eq(&self, rhs: &Self) -> bool {
2209 self.x_axis.eq(&rhs.x_axis)
2210 && self.y_axis.eq(&rhs.y_axis)
2211 && self.z_axis.eq(&rhs.z_axis)
2212 && self.w_axis.eq(&rhs.w_axis)
2213 }
2214}
2215
2216impl AsRef<[f32; 16]> for Mat4 {
2217 #[inline]
2218 fn as_ref(&self) -> &[f32; 16] {
2219 unsafe { &*(self as *const Self as *const [f32; 16]) }
2220 }
2221}
2222
2223impl AsMut<[f32; 16]> for Mat4 {
2224 #[inline]
2225 fn as_mut(&mut self) -> &mut [f32; 16] {
2226 unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
2227 }
2228}
2229
2230impl fmt::Debug for Mat4 {
2231 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2232 fmt.debug_struct(stringify!(Mat4))
2233 .field("x_axis", &self.x_axis)
2234 .field("y_axis", &self.y_axis)
2235 .field("z_axis", &self.z_axis)
2236 .field("w_axis", &self.w_axis)
2237 .finish()
2238 }
2239}
2240
2241impl fmt::Display for Mat4 {
2242 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2243 if let Some(p) = f.precision() {
2244 write!(
2245 f,
2246 "[{:.*}, {:.*}, {:.*}, {:.*}]",
2247 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
2248 )
2249 } else {
2250 write!(
2251 f,
2252 "[{}, {}, {}, {}]",
2253 self.x_axis, self.y_axis, self.z_axis, self.w_axis
2254 )
2255 }
2256 }
2257}