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)]
48#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
49#[cfg_attr(
50 feature = "zerocopy",
51 derive(FromBytes, Immutable, IntoBytes, KnownLayout)
52)]
53#[repr(C)]
54pub struct Mat4 {
55 pub x_axis: Vec4,
56 pub y_axis: Vec4,
57 pub z_axis: Vec4,
58 pub w_axis: Vec4,
59}
60
61impl Mat4 {
62 pub const ZERO: Self = Self::from_cols(Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO);
64
65 pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W);
67
68 pub const NAN: Self = Self::from_cols(Vec4::NAN, Vec4::NAN, Vec4::NAN, Vec4::NAN);
70
71 #[allow(clippy::too_many_arguments)]
72 #[inline(always)]
73 #[must_use]
74 const fn new(
75 m00: f32,
76 m01: f32,
77 m02: f32,
78 m03: f32,
79 m10: f32,
80 m11: f32,
81 m12: f32,
82 m13: f32,
83 m20: f32,
84 m21: f32,
85 m22: f32,
86 m23: f32,
87 m30: f32,
88 m31: f32,
89 m32: f32,
90 m33: f32,
91 ) -> Self {
92 Self {
93 x_axis: Vec4::new(m00, m01, m02, m03),
94 y_axis: Vec4::new(m10, m11, m12, m13),
95 z_axis: Vec4::new(m20, m21, m22, m23),
96 w_axis: Vec4::new(m30, m31, m32, m33),
97 }
98 }
99
100 #[inline(always)]
102 #[must_use]
103 pub const fn from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self {
104 Self {
105 x_axis,
106 y_axis,
107 z_axis,
108 w_axis,
109 }
110 }
111
112 #[inline]
116 #[must_use]
117 pub const fn from_cols_array(m: &[f32; 16]) -> Self {
118 Self::new(
119 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],
120 m[14], m[15],
121 )
122 }
123
124 #[inline]
127 #[must_use]
128 pub const fn to_cols_array(&self) -> [f32; 16] {
129 let [x_axis_x, x_axis_y, x_axis_z, x_axis_w] = self.x_axis.to_array();
130 let [y_axis_x, y_axis_y, y_axis_z, y_axis_w] = self.y_axis.to_array();
131 let [z_axis_x, z_axis_y, z_axis_z, z_axis_w] = self.z_axis.to_array();
132 let [w_axis_x, w_axis_y, w_axis_z, w_axis_w] = self.w_axis.to_array();
133
134 [
135 x_axis_x, x_axis_y, x_axis_z, x_axis_w, y_axis_x, y_axis_y, y_axis_z, y_axis_w,
136 z_axis_x, z_axis_y, z_axis_z, z_axis_w, w_axis_x, w_axis_y, w_axis_z, w_axis_w,
137 ]
138 }
139
140 #[inline]
144 #[must_use]
145 pub const fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self {
146 Self::from_cols(
147 Vec4::from_array(m[0]),
148 Vec4::from_array(m[1]),
149 Vec4::from_array(m[2]),
150 Vec4::from_array(m[3]),
151 )
152 }
153
154 #[inline]
157 #[must_use]
158 pub const fn to_cols_array_2d(&self) -> [[f32; 4]; 4] {
159 [
160 self.x_axis.to_array(),
161 self.y_axis.to_array(),
162 self.z_axis.to_array(),
163 self.w_axis.to_array(),
164 ]
165 }
166
167 #[doc(alias = "scale")]
169 #[inline]
170 #[must_use]
171 pub const fn from_diagonal(diagonal: Vec4) -> Self {
172 let [x, y, z, w] = diagonal.to_array();
174 Self::new(
175 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,
176 )
177 }
178
179 #[inline]
180 #[must_use]
181 fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) {
182 glam_assert!(rotation.is_normalized());
183
184 let (x, y, z, w) = rotation.into();
185 let x2 = x + x;
186 let y2 = y + y;
187 let z2 = z + z;
188 let xx = x * x2;
189 let xy = x * y2;
190 let xz = x * z2;
191 let yy = y * y2;
192 let yz = y * z2;
193 let zz = z * z2;
194 let wx = w * x2;
195 let wy = w * y2;
196 let wz = w * z2;
197
198 let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
199 let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
200 let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
201 (x_axis, y_axis, z_axis)
202 }
203
204 #[inline]
214 #[must_use]
215 pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
216 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
217 Self::from_cols(
218 x_axis.mul(scale.x),
219 y_axis.mul(scale.y),
220 z_axis.mul(scale.z),
221 Vec4::from((translation, 1.0)),
222 )
223 }
224
225 #[inline]
234 #[must_use]
235 pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
236 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
237 Self::from_cols(x_axis, y_axis, z_axis, Vec4::from((translation, 1.0)))
238 }
239
240 #[inline]
248 #[must_use]
249 pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
250 let det = self.determinant();
251 glam_assert!(det != 0.0);
252
253 let scale = Vec3::new(
254 self.x_axis.length() * math::signum(det),
255 self.y_axis.length(),
256 self.z_axis.length(),
257 );
258
259 glam_assert!(scale.cmpne(Vec3::ZERO).all());
260
261 let inv_scale = scale.recip();
262
263 let rotation = Quat::from_rotation_axes(
264 self.x_axis.mul(inv_scale.x).xyz(),
265 self.y_axis.mul(inv_scale.y).xyz(),
266 self.z_axis.mul(inv_scale.z).xyz(),
267 );
268
269 let translation = self.w_axis.xyz();
270
271 (scale, rotation, translation)
272 }
273
274 #[inline]
283 #[must_use]
284 pub fn from_quat(rotation: Quat) -> Self {
285 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
286 Self::from_cols(x_axis, y_axis, z_axis, Vec4::W)
287 }
288
289 #[inline]
295 #[must_use]
296 pub fn from_mat3(m: Mat3) -> Self {
297 Self::from_cols(
298 Vec4::from((m.x_axis, 0.0)),
299 Vec4::from((m.y_axis, 0.0)),
300 Vec4::from((m.z_axis, 0.0)),
301 Vec4::W,
302 )
303 }
304
305 #[inline]
310 #[must_use]
311 pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
312 Self::from_cols(
313 Vec4::from((mat3.x_axis, 0.0)),
314 Vec4::from((mat3.y_axis, 0.0)),
315 Vec4::from((mat3.z_axis, 0.0)),
316 Vec4::from((translation, 1.0)),
317 )
318 }
319
320 #[inline]
326 #[must_use]
327 pub fn from_mat3a(m: Mat3A) -> Self {
328 Self::from_cols(
329 Vec4::from((m.x_axis, 0.0)),
330 Vec4::from((m.y_axis, 0.0)),
331 Vec4::from((m.z_axis, 0.0)),
332 Vec4::W,
333 )
334 }
335
336 #[inline]
341 #[must_use]
342 pub fn from_translation(translation: Vec3) -> Self {
343 Self::from_cols(
344 Vec4::X,
345 Vec4::Y,
346 Vec4::Z,
347 Vec4::new(translation.x, translation.y, translation.z, 1.0),
348 )
349 }
350
351 #[inline]
361 #[must_use]
362 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
363 glam_assert!(axis.is_normalized());
364
365 let (sin, cos) = math::sin_cos(angle);
366 let axis_sin = axis.mul(sin);
367 let axis_sq = axis.mul(axis);
368 let omc = 1.0 - cos;
369 let xyomc = axis.x * axis.y * omc;
370 let xzomc = axis.x * axis.z * omc;
371 let yzomc = axis.y * axis.z * omc;
372 Self::from_cols(
373 Vec4::new(
374 axis_sq.x * omc + cos,
375 xyomc + axis_sin.z,
376 xzomc - axis_sin.y,
377 0.0,
378 ),
379 Vec4::new(
380 xyomc - axis_sin.z,
381 axis_sq.y * omc + cos,
382 yzomc + axis_sin.x,
383 0.0,
384 ),
385 Vec4::new(
386 xzomc + axis_sin.y,
387 yzomc - axis_sin.x,
388 axis_sq.z * omc + cos,
389 0.0,
390 ),
391 Vec4::W,
392 )
393 }
394
395 #[inline]
401 #[must_use]
402 pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
403 Self::from_euler_angles(order, a, b, c)
404 }
405
406 #[inline]
416 #[must_use]
417 pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
418 glam_assert!(
419 self.x_axis.xyz().is_normalized()
420 && self.y_axis.xyz().is_normalized()
421 && self.z_axis.xyz().is_normalized()
422 );
423 self.to_euler_angles(order)
424 }
425
426 #[inline]
432 #[must_use]
433 pub fn from_rotation_x(angle: f32) -> Self {
434 let (sina, cosa) = math::sin_cos(angle);
435 Self::from_cols(
436 Vec4::X,
437 Vec4::new(0.0, cosa, sina, 0.0),
438 Vec4::new(0.0, -sina, cosa, 0.0),
439 Vec4::W,
440 )
441 }
442
443 #[inline]
449 #[must_use]
450 pub fn from_rotation_y(angle: f32) -> Self {
451 let (sina, cosa) = math::sin_cos(angle);
452 Self::from_cols(
453 Vec4::new(cosa, 0.0, -sina, 0.0),
454 Vec4::Y,
455 Vec4::new(sina, 0.0, cosa, 0.0),
456 Vec4::W,
457 )
458 }
459
460 #[inline]
466 #[must_use]
467 pub fn from_rotation_z(angle: f32) -> Self {
468 let (sina, cosa) = math::sin_cos(angle);
469 Self::from_cols(
470 Vec4::new(cosa, sina, 0.0, 0.0),
471 Vec4::new(-sina, cosa, 0.0, 0.0),
472 Vec4::Z,
473 Vec4::W,
474 )
475 }
476
477 #[inline]
486 #[must_use]
487 pub fn from_scale(scale: Vec3) -> Self {
488 glam_assert!(scale.cmpne(Vec3::ZERO).any());
490
491 Self::from_cols(
492 Vec4::new(scale.x, 0.0, 0.0, 0.0),
493 Vec4::new(0.0, scale.y, 0.0, 0.0),
494 Vec4::new(0.0, 0.0, scale.z, 0.0),
495 Vec4::W,
496 )
497 }
498
499 #[inline]
505 #[must_use]
506 pub const fn from_cols_slice(slice: &[f32]) -> Self {
507 Self::new(
508 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
509 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
510 )
511 }
512
513 #[inline]
519 pub fn write_cols_to_slice(&self, slice: &mut [f32]) {
520 slice[0] = self.x_axis.x;
521 slice[1] = self.x_axis.y;
522 slice[2] = self.x_axis.z;
523 slice[3] = self.x_axis.w;
524 slice[4] = self.y_axis.x;
525 slice[5] = self.y_axis.y;
526 slice[6] = self.y_axis.z;
527 slice[7] = self.y_axis.w;
528 slice[8] = self.z_axis.x;
529 slice[9] = self.z_axis.y;
530 slice[10] = self.z_axis.z;
531 slice[11] = self.z_axis.w;
532 slice[12] = self.w_axis.x;
533 slice[13] = self.w_axis.y;
534 slice[14] = self.w_axis.z;
535 slice[15] = self.w_axis.w;
536 }
537
538 #[inline]
544 #[must_use]
545 pub fn col(&self, index: usize) -> Vec4 {
546 match index {
547 0 => self.x_axis,
548 1 => self.y_axis,
549 2 => self.z_axis,
550 3 => self.w_axis,
551 _ => panic!("index out of bounds"),
552 }
553 }
554
555 #[inline]
561 pub fn col_mut(&mut self, index: usize) -> &mut Vec4 {
562 match index {
563 0 => &mut self.x_axis,
564 1 => &mut self.y_axis,
565 2 => &mut self.z_axis,
566 3 => &mut self.w_axis,
567 _ => panic!("index out of bounds"),
568 }
569 }
570
571 #[inline]
577 #[must_use]
578 pub fn row(&self, index: usize) -> Vec4 {
579 match index {
580 0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
581 1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
582 2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
583 3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
584 _ => panic!("index out of bounds"),
585 }
586 }
587
588 #[inline]
591 #[must_use]
592 pub fn is_finite(&self) -> bool {
593 self.x_axis.is_finite()
594 && self.y_axis.is_finite()
595 && self.z_axis.is_finite()
596 && self.w_axis.is_finite()
597 }
598
599 #[inline]
601 #[must_use]
602 pub fn is_nan(&self) -> bool {
603 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
604 }
605
606 #[inline]
608 #[must_use]
609 pub fn transpose(&self) -> Self {
610 unsafe {
611 let tmp0 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b01_00_01_00);
613 let tmp1 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b11_10_11_10);
614 let tmp2 = _mm_shuffle_ps(self.z_axis.0, self.w_axis.0, 0b01_00_01_00);
615 let tmp3 = _mm_shuffle_ps(self.z_axis.0, self.w_axis.0, 0b11_10_11_10);
616
617 Self {
618 x_axis: Vec4(_mm_shuffle_ps(tmp0, tmp2, 0b10_00_10_00)),
619 y_axis: Vec4(_mm_shuffle_ps(tmp0, tmp2, 0b11_01_11_01)),
620 z_axis: Vec4(_mm_shuffle_ps(tmp1, tmp3, 0b10_00_10_00)),
621 w_axis: Vec4(_mm_shuffle_ps(tmp1, tmp3, 0b11_01_11_01)),
622 }
623 }
624 }
625
626 #[inline]
628 #[must_use]
629 pub fn diagonal(&self) -> Vec4 {
630 Vec4::new(self.x_axis.x, self.y_axis.y, self.z_axis.z, self.w_axis.w)
631 }
632
633 #[must_use]
635 pub fn determinant(&self) -> f32 {
636 unsafe {
637 let swp2a = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_01_01_10);
639 let swp3a = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b11_10_11_11);
640 let swp2b = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b11_10_11_11);
641 let swp3b = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b00_01_01_10);
642 let swp2c = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_00_01_10);
643 let swp3c = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b01_10_00_00);
644
645 let mula = _mm_mul_ps(swp2a, swp3a);
646 let mulb = _mm_mul_ps(swp2b, swp3b);
647 let mulc = _mm_mul_ps(swp2c, swp3c);
648 let sube = _mm_sub_ps(mula, mulb);
649 let subf = _mm_sub_ps(_mm_movehl_ps(mulc, mulc), mulc);
650
651 let subfaca = _mm_shuffle_ps(sube, sube, 0b10_01_00_00);
652 let swpfaca = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b00_00_00_01);
653 let mulfaca = _mm_mul_ps(swpfaca, subfaca);
654
655 let subtmpb = _mm_shuffle_ps(sube, subf, 0b00_00_11_01);
656 let subfacb = _mm_shuffle_ps(subtmpb, subtmpb, 0b11_01_01_00);
657 let swpfacb = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b01_01_10_10);
658 let mulfacb = _mm_mul_ps(swpfacb, subfacb);
659
660 let subres = _mm_sub_ps(mulfaca, mulfacb);
661 let subtmpc = _mm_shuffle_ps(sube, subf, 0b01_00_10_10);
662 let subfacc = _mm_shuffle_ps(subtmpc, subtmpc, 0b11_11_10_00);
663 let swpfacc = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b10_11_11_11);
664 let mulfacc = _mm_mul_ps(swpfacc, subfacc);
665
666 let addres = _mm_add_ps(subres, mulfacc);
667 let detcof = _mm_mul_ps(addres, _mm_setr_ps(1.0, -1.0, 1.0, -1.0));
668
669 dot4(self.x_axis.0, detcof)
670 }
671 }
672
673 #[inline(always)]
685 #[must_use]
686 fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
687 unsafe {
688 let fac0 = {
690 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
691 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
692
693 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
694 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
695 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
696 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
697
698 let mul00 = _mm_mul_ps(swp00, swp01);
699 let mul01 = _mm_mul_ps(swp02, swp03);
700 _mm_sub_ps(mul00, mul01)
701 };
702 let fac1 = {
703 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
704 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
705
706 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
707 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
708 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
709 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
710
711 let mul00 = _mm_mul_ps(swp00, swp01);
712 let mul01 = _mm_mul_ps(swp02, swp03);
713 _mm_sub_ps(mul00, mul01)
714 };
715 let fac2 = {
716 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
717 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
718
719 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
720 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
721 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
722 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
723
724 let mul00 = _mm_mul_ps(swp00, swp01);
725 let mul01 = _mm_mul_ps(swp02, swp03);
726 _mm_sub_ps(mul00, mul01)
727 };
728 let fac3 = {
729 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
730 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
731
732 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
733 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
734 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
735 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
736
737 let mul00 = _mm_mul_ps(swp00, swp01);
738 let mul01 = _mm_mul_ps(swp02, swp03);
739 _mm_sub_ps(mul00, mul01)
740 };
741 let fac4 = {
742 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
743 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
744
745 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
746 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
747 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
748 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
749
750 let mul00 = _mm_mul_ps(swp00, swp01);
751 let mul01 = _mm_mul_ps(swp02, swp03);
752 _mm_sub_ps(mul00, mul01)
753 };
754 let fac5 = {
755 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
756 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
757
758 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
759 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
760 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
761 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
762
763 let mul00 = _mm_mul_ps(swp00, swp01);
764 let mul01 = _mm_mul_ps(swp02, swp03);
765 _mm_sub_ps(mul00, mul01)
766 };
767 let sign_a = _mm_set_ps(1.0, -1.0, 1.0, -1.0);
768 let sign_b = _mm_set_ps(-1.0, 1.0, -1.0, 1.0);
769
770 let temp0 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b00_00_00_00);
771 let vec0 = _mm_shuffle_ps(temp0, temp0, 0b10_10_10_00);
772
773 let temp1 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b01_01_01_01);
774 let vec1 = _mm_shuffle_ps(temp1, temp1, 0b10_10_10_00);
775
776 let temp2 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b10_10_10_10);
777 let vec2 = _mm_shuffle_ps(temp2, temp2, 0b10_10_10_00);
778
779 let temp3 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b11_11_11_11);
780 let vec3 = _mm_shuffle_ps(temp3, temp3, 0b10_10_10_00);
781
782 let mul00 = _mm_mul_ps(vec1, fac0);
783 let mul01 = _mm_mul_ps(vec2, fac1);
784 let mul02 = _mm_mul_ps(vec3, fac2);
785 let sub00 = _mm_sub_ps(mul00, mul01);
786 let add00 = _mm_add_ps(sub00, mul02);
787 let inv0 = _mm_mul_ps(sign_b, add00);
788
789 let mul03 = _mm_mul_ps(vec0, fac0);
790 let mul04 = _mm_mul_ps(vec2, fac3);
791 let mul05 = _mm_mul_ps(vec3, fac4);
792 let sub01 = _mm_sub_ps(mul03, mul04);
793 let add01 = _mm_add_ps(sub01, mul05);
794 let inv1 = _mm_mul_ps(sign_a, add01);
795
796 let mul06 = _mm_mul_ps(vec0, fac1);
797 let mul07 = _mm_mul_ps(vec1, fac3);
798 let mul08 = _mm_mul_ps(vec3, fac5);
799 let sub02 = _mm_sub_ps(mul06, mul07);
800 let add02 = _mm_add_ps(sub02, mul08);
801 let inv2 = _mm_mul_ps(sign_b, add02);
802
803 let mul09 = _mm_mul_ps(vec0, fac2);
804 let mul10 = _mm_mul_ps(vec1, fac4);
805 let mul11 = _mm_mul_ps(vec2, fac5);
806 let sub03 = _mm_sub_ps(mul09, mul10);
807 let add03 = _mm_add_ps(sub03, mul11);
808 let inv3 = _mm_mul_ps(sign_a, add03);
809
810 let row0 = _mm_shuffle_ps(inv0, inv1, 0b00_00_00_00);
811 let row1 = _mm_shuffle_ps(inv2, inv3, 0b00_00_00_00);
812 let row2 = _mm_shuffle_ps(row0, row1, 0b10_00_10_00);
813
814 let dot0 = dot4(self.x_axis.0, row2);
815
816 if CHECKED {
817 if dot0 == 0.0 {
818 return (Self::ZERO, false);
819 }
820 } else {
821 glam_assert!(dot0 != 0.0);
822 }
823
824 let rcp0 = _mm_set1_ps(dot0.recip());
825
826 (
827 Self {
828 x_axis: Vec4(_mm_mul_ps(inv0, rcp0)),
829 y_axis: Vec4(_mm_mul_ps(inv1, rcp0)),
830 z_axis: Vec4(_mm_mul_ps(inv2, rcp0)),
831 w_axis: Vec4(_mm_mul_ps(inv3, rcp0)),
832 },
833 true,
834 )
835 }
836 }
837
838 #[must_use]
846 pub fn inverse(&self) -> Self {
847 self.inverse_checked::<false>().0
848 }
849
850 #[must_use]
852 pub fn try_inverse(&self) -> Option<Self> {
853 let (m, is_valid) = self.inverse_checked::<true>();
854 if is_valid {
855 Some(m)
856 } else {
857 None
858 }
859 }
860
861 #[must_use]
863 pub fn inverse_or_zero(&self) -> Self {
864 self.inverse_checked::<true>().0
865 }
866
867 #[deprecated(
876 since = "0.33.1",
877 note = "use the `glam::camera::lh::view::look_to_mat4` function instead"
878 )]
879 #[inline]
880 #[must_use]
881 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
882 #[allow(deprecated)]
883 Self::look_to_rh(eye, -dir, up)
884 }
885
886 #[deprecated(
895 since = "0.33.1",
896 note = "use the `glam::camera::rh::view::look_to_mat4` function instead"
897 )]
898 #[inline]
899 #[must_use]
900 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
901 glam_assert!(dir.is_normalized());
902 glam_assert!(up.is_normalized());
903 let f = dir;
904 let s = f.cross(up).normalize();
905 let u = s.cross(f);
906
907 Self::from_cols(
908 Vec4::new(s.x, u.x, -f.x, 0.0),
909 Vec4::new(s.y, u.y, -f.y, 0.0),
910 Vec4::new(s.z, u.z, -f.z, 0.0),
911 Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
912 )
913 }
914
915 #[deprecated(
924 since = "0.33.1",
925 note = "use the `glam::camera::lh::view::look_at_mat4` function instead"
926 )]
927 #[inline]
928 #[must_use]
929 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
930 #[allow(deprecated)]
931 Self::look_to_lh(eye, center.sub(eye).normalize(), up)
932 }
933
934 #[deprecated(
943 since = "0.33.1",
944 note = "use the `glam::camera::rh::view::look_at_mat4` function instead"
945 )]
946 #[inline]
947 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
948 #[allow(deprecated)]
949 Self::look_to_rh(eye, center.sub(eye).normalize(), up)
950 }
951
952 #[deprecated(
958 since = "0.33.1",
959 note = "use the `glam::camera::rh::proj::opengl::frustum` function instead"
960 )]
961 #[inline]
962 #[must_use]
963 pub fn frustum_rh_gl(
964 left: f32,
965 right: f32,
966 bottom: f32,
967 top: f32,
968 z_near: f32,
969 z_far: f32,
970 ) -> Self {
971 let inv_width = 1.0 / (right - left);
972 let inv_height = 1.0 / (top - bottom);
973 let inv_depth = 1.0 / (z_far - z_near);
974 let a = (right + left) * inv_width;
975 let b = (top + bottom) * inv_height;
976 let c = -(z_far + z_near) * inv_depth;
977 let d = -(2.0 * z_far * z_near) * inv_depth;
978 let two_z_near = 2.0 * z_near;
979 Self::from_cols(
980 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
981 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
982 Vec4::new(a, b, c, -1.0),
983 Vec4::new(0.0, 0.0, d, 0.0),
984 )
985 }
986
987 #[deprecated(
994 since = "0.33.1",
995 note = "use the `glam::camera::lh::proj::directx::frustum` function instead"
996 )]
997 #[inline]
998 #[must_use]
999 pub fn frustum_lh(
1000 left: f32,
1001 right: f32,
1002 bottom: f32,
1003 top: f32,
1004 z_near: f32,
1005 z_far: f32,
1006 ) -> Self {
1007 glam_assert!(z_near > 0.0 && z_far > 0.0);
1008 let inv_width = 1.0 / (right - left);
1009 let inv_height = 1.0 / (top - bottom);
1010 let inv_depth = 1.0 / (z_far - z_near);
1011 let a = (right + left) * inv_width;
1012 let b = (top + bottom) * inv_height;
1013 let c = z_far * inv_depth;
1014 let d = -(z_far * z_near) * inv_depth;
1015 let two_z_near = 2.0 * z_near;
1016 Self::from_cols(
1017 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
1018 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
1019 Vec4::new(a, b, c, 1.0),
1020 Vec4::new(0.0, 0.0, d, 0.0),
1021 )
1022 }
1023
1024 #[deprecated(
1031 since = "0.33.1",
1032 note = "use the `glam::camera::rh::proj::directx::frustum` function instead"
1033 )]
1034 #[inline]
1035 #[must_use]
1036 pub fn frustum_rh(
1037 left: f32,
1038 right: f32,
1039 bottom: f32,
1040 top: f32,
1041 z_near: f32,
1042 z_far: f32,
1043 ) -> Self {
1044 glam_assert!(z_near > 0.0 && z_far > 0.0);
1045 let inv_width = 1.0 / (right - left);
1046 let inv_height = 1.0 / (top - bottom);
1047 let inv_depth = 1.0 / (z_far - z_near);
1048 let a = (right + left) * inv_width;
1049 let b = (top + bottom) * inv_height;
1050 let c = -z_far * inv_depth;
1051 let d = -(z_far * z_near) * inv_depth;
1052 let two_z_near = 2.0 * z_near;
1053 Self::from_cols(
1054 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
1055 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
1056 Vec4::new(a, b, c, -1.0),
1057 Vec4::new(0.0, 0.0, d, 0.0),
1058 )
1059 }
1060
1061 #[deprecated(
1068 since = "0.33.1",
1069 note = "use the `glam::camera::rh::proj::opengl::perspective` function instead"
1070 )]
1071 #[inline]
1072 #[must_use]
1073 pub fn perspective_rh_gl(
1074 fov_y_radians: f32,
1075 aspect_ratio: f32,
1076 z_near: f32,
1077 z_far: f32,
1078 ) -> Self {
1079 let inv_length = 1.0 / (z_near - z_far);
1080 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1081 let a = f / aspect_ratio;
1082 let b = (z_near + z_far) * inv_length;
1083 let c = (2.0 * z_near * z_far) * inv_length;
1084 Self::from_cols(
1085 Vec4::new(a, 0.0, 0.0, 0.0),
1086 Vec4::new(0.0, f, 0.0, 0.0),
1087 Vec4::new(0.0, 0.0, b, -1.0),
1088 Vec4::new(0.0, 0.0, c, 0.0),
1089 )
1090 }
1091
1092 #[deprecated(
1101 since = "0.33.1",
1102 note = "use the `glam::camera::lh::proj::directx::perspective` function instead"
1103 )]
1104 #[inline]
1105 #[must_use]
1106 pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
1107 glam_assert!(z_near > 0.0 && z_far > 0.0);
1108 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1109 let h = cos_fov / sin_fov;
1110 let w = h / aspect_ratio;
1111 let r = z_far / (z_far - z_near);
1112 Self::from_cols(
1113 Vec4::new(w, 0.0, 0.0, 0.0),
1114 Vec4::new(0.0, h, 0.0, 0.0),
1115 Vec4::new(0.0, 0.0, r, 1.0),
1116 Vec4::new(0.0, 0.0, -r * z_near, 0.0),
1117 )
1118 }
1119
1120 #[deprecated(
1129 since = "0.33.1",
1130 note = "use the `glam::camera::rh::proj::directx::perspective` function instead"
1131 )]
1132 #[inline]
1133 #[must_use]
1134 pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
1135 glam_assert!(z_near > 0.0 && z_far > 0.0);
1136 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1137 let h = cos_fov / sin_fov;
1138 let w = h / aspect_ratio;
1139 let r = z_far / (z_near - z_far);
1140 Self::from_cols(
1141 Vec4::new(w, 0.0, 0.0, 0.0),
1142 Vec4::new(0.0, h, 0.0, 0.0),
1143 Vec4::new(0.0, 0.0, r, -1.0),
1144 Vec4::new(0.0, 0.0, r * z_near, 0.0),
1145 )
1146 }
1147
1148 #[deprecated(
1158 since = "0.33.1",
1159 note = "use the `glam::camera::lh::proj::directx::perspective_infinite` function instead"
1160 )]
1161 #[inline]
1162 #[must_use]
1163 pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1164 glam_assert!(z_near > 0.0);
1165 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1166 let h = cos_fov / sin_fov;
1167 let w = h / aspect_ratio;
1168 Self::from_cols(
1169 Vec4::new(w, 0.0, 0.0, 0.0),
1170 Vec4::new(0.0, h, 0.0, 0.0),
1171 Vec4::new(0.0, 0.0, 1.0, 1.0),
1172 Vec4::new(0.0, 0.0, -z_near, 0.0),
1173 )
1174 }
1175
1176 #[deprecated(
1184 since = "0.33.1",
1185 note = "use the `glam::camera::lh::proj::directx::perspective_infinite_reverse` function instead"
1186 )]
1187 #[inline]
1188 #[must_use]
1189 pub fn perspective_infinite_reverse_lh(
1190 fov_y_radians: f32,
1191 aspect_ratio: f32,
1192 z_near: f32,
1193 ) -> Self {
1194 glam_assert!(z_near > 0.0);
1195 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1196 let h = cos_fov / sin_fov;
1197 let w = h / aspect_ratio;
1198 Self::from_cols(
1199 Vec4::new(w, 0.0, 0.0, 0.0),
1200 Vec4::new(0.0, h, 0.0, 0.0),
1201 Vec4::new(0.0, 0.0, 0.0, 1.0),
1202 Vec4::new(0.0, 0.0, z_near, 0.0),
1203 )
1204 }
1205
1206 #[deprecated(
1216 since = "0.33.1",
1217 note = "use the `glam::camera::rh::proj::directx::perspective_infinite` function instead"
1218 )]
1219 #[inline]
1220 #[must_use]
1221 pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1222 glam_assert!(z_near > 0.0);
1223 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1224 Self::from_cols(
1225 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1226 Vec4::new(0.0, f, 0.0, 0.0),
1227 Vec4::new(0.0, 0.0, -1.0, -1.0),
1228 Vec4::new(0.0, 0.0, -z_near, 0.0),
1229 )
1230 }
1231
1232 #[deprecated(
1240 since = "0.33.1",
1241 note = "use the `glam::camera::rh::proj::directx::perspective_infinite_reverse` function instead"
1242 )]
1243 #[inline]
1244 #[must_use]
1245 pub fn perspective_infinite_reverse_rh(
1246 fov_y_radians: f32,
1247 aspect_ratio: f32,
1248 z_near: f32,
1249 ) -> Self {
1250 glam_assert!(z_near > 0.0);
1251 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1252 Self::from_cols(
1253 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1254 Vec4::new(0.0, f, 0.0, 0.0),
1255 Vec4::new(0.0, 0.0, 0.0, -1.0),
1256 Vec4::new(0.0, 0.0, z_near, 0.0),
1257 )
1258 }
1259
1260 #[deprecated(
1267 since = "0.33.1",
1268 note = "use the `glam::camera::rh::proj::opengl::orthographic` function instead"
1269 )]
1270 #[inline]
1271 #[must_use]
1272 pub fn orthographic_rh_gl(
1273 left: f32,
1274 right: f32,
1275 bottom: f32,
1276 top: f32,
1277 near: f32,
1278 far: f32,
1279 ) -> Self {
1280 let a = 2.0 / (right - left);
1281 let b = 2.0 / (top - bottom);
1282 let c = 2.0 / (near - far);
1283 let tx = -(right + left) / (right - left);
1284 let ty = -(top + bottom) / (top - bottom);
1285 let tz = -(far + near) / (far - near);
1286
1287 Self::from_cols(
1288 Vec4::new(a, 0.0, 0.0, 0.0),
1289 Vec4::new(0.0, b, 0.0, 0.0),
1290 Vec4::new(0.0, 0.0, c, 0.0),
1291 Vec4::new(tx, ty, tz, 1.0),
1292 )
1293 }
1294
1295 #[deprecated(
1299 since = "0.33.1",
1300 note = "use the `glam::camera::lh::proj::directx::orthographic` function instead"
1301 )]
1302 #[inline]
1303 #[must_use]
1304 pub fn orthographic_lh(
1305 left: f32,
1306 right: f32,
1307 bottom: f32,
1308 top: f32,
1309 near: f32,
1310 far: f32,
1311 ) -> Self {
1312 let rcp_width = 1.0 / (right - left);
1313 let rcp_height = 1.0 / (top - bottom);
1314 let r = 1.0 / (far - near);
1315 Self::from_cols(
1316 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1317 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1318 Vec4::new(0.0, 0.0, r, 0.0),
1319 Vec4::new(
1320 -(left + right) * rcp_width,
1321 -(top + bottom) * rcp_height,
1322 -r * near,
1323 1.0,
1324 ),
1325 )
1326 }
1327
1328 #[deprecated(
1332 since = "0.33.1",
1333 note = "use the `glam::camera::rh::proj::directx::orthographic` function instead"
1334 )]
1335 #[inline]
1336 #[must_use]
1337 pub fn orthographic_rh(
1338 left: f32,
1339 right: f32,
1340 bottom: f32,
1341 top: f32,
1342 near: f32,
1343 far: f32,
1344 ) -> Self {
1345 let rcp_width = 1.0 / (right - left);
1346 let rcp_height = 1.0 / (top - bottom);
1347 let r = 1.0 / (near - far);
1348 Self::from_cols(
1349 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1350 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1351 Vec4::new(0.0, 0.0, r, 0.0),
1352 Vec4::new(
1353 -(left + right) * rcp_width,
1354 -(top + bottom) * rcp_height,
1355 r * near,
1356 1.0,
1357 ),
1358 )
1359 }
1360
1361 #[inline]
1368 #[must_use]
1369 pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
1370 let mut res = self.x_axis.mul(rhs.x);
1371 res = self.y_axis.mul(rhs.y).add(res);
1372 res = self.z_axis.mul(rhs.z).add(res);
1373 res = self.w_axis.add(res);
1374 res = res.div(res.w);
1375 res.xyz()
1376 }
1377
1378 #[inline]
1391 #[must_use]
1392 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1393 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1394 let mut res = self.x_axis.mul(rhs.x);
1395 res = self.y_axis.mul(rhs.y).add(res);
1396 res = self.z_axis.mul(rhs.z).add(res);
1397 res = self.w_axis.add(res);
1398 res.xyz()
1399 }
1400
1401 #[inline]
1412 #[must_use]
1413 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1414 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1415 let mut res = self.x_axis.mul(rhs.x);
1416 res = self.y_axis.mul(rhs.y).add(res);
1417 res = self.z_axis.mul(rhs.z).add(res);
1418 res.xyz()
1419 }
1420
1421 #[inline]
1428 #[must_use]
1429 pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
1430 let mut res = self.x_axis.mul(rhs.xxxx());
1431 res = self.y_axis.mul(rhs.yyyy()).add(res);
1432 res = self.z_axis.mul(rhs.zzzz()).add(res);
1433 res = self.w_axis.add(res);
1434 res = res.div(res.wwww());
1435 Vec3A::from_vec4(res)
1436 }
1437
1438 #[inline]
1442 #[must_use]
1443 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1444 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1445 let mut res = self.x_axis.mul(rhs.xxxx());
1446 res = self.y_axis.mul(rhs.yyyy()).add(res);
1447 res = self.z_axis.mul(rhs.zzzz()).add(res);
1448 res = self.w_axis.add(res);
1449 Vec3A::from_vec4(res)
1450 }
1451
1452 #[inline]
1456 #[must_use]
1457 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1458 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1459 let mut res = self.x_axis.mul(rhs.xxxx());
1460 res = self.y_axis.mul(rhs.yyyy()).add(res);
1461 res = self.z_axis.mul(rhs.zzzz()).add(res);
1462 Vec3A::from_vec4(res)
1463 }
1464
1465 #[inline]
1467 #[must_use]
1468 pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1469 let mut res = self.x_axis.mul(rhs.xxxx());
1470 res = res.add(self.y_axis.mul(rhs.yyyy()));
1471 res = res.add(self.z_axis.mul(rhs.zzzz()));
1472 res = res.add(self.w_axis.mul(rhs.wwww()));
1473 res
1474 }
1475
1476 #[inline]
1478 #[must_use]
1479 pub fn mul_transpose_vec4(&self, rhs: Vec4) -> Vec4 {
1480 Vec4::new(
1481 self.x_axis.dot(rhs),
1482 self.y_axis.dot(rhs),
1483 self.z_axis.dot(rhs),
1484 self.w_axis.dot(rhs),
1485 )
1486 }
1487
1488 #[inline]
1490 #[must_use]
1491 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1492 self.mul(rhs)
1493 }
1494
1495 #[inline]
1497 #[must_use]
1498 pub fn add_mat4(&self, rhs: &Self) -> Self {
1499 self.add(rhs)
1500 }
1501
1502 #[inline]
1504 #[must_use]
1505 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1506 self.sub(rhs)
1507 }
1508
1509 #[inline]
1511 #[must_use]
1512 pub fn mul_scalar(&self, rhs: f32) -> Self {
1513 Self::from_cols(
1514 self.x_axis.mul(rhs),
1515 self.y_axis.mul(rhs),
1516 self.z_axis.mul(rhs),
1517 self.w_axis.mul(rhs),
1518 )
1519 }
1520
1521 #[inline]
1525 #[must_use]
1526 pub fn mul_diagonal_scale(&self, scale: Vec4) -> Self {
1527 Self::from_cols(
1528 self.x_axis * scale.x,
1529 self.y_axis * scale.y,
1530 self.z_axis * scale.z,
1531 self.w_axis * scale.w,
1532 )
1533 }
1534
1535 #[inline]
1537 #[must_use]
1538 pub fn div_scalar(&self, rhs: f32) -> Self {
1539 let rhs = Vec4::splat(rhs);
1540 Self::from_cols(
1541 self.x_axis.div(rhs),
1542 self.y_axis.div(rhs),
1543 self.z_axis.div(rhs),
1544 self.w_axis.div(rhs),
1545 )
1546 }
1547
1548 #[inline]
1550 #[must_use]
1551 pub fn recip(&self) -> Self {
1552 Self::from_cols(
1553 self.x_axis.recip(),
1554 self.y_axis.recip(),
1555 self.z_axis.recip(),
1556 self.w_axis.recip(),
1557 )
1558 }
1559
1560 #[inline]
1570 #[must_use]
1571 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1572 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1573 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1574 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1575 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1576 }
1577
1578 #[inline]
1580 #[must_use]
1581 pub fn abs(&self) -> Self {
1582 Self::from_cols(
1583 self.x_axis.abs(),
1584 self.y_axis.abs(),
1585 self.z_axis.abs(),
1586 self.w_axis.abs(),
1587 )
1588 }
1589
1590 #[cfg(feature = "f64")]
1591 #[inline]
1592 #[must_use]
1593 pub fn as_dmat4(&self) -> DMat4 {
1594 DMat4::from_cols(
1595 self.x_axis.as_dvec4(),
1596 self.y_axis.as_dvec4(),
1597 self.z_axis.as_dvec4(),
1598 self.w_axis.as_dvec4(),
1599 )
1600 }
1601}
1602
1603impl Default for Mat4 {
1604 #[inline]
1605 fn default() -> Self {
1606 Self::IDENTITY
1607 }
1608}
1609
1610impl Add for Mat4 {
1611 type Output = Self;
1612 #[inline]
1613 fn add(self, rhs: Self) -> Self {
1614 Self::from_cols(
1615 self.x_axis.add(rhs.x_axis),
1616 self.y_axis.add(rhs.y_axis),
1617 self.z_axis.add(rhs.z_axis),
1618 self.w_axis.add(rhs.w_axis),
1619 )
1620 }
1621}
1622
1623impl Add<&Self> for Mat4 {
1624 type Output = Self;
1625 #[inline]
1626 fn add(self, rhs: &Self) -> Self {
1627 self.add(*rhs)
1628 }
1629}
1630
1631impl Add<&Mat4> for &Mat4 {
1632 type Output = Mat4;
1633 #[inline]
1634 fn add(self, rhs: &Mat4) -> Mat4 {
1635 (*self).add(*rhs)
1636 }
1637}
1638
1639impl Add<Mat4> for &Mat4 {
1640 type Output = Mat4;
1641 #[inline]
1642 fn add(self, rhs: Mat4) -> Mat4 {
1643 (*self).add(rhs)
1644 }
1645}
1646
1647impl AddAssign for Mat4 {
1648 #[inline]
1649 fn add_assign(&mut self, rhs: Self) {
1650 *self = self.add(rhs);
1651 }
1652}
1653
1654impl AddAssign<&Self> for Mat4 {
1655 #[inline]
1656 fn add_assign(&mut self, rhs: &Self) {
1657 self.add_assign(*rhs);
1658 }
1659}
1660
1661impl Sub for Mat4 {
1662 type Output = Self;
1663 #[inline]
1664 fn sub(self, rhs: Self) -> Self {
1665 Self::from_cols(
1666 self.x_axis.sub(rhs.x_axis),
1667 self.y_axis.sub(rhs.y_axis),
1668 self.z_axis.sub(rhs.z_axis),
1669 self.w_axis.sub(rhs.w_axis),
1670 )
1671 }
1672}
1673
1674impl Sub<&Self> for Mat4 {
1675 type Output = Self;
1676 #[inline]
1677 fn sub(self, rhs: &Self) -> Self {
1678 self.sub(*rhs)
1679 }
1680}
1681
1682impl Sub<&Mat4> for &Mat4 {
1683 type Output = Mat4;
1684 #[inline]
1685 fn sub(self, rhs: &Mat4) -> Mat4 {
1686 (*self).sub(*rhs)
1687 }
1688}
1689
1690impl Sub<Mat4> for &Mat4 {
1691 type Output = Mat4;
1692 #[inline]
1693 fn sub(self, rhs: Mat4) -> Mat4 {
1694 (*self).sub(rhs)
1695 }
1696}
1697
1698impl SubAssign for Mat4 {
1699 #[inline]
1700 fn sub_assign(&mut self, rhs: Self) {
1701 *self = self.sub(rhs);
1702 }
1703}
1704
1705impl SubAssign<&Self> for Mat4 {
1706 #[inline]
1707 fn sub_assign(&mut self, rhs: &Self) {
1708 self.sub_assign(*rhs);
1709 }
1710}
1711
1712impl Neg for Mat4 {
1713 type Output = Self;
1714 #[inline]
1715 fn neg(self) -> Self::Output {
1716 Self::from_cols(
1717 self.x_axis.neg(),
1718 self.y_axis.neg(),
1719 self.z_axis.neg(),
1720 self.w_axis.neg(),
1721 )
1722 }
1723}
1724
1725impl Neg for &Mat4 {
1726 type Output = Mat4;
1727 #[inline]
1728 fn neg(self) -> Mat4 {
1729 (*self).neg()
1730 }
1731}
1732
1733impl Mul for Mat4 {
1734 type Output = Self;
1735 #[inline]
1736 fn mul(self, rhs: Self) -> Self {
1737 Self::from_cols(
1738 self.mul(rhs.x_axis),
1739 self.mul(rhs.y_axis),
1740 self.mul(rhs.z_axis),
1741 self.mul(rhs.w_axis),
1742 )
1743 }
1744}
1745
1746impl Mul<&Self> for Mat4 {
1747 type Output = Self;
1748 #[inline]
1749 fn mul(self, rhs: &Self) -> Self {
1750 self.mul(*rhs)
1751 }
1752}
1753
1754impl Mul<&Mat4> for &Mat4 {
1755 type Output = Mat4;
1756 #[inline]
1757 fn mul(self, rhs: &Mat4) -> Mat4 {
1758 (*self).mul(*rhs)
1759 }
1760}
1761
1762impl Mul<Mat4> for &Mat4 {
1763 type Output = Mat4;
1764 #[inline]
1765 fn mul(self, rhs: Mat4) -> Mat4 {
1766 (*self).mul(rhs)
1767 }
1768}
1769
1770impl MulAssign for Mat4 {
1771 #[inline]
1772 fn mul_assign(&mut self, rhs: Self) {
1773 *self = self.mul(rhs);
1774 }
1775}
1776
1777impl MulAssign<&Self> for Mat4 {
1778 #[inline]
1779 fn mul_assign(&mut self, rhs: &Self) {
1780 self.mul_assign(*rhs);
1781 }
1782}
1783
1784impl Mul<Vec4> for Mat4 {
1785 type Output = Vec4;
1786 #[inline]
1787 fn mul(self, rhs: Vec4) -> Self::Output {
1788 self.mul_vec4(rhs)
1789 }
1790}
1791
1792impl Mul<&Vec4> for Mat4 {
1793 type Output = Vec4;
1794 #[inline]
1795 fn mul(self, rhs: &Vec4) -> Vec4 {
1796 self.mul(*rhs)
1797 }
1798}
1799
1800impl Mul<&Vec4> for &Mat4 {
1801 type Output = Vec4;
1802 #[inline]
1803 fn mul(self, rhs: &Vec4) -> Vec4 {
1804 (*self).mul(*rhs)
1805 }
1806}
1807
1808impl Mul<Vec4> for &Mat4 {
1809 type Output = Vec4;
1810 #[inline]
1811 fn mul(self, rhs: Vec4) -> Vec4 {
1812 (*self).mul(rhs)
1813 }
1814}
1815
1816impl Mul<Mat4> for f32 {
1817 type Output = Mat4;
1818 #[inline]
1819 fn mul(self, rhs: Mat4) -> Self::Output {
1820 rhs.mul_scalar(self)
1821 }
1822}
1823
1824impl Mul<&Mat4> for f32 {
1825 type Output = Mat4;
1826 #[inline]
1827 fn mul(self, rhs: &Mat4) -> Mat4 {
1828 self.mul(*rhs)
1829 }
1830}
1831
1832impl Mul<&Mat4> for &f32 {
1833 type Output = Mat4;
1834 #[inline]
1835 fn mul(self, rhs: &Mat4) -> Mat4 {
1836 (*self).mul(*rhs)
1837 }
1838}
1839
1840impl Mul<Mat4> for &f32 {
1841 type Output = Mat4;
1842 #[inline]
1843 fn mul(self, rhs: Mat4) -> Mat4 {
1844 (*self).mul(rhs)
1845 }
1846}
1847
1848impl Mul<f32> for Mat4 {
1849 type Output = Self;
1850 #[inline]
1851 fn mul(self, rhs: f32) -> Self {
1852 self.mul_scalar(rhs)
1853 }
1854}
1855
1856impl Mul<&f32> for Mat4 {
1857 type Output = Self;
1858 #[inline]
1859 fn mul(self, rhs: &f32) -> Self {
1860 self.mul(*rhs)
1861 }
1862}
1863
1864impl Mul<&f32> for &Mat4 {
1865 type Output = Mat4;
1866 #[inline]
1867 fn mul(self, rhs: &f32) -> Mat4 {
1868 (*self).mul(*rhs)
1869 }
1870}
1871
1872impl Mul<f32> for &Mat4 {
1873 type Output = Mat4;
1874 #[inline]
1875 fn mul(self, rhs: f32) -> Mat4 {
1876 (*self).mul(rhs)
1877 }
1878}
1879
1880impl MulAssign<f32> for Mat4 {
1881 #[inline]
1882 fn mul_assign(&mut self, rhs: f32) {
1883 *self = self.mul(rhs);
1884 }
1885}
1886
1887impl MulAssign<&f32> for Mat4 {
1888 #[inline]
1889 fn mul_assign(&mut self, rhs: &f32) {
1890 self.mul_assign(*rhs);
1891 }
1892}
1893
1894impl Div<Mat4> for f32 {
1895 type Output = Mat4;
1896 #[inline]
1897 fn div(self, rhs: Mat4) -> Self::Output {
1898 Mat4::from_cols(
1899 self.div(rhs.x_axis),
1900 self.div(rhs.y_axis),
1901 self.div(rhs.z_axis),
1902 self.div(rhs.w_axis),
1903 )
1904 }
1905}
1906
1907impl Div<&Mat4> for f32 {
1908 type Output = Mat4;
1909 #[inline]
1910 fn div(self, rhs: &Mat4) -> Mat4 {
1911 self.div(*rhs)
1912 }
1913}
1914
1915impl Div<&Mat4> for &f32 {
1916 type Output = Mat4;
1917 #[inline]
1918 fn div(self, rhs: &Mat4) -> Mat4 {
1919 (*self).div(*rhs)
1920 }
1921}
1922
1923impl Div<Mat4> for &f32 {
1924 type Output = Mat4;
1925 #[inline]
1926 fn div(self, rhs: Mat4) -> Mat4 {
1927 (*self).div(rhs)
1928 }
1929}
1930
1931impl Div<f32> for Mat4 {
1932 type Output = Self;
1933 #[inline]
1934 fn div(self, rhs: f32) -> Self {
1935 self.div_scalar(rhs)
1936 }
1937}
1938
1939impl Div<&f32> for Mat4 {
1940 type Output = Self;
1941 #[inline]
1942 fn div(self, rhs: &f32) -> Self {
1943 self.div(*rhs)
1944 }
1945}
1946
1947impl Div<&f32> for &Mat4 {
1948 type Output = Mat4;
1949 #[inline]
1950 fn div(self, rhs: &f32) -> Mat4 {
1951 (*self).div(*rhs)
1952 }
1953}
1954
1955impl Div<f32> for &Mat4 {
1956 type Output = Mat4;
1957 #[inline]
1958 fn div(self, rhs: f32) -> Mat4 {
1959 (*self).div(rhs)
1960 }
1961}
1962
1963impl DivAssign<f32> for Mat4 {
1964 #[inline]
1965 fn div_assign(&mut self, rhs: f32) {
1966 *self = self.div(rhs);
1967 }
1968}
1969
1970impl DivAssign<&f32> for Mat4 {
1971 #[inline]
1972 fn div_assign(&mut self, rhs: &f32) {
1973 self.div_assign(*rhs);
1974 }
1975}
1976
1977impl Sum<Self> for Mat4 {
1978 fn sum<I>(iter: I) -> Self
1979 where
1980 I: Iterator<Item = Self>,
1981 {
1982 iter.fold(Self::ZERO, Self::add)
1983 }
1984}
1985
1986impl<'a> Sum<&'a Self> for Mat4 {
1987 fn sum<I>(iter: I) -> Self
1988 where
1989 I: Iterator<Item = &'a Self>,
1990 {
1991 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1992 }
1993}
1994
1995impl Product for Mat4 {
1996 fn product<I>(iter: I) -> Self
1997 where
1998 I: Iterator<Item = Self>,
1999 {
2000 iter.fold(Self::IDENTITY, Self::mul)
2001 }
2002}
2003
2004impl<'a> Product<&'a Self> for Mat4 {
2005 fn product<I>(iter: I) -> Self
2006 where
2007 I: Iterator<Item = &'a Self>,
2008 {
2009 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
2010 }
2011}
2012
2013impl PartialEq for Mat4 {
2014 #[inline]
2015 fn eq(&self, rhs: &Self) -> bool {
2016 self.x_axis.eq(&rhs.x_axis)
2017 && self.y_axis.eq(&rhs.y_axis)
2018 && self.z_axis.eq(&rhs.z_axis)
2019 && self.w_axis.eq(&rhs.w_axis)
2020 }
2021}
2022
2023impl AsRef<[f32; 16]> for Mat4 {
2024 #[inline]
2025 fn as_ref(&self) -> &[f32; 16] {
2026 unsafe { &*(self as *const Self as *const [f32; 16]) }
2027 }
2028}
2029
2030impl AsMut<[f32; 16]> for Mat4 {
2031 #[inline]
2032 fn as_mut(&mut self) -> &mut [f32; 16] {
2033 unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
2034 }
2035}
2036
2037impl fmt::Debug for Mat4 {
2038 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2039 fmt.debug_struct(stringify!(Mat4))
2040 .field("x_axis", &self.x_axis)
2041 .field("y_axis", &self.y_axis)
2042 .field("z_axis", &self.z_axis)
2043 .field("w_axis", &self.w_axis)
2044 .finish()
2045 }
2046}
2047
2048impl fmt::Display for Mat4 {
2049 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2050 if let Some(p) = f.precision() {
2051 write!(
2052 f,
2053 "[{:.*}, {:.*}, {:.*}, {:.*}]",
2054 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
2055 )
2056 } else {
2057 write!(
2058 f,
2059 "[{}, {}, {}, {}]",
2060 self.x_axis, self.y_axis, self.z_axis, self.w_axis
2061 )
2062 }
2063 }
2064}