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")]
23use zerocopy_derive::*;
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",
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 fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) {
236 glam_assert!(rotation.is_normalized());
237
238 let (x, y, z, w) = rotation.into();
239 let x2 = x + x;
240 let y2 = y + y;
241 let z2 = z + z;
242 let xx = x * x2;
243 let xy = x * y2;
244 let xz = x * z2;
245 let yy = y * y2;
246 let yz = y * z2;
247 let zz = z * z2;
248 let wx = w * x2;
249 let wy = w * y2;
250 let wz = w * z2;
251
252 let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
253 let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
254 let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
255 (x_axis, y_axis, z_axis)
256 }
257
258 #[inline]
268 #[must_use]
269 pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
270 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
271 Self::from_cols(
272 x_axis.mul(scale.x),
273 y_axis.mul(scale.y),
274 z_axis.mul(scale.z),
275 Vec4::from((translation, 1.0)),
276 )
277 }
278
279 #[inline]
288 #[must_use]
289 pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
290 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
291 Self::from_cols(x_axis, y_axis, z_axis, Vec4::from((translation, 1.0)))
292 }
293
294 #[inline]
302 #[must_use]
303 pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
304 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
305
306 let r = Mat3A::from_mat4(*self);
307
308 let det = r.determinant();
309
310 glam_assert!(det != 0.0);
311
312 let scale = Vec3::new(
313 r.x_axis.length() * math::signum(det),
314 r.y_axis.length(),
315 r.z_axis.length(),
316 );
317
318 glam_assert!(scale.cmpne(Vec3::ZERO).all());
319
320 let inv_scale = scale.recip();
321
322 let rotation = Quat::from_mat3a(&Mat3A::from_cols(
323 r.x_axis.mul(inv_scale.x),
324 r.y_axis.mul(inv_scale.y),
325 r.z_axis.mul(inv_scale.z),
326 ));
327
328 let translation = self.w_axis.xyz();
329
330 (scale, rotation, translation)
331 }
332
333 #[inline]
342 #[must_use]
343 pub fn from_quat(rotation: Quat) -> Self {
344 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
345 Self::from_cols(x_axis, y_axis, z_axis, Vec4::W)
346 }
347
348 #[inline]
354 #[must_use]
355 pub fn from_mat3(m: Mat3) -> Self {
356 Self::from_cols(
357 Vec4::from((m.x_axis, 0.0)),
358 Vec4::from((m.y_axis, 0.0)),
359 Vec4::from((m.z_axis, 0.0)),
360 Vec4::W,
361 )
362 }
363
364 #[inline]
369 #[must_use]
370 pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
371 Self::from_cols(
372 Vec4::from((mat3.x_axis, 0.0)),
373 Vec4::from((mat3.y_axis, 0.0)),
374 Vec4::from((mat3.z_axis, 0.0)),
375 Vec4::from((translation, 1.0)),
376 )
377 }
378
379 #[inline]
385 #[must_use]
386 pub fn from_mat3a(m: Mat3A) -> Self {
387 Self::from_cols(
388 Vec4::from((m.x_axis, 0.0)),
389 Vec4::from((m.y_axis, 0.0)),
390 Vec4::from((m.z_axis, 0.0)),
391 Vec4::W,
392 )
393 }
394
395 #[inline]
400 #[must_use]
401 pub fn from_translation(translation: Vec3) -> Self {
402 Self::from_cols(
403 Vec4::X,
404 Vec4::Y,
405 Vec4::Z,
406 Vec4::new(translation.x, translation.y, translation.z, 1.0),
407 )
408 }
409
410 #[inline]
420 #[must_use]
421 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
422 glam_assert!(axis.is_normalized());
423
424 let (sin, cos) = math::sin_cos(angle);
425 let axis_sin = axis.mul(sin);
426 let axis_sq = axis.mul(axis);
427 let omc = 1.0 - cos;
428 let xyomc = axis.x * axis.y * omc;
429 let xzomc = axis.x * axis.z * omc;
430 let yzomc = axis.y * axis.z * omc;
431 Self::from_cols(
432 Vec4::new(
433 axis_sq.x * omc + cos,
434 xyomc + axis_sin.z,
435 xzomc - axis_sin.y,
436 0.0,
437 ),
438 Vec4::new(
439 xyomc - axis_sin.z,
440 axis_sq.y * omc + cos,
441 yzomc + axis_sin.x,
442 0.0,
443 ),
444 Vec4::new(
445 xzomc + axis_sin.y,
446 yzomc - axis_sin.x,
447 axis_sq.z * omc + cos,
448 0.0,
449 ),
450 Vec4::W,
451 )
452 }
453
454 #[inline]
460 #[must_use]
461 pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
462 Self::from_euler_angles(order, a, b, c)
463 }
464
465 #[inline]
475 #[must_use]
476 pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
477 glam_assert!(
478 self.x_axis.xyz().is_normalized()
479 && self.y_axis.xyz().is_normalized()
480 && self.z_axis.xyz().is_normalized()
481 );
482 self.to_euler_angles(order)
483 }
484
485 #[inline]
491 #[must_use]
492 pub fn from_rotation_x(angle: f32) -> Self {
493 let (sina, cosa) = math::sin_cos(angle);
494 Self::from_cols(
495 Vec4::X,
496 Vec4::new(0.0, cosa, sina, 0.0),
497 Vec4::new(0.0, -sina, cosa, 0.0),
498 Vec4::W,
499 )
500 }
501
502 #[inline]
508 #[must_use]
509 pub fn from_rotation_y(angle: f32) -> Self {
510 let (sina, cosa) = math::sin_cos(angle);
511 Self::from_cols(
512 Vec4::new(cosa, 0.0, -sina, 0.0),
513 Vec4::Y,
514 Vec4::new(sina, 0.0, cosa, 0.0),
515 Vec4::W,
516 )
517 }
518
519 #[inline]
525 #[must_use]
526 pub fn from_rotation_z(angle: f32) -> Self {
527 let (sina, cosa) = math::sin_cos(angle);
528 Self::from_cols(
529 Vec4::new(cosa, sina, 0.0, 0.0),
530 Vec4::new(-sina, cosa, 0.0, 0.0),
531 Vec4::Z,
532 Vec4::W,
533 )
534 }
535
536 #[inline]
545 #[must_use]
546 pub fn from_scale(scale: Vec3) -> Self {
547 glam_assert!(scale.cmpne(Vec3::ZERO).any());
549
550 Self::from_cols(
551 Vec4::new(scale.x, 0.0, 0.0, 0.0),
552 Vec4::new(0.0, scale.y, 0.0, 0.0),
553 Vec4::new(0.0, 0.0, scale.z, 0.0),
554 Vec4::W,
555 )
556 }
557
558 #[inline]
566 #[must_use]
567 pub const fn from_cols_slice(slice: &[f32]) -> Self {
568 Self::new(
569 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
570 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
571 )
572 }
573
574 #[inline]
580 pub fn write_cols_to_slice(&self, slice: &mut [f32]) {
581 slice[0] = self.x_axis.x;
582 slice[1] = self.x_axis.y;
583 slice[2] = self.x_axis.z;
584 slice[3] = self.x_axis.w;
585 slice[4] = self.y_axis.x;
586 slice[5] = self.y_axis.y;
587 slice[6] = self.y_axis.z;
588 slice[7] = self.y_axis.w;
589 slice[8] = self.z_axis.x;
590 slice[9] = self.z_axis.y;
591 slice[10] = self.z_axis.z;
592 slice[11] = self.z_axis.w;
593 slice[12] = self.w_axis.x;
594 slice[13] = self.w_axis.y;
595 slice[14] = self.w_axis.z;
596 slice[15] = self.w_axis.w;
597 }
598
599 #[inline]
610 #[must_use]
611 pub const fn from_rows_slice(slice: &[f32]) -> Self {
612 Self::new(
613 slice[0], slice[4], slice[8], slice[12], slice[1], slice[5], slice[9], slice[13],
614 slice[2], slice[6], slice[10], slice[14], slice[3], slice[7], slice[11], slice[15],
615 )
616 }
617
618 #[inline]
624 #[must_use]
625 pub fn col(&self, index: usize) -> Vec4 {
626 match index {
627 0 => self.x_axis,
628 1 => self.y_axis,
629 2 => self.z_axis,
630 3 => self.w_axis,
631 _ => panic!("index out of bounds"),
632 }
633 }
634
635 #[inline]
641 pub fn col_mut(&mut self, index: usize) -> &mut Vec4 {
642 match index {
643 0 => &mut self.x_axis,
644 1 => &mut self.y_axis,
645 2 => &mut self.z_axis,
646 3 => &mut self.w_axis,
647 _ => panic!("index out of bounds"),
648 }
649 }
650
651 #[inline]
659 #[must_use]
660 pub fn row(&self, index: usize) -> Vec4 {
661 match index {
662 0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
663 1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
664 2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
665 3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
666 _ => panic!("index out of bounds"),
667 }
668 }
669
670 #[inline]
680 pub fn set_row(&mut self, index: usize, row: Vec4) {
681 match index {
682 0 => {
683 self.x_axis.x = row.x;
684 self.y_axis.x = row.y;
685 self.z_axis.x = row.z;
686 self.w_axis.x = row.w;
687 }
688 1 => {
689 self.x_axis.y = row.x;
690 self.y_axis.y = row.y;
691 self.z_axis.y = row.z;
692 self.w_axis.y = row.w;
693 }
694 2 => {
695 self.x_axis.z = row.x;
696 self.y_axis.z = row.y;
697 self.z_axis.z = row.z;
698 self.w_axis.z = row.w;
699 }
700 3 => {
701 self.x_axis.w = row.x;
702 self.y_axis.w = row.y;
703 self.z_axis.w = row.z;
704 self.w_axis.w = row.w;
705 }
706 _ => panic!("index out of bounds"),
707 }
708 }
709
710 #[inline]
713 #[must_use]
714 pub fn is_finite(&self) -> bool {
715 self.x_axis.is_finite()
716 && self.y_axis.is_finite()
717 && self.z_axis.is_finite()
718 && self.w_axis.is_finite()
719 }
720
721 #[inline]
723 #[must_use]
724 pub fn is_nan(&self) -> bool {
725 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
726 }
727
728 #[inline]
730 #[must_use]
731 pub fn transpose(&self) -> Self {
732 unsafe {
733 let tmp0 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b01_00_01_00);
735 let tmp1 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b11_10_11_10);
736 let tmp2 = _mm_shuffle_ps(self.z_axis.0, self.w_axis.0, 0b01_00_01_00);
737 let tmp3 = _mm_shuffle_ps(self.z_axis.0, self.w_axis.0, 0b11_10_11_10);
738
739 Self {
740 x_axis: Vec4(_mm_shuffle_ps(tmp0, tmp2, 0b10_00_10_00)),
741 y_axis: Vec4(_mm_shuffle_ps(tmp0, tmp2, 0b11_01_11_01)),
742 z_axis: Vec4(_mm_shuffle_ps(tmp1, tmp3, 0b10_00_10_00)),
743 w_axis: Vec4(_mm_shuffle_ps(tmp1, tmp3, 0b11_01_11_01)),
744 }
745 }
746 }
747
748 #[inline]
750 #[must_use]
751 pub fn diagonal(&self) -> Vec4 {
752 Vec4::new(self.x_axis.x, self.y_axis.y, self.z_axis.z, self.w_axis.w)
753 }
754
755 #[must_use]
757 pub fn determinant(&self) -> f32 {
758 unsafe {
759 let swp2a = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_01_01_10);
761 let swp3a = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b11_10_11_11);
762 let swp2b = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b11_10_11_11);
763 let swp3b = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b00_01_01_10);
764 let swp2c = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_00_01_10);
765 let swp3c = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b01_10_00_00);
766
767 let mula = _mm_mul_ps(swp2a, swp3a);
768 let mulb = _mm_mul_ps(swp2b, swp3b);
769 let mulc = _mm_mul_ps(swp2c, swp3c);
770 let sube = _mm_sub_ps(mula, mulb);
771 let subf = _mm_sub_ps(_mm_movehl_ps(mulc, mulc), mulc);
772
773 let subfaca = _mm_shuffle_ps(sube, sube, 0b10_01_00_00);
774 let swpfaca = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b00_00_00_01);
775 let mulfaca = _mm_mul_ps(swpfaca, subfaca);
776
777 let subtmpb = _mm_shuffle_ps(sube, subf, 0b00_00_11_01);
778 let subfacb = _mm_shuffle_ps(subtmpb, subtmpb, 0b11_01_01_00);
779 let swpfacb = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b01_01_10_10);
780 let mulfacb = _mm_mul_ps(swpfacb, subfacb);
781
782 let subres = _mm_sub_ps(mulfaca, mulfacb);
783 let subtmpc = _mm_shuffle_ps(sube, subf, 0b01_00_10_10);
784 let subfacc = _mm_shuffle_ps(subtmpc, subtmpc, 0b11_11_10_00);
785 let swpfacc = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b10_11_11_11);
786 let mulfacc = _mm_mul_ps(swpfacc, subfacc);
787
788 let addres = _mm_add_ps(subres, mulfacc);
789 let detcof = _mm_mul_ps(addres, _mm_setr_ps(1.0, -1.0, 1.0, -1.0));
790
791 dot4(self.x_axis.0, detcof)
792 }
793 }
794
795 #[inline(always)]
807 #[must_use]
808 fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
809 unsafe {
810 let fac0 = {
812 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
813 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
814
815 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
816 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
817 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
818 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
819
820 let mul00 = _mm_mul_ps(swp00, swp01);
821 let mul01 = _mm_mul_ps(swp02, swp03);
822 _mm_sub_ps(mul00, mul01)
823 };
824 let fac1 = {
825 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
826 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
827
828 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
829 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
830 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
831 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
832
833 let mul00 = _mm_mul_ps(swp00, swp01);
834 let mul01 = _mm_mul_ps(swp02, swp03);
835 _mm_sub_ps(mul00, mul01)
836 };
837 let fac2 = {
838 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
839 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
840
841 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
842 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
843 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
844 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
845
846 let mul00 = _mm_mul_ps(swp00, swp01);
847 let mul01 = _mm_mul_ps(swp02, swp03);
848 _mm_sub_ps(mul00, mul01)
849 };
850 let fac3 = {
851 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
852 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
853
854 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
855 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
856 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
857 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
858
859 let mul00 = _mm_mul_ps(swp00, swp01);
860 let mul01 = _mm_mul_ps(swp02, swp03);
861 _mm_sub_ps(mul00, mul01)
862 };
863 let fac4 = {
864 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
865 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
866
867 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
868 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
869 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
870 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
871
872 let mul00 = _mm_mul_ps(swp00, swp01);
873 let mul01 = _mm_mul_ps(swp02, swp03);
874 _mm_sub_ps(mul00, mul01)
875 };
876 let fac5 = {
877 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
878 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
879
880 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
881 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
882 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
883 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
884
885 let mul00 = _mm_mul_ps(swp00, swp01);
886 let mul01 = _mm_mul_ps(swp02, swp03);
887 _mm_sub_ps(mul00, mul01)
888 };
889 let sign_a = _mm_set_ps(1.0, -1.0, 1.0, -1.0);
890 let sign_b = _mm_set_ps(-1.0, 1.0, -1.0, 1.0);
891
892 let temp0 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b00_00_00_00);
893 let vec0 = _mm_shuffle_ps(temp0, temp0, 0b10_10_10_00);
894
895 let temp1 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b01_01_01_01);
896 let vec1 = _mm_shuffle_ps(temp1, temp1, 0b10_10_10_00);
897
898 let temp2 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b10_10_10_10);
899 let vec2 = _mm_shuffle_ps(temp2, temp2, 0b10_10_10_00);
900
901 let temp3 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b11_11_11_11);
902 let vec3 = _mm_shuffle_ps(temp3, temp3, 0b10_10_10_00);
903
904 let mul00 = _mm_mul_ps(vec1, fac0);
905 let mul01 = _mm_mul_ps(vec2, fac1);
906 let mul02 = _mm_mul_ps(vec3, fac2);
907 let sub00 = _mm_sub_ps(mul00, mul01);
908 let add00 = _mm_add_ps(sub00, mul02);
909 let inv0 = _mm_mul_ps(sign_b, add00);
910
911 let mul03 = _mm_mul_ps(vec0, fac0);
912 let mul04 = _mm_mul_ps(vec2, fac3);
913 let mul05 = _mm_mul_ps(vec3, fac4);
914 let sub01 = _mm_sub_ps(mul03, mul04);
915 let add01 = _mm_add_ps(sub01, mul05);
916 let inv1 = _mm_mul_ps(sign_a, add01);
917
918 let mul06 = _mm_mul_ps(vec0, fac1);
919 let mul07 = _mm_mul_ps(vec1, fac3);
920 let mul08 = _mm_mul_ps(vec3, fac5);
921 let sub02 = _mm_sub_ps(mul06, mul07);
922 let add02 = _mm_add_ps(sub02, mul08);
923 let inv2 = _mm_mul_ps(sign_b, add02);
924
925 let mul09 = _mm_mul_ps(vec0, fac2);
926 let mul10 = _mm_mul_ps(vec1, fac4);
927 let mul11 = _mm_mul_ps(vec2, fac5);
928 let sub03 = _mm_sub_ps(mul09, mul10);
929 let add03 = _mm_add_ps(sub03, mul11);
930 let inv3 = _mm_mul_ps(sign_a, add03);
931
932 let row0 = _mm_shuffle_ps(inv0, inv1, 0b00_00_00_00);
933 let row1 = _mm_shuffle_ps(inv2, inv3, 0b00_00_00_00);
934 let row2 = _mm_shuffle_ps(row0, row1, 0b10_00_10_00);
935
936 let dot0 = dot4(self.x_axis.0, row2);
937
938 if CHECKED {
939 if dot0 == 0.0 {
940 return (Self::ZERO, false);
941 }
942 } else {
943 glam_assert!(dot0 != 0.0);
944 }
945
946 let rcp0 = _mm_set1_ps(dot0.recip());
947
948 (
949 Self {
950 x_axis: Vec4(_mm_mul_ps(inv0, rcp0)),
951 y_axis: Vec4(_mm_mul_ps(inv1, rcp0)),
952 z_axis: Vec4(_mm_mul_ps(inv2, rcp0)),
953 w_axis: Vec4(_mm_mul_ps(inv3, rcp0)),
954 },
955 true,
956 )
957 }
958 }
959
960 #[must_use]
968 pub fn inverse(&self) -> Self {
969 self.inverse_checked::<false>().0
970 }
971
972 #[must_use]
974 pub fn try_inverse(&self) -> Option<Self> {
975 let (m, is_valid) = self.inverse_checked::<true>();
976 if is_valid {
977 Some(m)
978 } else {
979 None
980 }
981 }
982
983 #[must_use]
985 pub fn inverse_or_zero(&self) -> Self {
986 self.inverse_checked::<true>().0
987 }
988
989 #[deprecated(
998 since = "0.33.1",
999 note = "use the `glam::camera::lh::view::look_to_mat4` function instead"
1000 )]
1001 #[inline]
1002 #[must_use]
1003 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
1004 #[allow(deprecated)]
1005 Self::look_to_rh(eye, -dir, up)
1006 }
1007
1008 #[deprecated(
1017 since = "0.33.1",
1018 note = "use the `glam::camera::rh::view::look_to_mat4` function instead"
1019 )]
1020 #[inline]
1021 #[must_use]
1022 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
1023 glam_assert!(dir.is_normalized());
1024 glam_assert!(up.is_normalized());
1025 let f = dir;
1026 let s = f.cross(up).normalize();
1027 let u = s.cross(f);
1028
1029 Self::from_cols(
1030 Vec4::new(s.x, u.x, -f.x, 0.0),
1031 Vec4::new(s.y, u.y, -f.y, 0.0),
1032 Vec4::new(s.z, u.z, -f.z, 0.0),
1033 Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
1034 )
1035 }
1036
1037 #[deprecated(
1046 since = "0.33.1",
1047 note = "use the `glam::camera::lh::view::look_at_mat4` function instead"
1048 )]
1049 #[inline]
1050 #[must_use]
1051 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
1052 #[allow(deprecated)]
1053 Self::look_to_lh(eye, center.sub(eye).normalize(), up)
1054 }
1055
1056 #[deprecated(
1065 since = "0.33.1",
1066 note = "use the `glam::camera::rh::view::look_at_mat4` function instead"
1067 )]
1068 #[inline]
1069 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
1070 #[allow(deprecated)]
1071 Self::look_to_rh(eye, center.sub(eye).normalize(), up)
1072 }
1073
1074 #[deprecated(
1080 since = "0.33.1",
1081 note = "use the `glam::camera::rh::proj::opengl::frustum` function instead"
1082 )]
1083 #[inline]
1084 #[must_use]
1085 pub fn frustum_rh_gl(
1086 left: f32,
1087 right: f32,
1088 bottom: f32,
1089 top: f32,
1090 z_near: f32,
1091 z_far: f32,
1092 ) -> Self {
1093 let inv_width = 1.0 / (right - left);
1094 let inv_height = 1.0 / (top - bottom);
1095 let inv_depth = 1.0 / (z_far - z_near);
1096 let a = (right + left) * inv_width;
1097 let b = (top + bottom) * inv_height;
1098 let c = -(z_far + z_near) * inv_depth;
1099 let d = -(2.0 * z_far * z_near) * inv_depth;
1100 let two_z_near = 2.0 * z_near;
1101 Self::from_cols(
1102 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
1103 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
1104 Vec4::new(a, b, c, -1.0),
1105 Vec4::new(0.0, 0.0, d, 0.0),
1106 )
1107 }
1108
1109 #[deprecated(
1116 since = "0.33.1",
1117 note = "use the `glam::camera::lh::proj::directx::frustum` function instead"
1118 )]
1119 #[inline]
1120 #[must_use]
1121 pub fn frustum_lh(
1122 left: f32,
1123 right: f32,
1124 bottom: f32,
1125 top: f32,
1126 z_near: f32,
1127 z_far: f32,
1128 ) -> Self {
1129 glam_assert!(z_near > 0.0 && z_far > 0.0);
1130 let inv_width = 1.0 / (right - left);
1131 let inv_height = 1.0 / (top - bottom);
1132 let inv_depth = 1.0 / (z_far - z_near);
1133 let a = (right + left) * inv_width;
1134 let b = (top + bottom) * inv_height;
1135 let c = z_far * inv_depth;
1136 let d = -(z_far * z_near) * inv_depth;
1137 let two_z_near = 2.0 * z_near;
1138 Self::from_cols(
1139 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
1140 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
1141 Vec4::new(a, b, c, 1.0),
1142 Vec4::new(0.0, 0.0, d, 0.0),
1143 )
1144 }
1145
1146 #[deprecated(
1153 since = "0.33.1",
1154 note = "use the `glam::camera::rh::proj::directx::frustum` function instead"
1155 )]
1156 #[inline]
1157 #[must_use]
1158 pub fn frustum_rh(
1159 left: f32,
1160 right: f32,
1161 bottom: f32,
1162 top: f32,
1163 z_near: f32,
1164 z_far: f32,
1165 ) -> Self {
1166 glam_assert!(z_near > 0.0 && z_far > 0.0);
1167 let inv_width = 1.0 / (right - left);
1168 let inv_height = 1.0 / (top - bottom);
1169 let inv_depth = 1.0 / (z_far - z_near);
1170 let a = (right + left) * inv_width;
1171 let b = (top + bottom) * inv_height;
1172 let c = -z_far * inv_depth;
1173 let d = -(z_far * z_near) * inv_depth;
1174 let two_z_near = 2.0 * z_near;
1175 Self::from_cols(
1176 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
1177 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
1178 Vec4::new(a, b, c, -1.0),
1179 Vec4::new(0.0, 0.0, d, 0.0),
1180 )
1181 }
1182
1183 #[deprecated(
1190 since = "0.33.1",
1191 note = "use the `glam::camera::rh::proj::opengl::perspective` function instead"
1192 )]
1193 #[inline]
1194 #[must_use]
1195 pub fn perspective_rh_gl(
1196 fov_y_radians: f32,
1197 aspect_ratio: f32,
1198 z_near: f32,
1199 z_far: f32,
1200 ) -> Self {
1201 let inv_length = 1.0 / (z_near - z_far);
1202 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1203 let a = f / aspect_ratio;
1204 let b = (z_near + z_far) * inv_length;
1205 let c = (2.0 * z_near * z_far) * inv_length;
1206 Self::from_cols(
1207 Vec4::new(a, 0.0, 0.0, 0.0),
1208 Vec4::new(0.0, f, 0.0, 0.0),
1209 Vec4::new(0.0, 0.0, b, -1.0),
1210 Vec4::new(0.0, 0.0, c, 0.0),
1211 )
1212 }
1213
1214 #[deprecated(
1223 since = "0.33.1",
1224 note = "use the `glam::camera::lh::proj::directx::perspective` function instead"
1225 )]
1226 #[inline]
1227 #[must_use]
1228 pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
1229 glam_assert!(z_near > 0.0 && z_far > 0.0);
1230 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1231 let h = cos_fov / sin_fov;
1232 let w = h / aspect_ratio;
1233 let r = z_far / (z_far - z_near);
1234 Self::from_cols(
1235 Vec4::new(w, 0.0, 0.0, 0.0),
1236 Vec4::new(0.0, h, 0.0, 0.0),
1237 Vec4::new(0.0, 0.0, r, 1.0),
1238 Vec4::new(0.0, 0.0, -r * z_near, 0.0),
1239 )
1240 }
1241
1242 #[deprecated(
1251 since = "0.33.1",
1252 note = "use the `glam::camera::rh::proj::directx::perspective` function instead"
1253 )]
1254 #[inline]
1255 #[must_use]
1256 pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
1257 glam_assert!(z_near > 0.0 && z_far > 0.0);
1258 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1259 let h = cos_fov / sin_fov;
1260 let w = h / aspect_ratio;
1261 let r = z_far / (z_near - z_far);
1262 Self::from_cols(
1263 Vec4::new(w, 0.0, 0.0, 0.0),
1264 Vec4::new(0.0, h, 0.0, 0.0),
1265 Vec4::new(0.0, 0.0, r, -1.0),
1266 Vec4::new(0.0, 0.0, r * z_near, 0.0),
1267 )
1268 }
1269
1270 #[deprecated(
1280 since = "0.33.1",
1281 note = "use the `glam::camera::lh::proj::directx::perspective_infinite` function instead"
1282 )]
1283 #[inline]
1284 #[must_use]
1285 pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1286 glam_assert!(z_near > 0.0);
1287 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1288 let h = cos_fov / sin_fov;
1289 let w = h / aspect_ratio;
1290 Self::from_cols(
1291 Vec4::new(w, 0.0, 0.0, 0.0),
1292 Vec4::new(0.0, h, 0.0, 0.0),
1293 Vec4::new(0.0, 0.0, 1.0, 1.0),
1294 Vec4::new(0.0, 0.0, -z_near, 0.0),
1295 )
1296 }
1297
1298 #[deprecated(
1306 since = "0.33.1",
1307 note = "use the `glam::camera::lh::proj::directx::perspective_infinite_reverse` function instead"
1308 )]
1309 #[inline]
1310 #[must_use]
1311 pub fn perspective_infinite_reverse_lh(
1312 fov_y_radians: f32,
1313 aspect_ratio: f32,
1314 z_near: f32,
1315 ) -> Self {
1316 glam_assert!(z_near > 0.0);
1317 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1318 let h = cos_fov / sin_fov;
1319 let w = h / aspect_ratio;
1320 Self::from_cols(
1321 Vec4::new(w, 0.0, 0.0, 0.0),
1322 Vec4::new(0.0, h, 0.0, 0.0),
1323 Vec4::new(0.0, 0.0, 0.0, 1.0),
1324 Vec4::new(0.0, 0.0, z_near, 0.0),
1325 )
1326 }
1327
1328 #[deprecated(
1338 since = "0.33.1",
1339 note = "use the `glam::camera::rh::proj::directx::perspective_infinite` function instead"
1340 )]
1341 #[inline]
1342 #[must_use]
1343 pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1344 glam_assert!(z_near > 0.0);
1345 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1346 Self::from_cols(
1347 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1348 Vec4::new(0.0, f, 0.0, 0.0),
1349 Vec4::new(0.0, 0.0, -1.0, -1.0),
1350 Vec4::new(0.0, 0.0, -z_near, 0.0),
1351 )
1352 }
1353
1354 #[deprecated(
1362 since = "0.33.1",
1363 note = "use the `glam::camera::rh::proj::directx::perspective_infinite_reverse` function instead"
1364 )]
1365 #[inline]
1366 #[must_use]
1367 pub fn perspective_infinite_reverse_rh(
1368 fov_y_radians: f32,
1369 aspect_ratio: f32,
1370 z_near: f32,
1371 ) -> Self {
1372 glam_assert!(z_near > 0.0);
1373 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1374 Self::from_cols(
1375 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1376 Vec4::new(0.0, f, 0.0, 0.0),
1377 Vec4::new(0.0, 0.0, 0.0, -1.0),
1378 Vec4::new(0.0, 0.0, z_near, 0.0),
1379 )
1380 }
1381
1382 #[deprecated(
1389 since = "0.33.1",
1390 note = "use the `glam::camera::rh::proj::opengl::orthographic` function instead"
1391 )]
1392 #[inline]
1393 #[must_use]
1394 pub fn orthographic_rh_gl(
1395 left: f32,
1396 right: f32,
1397 bottom: f32,
1398 top: f32,
1399 near: f32,
1400 far: f32,
1401 ) -> Self {
1402 let a = 2.0 / (right - left);
1403 let b = 2.0 / (top - bottom);
1404 let c = 2.0 / (near - far);
1405 let tx = -(right + left) / (right - left);
1406 let ty = -(top + bottom) / (top - bottom);
1407 let tz = -(far + near) / (far - near);
1408
1409 Self::from_cols(
1410 Vec4::new(a, 0.0, 0.0, 0.0),
1411 Vec4::new(0.0, b, 0.0, 0.0),
1412 Vec4::new(0.0, 0.0, c, 0.0),
1413 Vec4::new(tx, ty, tz, 1.0),
1414 )
1415 }
1416
1417 #[deprecated(
1421 since = "0.33.1",
1422 note = "use the `glam::camera::lh::proj::directx::orthographic` function instead"
1423 )]
1424 #[inline]
1425 #[must_use]
1426 pub fn orthographic_lh(
1427 left: f32,
1428 right: f32,
1429 bottom: f32,
1430 top: f32,
1431 near: f32,
1432 far: f32,
1433 ) -> Self {
1434 let rcp_width = 1.0 / (right - left);
1435 let rcp_height = 1.0 / (top - bottom);
1436 let r = 1.0 / (far - near);
1437 Self::from_cols(
1438 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1439 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1440 Vec4::new(0.0, 0.0, r, 0.0),
1441 Vec4::new(
1442 -(left + right) * rcp_width,
1443 -(top + bottom) * rcp_height,
1444 -r * near,
1445 1.0,
1446 ),
1447 )
1448 }
1449
1450 #[deprecated(
1454 since = "0.33.1",
1455 note = "use the `glam::camera::rh::proj::directx::orthographic` function instead"
1456 )]
1457 #[inline]
1458 #[must_use]
1459 pub fn orthographic_rh(
1460 left: f32,
1461 right: f32,
1462 bottom: f32,
1463 top: f32,
1464 near: f32,
1465 far: f32,
1466 ) -> Self {
1467 let rcp_width = 1.0 / (right - left);
1468 let rcp_height = 1.0 / (top - bottom);
1469 let r = 1.0 / (near - far);
1470 Self::from_cols(
1471 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1472 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1473 Vec4::new(0.0, 0.0, r, 0.0),
1474 Vec4::new(
1475 -(left + right) * rcp_width,
1476 -(top + bottom) * rcp_height,
1477 r * near,
1478 1.0,
1479 ),
1480 )
1481 }
1482
1483 #[inline]
1490 #[must_use]
1491 pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
1492 let mut res = self.x_axis.mul(rhs.x);
1493 res = self.y_axis.mul(rhs.y).add(res);
1494 res = self.z_axis.mul(rhs.z).add(res);
1495 res = self.w_axis.add(res);
1496 res = res.div(res.w);
1497 res.xyz()
1498 }
1499
1500 #[inline]
1513 #[must_use]
1514 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1515 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1516 let mut res = self.x_axis.mul(rhs.x);
1517 res = self.y_axis.mul(rhs.y).add(res);
1518 res = self.z_axis.mul(rhs.z).add(res);
1519 res = self.w_axis.add(res);
1520 res.xyz()
1521 }
1522
1523 #[inline]
1534 #[must_use]
1535 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1536 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1537 let mut res = self.x_axis.mul(rhs.x);
1538 res = self.y_axis.mul(rhs.y).add(res);
1539 res = self.z_axis.mul(rhs.z).add(res);
1540 res.xyz()
1541 }
1542
1543 #[inline]
1550 #[must_use]
1551 pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
1552 let mut res = self.x_axis.mul(rhs.xxxx());
1553 res = self.y_axis.mul(rhs.yyyy()).add(res);
1554 res = self.z_axis.mul(rhs.zzzz()).add(res);
1555 res = self.w_axis.add(res);
1556 res = res.div(res.wwww());
1557 Vec3A::from_vec4(res)
1558 }
1559
1560 #[inline]
1564 #[must_use]
1565 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1566 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1567 let mut res = self.x_axis.mul(rhs.xxxx());
1568 res = self.y_axis.mul(rhs.yyyy()).add(res);
1569 res = self.z_axis.mul(rhs.zzzz()).add(res);
1570 res = self.w_axis.add(res);
1571 Vec3A::from_vec4(res)
1572 }
1573
1574 #[inline]
1578 #[must_use]
1579 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1580 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1581 let mut res = self.x_axis.mul(rhs.xxxx());
1582 res = self.y_axis.mul(rhs.yyyy()).add(res);
1583 res = self.z_axis.mul(rhs.zzzz()).add(res);
1584 Vec3A::from_vec4(res)
1585 }
1586
1587 #[inline]
1589 #[must_use]
1590 pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1591 let mut res = self.x_axis.mul(rhs.xxxx());
1592 res = res.add(self.y_axis.mul(rhs.yyyy()));
1593 res = res.add(self.z_axis.mul(rhs.zzzz()));
1594 res = res.add(self.w_axis.mul(rhs.wwww()));
1595 res
1596 }
1597
1598 #[inline]
1600 #[must_use]
1601 pub fn mul_transpose_vec4(&self, rhs: Vec4) -> Vec4 {
1602 Vec4::new(
1603 self.x_axis.dot(rhs),
1604 self.y_axis.dot(rhs),
1605 self.z_axis.dot(rhs),
1606 self.w_axis.dot(rhs),
1607 )
1608 }
1609
1610 #[inline]
1612 #[must_use]
1613 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1614 self.mul(rhs)
1615 }
1616
1617 #[inline]
1619 #[must_use]
1620 pub fn add_mat4(&self, rhs: &Self) -> Self {
1621 self.add(rhs)
1622 }
1623
1624 #[inline]
1626 #[must_use]
1627 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1628 self.sub(rhs)
1629 }
1630
1631 #[inline]
1633 #[must_use]
1634 pub fn mul_scalar(&self, rhs: f32) -> Self {
1635 Self::from_cols(
1636 self.x_axis.mul(rhs),
1637 self.y_axis.mul(rhs),
1638 self.z_axis.mul(rhs),
1639 self.w_axis.mul(rhs),
1640 )
1641 }
1642
1643 #[inline]
1647 #[must_use]
1648 pub fn mul_diagonal_scale(&self, scale: Vec4) -> Self {
1649 Self::from_cols(
1650 self.x_axis * scale.x,
1651 self.y_axis * scale.y,
1652 self.z_axis * scale.z,
1653 self.w_axis * scale.w,
1654 )
1655 }
1656
1657 #[inline]
1659 #[must_use]
1660 pub fn div_scalar(&self, rhs: f32) -> Self {
1661 let rhs = Vec4::splat(rhs);
1662 Self::from_cols(
1663 self.x_axis.div(rhs),
1664 self.y_axis.div(rhs),
1665 self.z_axis.div(rhs),
1666 self.w_axis.div(rhs),
1667 )
1668 }
1669
1670 #[inline]
1672 #[must_use]
1673 pub fn recip(&self) -> Self {
1674 Self::from_cols(
1675 self.x_axis.recip(),
1676 self.y_axis.recip(),
1677 self.z_axis.recip(),
1678 self.w_axis.recip(),
1679 )
1680 }
1681
1682 #[inline]
1692 #[must_use]
1693 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1694 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1695 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1696 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1697 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1698 }
1699
1700 #[inline]
1702 #[must_use]
1703 pub fn abs(&self) -> Self {
1704 Self::from_cols(
1705 self.x_axis.abs(),
1706 self.y_axis.abs(),
1707 self.z_axis.abs(),
1708 self.w_axis.abs(),
1709 )
1710 }
1711
1712 #[cfg(feature = "f64")]
1713 #[inline]
1714 #[must_use]
1715 pub fn as_dmat4(&self) -> DMat4 {
1716 DMat4::from_cols(
1717 self.x_axis.as_dvec4(),
1718 self.y_axis.as_dvec4(),
1719 self.z_axis.as_dvec4(),
1720 self.w_axis.as_dvec4(),
1721 )
1722 }
1723}
1724
1725impl Default for Mat4 {
1726 #[inline]
1727 fn default() -> Self {
1728 Self::IDENTITY
1729 }
1730}
1731
1732impl Add for Mat4 {
1733 type Output = Self;
1734 #[inline]
1735 fn add(self, rhs: Self) -> Self {
1736 Self::from_cols(
1737 self.x_axis.add(rhs.x_axis),
1738 self.y_axis.add(rhs.y_axis),
1739 self.z_axis.add(rhs.z_axis),
1740 self.w_axis.add(rhs.w_axis),
1741 )
1742 }
1743}
1744
1745impl Add<&Self> for Mat4 {
1746 type Output = Self;
1747 #[inline]
1748 fn add(self, rhs: &Self) -> Self {
1749 self.add(*rhs)
1750 }
1751}
1752
1753impl Add<&Mat4> for &Mat4 {
1754 type Output = Mat4;
1755 #[inline]
1756 fn add(self, rhs: &Mat4) -> Mat4 {
1757 (*self).add(*rhs)
1758 }
1759}
1760
1761impl Add<Mat4> for &Mat4 {
1762 type Output = Mat4;
1763 #[inline]
1764 fn add(self, rhs: Mat4) -> Mat4 {
1765 (*self).add(rhs)
1766 }
1767}
1768
1769impl AddAssign for Mat4 {
1770 #[inline]
1771 fn add_assign(&mut self, rhs: Self) {
1772 *self = self.add(rhs);
1773 }
1774}
1775
1776impl AddAssign<&Self> for Mat4 {
1777 #[inline]
1778 fn add_assign(&mut self, rhs: &Self) {
1779 self.add_assign(*rhs);
1780 }
1781}
1782
1783impl Sub for Mat4 {
1784 type Output = Self;
1785 #[inline]
1786 fn sub(self, rhs: Self) -> Self {
1787 Self::from_cols(
1788 self.x_axis.sub(rhs.x_axis),
1789 self.y_axis.sub(rhs.y_axis),
1790 self.z_axis.sub(rhs.z_axis),
1791 self.w_axis.sub(rhs.w_axis),
1792 )
1793 }
1794}
1795
1796impl Sub<&Self> for Mat4 {
1797 type Output = Self;
1798 #[inline]
1799 fn sub(self, rhs: &Self) -> Self {
1800 self.sub(*rhs)
1801 }
1802}
1803
1804impl Sub<&Mat4> for &Mat4 {
1805 type Output = Mat4;
1806 #[inline]
1807 fn sub(self, rhs: &Mat4) -> Mat4 {
1808 (*self).sub(*rhs)
1809 }
1810}
1811
1812impl Sub<Mat4> for &Mat4 {
1813 type Output = Mat4;
1814 #[inline]
1815 fn sub(self, rhs: Mat4) -> Mat4 {
1816 (*self).sub(rhs)
1817 }
1818}
1819
1820impl SubAssign for Mat4 {
1821 #[inline]
1822 fn sub_assign(&mut self, rhs: Self) {
1823 *self = self.sub(rhs);
1824 }
1825}
1826
1827impl SubAssign<&Self> for Mat4 {
1828 #[inline]
1829 fn sub_assign(&mut self, rhs: &Self) {
1830 self.sub_assign(*rhs);
1831 }
1832}
1833
1834impl Neg for Mat4 {
1835 type Output = Self;
1836 #[inline]
1837 fn neg(self) -> Self::Output {
1838 Self::from_cols(
1839 self.x_axis.neg(),
1840 self.y_axis.neg(),
1841 self.z_axis.neg(),
1842 self.w_axis.neg(),
1843 )
1844 }
1845}
1846
1847impl Neg for &Mat4 {
1848 type Output = Mat4;
1849 #[inline]
1850 fn neg(self) -> Mat4 {
1851 (*self).neg()
1852 }
1853}
1854
1855impl Mul for Mat4 {
1856 type Output = Self;
1857 #[inline]
1858 fn mul(self, rhs: Self) -> Self {
1859 Self::from_cols(
1860 self.mul(rhs.x_axis),
1861 self.mul(rhs.y_axis),
1862 self.mul(rhs.z_axis),
1863 self.mul(rhs.w_axis),
1864 )
1865 }
1866}
1867
1868impl Mul<&Self> for Mat4 {
1869 type Output = Self;
1870 #[inline]
1871 fn mul(self, rhs: &Self) -> Self {
1872 self.mul(*rhs)
1873 }
1874}
1875
1876impl Mul<&Mat4> for &Mat4 {
1877 type Output = Mat4;
1878 #[inline]
1879 fn mul(self, rhs: &Mat4) -> Mat4 {
1880 (*self).mul(*rhs)
1881 }
1882}
1883
1884impl Mul<Mat4> for &Mat4 {
1885 type Output = Mat4;
1886 #[inline]
1887 fn mul(self, rhs: Mat4) -> Mat4 {
1888 (*self).mul(rhs)
1889 }
1890}
1891
1892impl MulAssign for Mat4 {
1893 #[inline]
1894 fn mul_assign(&mut self, rhs: Self) {
1895 *self = self.mul(rhs);
1896 }
1897}
1898
1899impl MulAssign<&Self> for Mat4 {
1900 #[inline]
1901 fn mul_assign(&mut self, rhs: &Self) {
1902 self.mul_assign(*rhs);
1903 }
1904}
1905
1906impl Mul<Vec4> for Mat4 {
1907 type Output = Vec4;
1908 #[inline]
1909 fn mul(self, rhs: Vec4) -> Self::Output {
1910 self.mul_vec4(rhs)
1911 }
1912}
1913
1914impl Mul<&Vec4> for Mat4 {
1915 type Output = Vec4;
1916 #[inline]
1917 fn mul(self, rhs: &Vec4) -> Vec4 {
1918 self.mul(*rhs)
1919 }
1920}
1921
1922impl Mul<&Vec4> for &Mat4 {
1923 type Output = Vec4;
1924 #[inline]
1925 fn mul(self, rhs: &Vec4) -> Vec4 {
1926 (*self).mul(*rhs)
1927 }
1928}
1929
1930impl Mul<Vec4> for &Mat4 {
1931 type Output = Vec4;
1932 #[inline]
1933 fn mul(self, rhs: Vec4) -> Vec4 {
1934 (*self).mul(rhs)
1935 }
1936}
1937
1938impl Mul<Mat4> for f32 {
1939 type Output = Mat4;
1940 #[inline]
1941 fn mul(self, rhs: Mat4) -> Self::Output {
1942 rhs.mul_scalar(self)
1943 }
1944}
1945
1946impl Mul<&Mat4> for f32 {
1947 type Output = Mat4;
1948 #[inline]
1949 fn mul(self, rhs: &Mat4) -> Mat4 {
1950 self.mul(*rhs)
1951 }
1952}
1953
1954impl Mul<&Mat4> for &f32 {
1955 type Output = Mat4;
1956 #[inline]
1957 fn mul(self, rhs: &Mat4) -> Mat4 {
1958 (*self).mul(*rhs)
1959 }
1960}
1961
1962impl Mul<Mat4> for &f32 {
1963 type Output = Mat4;
1964 #[inline]
1965 fn mul(self, rhs: Mat4) -> Mat4 {
1966 (*self).mul(rhs)
1967 }
1968}
1969
1970impl Mul<f32> for Mat4 {
1971 type Output = Self;
1972 #[inline]
1973 fn mul(self, rhs: f32) -> Self {
1974 self.mul_scalar(rhs)
1975 }
1976}
1977
1978impl Mul<&f32> for Mat4 {
1979 type Output = Self;
1980 #[inline]
1981 fn mul(self, rhs: &f32) -> Self {
1982 self.mul(*rhs)
1983 }
1984}
1985
1986impl Mul<&f32> for &Mat4 {
1987 type Output = Mat4;
1988 #[inline]
1989 fn mul(self, rhs: &f32) -> Mat4 {
1990 (*self).mul(*rhs)
1991 }
1992}
1993
1994impl Mul<f32> for &Mat4 {
1995 type Output = Mat4;
1996 #[inline]
1997 fn mul(self, rhs: f32) -> Mat4 {
1998 (*self).mul(rhs)
1999 }
2000}
2001
2002impl MulAssign<f32> for Mat4 {
2003 #[inline]
2004 fn mul_assign(&mut self, rhs: f32) {
2005 *self = self.mul(rhs);
2006 }
2007}
2008
2009impl MulAssign<&f32> for Mat4 {
2010 #[inline]
2011 fn mul_assign(&mut self, rhs: &f32) {
2012 self.mul_assign(*rhs);
2013 }
2014}
2015
2016impl Div<Mat4> for f32 {
2017 type Output = Mat4;
2018 #[inline]
2019 fn div(self, rhs: Mat4) -> Self::Output {
2020 Mat4::from_cols(
2021 self.div(rhs.x_axis),
2022 self.div(rhs.y_axis),
2023 self.div(rhs.z_axis),
2024 self.div(rhs.w_axis),
2025 )
2026 }
2027}
2028
2029impl Div<&Mat4> for f32 {
2030 type Output = Mat4;
2031 #[inline]
2032 fn div(self, rhs: &Mat4) -> Mat4 {
2033 self.div(*rhs)
2034 }
2035}
2036
2037impl Div<&Mat4> for &f32 {
2038 type Output = Mat4;
2039 #[inline]
2040 fn div(self, rhs: &Mat4) -> Mat4 {
2041 (*self).div(*rhs)
2042 }
2043}
2044
2045impl Div<Mat4> for &f32 {
2046 type Output = Mat4;
2047 #[inline]
2048 fn div(self, rhs: Mat4) -> Mat4 {
2049 (*self).div(rhs)
2050 }
2051}
2052
2053impl Div<f32> for Mat4 {
2054 type Output = Self;
2055 #[inline]
2056 fn div(self, rhs: f32) -> Self {
2057 self.div_scalar(rhs)
2058 }
2059}
2060
2061impl Div<&f32> for Mat4 {
2062 type Output = Self;
2063 #[inline]
2064 fn div(self, rhs: &f32) -> Self {
2065 self.div(*rhs)
2066 }
2067}
2068
2069impl Div<&f32> for &Mat4 {
2070 type Output = Mat4;
2071 #[inline]
2072 fn div(self, rhs: &f32) -> Mat4 {
2073 (*self).div(*rhs)
2074 }
2075}
2076
2077impl Div<f32> for &Mat4 {
2078 type Output = Mat4;
2079 #[inline]
2080 fn div(self, rhs: f32) -> Mat4 {
2081 (*self).div(rhs)
2082 }
2083}
2084
2085impl DivAssign<f32> for Mat4 {
2086 #[inline]
2087 fn div_assign(&mut self, rhs: f32) {
2088 *self = self.div(rhs);
2089 }
2090}
2091
2092impl DivAssign<&f32> for Mat4 {
2093 #[inline]
2094 fn div_assign(&mut self, rhs: &f32) {
2095 self.div_assign(*rhs);
2096 }
2097}
2098
2099impl Sum<Self> for Mat4 {
2100 fn sum<I>(iter: I) -> Self
2101 where
2102 I: Iterator<Item = Self>,
2103 {
2104 iter.fold(Self::ZERO, Self::add)
2105 }
2106}
2107
2108impl<'a> Sum<&'a Self> for Mat4 {
2109 fn sum<I>(iter: I) -> Self
2110 where
2111 I: Iterator<Item = &'a Self>,
2112 {
2113 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
2114 }
2115}
2116
2117impl Product for Mat4 {
2118 fn product<I>(iter: I) -> Self
2119 where
2120 I: Iterator<Item = Self>,
2121 {
2122 iter.fold(Self::IDENTITY, Self::mul)
2123 }
2124}
2125
2126impl<'a> Product<&'a Self> for Mat4 {
2127 fn product<I>(iter: I) -> Self
2128 where
2129 I: Iterator<Item = &'a Self>,
2130 {
2131 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
2132 }
2133}
2134
2135impl PartialEq for Mat4 {
2136 #[inline]
2137 fn eq(&self, rhs: &Self) -> bool {
2138 self.x_axis.eq(&rhs.x_axis)
2139 && self.y_axis.eq(&rhs.y_axis)
2140 && self.z_axis.eq(&rhs.z_axis)
2141 && self.w_axis.eq(&rhs.w_axis)
2142 }
2143}
2144
2145impl AsRef<[f32; 16]> for Mat4 {
2146 #[inline]
2147 fn as_ref(&self) -> &[f32; 16] {
2148 unsafe { &*(self as *const Self as *const [f32; 16]) }
2149 }
2150}
2151
2152impl AsMut<[f32; 16]> for Mat4 {
2153 #[inline]
2154 fn as_mut(&mut self) -> &mut [f32; 16] {
2155 unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
2156 }
2157}
2158
2159impl fmt::Debug for Mat4 {
2160 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2161 fmt.debug_struct(stringify!(Mat4))
2162 .field("x_axis", &self.x_axis)
2163 .field("y_axis", &self.y_axis)
2164 .field("z_axis", &self.z_axis)
2165 .field("w_axis", &self.w_axis)
2166 .finish()
2167 }
2168}
2169
2170impl fmt::Display for Mat4 {
2171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2172 if let Some(p) = f.precision() {
2173 write!(
2174 f,
2175 "[{:.*}, {:.*}, {:.*}, {:.*}]",
2176 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
2177 )
2178 } else {
2179 write!(
2180 f,
2181 "[{}, {}, {}, {}]",
2182 self.x_axis, self.y_axis, self.z_axis, self.w_axis
2183 )
2184 }
2185 }
2186}