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 #[must_use]
639 pub fn determinant(&self) -> f32 {
640 unsafe {
641 let swp2a = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_01_01_10);
643 let swp3a = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b11_10_11_11);
644 let swp2b = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b11_10_11_11);
645 let swp3b = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b00_01_01_10);
646 let swp2c = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_00_01_10);
647 let swp3c = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b01_10_00_00);
648
649 let mula = _mm_mul_ps(swp2a, swp3a);
650 let mulb = _mm_mul_ps(swp2b, swp3b);
651 let mulc = _mm_mul_ps(swp2c, swp3c);
652 let sube = _mm_sub_ps(mula, mulb);
653 let subf = _mm_sub_ps(_mm_movehl_ps(mulc, mulc), mulc);
654
655 let subfaca = _mm_shuffle_ps(sube, sube, 0b10_01_00_00);
656 let swpfaca = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b00_00_00_01);
657 let mulfaca = _mm_mul_ps(swpfaca, subfaca);
658
659 let subtmpb = _mm_shuffle_ps(sube, subf, 0b00_00_11_01);
660 let subfacb = _mm_shuffle_ps(subtmpb, subtmpb, 0b11_01_01_00);
661 let swpfacb = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b01_01_10_10);
662 let mulfacb = _mm_mul_ps(swpfacb, subfacb);
663
664 let subres = _mm_sub_ps(mulfaca, mulfacb);
665 let subtmpc = _mm_shuffle_ps(sube, subf, 0b01_00_10_10);
666 let subfacc = _mm_shuffle_ps(subtmpc, subtmpc, 0b11_11_10_00);
667 let swpfacc = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b10_11_11_11);
668 let mulfacc = _mm_mul_ps(swpfacc, subfacc);
669
670 let addres = _mm_add_ps(subres, mulfacc);
671 let detcof = _mm_mul_ps(addres, _mm_setr_ps(1.0, -1.0, 1.0, -1.0));
672
673 dot4(self.x_axis.0, detcof)
674 }
675 }
676
677 #[must_use]
685 pub fn inverse(&self) -> Self {
686 unsafe {
687 let fac0 = {
689 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
690 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
691
692 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
693 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
694 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
695 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
696
697 let mul00 = _mm_mul_ps(swp00, swp01);
698 let mul01 = _mm_mul_ps(swp02, swp03);
699 _mm_sub_ps(mul00, mul01)
700 };
701 let fac1 = {
702 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
703 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
704
705 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
706 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
707 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
708 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
709
710 let mul00 = _mm_mul_ps(swp00, swp01);
711 let mul01 = _mm_mul_ps(swp02, swp03);
712 _mm_sub_ps(mul00, mul01)
713 };
714 let fac2 = {
715 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
716 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
717
718 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
719 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
720 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
721 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
722
723 let mul00 = _mm_mul_ps(swp00, swp01);
724 let mul01 = _mm_mul_ps(swp02, swp03);
725 _mm_sub_ps(mul00, mul01)
726 };
727 let fac3 = {
728 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
729 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
730
731 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
732 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
733 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
734 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
735
736 let mul00 = _mm_mul_ps(swp00, swp01);
737 let mul01 = _mm_mul_ps(swp02, swp03);
738 _mm_sub_ps(mul00, mul01)
739 };
740 let fac4 = {
741 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
742 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
743
744 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
745 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
746 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
747 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
748
749 let mul00 = _mm_mul_ps(swp00, swp01);
750 let mul01 = _mm_mul_ps(swp02, swp03);
751 _mm_sub_ps(mul00, mul01)
752 };
753 let fac5 = {
754 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
755 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
756
757 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
758 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
759 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
760 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
761
762 let mul00 = _mm_mul_ps(swp00, swp01);
763 let mul01 = _mm_mul_ps(swp02, swp03);
764 _mm_sub_ps(mul00, mul01)
765 };
766 let sign_a = _mm_set_ps(1.0, -1.0, 1.0, -1.0);
767 let sign_b = _mm_set_ps(-1.0, 1.0, -1.0, 1.0);
768
769 let temp0 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b00_00_00_00);
770 let vec0 = _mm_shuffle_ps(temp0, temp0, 0b10_10_10_00);
771
772 let temp1 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b01_01_01_01);
773 let vec1 = _mm_shuffle_ps(temp1, temp1, 0b10_10_10_00);
774
775 let temp2 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b10_10_10_10);
776 let vec2 = _mm_shuffle_ps(temp2, temp2, 0b10_10_10_00);
777
778 let temp3 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b11_11_11_11);
779 let vec3 = _mm_shuffle_ps(temp3, temp3, 0b10_10_10_00);
780
781 let mul00 = _mm_mul_ps(vec1, fac0);
782 let mul01 = _mm_mul_ps(vec2, fac1);
783 let mul02 = _mm_mul_ps(vec3, fac2);
784 let sub00 = _mm_sub_ps(mul00, mul01);
785 let add00 = _mm_add_ps(sub00, mul02);
786 let inv0 = _mm_mul_ps(sign_b, add00);
787
788 let mul03 = _mm_mul_ps(vec0, fac0);
789 let mul04 = _mm_mul_ps(vec2, fac3);
790 let mul05 = _mm_mul_ps(vec3, fac4);
791 let sub01 = _mm_sub_ps(mul03, mul04);
792 let add01 = _mm_add_ps(sub01, mul05);
793 let inv1 = _mm_mul_ps(sign_a, add01);
794
795 let mul06 = _mm_mul_ps(vec0, fac1);
796 let mul07 = _mm_mul_ps(vec1, fac3);
797 let mul08 = _mm_mul_ps(vec3, fac5);
798 let sub02 = _mm_sub_ps(mul06, mul07);
799 let add02 = _mm_add_ps(sub02, mul08);
800 let inv2 = _mm_mul_ps(sign_b, add02);
801
802 let mul09 = _mm_mul_ps(vec0, fac2);
803 let mul10 = _mm_mul_ps(vec1, fac4);
804 let mul11 = _mm_mul_ps(vec2, fac5);
805 let sub03 = _mm_sub_ps(mul09, mul10);
806 let add03 = _mm_add_ps(sub03, mul11);
807 let inv3 = _mm_mul_ps(sign_a, add03);
808
809 let row0 = _mm_shuffle_ps(inv0, inv1, 0b00_00_00_00);
810 let row1 = _mm_shuffle_ps(inv2, inv3, 0b00_00_00_00);
811 let row2 = _mm_shuffle_ps(row0, row1, 0b10_00_10_00);
812
813 let dot0 = dot4(self.x_axis.0, row2);
814 glam_assert!(dot0 != 0.0);
815
816 let rcp0 = _mm_set1_ps(dot0.recip());
817
818 Self {
819 x_axis: Vec4(_mm_mul_ps(inv0, rcp0)),
820 y_axis: Vec4(_mm_mul_ps(inv1, rcp0)),
821 z_axis: Vec4(_mm_mul_ps(inv2, rcp0)),
822 w_axis: Vec4(_mm_mul_ps(inv3, rcp0)),
823 }
824 }
825 }
826
827 #[inline]
836 #[must_use]
837 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
838 Self::look_to_rh(eye, -dir, up)
839 }
840
841 #[inline]
850 #[must_use]
851 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
852 glam_assert!(dir.is_normalized());
853 glam_assert!(up.is_normalized());
854 let f = dir;
855 let s = f.cross(up).normalize();
856 let u = s.cross(f);
857
858 Self::from_cols(
859 Vec4::new(s.x, u.x, -f.x, 0.0),
860 Vec4::new(s.y, u.y, -f.y, 0.0),
861 Vec4::new(s.z, u.z, -f.z, 0.0),
862 Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
863 )
864 }
865
866 #[inline]
875 #[must_use]
876 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
877 Self::look_to_lh(eye, center.sub(eye).normalize(), up)
878 }
879
880 #[inline]
889 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
890 Self::look_to_rh(eye, center.sub(eye).normalize(), up)
891 }
892
893 #[inline]
899 #[must_use]
900 pub fn frustum_rh_gl(
901 left: f32,
902 right: f32,
903 bottom: f32,
904 top: f32,
905 z_near: f32,
906 z_far: f32,
907 ) -> Self {
908 let inv_width = 1.0 / (right - left);
909 let inv_height = 1.0 / (top - bottom);
910 let inv_depth = 1.0 / (z_far - z_near);
911 let a = (right + left) * inv_width;
912 let b = (top + bottom) * inv_height;
913 let c = -(z_far + z_near) * inv_depth;
914 let d = -(2.0 * z_far * z_near) * inv_depth;
915 let two_z_near = 2.0 * z_near;
916 Self::from_cols(
917 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
918 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
919 Vec4::new(a, b, c, -1.0),
920 Vec4::new(0.0, 0.0, d, 0.0),
921 )
922 }
923
924 #[inline]
931 #[must_use]
932 pub fn frustum_lh(
933 left: f32,
934 right: f32,
935 bottom: f32,
936 top: f32,
937 z_near: f32,
938 z_far: f32,
939 ) -> Self {
940 glam_assert!(z_near > 0.0 && z_far > 0.0);
941 let inv_width = 1.0 / (right - left);
942 let inv_height = 1.0 / (top - bottom);
943 let inv_depth = 1.0 / (z_far - z_near);
944 let a = (right + left) * inv_width;
945 let b = (top + bottom) * inv_height;
946 let c = z_far * inv_depth;
947 let d = -(z_far * z_near) * inv_depth;
948 let two_z_near = 2.0 * z_near;
949 Self::from_cols(
950 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
951 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
952 Vec4::new(a, b, c, 1.0),
953 Vec4::new(0.0, 0.0, d, 0.0),
954 )
955 }
956
957 #[inline]
964 #[must_use]
965 pub fn frustum_rh(
966 left: f32,
967 right: f32,
968 bottom: f32,
969 top: f32,
970 z_near: f32,
971 z_far: f32,
972 ) -> Self {
973 glam_assert!(z_near > 0.0 && z_far > 0.0);
974 let inv_width = 1.0 / (right - left);
975 let inv_height = 1.0 / (top - bottom);
976 let inv_depth = 1.0 / (z_far - z_near);
977 let a = (right + left) * inv_width;
978 let b = (top + bottom) * inv_height;
979 let c = -z_far * inv_depth;
980 let d = -(z_far * z_near) * inv_depth;
981 let two_z_near = 2.0 * z_near;
982 Self::from_cols(
983 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
984 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
985 Vec4::new(a, b, c, -1.0),
986 Vec4::new(0.0, 0.0, d, 0.0),
987 )
988 }
989
990 #[inline]
997 #[must_use]
998 pub fn perspective_rh_gl(
999 fov_y_radians: f32,
1000 aspect_ratio: f32,
1001 z_near: f32,
1002 z_far: f32,
1003 ) -> Self {
1004 let inv_length = 1.0 / (z_near - z_far);
1005 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1006 let a = f / aspect_ratio;
1007 let b = (z_near + z_far) * inv_length;
1008 let c = (2.0 * z_near * z_far) * inv_length;
1009 Self::from_cols(
1010 Vec4::new(a, 0.0, 0.0, 0.0),
1011 Vec4::new(0.0, f, 0.0, 0.0),
1012 Vec4::new(0.0, 0.0, b, -1.0),
1013 Vec4::new(0.0, 0.0, c, 0.0),
1014 )
1015 }
1016
1017 #[inline]
1026 #[must_use]
1027 pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
1028 glam_assert!(z_near > 0.0 && z_far > 0.0);
1029 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1030 let h = cos_fov / sin_fov;
1031 let w = h / aspect_ratio;
1032 let r = z_far / (z_far - z_near);
1033 Self::from_cols(
1034 Vec4::new(w, 0.0, 0.0, 0.0),
1035 Vec4::new(0.0, h, 0.0, 0.0),
1036 Vec4::new(0.0, 0.0, r, 1.0),
1037 Vec4::new(0.0, 0.0, -r * z_near, 0.0),
1038 )
1039 }
1040
1041 #[inline]
1050 #[must_use]
1051 pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
1052 glam_assert!(z_near > 0.0 && z_far > 0.0);
1053 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1054 let h = cos_fov / sin_fov;
1055 let w = h / aspect_ratio;
1056 let r = z_far / (z_near - z_far);
1057 Self::from_cols(
1058 Vec4::new(w, 0.0, 0.0, 0.0),
1059 Vec4::new(0.0, h, 0.0, 0.0),
1060 Vec4::new(0.0, 0.0, r, -1.0),
1061 Vec4::new(0.0, 0.0, r * z_near, 0.0),
1062 )
1063 }
1064
1065 #[inline]
1075 #[must_use]
1076 pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1077 glam_assert!(z_near > 0.0);
1078 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1079 let h = cos_fov / sin_fov;
1080 let w = h / aspect_ratio;
1081 Self::from_cols(
1082 Vec4::new(w, 0.0, 0.0, 0.0),
1083 Vec4::new(0.0, h, 0.0, 0.0),
1084 Vec4::new(0.0, 0.0, 1.0, 1.0),
1085 Vec4::new(0.0, 0.0, -z_near, 0.0),
1086 )
1087 }
1088
1089 #[inline]
1097 #[must_use]
1098 pub fn perspective_infinite_reverse_lh(
1099 fov_y_radians: f32,
1100 aspect_ratio: f32,
1101 z_near: f32,
1102 ) -> Self {
1103 glam_assert!(z_near > 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 Self::from_cols(
1108 Vec4::new(w, 0.0, 0.0, 0.0),
1109 Vec4::new(0.0, h, 0.0, 0.0),
1110 Vec4::new(0.0, 0.0, 0.0, 1.0),
1111 Vec4::new(0.0, 0.0, z_near, 0.0),
1112 )
1113 }
1114
1115 #[inline]
1125 #[must_use]
1126 pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1127 glam_assert!(z_near > 0.0);
1128 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1129 Self::from_cols(
1130 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1131 Vec4::new(0.0, f, 0.0, 0.0),
1132 Vec4::new(0.0, 0.0, -1.0, -1.0),
1133 Vec4::new(0.0, 0.0, -z_near, 0.0),
1134 )
1135 }
1136
1137 #[inline]
1145 #[must_use]
1146 pub fn perspective_infinite_reverse_rh(
1147 fov_y_radians: f32,
1148 aspect_ratio: f32,
1149 z_near: f32,
1150 ) -> Self {
1151 glam_assert!(z_near > 0.0);
1152 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1153 Self::from_cols(
1154 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1155 Vec4::new(0.0, f, 0.0, 0.0),
1156 Vec4::new(0.0, 0.0, 0.0, -1.0),
1157 Vec4::new(0.0, 0.0, z_near, 0.0),
1158 )
1159 }
1160
1161 #[inline]
1168 #[must_use]
1169 pub fn orthographic_rh_gl(
1170 left: f32,
1171 right: f32,
1172 bottom: f32,
1173 top: f32,
1174 near: f32,
1175 far: f32,
1176 ) -> Self {
1177 let a = 2.0 / (right - left);
1178 let b = 2.0 / (top - bottom);
1179 let c = -2.0 / (far - near);
1180 let tx = -(right + left) / (right - left);
1181 let ty = -(top + bottom) / (top - bottom);
1182 let tz = -(far + near) / (far - near);
1183
1184 Self::from_cols(
1185 Vec4::new(a, 0.0, 0.0, 0.0),
1186 Vec4::new(0.0, b, 0.0, 0.0),
1187 Vec4::new(0.0, 0.0, c, 0.0),
1188 Vec4::new(tx, ty, tz, 1.0),
1189 )
1190 }
1191
1192 #[inline]
1196 #[must_use]
1197 pub fn orthographic_lh(
1198 left: f32,
1199 right: f32,
1200 bottom: f32,
1201 top: f32,
1202 near: f32,
1203 far: f32,
1204 ) -> Self {
1205 let rcp_width = 1.0 / (right - left);
1206 let rcp_height = 1.0 / (top - bottom);
1207 let r = 1.0 / (far - near);
1208 Self::from_cols(
1209 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1210 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1211 Vec4::new(0.0, 0.0, r, 0.0),
1212 Vec4::new(
1213 -(left + right) * rcp_width,
1214 -(top + bottom) * rcp_height,
1215 -r * near,
1216 1.0,
1217 ),
1218 )
1219 }
1220
1221 #[inline]
1225 #[must_use]
1226 pub fn orthographic_rh(
1227 left: f32,
1228 right: f32,
1229 bottom: f32,
1230 top: f32,
1231 near: f32,
1232 far: f32,
1233 ) -> Self {
1234 let rcp_width = 1.0 / (right - left);
1235 let rcp_height = 1.0 / (top - bottom);
1236 let r = 1.0 / (near - far);
1237 Self::from_cols(
1238 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1239 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1240 Vec4::new(0.0, 0.0, r, 0.0),
1241 Vec4::new(
1242 -(left + right) * rcp_width,
1243 -(top + bottom) * rcp_height,
1244 r * near,
1245 1.0,
1246 ),
1247 )
1248 }
1249
1250 #[inline]
1257 #[must_use]
1258 pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
1259 let mut res = self.x_axis.mul(rhs.x);
1260 res = self.y_axis.mul(rhs.y).add(res);
1261 res = self.z_axis.mul(rhs.z).add(res);
1262 res = self.w_axis.add(res);
1263 res = res.div(res.w);
1264 res.xyz()
1265 }
1266
1267 #[inline]
1280 #[must_use]
1281 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1282 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1283 let mut res = self.x_axis.mul(rhs.x);
1284 res = self.y_axis.mul(rhs.y).add(res);
1285 res = self.z_axis.mul(rhs.z).add(res);
1286 res = self.w_axis.add(res);
1287 res.xyz()
1288 }
1289
1290 #[inline]
1301 #[must_use]
1302 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1303 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1304 let mut res = self.x_axis.mul(rhs.x);
1305 res = self.y_axis.mul(rhs.y).add(res);
1306 res = self.z_axis.mul(rhs.z).add(res);
1307 res.xyz()
1308 }
1309
1310 #[inline]
1317 #[must_use]
1318 pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
1319 let mut res = self.x_axis.mul(rhs.xxxx());
1320 res = self.y_axis.mul(rhs.yyyy()).add(res);
1321 res = self.z_axis.mul(rhs.zzzz()).add(res);
1322 res = self.w_axis.add(res);
1323 res = res.div(res.wwww());
1324 Vec3A::from_vec4(res)
1325 }
1326
1327 #[inline]
1331 #[must_use]
1332 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1333 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1334 let mut res = self.x_axis.mul(rhs.xxxx());
1335 res = self.y_axis.mul(rhs.yyyy()).add(res);
1336 res = self.z_axis.mul(rhs.zzzz()).add(res);
1337 res = self.w_axis.add(res);
1338 Vec3A::from_vec4(res)
1339 }
1340
1341 #[inline]
1345 #[must_use]
1346 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1347 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1348 let mut res = self.x_axis.mul(rhs.xxxx());
1349 res = self.y_axis.mul(rhs.yyyy()).add(res);
1350 res = self.z_axis.mul(rhs.zzzz()).add(res);
1351 Vec3A::from_vec4(res)
1352 }
1353
1354 #[inline]
1356 #[must_use]
1357 pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1358 let mut res = self.x_axis.mul(rhs.xxxx());
1359 res = res.add(self.y_axis.mul(rhs.yyyy()));
1360 res = res.add(self.z_axis.mul(rhs.zzzz()));
1361 res = res.add(self.w_axis.mul(rhs.wwww()));
1362 res
1363 }
1364
1365 #[inline]
1367 #[must_use]
1368 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1369 self.mul(rhs)
1370 }
1371
1372 #[inline]
1374 #[must_use]
1375 pub fn add_mat4(&self, rhs: &Self) -> Self {
1376 self.add(rhs)
1377 }
1378
1379 #[inline]
1381 #[must_use]
1382 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1383 self.sub(rhs)
1384 }
1385
1386 #[inline]
1388 #[must_use]
1389 pub fn mul_scalar(&self, rhs: f32) -> Self {
1390 Self::from_cols(
1391 self.x_axis.mul(rhs),
1392 self.y_axis.mul(rhs),
1393 self.z_axis.mul(rhs),
1394 self.w_axis.mul(rhs),
1395 )
1396 }
1397
1398 #[inline]
1400 #[must_use]
1401 pub fn div_scalar(&self, rhs: f32) -> Self {
1402 let rhs = Vec4::splat(rhs);
1403 Self::from_cols(
1404 self.x_axis.div(rhs),
1405 self.y_axis.div(rhs),
1406 self.z_axis.div(rhs),
1407 self.w_axis.div(rhs),
1408 )
1409 }
1410
1411 #[inline]
1421 #[must_use]
1422 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1423 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1424 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1425 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1426 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1427 }
1428
1429 #[inline]
1431 #[must_use]
1432 pub fn abs(&self) -> Self {
1433 Self::from_cols(
1434 self.x_axis.abs(),
1435 self.y_axis.abs(),
1436 self.z_axis.abs(),
1437 self.w_axis.abs(),
1438 )
1439 }
1440
1441 #[inline]
1442 pub fn as_dmat4(&self) -> DMat4 {
1443 DMat4::from_cols(
1444 self.x_axis.as_dvec4(),
1445 self.y_axis.as_dvec4(),
1446 self.z_axis.as_dvec4(),
1447 self.w_axis.as_dvec4(),
1448 )
1449 }
1450}
1451
1452impl Default for Mat4 {
1453 #[inline]
1454 fn default() -> Self {
1455 Self::IDENTITY
1456 }
1457}
1458
1459impl Add for Mat4 {
1460 type Output = Self;
1461 #[inline]
1462 fn add(self, rhs: Self) -> Self {
1463 Self::from_cols(
1464 self.x_axis.add(rhs.x_axis),
1465 self.y_axis.add(rhs.y_axis),
1466 self.z_axis.add(rhs.z_axis),
1467 self.w_axis.add(rhs.w_axis),
1468 )
1469 }
1470}
1471
1472impl Add<&Self> for Mat4 {
1473 type Output = Self;
1474 #[inline]
1475 fn add(self, rhs: &Self) -> Self {
1476 self.add(*rhs)
1477 }
1478}
1479
1480impl Add<&Mat4> for &Mat4 {
1481 type Output = Mat4;
1482 #[inline]
1483 fn add(self, rhs: &Mat4) -> Mat4 {
1484 (*self).add(*rhs)
1485 }
1486}
1487
1488impl Add<Mat4> for &Mat4 {
1489 type Output = Mat4;
1490 #[inline]
1491 fn add(self, rhs: Mat4) -> Mat4 {
1492 (*self).add(rhs)
1493 }
1494}
1495
1496impl AddAssign for Mat4 {
1497 #[inline]
1498 fn add_assign(&mut self, rhs: Self) {
1499 *self = self.add(rhs);
1500 }
1501}
1502
1503impl AddAssign<&Self> for Mat4 {
1504 #[inline]
1505 fn add_assign(&mut self, rhs: &Self) {
1506 self.add_assign(*rhs);
1507 }
1508}
1509
1510impl Sub for Mat4 {
1511 type Output = Self;
1512 #[inline]
1513 fn sub(self, rhs: Self) -> Self {
1514 Self::from_cols(
1515 self.x_axis.sub(rhs.x_axis),
1516 self.y_axis.sub(rhs.y_axis),
1517 self.z_axis.sub(rhs.z_axis),
1518 self.w_axis.sub(rhs.w_axis),
1519 )
1520 }
1521}
1522
1523impl Sub<&Self> for Mat4 {
1524 type Output = Self;
1525 #[inline]
1526 fn sub(self, rhs: &Self) -> Self {
1527 self.sub(*rhs)
1528 }
1529}
1530
1531impl Sub<&Mat4> for &Mat4 {
1532 type Output = Mat4;
1533 #[inline]
1534 fn sub(self, rhs: &Mat4) -> Mat4 {
1535 (*self).sub(*rhs)
1536 }
1537}
1538
1539impl Sub<Mat4> for &Mat4 {
1540 type Output = Mat4;
1541 #[inline]
1542 fn sub(self, rhs: Mat4) -> Mat4 {
1543 (*self).sub(rhs)
1544 }
1545}
1546
1547impl SubAssign for Mat4 {
1548 #[inline]
1549 fn sub_assign(&mut self, rhs: Self) {
1550 *self = self.sub(rhs);
1551 }
1552}
1553
1554impl SubAssign<&Self> for Mat4 {
1555 #[inline]
1556 fn sub_assign(&mut self, rhs: &Self) {
1557 self.sub_assign(*rhs);
1558 }
1559}
1560
1561impl Neg for Mat4 {
1562 type Output = Self;
1563 #[inline]
1564 fn neg(self) -> Self::Output {
1565 Self::from_cols(
1566 self.x_axis.neg(),
1567 self.y_axis.neg(),
1568 self.z_axis.neg(),
1569 self.w_axis.neg(),
1570 )
1571 }
1572}
1573
1574impl Neg for &Mat4 {
1575 type Output = Mat4;
1576 #[inline]
1577 fn neg(self) -> Mat4 {
1578 (*self).neg()
1579 }
1580}
1581
1582impl Mul for Mat4 {
1583 type Output = Self;
1584 #[inline]
1585 fn mul(self, rhs: Self) -> Self {
1586 Self::from_cols(
1587 self.mul(rhs.x_axis),
1588 self.mul(rhs.y_axis),
1589 self.mul(rhs.z_axis),
1590 self.mul(rhs.w_axis),
1591 )
1592 }
1593}
1594
1595impl Mul<&Self> for Mat4 {
1596 type Output = Self;
1597 #[inline]
1598 fn mul(self, rhs: &Self) -> Self {
1599 self.mul(*rhs)
1600 }
1601}
1602
1603impl Mul<&Mat4> for &Mat4 {
1604 type Output = Mat4;
1605 #[inline]
1606 fn mul(self, rhs: &Mat4) -> Mat4 {
1607 (*self).mul(*rhs)
1608 }
1609}
1610
1611impl Mul<Mat4> for &Mat4 {
1612 type Output = Mat4;
1613 #[inline]
1614 fn mul(self, rhs: Mat4) -> Mat4 {
1615 (*self).mul(rhs)
1616 }
1617}
1618
1619impl MulAssign for Mat4 {
1620 #[inline]
1621 fn mul_assign(&mut self, rhs: Self) {
1622 *self = self.mul(rhs);
1623 }
1624}
1625
1626impl MulAssign<&Self> for Mat4 {
1627 #[inline]
1628 fn mul_assign(&mut self, rhs: &Self) {
1629 self.mul_assign(*rhs);
1630 }
1631}
1632
1633impl Mul<Vec4> for Mat4 {
1634 type Output = Vec4;
1635 #[inline]
1636 fn mul(self, rhs: Vec4) -> Self::Output {
1637 self.mul_vec4(rhs)
1638 }
1639}
1640
1641impl Mul<&Vec4> for Mat4 {
1642 type Output = Vec4;
1643 #[inline]
1644 fn mul(self, rhs: &Vec4) -> Vec4 {
1645 self.mul(*rhs)
1646 }
1647}
1648
1649impl Mul<&Vec4> for &Mat4 {
1650 type Output = Vec4;
1651 #[inline]
1652 fn mul(self, rhs: &Vec4) -> Vec4 {
1653 (*self).mul(*rhs)
1654 }
1655}
1656
1657impl Mul<Vec4> for &Mat4 {
1658 type Output = Vec4;
1659 #[inline]
1660 fn mul(self, rhs: Vec4) -> Vec4 {
1661 (*self).mul(rhs)
1662 }
1663}
1664
1665impl Mul<Mat4> for f32 {
1666 type Output = Mat4;
1667 #[inline]
1668 fn mul(self, rhs: Mat4) -> Self::Output {
1669 rhs.mul_scalar(self)
1670 }
1671}
1672
1673impl Mul<&Mat4> for f32 {
1674 type Output = Mat4;
1675 #[inline]
1676 fn mul(self, rhs: &Mat4) -> Mat4 {
1677 self.mul(*rhs)
1678 }
1679}
1680
1681impl Mul<&Mat4> for &f32 {
1682 type Output = Mat4;
1683 #[inline]
1684 fn mul(self, rhs: &Mat4) -> Mat4 {
1685 (*self).mul(*rhs)
1686 }
1687}
1688
1689impl Mul<Mat4> for &f32 {
1690 type Output = Mat4;
1691 #[inline]
1692 fn mul(self, rhs: Mat4) -> Mat4 {
1693 (*self).mul(rhs)
1694 }
1695}
1696
1697impl Mul<f32> for Mat4 {
1698 type Output = Self;
1699 #[inline]
1700 fn mul(self, rhs: f32) -> Self {
1701 self.mul_scalar(rhs)
1702 }
1703}
1704
1705impl Mul<&f32> for Mat4 {
1706 type Output = Self;
1707 #[inline]
1708 fn mul(self, rhs: &f32) -> Self {
1709 self.mul(*rhs)
1710 }
1711}
1712
1713impl Mul<&f32> for &Mat4 {
1714 type Output = Mat4;
1715 #[inline]
1716 fn mul(self, rhs: &f32) -> Mat4 {
1717 (*self).mul(*rhs)
1718 }
1719}
1720
1721impl Mul<f32> for &Mat4 {
1722 type Output = Mat4;
1723 #[inline]
1724 fn mul(self, rhs: f32) -> Mat4 {
1725 (*self).mul(rhs)
1726 }
1727}
1728
1729impl MulAssign<f32> for Mat4 {
1730 #[inline]
1731 fn mul_assign(&mut self, rhs: f32) {
1732 *self = self.mul(rhs);
1733 }
1734}
1735
1736impl MulAssign<&f32> for Mat4 {
1737 #[inline]
1738 fn mul_assign(&mut self, rhs: &f32) {
1739 self.mul_assign(*rhs);
1740 }
1741}
1742
1743impl Div<Mat4> for f32 {
1744 type Output = Mat4;
1745 #[inline]
1746 fn div(self, rhs: Mat4) -> Self::Output {
1747 rhs.div_scalar(self)
1748 }
1749}
1750
1751impl Div<&Mat4> for f32 {
1752 type Output = Mat4;
1753 #[inline]
1754 fn div(self, rhs: &Mat4) -> Mat4 {
1755 self.div(*rhs)
1756 }
1757}
1758
1759impl Div<&Mat4> for &f32 {
1760 type Output = Mat4;
1761 #[inline]
1762 fn div(self, rhs: &Mat4) -> Mat4 {
1763 (*self).div(*rhs)
1764 }
1765}
1766
1767impl Div<Mat4> for &f32 {
1768 type Output = Mat4;
1769 #[inline]
1770 fn div(self, rhs: Mat4) -> Mat4 {
1771 (*self).div(rhs)
1772 }
1773}
1774
1775impl Div<f32> for Mat4 {
1776 type Output = Self;
1777 #[inline]
1778 fn div(self, rhs: f32) -> Self {
1779 self.div_scalar(rhs)
1780 }
1781}
1782
1783impl Div<&f32> for Mat4 {
1784 type Output = Self;
1785 #[inline]
1786 fn div(self, rhs: &f32) -> Self {
1787 self.div(*rhs)
1788 }
1789}
1790
1791impl Div<&f32> for &Mat4 {
1792 type Output = Mat4;
1793 #[inline]
1794 fn div(self, rhs: &f32) -> Mat4 {
1795 (*self).div(*rhs)
1796 }
1797}
1798
1799impl Div<f32> for &Mat4 {
1800 type Output = Mat4;
1801 #[inline]
1802 fn div(self, rhs: f32) -> Mat4 {
1803 (*self).div(rhs)
1804 }
1805}
1806
1807impl DivAssign<f32> for Mat4 {
1808 #[inline]
1809 fn div_assign(&mut self, rhs: f32) {
1810 *self = self.div(rhs);
1811 }
1812}
1813
1814impl DivAssign<&f32> for Mat4 {
1815 #[inline]
1816 fn div_assign(&mut self, rhs: &f32) {
1817 self.div_assign(*rhs);
1818 }
1819}
1820
1821impl Sum<Self> for Mat4 {
1822 fn sum<I>(iter: I) -> Self
1823 where
1824 I: Iterator<Item = Self>,
1825 {
1826 iter.fold(Self::ZERO, Self::add)
1827 }
1828}
1829
1830impl<'a> Sum<&'a Self> for Mat4 {
1831 fn sum<I>(iter: I) -> Self
1832 where
1833 I: Iterator<Item = &'a Self>,
1834 {
1835 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1836 }
1837}
1838
1839impl Product for Mat4 {
1840 fn product<I>(iter: I) -> Self
1841 where
1842 I: Iterator<Item = Self>,
1843 {
1844 iter.fold(Self::IDENTITY, Self::mul)
1845 }
1846}
1847
1848impl<'a> Product<&'a Self> for Mat4 {
1849 fn product<I>(iter: I) -> Self
1850 where
1851 I: Iterator<Item = &'a Self>,
1852 {
1853 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1854 }
1855}
1856
1857impl PartialEq for Mat4 {
1858 #[inline]
1859 fn eq(&self, rhs: &Self) -> bool {
1860 self.x_axis.eq(&rhs.x_axis)
1861 && self.y_axis.eq(&rhs.y_axis)
1862 && self.z_axis.eq(&rhs.z_axis)
1863 && self.w_axis.eq(&rhs.w_axis)
1864 }
1865}
1866
1867impl AsRef<[f32; 16]> for Mat4 {
1868 #[inline]
1869 fn as_ref(&self) -> &[f32; 16] {
1870 unsafe { &*(self as *const Self as *const [f32; 16]) }
1871 }
1872}
1873
1874impl AsMut<[f32; 16]> for Mat4 {
1875 #[inline]
1876 fn as_mut(&mut self) -> &mut [f32; 16] {
1877 unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
1878 }
1879}
1880
1881impl fmt::Debug for Mat4 {
1882 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1883 fmt.debug_struct(stringify!(Mat4))
1884 .field("x_axis", &self.x_axis)
1885 .field("y_axis", &self.y_axis)
1886 .field("z_axis", &self.z_axis)
1887 .field("w_axis", &self.w_axis)
1888 .finish()
1889 }
1890}
1891
1892impl fmt::Display for Mat4 {
1893 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1894 if let Some(p) = f.precision() {
1895 write!(
1896 f,
1897 "[{:.*}, {:.*}, {:.*}, {:.*}]",
1898 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
1899 )
1900 } else {
1901 write!(
1902 f,
1903 "[{}, {}, {}, {}]",
1904 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1905 )
1906 }
1907 }
1908}