1use crate::{
4 euler::{FromEuler, ToEuler},
5 f32::math,
6 sse2::*,
7 swizzles::*,
8 DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4,
9};
10use core::fmt;
11use core::iter::{Product, Sum};
12use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
13
14#[cfg(target_arch = "x86")]
15use core::arch::x86::*;
16#[cfg(target_arch = "x86_64")]
17use core::arch::x86_64::*;
18
19#[cfg(feature = "zerocopy")]
20use zerocopy_derive::*;
21
22#[inline(always)]
24#[must_use]
25pub const fn mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat4 {
26 Mat4::from_cols(x_axis, y_axis, z_axis, w_axis)
27}
28
29#[derive(Clone, Copy)]
59#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
60#[cfg_attr(
61 feature = "zerocopy",
62 derive(FromBytes, Immutable, IntoBytes, KnownLayout)
63)]
64#[repr(C)]
65pub struct Mat4 {
66 pub x_axis: Vec4,
67 pub y_axis: Vec4,
68 pub z_axis: Vec4,
69 pub w_axis: Vec4,
70}
71
72impl Mat4 {
73 pub const ZERO: Self = Self::from_cols(Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO);
75
76 pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W);
78
79 pub const NAN: Self = Self::from_cols(Vec4::NAN, Vec4::NAN, Vec4::NAN, Vec4::NAN);
81
82 #[allow(clippy::too_many_arguments)]
83 #[inline(always)]
84 #[must_use]
85 const fn new(
86 m00: f32,
87 m01: f32,
88 m02: f32,
89 m03: f32,
90 m10: f32,
91 m11: f32,
92 m12: f32,
93 m13: f32,
94 m20: f32,
95 m21: f32,
96 m22: f32,
97 m23: f32,
98 m30: f32,
99 m31: f32,
100 m32: f32,
101 m33: f32,
102 ) -> Self {
103 Self {
104 x_axis: Vec4::new(m00, m01, m02, m03),
105 y_axis: Vec4::new(m10, m11, m12, m13),
106 z_axis: Vec4::new(m20, m21, m22, m23),
107 w_axis: Vec4::new(m30, m31, m32, m33),
108 }
109 }
110
111 #[inline(always)]
113 #[must_use]
114 pub const fn from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self {
115 Self {
116 x_axis,
117 y_axis,
118 z_axis,
119 w_axis,
120 }
121 }
122
123 #[inline]
127 #[must_use]
128 pub const fn from_cols_array(m: &[f32; 16]) -> Self {
129 Self::new(
130 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],
131 m[14], m[15],
132 )
133 }
134
135 #[inline]
138 #[must_use]
139 pub const fn to_cols_array(&self) -> [f32; 16] {
140 let [x_axis_x, x_axis_y, x_axis_z, x_axis_w] = self.x_axis.to_array();
141 let [y_axis_x, y_axis_y, y_axis_z, y_axis_w] = self.y_axis.to_array();
142 let [z_axis_x, z_axis_y, z_axis_z, z_axis_w] = self.z_axis.to_array();
143 let [w_axis_x, w_axis_y, w_axis_z, w_axis_w] = self.w_axis.to_array();
144
145 [
146 x_axis_x, x_axis_y, x_axis_z, x_axis_w, y_axis_x, y_axis_y, y_axis_z, y_axis_w,
147 z_axis_x, z_axis_y, z_axis_z, z_axis_w, w_axis_x, w_axis_y, w_axis_z, w_axis_w,
148 ]
149 }
150
151 #[inline]
155 #[must_use]
156 pub const fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self {
157 Self::from_cols(
158 Vec4::from_array(m[0]),
159 Vec4::from_array(m[1]),
160 Vec4::from_array(m[2]),
161 Vec4::from_array(m[3]),
162 )
163 }
164
165 #[inline]
168 #[must_use]
169 pub const fn to_cols_array_2d(&self) -> [[f32; 4]; 4] {
170 [
171 self.x_axis.to_array(),
172 self.y_axis.to_array(),
173 self.z_axis.to_array(),
174 self.w_axis.to_array(),
175 ]
176 }
177
178 #[doc(alias = "scale")]
180 #[inline]
181 #[must_use]
182 pub const fn from_diagonal(diagonal: Vec4) -> Self {
183 let [x, y, z, w] = diagonal.to_array();
185 Self::new(
186 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,
187 )
188 }
189
190 #[inline]
191 #[must_use]
192 fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) {
193 glam_assert!(rotation.is_normalized());
194
195 let (x, y, z, w) = rotation.into();
196 let x2 = x + x;
197 let y2 = y + y;
198 let z2 = z + z;
199 let xx = x * x2;
200 let xy = x * y2;
201 let xz = x * z2;
202 let yy = y * y2;
203 let yz = y * z2;
204 let zz = z * z2;
205 let wx = w * x2;
206 let wy = w * y2;
207 let wz = w * z2;
208
209 let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
210 let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
211 let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
212 (x_axis, y_axis, z_axis)
213 }
214
215 #[inline]
225 #[must_use]
226 pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
227 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
228 Self::from_cols(
229 x_axis.mul(scale.x),
230 y_axis.mul(scale.y),
231 z_axis.mul(scale.z),
232 Vec4::from((translation, 1.0)),
233 )
234 }
235
236 #[inline]
245 #[must_use]
246 pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
247 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
248 Self::from_cols(x_axis, y_axis, z_axis, Vec4::from((translation, 1.0)))
249 }
250
251 #[inline]
259 #[must_use]
260 pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
261 let det = self.determinant();
262 glam_assert!(det != 0.0);
263
264 let scale = Vec3::new(
265 self.x_axis.length() * math::signum(det),
266 self.y_axis.length(),
267 self.z_axis.length(),
268 );
269
270 glam_assert!(scale.cmpne(Vec3::ZERO).all());
271
272 let inv_scale = scale.recip();
273
274 let rotation = Quat::from_rotation_axes(
275 self.x_axis.mul(inv_scale.x).xyz(),
276 self.y_axis.mul(inv_scale.y).xyz(),
277 self.z_axis.mul(inv_scale.z).xyz(),
278 );
279
280 let translation = self.w_axis.xyz();
281
282 (scale, rotation, translation)
283 }
284
285 #[inline]
294 #[must_use]
295 pub fn from_quat(rotation: Quat) -> Self {
296 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
297 Self::from_cols(x_axis, y_axis, z_axis, Vec4::W)
298 }
299
300 #[inline]
306 #[must_use]
307 pub fn from_mat3(m: Mat3) -> Self {
308 Self::from_cols(
309 Vec4::from((m.x_axis, 0.0)),
310 Vec4::from((m.y_axis, 0.0)),
311 Vec4::from((m.z_axis, 0.0)),
312 Vec4::W,
313 )
314 }
315
316 #[inline]
321 #[must_use]
322 pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
323 Self::from_cols(
324 Vec4::from((mat3.x_axis, 0.0)),
325 Vec4::from((mat3.y_axis, 0.0)),
326 Vec4::from((mat3.z_axis, 0.0)),
327 Vec4::from((translation, 1.0)),
328 )
329 }
330
331 #[inline]
337 #[must_use]
338 pub fn from_mat3a(m: Mat3A) -> Self {
339 Self::from_cols(
340 Vec4::from((m.x_axis, 0.0)),
341 Vec4::from((m.y_axis, 0.0)),
342 Vec4::from((m.z_axis, 0.0)),
343 Vec4::W,
344 )
345 }
346
347 #[inline]
352 #[must_use]
353 pub fn from_translation(translation: Vec3) -> Self {
354 Self::from_cols(
355 Vec4::X,
356 Vec4::Y,
357 Vec4::Z,
358 Vec4::new(translation.x, translation.y, translation.z, 1.0),
359 )
360 }
361
362 #[inline]
372 #[must_use]
373 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
374 glam_assert!(axis.is_normalized());
375
376 let (sin, cos) = math::sin_cos(angle);
377 let axis_sin = axis.mul(sin);
378 let axis_sq = axis.mul(axis);
379 let omc = 1.0 - cos;
380 let xyomc = axis.x * axis.y * omc;
381 let xzomc = axis.x * axis.z * omc;
382 let yzomc = axis.y * axis.z * omc;
383 Self::from_cols(
384 Vec4::new(
385 axis_sq.x * omc + cos,
386 xyomc + axis_sin.z,
387 xzomc - axis_sin.y,
388 0.0,
389 ),
390 Vec4::new(
391 xyomc - axis_sin.z,
392 axis_sq.y * omc + cos,
393 yzomc + axis_sin.x,
394 0.0,
395 ),
396 Vec4::new(
397 xzomc + axis_sin.y,
398 yzomc - axis_sin.x,
399 axis_sq.z * omc + cos,
400 0.0,
401 ),
402 Vec4::W,
403 )
404 }
405
406 #[inline]
412 #[must_use]
413 pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
414 Self::from_euler_angles(order, a, b, c)
415 }
416
417 #[inline]
427 #[must_use]
428 pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
429 glam_assert!(
430 self.x_axis.xyz().is_normalized()
431 && self.y_axis.xyz().is_normalized()
432 && self.z_axis.xyz().is_normalized()
433 );
434 self.to_euler_angles(order)
435 }
436
437 #[inline]
443 #[must_use]
444 pub fn from_rotation_x(angle: f32) -> Self {
445 let (sina, cosa) = math::sin_cos(angle);
446 Self::from_cols(
447 Vec4::X,
448 Vec4::new(0.0, cosa, sina, 0.0),
449 Vec4::new(0.0, -sina, cosa, 0.0),
450 Vec4::W,
451 )
452 }
453
454 #[inline]
460 #[must_use]
461 pub fn from_rotation_y(angle: f32) -> Self {
462 let (sina, cosa) = math::sin_cos(angle);
463 Self::from_cols(
464 Vec4::new(cosa, 0.0, -sina, 0.0),
465 Vec4::Y,
466 Vec4::new(sina, 0.0, cosa, 0.0),
467 Vec4::W,
468 )
469 }
470
471 #[inline]
477 #[must_use]
478 pub fn from_rotation_z(angle: f32) -> Self {
479 let (sina, cosa) = math::sin_cos(angle);
480 Self::from_cols(
481 Vec4::new(cosa, sina, 0.0, 0.0),
482 Vec4::new(-sina, cosa, 0.0, 0.0),
483 Vec4::Z,
484 Vec4::W,
485 )
486 }
487
488 #[inline]
497 #[must_use]
498 pub fn from_scale(scale: Vec3) -> Self {
499 glam_assert!(scale.cmpne(Vec3::ZERO).any());
501
502 Self::from_cols(
503 Vec4::new(scale.x, 0.0, 0.0, 0.0),
504 Vec4::new(0.0, scale.y, 0.0, 0.0),
505 Vec4::new(0.0, 0.0, scale.z, 0.0),
506 Vec4::W,
507 )
508 }
509
510 #[inline]
516 #[must_use]
517 pub const fn from_cols_slice(slice: &[f32]) -> Self {
518 Self::new(
519 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
520 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
521 )
522 }
523
524 #[inline]
530 pub fn write_cols_to_slice(&self, slice: &mut [f32]) {
531 slice[0] = self.x_axis.x;
532 slice[1] = self.x_axis.y;
533 slice[2] = self.x_axis.z;
534 slice[3] = self.x_axis.w;
535 slice[4] = self.y_axis.x;
536 slice[5] = self.y_axis.y;
537 slice[6] = self.y_axis.z;
538 slice[7] = self.y_axis.w;
539 slice[8] = self.z_axis.x;
540 slice[9] = self.z_axis.y;
541 slice[10] = self.z_axis.z;
542 slice[11] = self.z_axis.w;
543 slice[12] = self.w_axis.x;
544 slice[13] = self.w_axis.y;
545 slice[14] = self.w_axis.z;
546 slice[15] = self.w_axis.w;
547 }
548
549 #[inline]
555 #[must_use]
556 pub fn col(&self, index: usize) -> Vec4 {
557 match index {
558 0 => self.x_axis,
559 1 => self.y_axis,
560 2 => self.z_axis,
561 3 => self.w_axis,
562 _ => panic!("index out of bounds"),
563 }
564 }
565
566 #[inline]
572 pub fn col_mut(&mut self, index: usize) -> &mut Vec4 {
573 match index {
574 0 => &mut self.x_axis,
575 1 => &mut self.y_axis,
576 2 => &mut self.z_axis,
577 3 => &mut self.w_axis,
578 _ => panic!("index out of bounds"),
579 }
580 }
581
582 #[inline]
588 #[must_use]
589 pub fn row(&self, index: usize) -> Vec4 {
590 match index {
591 0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
592 1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
593 2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
594 3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
595 _ => panic!("index out of bounds"),
596 }
597 }
598
599 #[inline]
602 #[must_use]
603 pub fn is_finite(&self) -> bool {
604 self.x_axis.is_finite()
605 && self.y_axis.is_finite()
606 && self.z_axis.is_finite()
607 && self.w_axis.is_finite()
608 }
609
610 #[inline]
612 #[must_use]
613 pub fn is_nan(&self) -> bool {
614 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
615 }
616
617 #[inline]
619 #[must_use]
620 pub fn transpose(&self) -> Self {
621 unsafe {
622 let tmp0 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b01_00_01_00);
624 let tmp1 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b11_10_11_10);
625 let tmp2 = _mm_shuffle_ps(self.z_axis.0, self.w_axis.0, 0b01_00_01_00);
626 let tmp3 = _mm_shuffle_ps(self.z_axis.0, self.w_axis.0, 0b11_10_11_10);
627
628 Self {
629 x_axis: Vec4(_mm_shuffle_ps(tmp0, tmp2, 0b10_00_10_00)),
630 y_axis: Vec4(_mm_shuffle_ps(tmp0, tmp2, 0b11_01_11_01)),
631 z_axis: Vec4(_mm_shuffle_ps(tmp1, tmp3, 0b10_00_10_00)),
632 w_axis: Vec4(_mm_shuffle_ps(tmp1, tmp3, 0b11_01_11_01)),
633 }
634 }
635 }
636
637 #[inline]
639 #[must_use]
640 pub fn diagonal(&self) -> Vec4 {
641 Vec4::new(self.x_axis.x, self.y_axis.y, self.z_axis.z, self.w_axis.w)
642 }
643
644 #[must_use]
646 pub fn determinant(&self) -> f32 {
647 unsafe {
648 let swp2a = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_01_01_10);
650 let swp3a = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b11_10_11_11);
651 let swp2b = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b11_10_11_11);
652 let swp3b = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b00_01_01_10);
653 let swp2c = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_00_01_10);
654 let swp3c = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b01_10_00_00);
655
656 let mula = _mm_mul_ps(swp2a, swp3a);
657 let mulb = _mm_mul_ps(swp2b, swp3b);
658 let mulc = _mm_mul_ps(swp2c, swp3c);
659 let sube = _mm_sub_ps(mula, mulb);
660 let subf = _mm_sub_ps(_mm_movehl_ps(mulc, mulc), mulc);
661
662 let subfaca = _mm_shuffle_ps(sube, sube, 0b10_01_00_00);
663 let swpfaca = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b00_00_00_01);
664 let mulfaca = _mm_mul_ps(swpfaca, subfaca);
665
666 let subtmpb = _mm_shuffle_ps(sube, subf, 0b00_00_11_01);
667 let subfacb = _mm_shuffle_ps(subtmpb, subtmpb, 0b11_01_01_00);
668 let swpfacb = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b01_01_10_10);
669 let mulfacb = _mm_mul_ps(swpfacb, subfacb);
670
671 let subres = _mm_sub_ps(mulfaca, mulfacb);
672 let subtmpc = _mm_shuffle_ps(sube, subf, 0b01_00_10_10);
673 let subfacc = _mm_shuffle_ps(subtmpc, subtmpc, 0b11_11_10_00);
674 let swpfacc = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b10_11_11_11);
675 let mulfacc = _mm_mul_ps(swpfacc, subfacc);
676
677 let addres = _mm_add_ps(subres, mulfacc);
678 let detcof = _mm_mul_ps(addres, _mm_setr_ps(1.0, -1.0, 1.0, -1.0));
679
680 dot4(self.x_axis.0, detcof)
681 }
682 }
683
684 #[inline(always)]
696 #[must_use]
697 fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
698 unsafe {
699 let fac0 = {
701 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
702 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
703
704 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
705 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
706 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
707 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
708
709 let mul00 = _mm_mul_ps(swp00, swp01);
710 let mul01 = _mm_mul_ps(swp02, swp03);
711 _mm_sub_ps(mul00, mul01)
712 };
713 let fac1 = {
714 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
715 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
716
717 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
718 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
719 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
720 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
721
722 let mul00 = _mm_mul_ps(swp00, swp01);
723 let mul01 = _mm_mul_ps(swp02, swp03);
724 _mm_sub_ps(mul00, mul01)
725 };
726 let fac2 = {
727 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
728 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
729
730 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
731 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
732 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
733 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
734
735 let mul00 = _mm_mul_ps(swp00, swp01);
736 let mul01 = _mm_mul_ps(swp02, swp03);
737 _mm_sub_ps(mul00, mul01)
738 };
739 let fac3 = {
740 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
741 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
742
743 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
744 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
745 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
746 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
747
748 let mul00 = _mm_mul_ps(swp00, swp01);
749 let mul01 = _mm_mul_ps(swp02, swp03);
750 _mm_sub_ps(mul00, mul01)
751 };
752 let fac4 = {
753 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
754 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
755
756 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
757 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
758 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
759 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
760
761 let mul00 = _mm_mul_ps(swp00, swp01);
762 let mul01 = _mm_mul_ps(swp02, swp03);
763 _mm_sub_ps(mul00, mul01)
764 };
765 let fac5 = {
766 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
767 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
768
769 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
770 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
771 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
772 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
773
774 let mul00 = _mm_mul_ps(swp00, swp01);
775 let mul01 = _mm_mul_ps(swp02, swp03);
776 _mm_sub_ps(mul00, mul01)
777 };
778 let sign_a = _mm_set_ps(1.0, -1.0, 1.0, -1.0);
779 let sign_b = _mm_set_ps(-1.0, 1.0, -1.0, 1.0);
780
781 let temp0 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b00_00_00_00);
782 let vec0 = _mm_shuffle_ps(temp0, temp0, 0b10_10_10_00);
783
784 let temp1 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b01_01_01_01);
785 let vec1 = _mm_shuffle_ps(temp1, temp1, 0b10_10_10_00);
786
787 let temp2 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b10_10_10_10);
788 let vec2 = _mm_shuffle_ps(temp2, temp2, 0b10_10_10_00);
789
790 let temp3 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b11_11_11_11);
791 let vec3 = _mm_shuffle_ps(temp3, temp3, 0b10_10_10_00);
792
793 let mul00 = _mm_mul_ps(vec1, fac0);
794 let mul01 = _mm_mul_ps(vec2, fac1);
795 let mul02 = _mm_mul_ps(vec3, fac2);
796 let sub00 = _mm_sub_ps(mul00, mul01);
797 let add00 = _mm_add_ps(sub00, mul02);
798 let inv0 = _mm_mul_ps(sign_b, add00);
799
800 let mul03 = _mm_mul_ps(vec0, fac0);
801 let mul04 = _mm_mul_ps(vec2, fac3);
802 let mul05 = _mm_mul_ps(vec3, fac4);
803 let sub01 = _mm_sub_ps(mul03, mul04);
804 let add01 = _mm_add_ps(sub01, mul05);
805 let inv1 = _mm_mul_ps(sign_a, add01);
806
807 let mul06 = _mm_mul_ps(vec0, fac1);
808 let mul07 = _mm_mul_ps(vec1, fac3);
809 let mul08 = _mm_mul_ps(vec3, fac5);
810 let sub02 = _mm_sub_ps(mul06, mul07);
811 let add02 = _mm_add_ps(sub02, mul08);
812 let inv2 = _mm_mul_ps(sign_b, add02);
813
814 let mul09 = _mm_mul_ps(vec0, fac2);
815 let mul10 = _mm_mul_ps(vec1, fac4);
816 let mul11 = _mm_mul_ps(vec2, fac5);
817 let sub03 = _mm_sub_ps(mul09, mul10);
818 let add03 = _mm_add_ps(sub03, mul11);
819 let inv3 = _mm_mul_ps(sign_a, add03);
820
821 let row0 = _mm_shuffle_ps(inv0, inv1, 0b00_00_00_00);
822 let row1 = _mm_shuffle_ps(inv2, inv3, 0b00_00_00_00);
823 let row2 = _mm_shuffle_ps(row0, row1, 0b10_00_10_00);
824
825 let dot0 = dot4(self.x_axis.0, row2);
826
827 if CHECKED {
828 if dot0 == 0.0 {
829 return (Self::ZERO, false);
830 }
831 } else {
832 glam_assert!(dot0 != 0.0);
833 }
834
835 let rcp0 = _mm_set1_ps(dot0.recip());
836
837 (
838 Self {
839 x_axis: Vec4(_mm_mul_ps(inv0, rcp0)),
840 y_axis: Vec4(_mm_mul_ps(inv1, rcp0)),
841 z_axis: Vec4(_mm_mul_ps(inv2, rcp0)),
842 w_axis: Vec4(_mm_mul_ps(inv3, rcp0)),
843 },
844 true,
845 )
846 }
847 }
848
849 #[must_use]
857 pub fn inverse(&self) -> Self {
858 self.inverse_checked::<false>().0
859 }
860
861 #[must_use]
863 pub fn try_inverse(&self) -> Option<Self> {
864 let (m, is_valid) = self.inverse_checked::<true>();
865 if is_valid {
866 Some(m)
867 } else {
868 None
869 }
870 }
871
872 #[must_use]
874 pub fn inverse_or_zero(&self) -> Self {
875 self.inverse_checked::<true>().0
876 }
877
878 #[inline]
887 #[must_use]
888 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
889 Self::look_to_rh(eye, -dir, up)
890 }
891
892 #[inline]
901 #[must_use]
902 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
903 glam_assert!(dir.is_normalized());
904 glam_assert!(up.is_normalized());
905 let f = dir;
906 let s = f.cross(up).normalize();
907 let u = s.cross(f);
908
909 Self::from_cols(
910 Vec4::new(s.x, u.x, -f.x, 0.0),
911 Vec4::new(s.y, u.y, -f.y, 0.0),
912 Vec4::new(s.z, u.z, -f.z, 0.0),
913 Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
914 )
915 }
916
917 #[inline]
926 #[must_use]
927 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
928 Self::look_to_lh(eye, center.sub(eye).normalize(), up)
929 }
930
931 #[inline]
940 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
941 Self::look_to_rh(eye, center.sub(eye).normalize(), up)
942 }
943
944 #[inline]
950 #[must_use]
951 pub fn frustum_rh_gl(
952 left: f32,
953 right: f32,
954 bottom: f32,
955 top: f32,
956 z_near: f32,
957 z_far: f32,
958 ) -> Self {
959 let inv_width = 1.0 / (right - left);
960 let inv_height = 1.0 / (top - bottom);
961 let inv_depth = 1.0 / (z_far - z_near);
962 let a = (right + left) * inv_width;
963 let b = (top + bottom) * inv_height;
964 let c = -(z_far + z_near) * inv_depth;
965 let d = -(2.0 * z_far * z_near) * inv_depth;
966 let two_z_near = 2.0 * z_near;
967 Self::from_cols(
968 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
969 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
970 Vec4::new(a, b, c, -1.0),
971 Vec4::new(0.0, 0.0, d, 0.0),
972 )
973 }
974
975 #[inline]
982 #[must_use]
983 pub fn frustum_lh(
984 left: f32,
985 right: f32,
986 bottom: f32,
987 top: f32,
988 z_near: f32,
989 z_far: f32,
990 ) -> Self {
991 glam_assert!(z_near > 0.0 && z_far > 0.0);
992 let inv_width = 1.0 / (right - left);
993 let inv_height = 1.0 / (top - bottom);
994 let inv_depth = 1.0 / (z_far - z_near);
995 let a = (right + left) * inv_width;
996 let b = (top + bottom) * inv_height;
997 let c = z_far * inv_depth;
998 let d = -(z_far * z_near) * inv_depth;
999 let two_z_near = 2.0 * z_near;
1000 Self::from_cols(
1001 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
1002 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
1003 Vec4::new(a, b, c, 1.0),
1004 Vec4::new(0.0, 0.0, d, 0.0),
1005 )
1006 }
1007
1008 #[inline]
1015 #[must_use]
1016 pub fn frustum_rh(
1017 left: f32,
1018 right: f32,
1019 bottom: f32,
1020 top: f32,
1021 z_near: f32,
1022 z_far: f32,
1023 ) -> Self {
1024 glam_assert!(z_near > 0.0 && z_far > 0.0);
1025 let inv_width = 1.0 / (right - left);
1026 let inv_height = 1.0 / (top - bottom);
1027 let inv_depth = 1.0 / (z_far - z_near);
1028 let a = (right + left) * inv_width;
1029 let b = (top + bottom) * inv_height;
1030 let c = -z_far * inv_depth;
1031 let d = -(z_far * z_near) * inv_depth;
1032 let two_z_near = 2.0 * z_near;
1033 Self::from_cols(
1034 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
1035 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
1036 Vec4::new(a, b, c, -1.0),
1037 Vec4::new(0.0, 0.0, d, 0.0),
1038 )
1039 }
1040
1041 #[inline]
1048 #[must_use]
1049 pub fn perspective_rh_gl(
1050 fov_y_radians: f32,
1051 aspect_ratio: f32,
1052 z_near: f32,
1053 z_far: f32,
1054 ) -> Self {
1055 let inv_length = 1.0 / (z_near - z_far);
1056 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1057 let a = f / aspect_ratio;
1058 let b = (z_near + z_far) * inv_length;
1059 let c = (2.0 * z_near * z_far) * inv_length;
1060 Self::from_cols(
1061 Vec4::new(a, 0.0, 0.0, 0.0),
1062 Vec4::new(0.0, f, 0.0, 0.0),
1063 Vec4::new(0.0, 0.0, b, -1.0),
1064 Vec4::new(0.0, 0.0, c, 0.0),
1065 )
1066 }
1067
1068 #[inline]
1077 #[must_use]
1078 pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
1079 glam_assert!(z_near > 0.0 && z_far > 0.0);
1080 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1081 let h = cos_fov / sin_fov;
1082 let w = h / aspect_ratio;
1083 let r = z_far / (z_far - z_near);
1084 Self::from_cols(
1085 Vec4::new(w, 0.0, 0.0, 0.0),
1086 Vec4::new(0.0, h, 0.0, 0.0),
1087 Vec4::new(0.0, 0.0, r, 1.0),
1088 Vec4::new(0.0, 0.0, -r * z_near, 0.0),
1089 )
1090 }
1091
1092 #[inline]
1101 #[must_use]
1102 pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
1103 glam_assert!(z_near > 0.0 && z_far > 0.0);
1104 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1105 let h = cos_fov / sin_fov;
1106 let w = h / aspect_ratio;
1107 let r = z_far / (z_near - z_far);
1108 Self::from_cols(
1109 Vec4::new(w, 0.0, 0.0, 0.0),
1110 Vec4::new(0.0, h, 0.0, 0.0),
1111 Vec4::new(0.0, 0.0, r, -1.0),
1112 Vec4::new(0.0, 0.0, r * z_near, 0.0),
1113 )
1114 }
1115
1116 #[inline]
1126 #[must_use]
1127 pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1128 glam_assert!(z_near > 0.0);
1129 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1130 let h = cos_fov / sin_fov;
1131 let w = h / aspect_ratio;
1132 Self::from_cols(
1133 Vec4::new(w, 0.0, 0.0, 0.0),
1134 Vec4::new(0.0, h, 0.0, 0.0),
1135 Vec4::new(0.0, 0.0, 1.0, 1.0),
1136 Vec4::new(0.0, 0.0, -z_near, 0.0),
1137 )
1138 }
1139
1140 #[inline]
1148 #[must_use]
1149 pub fn perspective_infinite_reverse_lh(
1150 fov_y_radians: f32,
1151 aspect_ratio: f32,
1152 z_near: f32,
1153 ) -> Self {
1154 glam_assert!(z_near > 0.0);
1155 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1156 let h = cos_fov / sin_fov;
1157 let w = h / aspect_ratio;
1158 Self::from_cols(
1159 Vec4::new(w, 0.0, 0.0, 0.0),
1160 Vec4::new(0.0, h, 0.0, 0.0),
1161 Vec4::new(0.0, 0.0, 0.0, 1.0),
1162 Vec4::new(0.0, 0.0, z_near, 0.0),
1163 )
1164 }
1165
1166 #[inline]
1176 #[must_use]
1177 pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1178 glam_assert!(z_near > 0.0);
1179 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1180 Self::from_cols(
1181 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1182 Vec4::new(0.0, f, 0.0, 0.0),
1183 Vec4::new(0.0, 0.0, -1.0, -1.0),
1184 Vec4::new(0.0, 0.0, -z_near, 0.0),
1185 )
1186 }
1187
1188 #[inline]
1196 #[must_use]
1197 pub fn perspective_infinite_reverse_rh(
1198 fov_y_radians: f32,
1199 aspect_ratio: f32,
1200 z_near: f32,
1201 ) -> Self {
1202 glam_assert!(z_near > 0.0);
1203 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1204 Self::from_cols(
1205 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1206 Vec4::new(0.0, f, 0.0, 0.0),
1207 Vec4::new(0.0, 0.0, 0.0, -1.0),
1208 Vec4::new(0.0, 0.0, z_near, 0.0),
1209 )
1210 }
1211
1212 #[inline]
1219 #[must_use]
1220 pub fn orthographic_rh_gl(
1221 left: f32,
1222 right: f32,
1223 bottom: f32,
1224 top: f32,
1225 near: f32,
1226 far: f32,
1227 ) -> Self {
1228 let a = 2.0 / (right - left);
1229 let b = 2.0 / (top - bottom);
1230 let c = -2.0 / (far - near);
1231 let tx = -(right + left) / (right - left);
1232 let ty = -(top + bottom) / (top - bottom);
1233 let tz = -(far + near) / (far - near);
1234
1235 Self::from_cols(
1236 Vec4::new(a, 0.0, 0.0, 0.0),
1237 Vec4::new(0.0, b, 0.0, 0.0),
1238 Vec4::new(0.0, 0.0, c, 0.0),
1239 Vec4::new(tx, ty, tz, 1.0),
1240 )
1241 }
1242
1243 #[inline]
1247 #[must_use]
1248 pub fn orthographic_lh(
1249 left: f32,
1250 right: f32,
1251 bottom: f32,
1252 top: f32,
1253 near: f32,
1254 far: f32,
1255 ) -> Self {
1256 let rcp_width = 1.0 / (right - left);
1257 let rcp_height = 1.0 / (top - bottom);
1258 let r = 1.0 / (far - near);
1259 Self::from_cols(
1260 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1261 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1262 Vec4::new(0.0, 0.0, r, 0.0),
1263 Vec4::new(
1264 -(left + right) * rcp_width,
1265 -(top + bottom) * rcp_height,
1266 -r * near,
1267 1.0,
1268 ),
1269 )
1270 }
1271
1272 #[inline]
1276 #[must_use]
1277 pub fn orthographic_rh(
1278 left: f32,
1279 right: f32,
1280 bottom: f32,
1281 top: f32,
1282 near: f32,
1283 far: f32,
1284 ) -> Self {
1285 let rcp_width = 1.0 / (right - left);
1286 let rcp_height = 1.0 / (top - bottom);
1287 let r = 1.0 / (near - far);
1288 Self::from_cols(
1289 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1290 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1291 Vec4::new(0.0, 0.0, r, 0.0),
1292 Vec4::new(
1293 -(left + right) * rcp_width,
1294 -(top + bottom) * rcp_height,
1295 r * near,
1296 1.0,
1297 ),
1298 )
1299 }
1300
1301 #[inline]
1308 #[must_use]
1309 pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
1310 let mut res = self.x_axis.mul(rhs.x);
1311 res = self.y_axis.mul(rhs.y).add(res);
1312 res = self.z_axis.mul(rhs.z).add(res);
1313 res = self.w_axis.add(res);
1314 res = res.div(res.w);
1315 res.xyz()
1316 }
1317
1318 #[inline]
1331 #[must_use]
1332 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1333 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1334 let mut res = self.x_axis.mul(rhs.x);
1335 res = self.y_axis.mul(rhs.y).add(res);
1336 res = self.z_axis.mul(rhs.z).add(res);
1337 res = self.w_axis.add(res);
1338 res.xyz()
1339 }
1340
1341 #[inline]
1352 #[must_use]
1353 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1354 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1355 let mut res = self.x_axis.mul(rhs.x);
1356 res = self.y_axis.mul(rhs.y).add(res);
1357 res = self.z_axis.mul(rhs.z).add(res);
1358 res.xyz()
1359 }
1360
1361 #[inline]
1368 #[must_use]
1369 pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
1370 let mut res = self.x_axis.mul(rhs.xxxx());
1371 res = self.y_axis.mul(rhs.yyyy()).add(res);
1372 res = self.z_axis.mul(rhs.zzzz()).add(res);
1373 res = self.w_axis.add(res);
1374 res = res.div(res.wwww());
1375 Vec3A::from_vec4(res)
1376 }
1377
1378 #[inline]
1382 #[must_use]
1383 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1384 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1385 let mut res = self.x_axis.mul(rhs.xxxx());
1386 res = self.y_axis.mul(rhs.yyyy()).add(res);
1387 res = self.z_axis.mul(rhs.zzzz()).add(res);
1388 res = self.w_axis.add(res);
1389 Vec3A::from_vec4(res)
1390 }
1391
1392 #[inline]
1396 #[must_use]
1397 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1398 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1399 let mut res = self.x_axis.mul(rhs.xxxx());
1400 res = self.y_axis.mul(rhs.yyyy()).add(res);
1401 res = self.z_axis.mul(rhs.zzzz()).add(res);
1402 Vec3A::from_vec4(res)
1403 }
1404
1405 #[inline]
1407 #[must_use]
1408 pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1409 let mut res = self.x_axis.mul(rhs.xxxx());
1410 res = res.add(self.y_axis.mul(rhs.yyyy()));
1411 res = res.add(self.z_axis.mul(rhs.zzzz()));
1412 res = res.add(self.w_axis.mul(rhs.wwww()));
1413 res
1414 }
1415
1416 #[inline]
1418 #[must_use]
1419 pub fn mul_transpose_vec4(&self, rhs: Vec4) -> Vec4 {
1420 Vec4::new(
1421 self.x_axis.dot(rhs),
1422 self.y_axis.dot(rhs),
1423 self.z_axis.dot(rhs),
1424 self.w_axis.dot(rhs),
1425 )
1426 }
1427
1428 #[inline]
1430 #[must_use]
1431 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1432 self.mul(rhs)
1433 }
1434
1435 #[inline]
1437 #[must_use]
1438 pub fn add_mat4(&self, rhs: &Self) -> Self {
1439 self.add(rhs)
1440 }
1441
1442 #[inline]
1444 #[must_use]
1445 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1446 self.sub(rhs)
1447 }
1448
1449 #[inline]
1451 #[must_use]
1452 pub fn mul_scalar(&self, rhs: f32) -> Self {
1453 Self::from_cols(
1454 self.x_axis.mul(rhs),
1455 self.y_axis.mul(rhs),
1456 self.z_axis.mul(rhs),
1457 self.w_axis.mul(rhs),
1458 )
1459 }
1460
1461 #[inline]
1465 #[must_use]
1466 pub fn mul_diagonal_scale(&self, scale: Vec4) -> Self {
1467 Self::from_cols(
1468 self.x_axis * scale.x,
1469 self.y_axis * scale.y,
1470 self.z_axis * scale.z,
1471 self.w_axis * scale.w,
1472 )
1473 }
1474
1475 #[inline]
1477 #[must_use]
1478 pub fn div_scalar(&self, rhs: f32) -> Self {
1479 let rhs = Vec4::splat(rhs);
1480 Self::from_cols(
1481 self.x_axis.div(rhs),
1482 self.y_axis.div(rhs),
1483 self.z_axis.div(rhs),
1484 self.w_axis.div(rhs),
1485 )
1486 }
1487
1488 #[inline]
1498 #[must_use]
1499 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1500 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1501 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1502 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1503 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1504 }
1505
1506 #[inline]
1508 #[must_use]
1509 pub fn abs(&self) -> Self {
1510 Self::from_cols(
1511 self.x_axis.abs(),
1512 self.y_axis.abs(),
1513 self.z_axis.abs(),
1514 self.w_axis.abs(),
1515 )
1516 }
1517
1518 #[inline]
1519 pub fn as_dmat4(&self) -> DMat4 {
1520 DMat4::from_cols(
1521 self.x_axis.as_dvec4(),
1522 self.y_axis.as_dvec4(),
1523 self.z_axis.as_dvec4(),
1524 self.w_axis.as_dvec4(),
1525 )
1526 }
1527}
1528
1529impl Default for Mat4 {
1530 #[inline]
1531 fn default() -> Self {
1532 Self::IDENTITY
1533 }
1534}
1535
1536impl Add for Mat4 {
1537 type Output = Self;
1538 #[inline]
1539 fn add(self, rhs: Self) -> Self {
1540 Self::from_cols(
1541 self.x_axis.add(rhs.x_axis),
1542 self.y_axis.add(rhs.y_axis),
1543 self.z_axis.add(rhs.z_axis),
1544 self.w_axis.add(rhs.w_axis),
1545 )
1546 }
1547}
1548
1549impl Add<&Self> for Mat4 {
1550 type Output = Self;
1551 #[inline]
1552 fn add(self, rhs: &Self) -> Self {
1553 self.add(*rhs)
1554 }
1555}
1556
1557impl Add<&Mat4> for &Mat4 {
1558 type Output = Mat4;
1559 #[inline]
1560 fn add(self, rhs: &Mat4) -> Mat4 {
1561 (*self).add(*rhs)
1562 }
1563}
1564
1565impl Add<Mat4> for &Mat4 {
1566 type Output = Mat4;
1567 #[inline]
1568 fn add(self, rhs: Mat4) -> Mat4 {
1569 (*self).add(rhs)
1570 }
1571}
1572
1573impl AddAssign for Mat4 {
1574 #[inline]
1575 fn add_assign(&mut self, rhs: Self) {
1576 *self = self.add(rhs);
1577 }
1578}
1579
1580impl AddAssign<&Self> for Mat4 {
1581 #[inline]
1582 fn add_assign(&mut self, rhs: &Self) {
1583 self.add_assign(*rhs);
1584 }
1585}
1586
1587impl Sub for Mat4 {
1588 type Output = Self;
1589 #[inline]
1590 fn sub(self, rhs: Self) -> Self {
1591 Self::from_cols(
1592 self.x_axis.sub(rhs.x_axis),
1593 self.y_axis.sub(rhs.y_axis),
1594 self.z_axis.sub(rhs.z_axis),
1595 self.w_axis.sub(rhs.w_axis),
1596 )
1597 }
1598}
1599
1600impl Sub<&Self> for Mat4 {
1601 type Output = Self;
1602 #[inline]
1603 fn sub(self, rhs: &Self) -> Self {
1604 self.sub(*rhs)
1605 }
1606}
1607
1608impl Sub<&Mat4> for &Mat4 {
1609 type Output = Mat4;
1610 #[inline]
1611 fn sub(self, rhs: &Mat4) -> Mat4 {
1612 (*self).sub(*rhs)
1613 }
1614}
1615
1616impl Sub<Mat4> for &Mat4 {
1617 type Output = Mat4;
1618 #[inline]
1619 fn sub(self, rhs: Mat4) -> Mat4 {
1620 (*self).sub(rhs)
1621 }
1622}
1623
1624impl SubAssign for Mat4 {
1625 #[inline]
1626 fn sub_assign(&mut self, rhs: Self) {
1627 *self = self.sub(rhs);
1628 }
1629}
1630
1631impl SubAssign<&Self> for Mat4 {
1632 #[inline]
1633 fn sub_assign(&mut self, rhs: &Self) {
1634 self.sub_assign(*rhs);
1635 }
1636}
1637
1638impl Neg for Mat4 {
1639 type Output = Self;
1640 #[inline]
1641 fn neg(self) -> Self::Output {
1642 Self::from_cols(
1643 self.x_axis.neg(),
1644 self.y_axis.neg(),
1645 self.z_axis.neg(),
1646 self.w_axis.neg(),
1647 )
1648 }
1649}
1650
1651impl Neg for &Mat4 {
1652 type Output = Mat4;
1653 #[inline]
1654 fn neg(self) -> Mat4 {
1655 (*self).neg()
1656 }
1657}
1658
1659impl Mul for Mat4 {
1660 type Output = Self;
1661 #[inline]
1662 fn mul(self, rhs: Self) -> Self {
1663 Self::from_cols(
1664 self.mul(rhs.x_axis),
1665 self.mul(rhs.y_axis),
1666 self.mul(rhs.z_axis),
1667 self.mul(rhs.w_axis),
1668 )
1669 }
1670}
1671
1672impl Mul<&Self> for Mat4 {
1673 type Output = Self;
1674 #[inline]
1675 fn mul(self, rhs: &Self) -> Self {
1676 self.mul(*rhs)
1677 }
1678}
1679
1680impl Mul<&Mat4> for &Mat4 {
1681 type Output = Mat4;
1682 #[inline]
1683 fn mul(self, rhs: &Mat4) -> Mat4 {
1684 (*self).mul(*rhs)
1685 }
1686}
1687
1688impl Mul<Mat4> for &Mat4 {
1689 type Output = Mat4;
1690 #[inline]
1691 fn mul(self, rhs: Mat4) -> Mat4 {
1692 (*self).mul(rhs)
1693 }
1694}
1695
1696impl MulAssign for Mat4 {
1697 #[inline]
1698 fn mul_assign(&mut self, rhs: Self) {
1699 *self = self.mul(rhs);
1700 }
1701}
1702
1703impl MulAssign<&Self> for Mat4 {
1704 #[inline]
1705 fn mul_assign(&mut self, rhs: &Self) {
1706 self.mul_assign(*rhs);
1707 }
1708}
1709
1710impl Mul<Vec4> for Mat4 {
1711 type Output = Vec4;
1712 #[inline]
1713 fn mul(self, rhs: Vec4) -> Self::Output {
1714 self.mul_vec4(rhs)
1715 }
1716}
1717
1718impl Mul<&Vec4> for Mat4 {
1719 type Output = Vec4;
1720 #[inline]
1721 fn mul(self, rhs: &Vec4) -> Vec4 {
1722 self.mul(*rhs)
1723 }
1724}
1725
1726impl Mul<&Vec4> for &Mat4 {
1727 type Output = Vec4;
1728 #[inline]
1729 fn mul(self, rhs: &Vec4) -> Vec4 {
1730 (*self).mul(*rhs)
1731 }
1732}
1733
1734impl Mul<Vec4> for &Mat4 {
1735 type Output = Vec4;
1736 #[inline]
1737 fn mul(self, rhs: Vec4) -> Vec4 {
1738 (*self).mul(rhs)
1739 }
1740}
1741
1742impl Mul<Mat4> for f32 {
1743 type Output = Mat4;
1744 #[inline]
1745 fn mul(self, rhs: Mat4) -> Self::Output {
1746 rhs.mul_scalar(self)
1747 }
1748}
1749
1750impl Mul<&Mat4> for f32 {
1751 type Output = Mat4;
1752 #[inline]
1753 fn mul(self, rhs: &Mat4) -> Mat4 {
1754 self.mul(*rhs)
1755 }
1756}
1757
1758impl Mul<&Mat4> for &f32 {
1759 type Output = Mat4;
1760 #[inline]
1761 fn mul(self, rhs: &Mat4) -> Mat4 {
1762 (*self).mul(*rhs)
1763 }
1764}
1765
1766impl Mul<Mat4> for &f32 {
1767 type Output = Mat4;
1768 #[inline]
1769 fn mul(self, rhs: Mat4) -> Mat4 {
1770 (*self).mul(rhs)
1771 }
1772}
1773
1774impl Mul<f32> for Mat4 {
1775 type Output = Self;
1776 #[inline]
1777 fn mul(self, rhs: f32) -> Self {
1778 self.mul_scalar(rhs)
1779 }
1780}
1781
1782impl Mul<&f32> for Mat4 {
1783 type Output = Self;
1784 #[inline]
1785 fn mul(self, rhs: &f32) -> Self {
1786 self.mul(*rhs)
1787 }
1788}
1789
1790impl Mul<&f32> for &Mat4 {
1791 type Output = Mat4;
1792 #[inline]
1793 fn mul(self, rhs: &f32) -> Mat4 {
1794 (*self).mul(*rhs)
1795 }
1796}
1797
1798impl Mul<f32> for &Mat4 {
1799 type Output = Mat4;
1800 #[inline]
1801 fn mul(self, rhs: f32) -> Mat4 {
1802 (*self).mul(rhs)
1803 }
1804}
1805
1806impl MulAssign<f32> for Mat4 {
1807 #[inline]
1808 fn mul_assign(&mut self, rhs: f32) {
1809 *self = self.mul(rhs);
1810 }
1811}
1812
1813impl MulAssign<&f32> for Mat4 {
1814 #[inline]
1815 fn mul_assign(&mut self, rhs: &f32) {
1816 self.mul_assign(*rhs);
1817 }
1818}
1819
1820impl Div<Mat4> for f32 {
1821 type Output = Mat4;
1822 #[inline]
1823 fn div(self, rhs: Mat4) -> Self::Output {
1824 rhs.div_scalar(self)
1825 }
1826}
1827
1828impl Div<&Mat4> for f32 {
1829 type Output = Mat4;
1830 #[inline]
1831 fn div(self, rhs: &Mat4) -> Mat4 {
1832 self.div(*rhs)
1833 }
1834}
1835
1836impl Div<&Mat4> for &f32 {
1837 type Output = Mat4;
1838 #[inline]
1839 fn div(self, rhs: &Mat4) -> Mat4 {
1840 (*self).div(*rhs)
1841 }
1842}
1843
1844impl Div<Mat4> for &f32 {
1845 type Output = Mat4;
1846 #[inline]
1847 fn div(self, rhs: Mat4) -> Mat4 {
1848 (*self).div(rhs)
1849 }
1850}
1851
1852impl Div<f32> for Mat4 {
1853 type Output = Self;
1854 #[inline]
1855 fn div(self, rhs: f32) -> Self {
1856 self.div_scalar(rhs)
1857 }
1858}
1859
1860impl Div<&f32> for Mat4 {
1861 type Output = Self;
1862 #[inline]
1863 fn div(self, rhs: &f32) -> Self {
1864 self.div(*rhs)
1865 }
1866}
1867
1868impl Div<&f32> for &Mat4 {
1869 type Output = Mat4;
1870 #[inline]
1871 fn div(self, rhs: &f32) -> Mat4 {
1872 (*self).div(*rhs)
1873 }
1874}
1875
1876impl Div<f32> for &Mat4 {
1877 type Output = Mat4;
1878 #[inline]
1879 fn div(self, rhs: f32) -> Mat4 {
1880 (*self).div(rhs)
1881 }
1882}
1883
1884impl DivAssign<f32> for Mat4 {
1885 #[inline]
1886 fn div_assign(&mut self, rhs: f32) {
1887 *self = self.div(rhs);
1888 }
1889}
1890
1891impl DivAssign<&f32> for Mat4 {
1892 #[inline]
1893 fn div_assign(&mut self, rhs: &f32) {
1894 self.div_assign(*rhs);
1895 }
1896}
1897
1898impl Sum<Self> for Mat4 {
1899 fn sum<I>(iter: I) -> Self
1900 where
1901 I: Iterator<Item = Self>,
1902 {
1903 iter.fold(Self::ZERO, Self::add)
1904 }
1905}
1906
1907impl<'a> Sum<&'a Self> for Mat4 {
1908 fn sum<I>(iter: I) -> Self
1909 where
1910 I: Iterator<Item = &'a Self>,
1911 {
1912 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1913 }
1914}
1915
1916impl Product for Mat4 {
1917 fn product<I>(iter: I) -> Self
1918 where
1919 I: Iterator<Item = Self>,
1920 {
1921 iter.fold(Self::IDENTITY, Self::mul)
1922 }
1923}
1924
1925impl<'a> Product<&'a Self> for Mat4 {
1926 fn product<I>(iter: I) -> Self
1927 where
1928 I: Iterator<Item = &'a Self>,
1929 {
1930 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1931 }
1932}
1933
1934impl PartialEq for Mat4 {
1935 #[inline]
1936 fn eq(&self, rhs: &Self) -> bool {
1937 self.x_axis.eq(&rhs.x_axis)
1938 && self.y_axis.eq(&rhs.y_axis)
1939 && self.z_axis.eq(&rhs.z_axis)
1940 && self.w_axis.eq(&rhs.w_axis)
1941 }
1942}
1943
1944impl AsRef<[f32; 16]> for Mat4 {
1945 #[inline]
1946 fn as_ref(&self) -> &[f32; 16] {
1947 unsafe { &*(self as *const Self as *const [f32; 16]) }
1948 }
1949}
1950
1951impl AsMut<[f32; 16]> for Mat4 {
1952 #[inline]
1953 fn as_mut(&mut self) -> &mut [f32; 16] {
1954 unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
1955 }
1956}
1957
1958impl fmt::Debug for Mat4 {
1959 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1960 fmt.debug_struct(stringify!(Mat4))
1961 .field("x_axis", &self.x_axis)
1962 .field("y_axis", &self.y_axis)
1963 .field("z_axis", &self.z_axis)
1964 .field("w_axis", &self.w_axis)
1965 .finish()
1966 }
1967}
1968
1969impl fmt::Display for Mat4 {
1970 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1971 if let Some(p) = f.precision() {
1972 write!(
1973 f,
1974 "[{:.*}, {:.*}, {:.*}, {:.*}]",
1975 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
1976 )
1977 } else {
1978 write!(
1979 f,
1980 "[{}, {}, {}, {}]",
1981 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1982 )
1983 }
1984 }
1985}