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#[inline(always)]
21#[must_use]
22pub const fn mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat4 {
23 Mat4::from_cols(x_axis, y_axis, z_axis, w_axis)
24}
25
26#[derive(Clone, Copy)]
56#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
57#[repr(C)]
58pub struct Mat4 {
59 pub x_axis: Vec4,
60 pub y_axis: Vec4,
61 pub z_axis: Vec4,
62 pub w_axis: Vec4,
63}
64
65impl Mat4 {
66 pub const ZERO: Self = Self::from_cols(Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO);
68
69 pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W);
71
72 pub const NAN: Self = Self::from_cols(Vec4::NAN, Vec4::NAN, Vec4::NAN, Vec4::NAN);
74
75 #[allow(clippy::too_many_arguments)]
76 #[inline(always)]
77 #[must_use]
78 const fn new(
79 m00: f32,
80 m01: f32,
81 m02: f32,
82 m03: f32,
83 m10: f32,
84 m11: f32,
85 m12: f32,
86 m13: f32,
87 m20: f32,
88 m21: f32,
89 m22: f32,
90 m23: f32,
91 m30: f32,
92 m31: f32,
93 m32: f32,
94 m33: f32,
95 ) -> Self {
96 Self {
97 x_axis: Vec4::new(m00, m01, m02, m03),
98 y_axis: Vec4::new(m10, m11, m12, m13),
99 z_axis: Vec4::new(m20, m21, m22, m23),
100 w_axis: Vec4::new(m30, m31, m32, m33),
101 }
102 }
103
104 #[inline(always)]
106 #[must_use]
107 pub const fn from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self {
108 Self {
109 x_axis,
110 y_axis,
111 z_axis,
112 w_axis,
113 }
114 }
115
116 #[inline]
120 #[must_use]
121 pub const fn from_cols_array(m: &[f32; 16]) -> Self {
122 Self::new(
123 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],
124 m[14], m[15],
125 )
126 }
127
128 #[inline]
131 #[must_use]
132 pub const fn to_cols_array(&self) -> [f32; 16] {
133 let [x_axis_x, x_axis_y, x_axis_z, x_axis_w] = self.x_axis.to_array();
134 let [y_axis_x, y_axis_y, y_axis_z, y_axis_w] = self.y_axis.to_array();
135 let [z_axis_x, z_axis_y, z_axis_z, z_axis_w] = self.z_axis.to_array();
136 let [w_axis_x, w_axis_y, w_axis_z, w_axis_w] = self.w_axis.to_array();
137
138 [
139 x_axis_x, x_axis_y, x_axis_z, x_axis_w, y_axis_x, y_axis_y, y_axis_z, y_axis_w,
140 z_axis_x, z_axis_y, z_axis_z, z_axis_w, w_axis_x, w_axis_y, w_axis_z, w_axis_w,
141 ]
142 }
143
144 #[inline]
148 #[must_use]
149 pub const fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self {
150 Self::from_cols(
151 Vec4::from_array(m[0]),
152 Vec4::from_array(m[1]),
153 Vec4::from_array(m[2]),
154 Vec4::from_array(m[3]),
155 )
156 }
157
158 #[inline]
161 #[must_use]
162 pub const fn to_cols_array_2d(&self) -> [[f32; 4]; 4] {
163 [
164 self.x_axis.to_array(),
165 self.y_axis.to_array(),
166 self.z_axis.to_array(),
167 self.w_axis.to_array(),
168 ]
169 }
170
171 #[doc(alias = "scale")]
173 #[inline]
174 #[must_use]
175 pub const fn from_diagonal(diagonal: Vec4) -> Self {
176 let [x, y, z, w] = diagonal.to_array();
178 Self::new(
179 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,
180 )
181 }
182
183 #[inline]
184 #[must_use]
185 fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) {
186 glam_assert!(rotation.is_normalized());
187
188 let (x, y, z, w) = rotation.into();
189 let x2 = x + x;
190 let y2 = y + y;
191 let z2 = z + z;
192 let xx = x * x2;
193 let xy = x * y2;
194 let xz = x * z2;
195 let yy = y * y2;
196 let yz = y * z2;
197 let zz = z * z2;
198 let wx = w * x2;
199 let wy = w * y2;
200 let wz = w * z2;
201
202 let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
203 let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
204 let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
205 (x_axis, y_axis, z_axis)
206 }
207
208 #[inline]
218 #[must_use]
219 pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
220 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
221 Self::from_cols(
222 x_axis.mul(scale.x),
223 y_axis.mul(scale.y),
224 z_axis.mul(scale.z),
225 Vec4::from((translation, 1.0)),
226 )
227 }
228
229 #[inline]
238 #[must_use]
239 pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
240 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
241 Self::from_cols(x_axis, y_axis, z_axis, Vec4::from((translation, 1.0)))
242 }
243
244 #[inline]
252 #[must_use]
253 pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
254 let det = self.determinant();
255 glam_assert!(det != 0.0);
256
257 let scale = Vec3::new(
258 self.x_axis.length() * math::signum(det),
259 self.y_axis.length(),
260 self.z_axis.length(),
261 );
262
263 glam_assert!(scale.cmpne(Vec3::ZERO).all());
264
265 let inv_scale = scale.recip();
266
267 let rotation = Quat::from_rotation_axes(
268 self.x_axis.mul(inv_scale.x).xyz(),
269 self.y_axis.mul(inv_scale.y).xyz(),
270 self.z_axis.mul(inv_scale.z).xyz(),
271 );
272
273 let translation = self.w_axis.xyz();
274
275 (scale, rotation, translation)
276 }
277
278 #[inline]
287 #[must_use]
288 pub fn from_quat(rotation: Quat) -> Self {
289 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
290 Self::from_cols(x_axis, y_axis, z_axis, Vec4::W)
291 }
292
293 #[inline]
299 #[must_use]
300 pub fn from_mat3(m: Mat3) -> Self {
301 Self::from_cols(
302 Vec4::from((m.x_axis, 0.0)),
303 Vec4::from((m.y_axis, 0.0)),
304 Vec4::from((m.z_axis, 0.0)),
305 Vec4::W,
306 )
307 }
308
309 #[inline]
314 #[must_use]
315 pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
316 Self::from_cols(
317 Vec4::from((mat3.x_axis, 0.0)),
318 Vec4::from((mat3.y_axis, 0.0)),
319 Vec4::from((mat3.z_axis, 0.0)),
320 Vec4::from((translation, 1.0)),
321 )
322 }
323
324 #[inline]
330 #[must_use]
331 pub fn from_mat3a(m: Mat3A) -> Self {
332 Self::from_cols(
333 Vec4::from((m.x_axis, 0.0)),
334 Vec4::from((m.y_axis, 0.0)),
335 Vec4::from((m.z_axis, 0.0)),
336 Vec4::W,
337 )
338 }
339
340 #[inline]
345 #[must_use]
346 pub fn from_translation(translation: Vec3) -> Self {
347 Self::from_cols(
348 Vec4::X,
349 Vec4::Y,
350 Vec4::Z,
351 Vec4::new(translation.x, translation.y, translation.z, 1.0),
352 )
353 }
354
355 #[inline]
365 #[must_use]
366 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
367 glam_assert!(axis.is_normalized());
368
369 let (sin, cos) = math::sin_cos(angle);
370 let axis_sin = axis.mul(sin);
371 let axis_sq = axis.mul(axis);
372 let omc = 1.0 - cos;
373 let xyomc = axis.x * axis.y * omc;
374 let xzomc = axis.x * axis.z * omc;
375 let yzomc = axis.y * axis.z * omc;
376 Self::from_cols(
377 Vec4::new(
378 axis_sq.x * omc + cos,
379 xyomc + axis_sin.z,
380 xzomc - axis_sin.y,
381 0.0,
382 ),
383 Vec4::new(
384 xyomc - axis_sin.z,
385 axis_sq.y * omc + cos,
386 yzomc + axis_sin.x,
387 0.0,
388 ),
389 Vec4::new(
390 xzomc + axis_sin.y,
391 yzomc - axis_sin.x,
392 axis_sq.z * omc + cos,
393 0.0,
394 ),
395 Vec4::W,
396 )
397 }
398
399 #[inline]
405 #[must_use]
406 pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
407 Self::from_euler_angles(order, a, b, c)
408 }
409
410 #[inline]
420 #[must_use]
421 pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
422 glam_assert!(
423 self.x_axis.xyz().is_normalized()
424 && self.y_axis.xyz().is_normalized()
425 && self.z_axis.xyz().is_normalized()
426 );
427 self.to_euler_angles(order)
428 }
429
430 #[inline]
436 #[must_use]
437 pub fn from_rotation_x(angle: f32) -> Self {
438 let (sina, cosa) = math::sin_cos(angle);
439 Self::from_cols(
440 Vec4::X,
441 Vec4::new(0.0, cosa, sina, 0.0),
442 Vec4::new(0.0, -sina, cosa, 0.0),
443 Vec4::W,
444 )
445 }
446
447 #[inline]
453 #[must_use]
454 pub fn from_rotation_y(angle: f32) -> Self {
455 let (sina, cosa) = math::sin_cos(angle);
456 Self::from_cols(
457 Vec4::new(cosa, 0.0, -sina, 0.0),
458 Vec4::Y,
459 Vec4::new(sina, 0.0, cosa, 0.0),
460 Vec4::W,
461 )
462 }
463
464 #[inline]
470 #[must_use]
471 pub fn from_rotation_z(angle: f32) -> Self {
472 let (sina, cosa) = math::sin_cos(angle);
473 Self::from_cols(
474 Vec4::new(cosa, sina, 0.0, 0.0),
475 Vec4::new(-sina, cosa, 0.0, 0.0),
476 Vec4::Z,
477 Vec4::W,
478 )
479 }
480
481 #[inline]
490 #[must_use]
491 pub fn from_scale(scale: Vec3) -> Self {
492 glam_assert!(scale.cmpne(Vec3::ZERO).any());
494
495 Self::from_cols(
496 Vec4::new(scale.x, 0.0, 0.0, 0.0),
497 Vec4::new(0.0, scale.y, 0.0, 0.0),
498 Vec4::new(0.0, 0.0, scale.z, 0.0),
499 Vec4::W,
500 )
501 }
502
503 #[inline]
509 #[must_use]
510 pub const fn from_cols_slice(slice: &[f32]) -> Self {
511 Self::new(
512 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
513 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
514 )
515 }
516
517 #[inline]
523 pub fn write_cols_to_slice(self, slice: &mut [f32]) {
524 slice[0] = self.x_axis.x;
525 slice[1] = self.x_axis.y;
526 slice[2] = self.x_axis.z;
527 slice[3] = self.x_axis.w;
528 slice[4] = self.y_axis.x;
529 slice[5] = self.y_axis.y;
530 slice[6] = self.y_axis.z;
531 slice[7] = self.y_axis.w;
532 slice[8] = self.z_axis.x;
533 slice[9] = self.z_axis.y;
534 slice[10] = self.z_axis.z;
535 slice[11] = self.z_axis.w;
536 slice[12] = self.w_axis.x;
537 slice[13] = self.w_axis.y;
538 slice[14] = self.w_axis.z;
539 slice[15] = self.w_axis.w;
540 }
541
542 #[inline]
548 #[must_use]
549 pub fn col(&self, index: usize) -> Vec4 {
550 match index {
551 0 => self.x_axis,
552 1 => self.y_axis,
553 2 => self.z_axis,
554 3 => self.w_axis,
555 _ => panic!("index out of bounds"),
556 }
557 }
558
559 #[inline]
565 pub fn col_mut(&mut self, index: usize) -> &mut Vec4 {
566 match index {
567 0 => &mut self.x_axis,
568 1 => &mut self.y_axis,
569 2 => &mut self.z_axis,
570 3 => &mut self.w_axis,
571 _ => panic!("index out of bounds"),
572 }
573 }
574
575 #[inline]
581 #[must_use]
582 pub fn row(&self, index: usize) -> Vec4 {
583 match index {
584 0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
585 1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
586 2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
587 3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
588 _ => panic!("index out of bounds"),
589 }
590 }
591
592 #[inline]
595 #[must_use]
596 pub fn is_finite(&self) -> bool {
597 self.x_axis.is_finite()
598 && self.y_axis.is_finite()
599 && self.z_axis.is_finite()
600 && self.w_axis.is_finite()
601 }
602
603 #[inline]
605 #[must_use]
606 pub fn is_nan(&self) -> bool {
607 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
608 }
609
610 #[inline]
612 #[must_use]
613 pub fn transpose(&self) -> Self {
614 unsafe {
615 let tmp0 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b01_00_01_00);
617 let tmp1 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b11_10_11_10);
618 let tmp2 = _mm_shuffle_ps(self.z_axis.0, self.w_axis.0, 0b01_00_01_00);
619 let tmp3 = _mm_shuffle_ps(self.z_axis.0, self.w_axis.0, 0b11_10_11_10);
620
621 Self {
622 x_axis: Vec4(_mm_shuffle_ps(tmp0, tmp2, 0b10_00_10_00)),
623 y_axis: Vec4(_mm_shuffle_ps(tmp0, tmp2, 0b11_01_11_01)),
624 z_axis: Vec4(_mm_shuffle_ps(tmp1, tmp3, 0b10_00_10_00)),
625 w_axis: Vec4(_mm_shuffle_ps(tmp1, tmp3, 0b11_01_11_01)),
626 }
627 }
628 }
629
630 #[must_use]
632 pub fn determinant(&self) -> f32 {
633 unsafe {
634 let swp2a = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_01_01_10);
636 let swp3a = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b11_10_11_11);
637 let swp2b = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b11_10_11_11);
638 let swp3b = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b00_01_01_10);
639 let swp2c = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_00_01_10);
640 let swp3c = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b01_10_00_00);
641
642 let mula = _mm_mul_ps(swp2a, swp3a);
643 let mulb = _mm_mul_ps(swp2b, swp3b);
644 let mulc = _mm_mul_ps(swp2c, swp3c);
645 let sube = _mm_sub_ps(mula, mulb);
646 let subf = _mm_sub_ps(_mm_movehl_ps(mulc, mulc), mulc);
647
648 let subfaca = _mm_shuffle_ps(sube, sube, 0b10_01_00_00);
649 let swpfaca = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b00_00_00_01);
650 let mulfaca = _mm_mul_ps(swpfaca, subfaca);
651
652 let subtmpb = _mm_shuffle_ps(sube, subf, 0b00_00_11_01);
653 let subfacb = _mm_shuffle_ps(subtmpb, subtmpb, 0b11_01_01_00);
654 let swpfacb = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b01_01_10_10);
655 let mulfacb = _mm_mul_ps(swpfacb, subfacb);
656
657 let subres = _mm_sub_ps(mulfaca, mulfacb);
658 let subtmpc = _mm_shuffle_ps(sube, subf, 0b01_00_10_10);
659 let subfacc = _mm_shuffle_ps(subtmpc, subtmpc, 0b11_11_10_00);
660 let swpfacc = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b10_11_11_11);
661 let mulfacc = _mm_mul_ps(swpfacc, subfacc);
662
663 let addres = _mm_add_ps(subres, mulfacc);
664 let detcof = _mm_mul_ps(addres, _mm_setr_ps(1.0, -1.0, 1.0, -1.0));
665
666 dot4(self.x_axis.0, detcof)
667 }
668 }
669
670 #[must_use]
678 pub fn inverse(&self) -> Self {
679 unsafe {
680 let fac0 = {
682 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
683 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
684
685 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
686 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
687 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
688 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
689
690 let mul00 = _mm_mul_ps(swp00, swp01);
691 let mul01 = _mm_mul_ps(swp02, swp03);
692 _mm_sub_ps(mul00, mul01)
693 };
694 let fac1 = {
695 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
696 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
697
698 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
699 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
700 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
701 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
702
703 let mul00 = _mm_mul_ps(swp00, swp01);
704 let mul01 = _mm_mul_ps(swp02, swp03);
705 _mm_sub_ps(mul00, mul01)
706 };
707 let fac2 = {
708 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
709 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
710
711 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
712 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
713 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
714 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
715
716 let mul00 = _mm_mul_ps(swp00, swp01);
717 let mul01 = _mm_mul_ps(swp02, swp03);
718 _mm_sub_ps(mul00, mul01)
719 };
720 let fac3 = {
721 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
722 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
723
724 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
725 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
726 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
727 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
728
729 let mul00 = _mm_mul_ps(swp00, swp01);
730 let mul01 = _mm_mul_ps(swp02, swp03);
731 _mm_sub_ps(mul00, mul01)
732 };
733 let fac4 = {
734 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
735 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
736
737 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
738 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
739 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
740 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
741
742 let mul00 = _mm_mul_ps(swp00, swp01);
743 let mul01 = _mm_mul_ps(swp02, swp03);
744 _mm_sub_ps(mul00, mul01)
745 };
746 let fac5 = {
747 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
748 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
749
750 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
751 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
752 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
753 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
754
755 let mul00 = _mm_mul_ps(swp00, swp01);
756 let mul01 = _mm_mul_ps(swp02, swp03);
757 _mm_sub_ps(mul00, mul01)
758 };
759 let sign_a = _mm_set_ps(1.0, -1.0, 1.0, -1.0);
760 let sign_b = _mm_set_ps(-1.0, 1.0, -1.0, 1.0);
761
762 let temp0 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b00_00_00_00);
763 let vec0 = _mm_shuffle_ps(temp0, temp0, 0b10_10_10_00);
764
765 let temp1 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b01_01_01_01);
766 let vec1 = _mm_shuffle_ps(temp1, temp1, 0b10_10_10_00);
767
768 let temp2 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b10_10_10_10);
769 let vec2 = _mm_shuffle_ps(temp2, temp2, 0b10_10_10_00);
770
771 let temp3 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b11_11_11_11);
772 let vec3 = _mm_shuffle_ps(temp3, temp3, 0b10_10_10_00);
773
774 let mul00 = _mm_mul_ps(vec1, fac0);
775 let mul01 = _mm_mul_ps(vec2, fac1);
776 let mul02 = _mm_mul_ps(vec3, fac2);
777 let sub00 = _mm_sub_ps(mul00, mul01);
778 let add00 = _mm_add_ps(sub00, mul02);
779 let inv0 = _mm_mul_ps(sign_b, add00);
780
781 let mul03 = _mm_mul_ps(vec0, fac0);
782 let mul04 = _mm_mul_ps(vec2, fac3);
783 let mul05 = _mm_mul_ps(vec3, fac4);
784 let sub01 = _mm_sub_ps(mul03, mul04);
785 let add01 = _mm_add_ps(sub01, mul05);
786 let inv1 = _mm_mul_ps(sign_a, add01);
787
788 let mul06 = _mm_mul_ps(vec0, fac1);
789 let mul07 = _mm_mul_ps(vec1, fac3);
790 let mul08 = _mm_mul_ps(vec3, fac5);
791 let sub02 = _mm_sub_ps(mul06, mul07);
792 let add02 = _mm_add_ps(sub02, mul08);
793 let inv2 = _mm_mul_ps(sign_b, add02);
794
795 let mul09 = _mm_mul_ps(vec0, fac2);
796 let mul10 = _mm_mul_ps(vec1, fac4);
797 let mul11 = _mm_mul_ps(vec2, fac5);
798 let sub03 = _mm_sub_ps(mul09, mul10);
799 let add03 = _mm_add_ps(sub03, mul11);
800 let inv3 = _mm_mul_ps(sign_a, add03);
801
802 let row0 = _mm_shuffle_ps(inv0, inv1, 0b00_00_00_00);
803 let row1 = _mm_shuffle_ps(inv2, inv3, 0b00_00_00_00);
804 let row2 = _mm_shuffle_ps(row0, row1, 0b10_00_10_00);
805
806 let dot0 = dot4(self.x_axis.0, row2);
807 glam_assert!(dot0 != 0.0);
808
809 let rcp0 = _mm_set1_ps(dot0.recip());
810
811 Self {
812 x_axis: Vec4(_mm_mul_ps(inv0, rcp0)),
813 y_axis: Vec4(_mm_mul_ps(inv1, rcp0)),
814 z_axis: Vec4(_mm_mul_ps(inv2, rcp0)),
815 w_axis: Vec4(_mm_mul_ps(inv3, rcp0)),
816 }
817 }
818 }
819
820 #[inline]
829 #[must_use]
830 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
831 Self::look_to_rh(eye, -dir, up)
832 }
833
834 #[inline]
843 #[must_use]
844 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
845 glam_assert!(dir.is_normalized());
846 glam_assert!(up.is_normalized());
847 let f = dir;
848 let s = f.cross(up).normalize();
849 let u = s.cross(f);
850
851 Self::from_cols(
852 Vec4::new(s.x, u.x, -f.x, 0.0),
853 Vec4::new(s.y, u.y, -f.y, 0.0),
854 Vec4::new(s.z, u.z, -f.z, 0.0),
855 Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
856 )
857 }
858
859 #[inline]
868 #[must_use]
869 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
870 Self::look_to_lh(eye, center.sub(eye).normalize(), up)
871 }
872
873 #[inline]
882 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
883 Self::look_to_rh(eye, center.sub(eye).normalize(), up)
884 }
885
886 #[inline]
892 #[must_use]
893 pub fn frustum_rh_gl(
894 left: f32,
895 right: f32,
896 bottom: f32,
897 top: f32,
898 z_near: f32,
899 z_far: f32,
900 ) -> Self {
901 let inv_width = 1.0 / (right - left);
902 let inv_height = 1.0 / (top - bottom);
903 let inv_depth = 1.0 / (z_far - z_near);
904 let a = (right + left) * inv_width;
905 let b = (top + bottom) * inv_height;
906 let c = -(z_far + z_near) * inv_depth;
907 let d = -(2.0 * z_far * z_near) * inv_depth;
908 let two_z_near = 2.0 * z_near;
909 Self::from_cols(
910 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
911 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
912 Vec4::new(a, b, c, -1.0),
913 Vec4::new(0.0, 0.0, d, 0.0),
914 )
915 }
916
917 #[inline]
924 #[must_use]
925 pub fn frustum_lh(
926 left: f32,
927 right: f32,
928 bottom: f32,
929 top: f32,
930 z_near: f32,
931 z_far: f32,
932 ) -> Self {
933 glam_assert!(z_near > 0.0 && z_far > 0.0);
934 let inv_width = 1.0 / (right - left);
935 let inv_height = 1.0 / (top - bottom);
936 let inv_depth = 1.0 / (z_far - z_near);
937 let a = (right + left) * inv_width;
938 let b = (top + bottom) * inv_height;
939 let c = z_far * inv_depth;
940 let d = -(z_far * z_near) * inv_depth;
941 let two_z_near = 2.0 * z_near;
942 Self::from_cols(
943 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
944 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
945 Vec4::new(a, b, c, 1.0),
946 Vec4::new(0.0, 0.0, d, 0.0),
947 )
948 }
949
950 #[inline]
957 #[must_use]
958 pub fn frustum_rh(
959 left: f32,
960 right: f32,
961 bottom: f32,
962 top: f32,
963 z_near: f32,
964 z_far: f32,
965 ) -> Self {
966 glam_assert!(z_near > 0.0 && z_far > 0.0);
967 let inv_width = 1.0 / (right - left);
968 let inv_height = 1.0 / (top - bottom);
969 let inv_depth = 1.0 / (z_far - z_near);
970 let a = (right + left) * inv_width;
971 let b = (top + bottom) * inv_height;
972 let c = -z_far * inv_depth;
973 let d = -(z_far * z_near) * inv_depth;
974 let two_z_near = 2.0 * z_near;
975 Self::from_cols(
976 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
977 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
978 Vec4::new(a, b, c, -1.0),
979 Vec4::new(0.0, 0.0, d, 0.0),
980 )
981 }
982
983 #[inline]
990 #[must_use]
991 pub fn perspective_rh_gl(
992 fov_y_radians: f32,
993 aspect_ratio: f32,
994 z_near: f32,
995 z_far: f32,
996 ) -> Self {
997 let inv_length = 1.0 / (z_near - z_far);
998 let f = 1.0 / math::tan(0.5 * fov_y_radians);
999 let a = f / aspect_ratio;
1000 let b = (z_near + z_far) * inv_length;
1001 let c = (2.0 * z_near * z_far) * inv_length;
1002 Self::from_cols(
1003 Vec4::new(a, 0.0, 0.0, 0.0),
1004 Vec4::new(0.0, f, 0.0, 0.0),
1005 Vec4::new(0.0, 0.0, b, -1.0),
1006 Vec4::new(0.0, 0.0, c, 0.0),
1007 )
1008 }
1009
1010 #[inline]
1019 #[must_use]
1020 pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
1021 glam_assert!(z_near > 0.0 && z_far > 0.0);
1022 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1023 let h = cos_fov / sin_fov;
1024 let w = h / aspect_ratio;
1025 let r = z_far / (z_far - z_near);
1026 Self::from_cols(
1027 Vec4::new(w, 0.0, 0.0, 0.0),
1028 Vec4::new(0.0, h, 0.0, 0.0),
1029 Vec4::new(0.0, 0.0, r, 1.0),
1030 Vec4::new(0.0, 0.0, -r * z_near, 0.0),
1031 )
1032 }
1033
1034 #[inline]
1043 #[must_use]
1044 pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
1045 glam_assert!(z_near > 0.0 && z_far > 0.0);
1046 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1047 let h = cos_fov / sin_fov;
1048 let w = h / aspect_ratio;
1049 let r = z_far / (z_near - z_far);
1050 Self::from_cols(
1051 Vec4::new(w, 0.0, 0.0, 0.0),
1052 Vec4::new(0.0, h, 0.0, 0.0),
1053 Vec4::new(0.0, 0.0, r, -1.0),
1054 Vec4::new(0.0, 0.0, r * z_near, 0.0),
1055 )
1056 }
1057
1058 #[inline]
1068 #[must_use]
1069 pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1070 glam_assert!(z_near > 0.0);
1071 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1072 let h = cos_fov / sin_fov;
1073 let w = h / aspect_ratio;
1074 Self::from_cols(
1075 Vec4::new(w, 0.0, 0.0, 0.0),
1076 Vec4::new(0.0, h, 0.0, 0.0),
1077 Vec4::new(0.0, 0.0, 1.0, 1.0),
1078 Vec4::new(0.0, 0.0, -z_near, 0.0),
1079 )
1080 }
1081
1082 #[inline]
1090 #[must_use]
1091 pub fn perspective_infinite_reverse_lh(
1092 fov_y_radians: f32,
1093 aspect_ratio: f32,
1094 z_near: f32,
1095 ) -> Self {
1096 glam_assert!(z_near > 0.0);
1097 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1098 let h = cos_fov / sin_fov;
1099 let w = h / aspect_ratio;
1100 Self::from_cols(
1101 Vec4::new(w, 0.0, 0.0, 0.0),
1102 Vec4::new(0.0, h, 0.0, 0.0),
1103 Vec4::new(0.0, 0.0, 0.0, 1.0),
1104 Vec4::new(0.0, 0.0, z_near, 0.0),
1105 )
1106 }
1107
1108 #[inline]
1118 #[must_use]
1119 pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1120 glam_assert!(z_near > 0.0);
1121 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1122 Self::from_cols(
1123 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1124 Vec4::new(0.0, f, 0.0, 0.0),
1125 Vec4::new(0.0, 0.0, -1.0, -1.0),
1126 Vec4::new(0.0, 0.0, -z_near, 0.0),
1127 )
1128 }
1129
1130 #[inline]
1138 #[must_use]
1139 pub fn perspective_infinite_reverse_rh(
1140 fov_y_radians: f32,
1141 aspect_ratio: f32,
1142 z_near: f32,
1143 ) -> Self {
1144 glam_assert!(z_near > 0.0);
1145 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1146 Self::from_cols(
1147 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1148 Vec4::new(0.0, f, 0.0, 0.0),
1149 Vec4::new(0.0, 0.0, 0.0, -1.0),
1150 Vec4::new(0.0, 0.0, z_near, 0.0),
1151 )
1152 }
1153
1154 #[inline]
1161 #[must_use]
1162 pub fn orthographic_rh_gl(
1163 left: f32,
1164 right: f32,
1165 bottom: f32,
1166 top: f32,
1167 near: f32,
1168 far: f32,
1169 ) -> Self {
1170 let a = 2.0 / (right - left);
1171 let b = 2.0 / (top - bottom);
1172 let c = -2.0 / (far - near);
1173 let tx = -(right + left) / (right - left);
1174 let ty = -(top + bottom) / (top - bottom);
1175 let tz = -(far + near) / (far - near);
1176
1177 Self::from_cols(
1178 Vec4::new(a, 0.0, 0.0, 0.0),
1179 Vec4::new(0.0, b, 0.0, 0.0),
1180 Vec4::new(0.0, 0.0, c, 0.0),
1181 Vec4::new(tx, ty, tz, 1.0),
1182 )
1183 }
1184
1185 #[inline]
1189 #[must_use]
1190 pub fn orthographic_lh(
1191 left: f32,
1192 right: f32,
1193 bottom: f32,
1194 top: f32,
1195 near: f32,
1196 far: f32,
1197 ) -> Self {
1198 let rcp_width = 1.0 / (right - left);
1199 let rcp_height = 1.0 / (top - bottom);
1200 let r = 1.0 / (far - near);
1201 Self::from_cols(
1202 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1203 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1204 Vec4::new(0.0, 0.0, r, 0.0),
1205 Vec4::new(
1206 -(left + right) * rcp_width,
1207 -(top + bottom) * rcp_height,
1208 -r * near,
1209 1.0,
1210 ),
1211 )
1212 }
1213
1214 #[inline]
1218 #[must_use]
1219 pub fn orthographic_rh(
1220 left: f32,
1221 right: f32,
1222 bottom: f32,
1223 top: f32,
1224 near: f32,
1225 far: f32,
1226 ) -> Self {
1227 let rcp_width = 1.0 / (right - left);
1228 let rcp_height = 1.0 / (top - bottom);
1229 let r = 1.0 / (near - far);
1230 Self::from_cols(
1231 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1232 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1233 Vec4::new(0.0, 0.0, r, 0.0),
1234 Vec4::new(
1235 -(left + right) * rcp_width,
1236 -(top + bottom) * rcp_height,
1237 r * near,
1238 1.0,
1239 ),
1240 )
1241 }
1242
1243 #[inline]
1250 #[must_use]
1251 pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
1252 let mut res = self.x_axis.mul(rhs.x);
1253 res = self.y_axis.mul(rhs.y).add(res);
1254 res = self.z_axis.mul(rhs.z).add(res);
1255 res = self.w_axis.add(res);
1256 res = res.div(res.w);
1257 res.xyz()
1258 }
1259
1260 #[inline]
1273 #[must_use]
1274 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1275 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1276 let mut res = self.x_axis.mul(rhs.x);
1277 res = self.y_axis.mul(rhs.y).add(res);
1278 res = self.z_axis.mul(rhs.z).add(res);
1279 res = self.w_axis.add(res);
1280 res.xyz()
1281 }
1282
1283 #[inline]
1294 #[must_use]
1295 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1296 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1297 let mut res = self.x_axis.mul(rhs.x);
1298 res = self.y_axis.mul(rhs.y).add(res);
1299 res = self.z_axis.mul(rhs.z).add(res);
1300 res.xyz()
1301 }
1302
1303 #[inline]
1310 #[must_use]
1311 pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
1312 let mut res = self.x_axis.mul(rhs.xxxx());
1313 res = self.y_axis.mul(rhs.yyyy()).add(res);
1314 res = self.z_axis.mul(rhs.zzzz()).add(res);
1315 res = self.w_axis.add(res);
1316 res = res.div(res.wwww());
1317 Vec3A::from_vec4(res)
1318 }
1319
1320 #[inline]
1324 #[must_use]
1325 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1326 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1327 let mut res = self.x_axis.mul(rhs.xxxx());
1328 res = self.y_axis.mul(rhs.yyyy()).add(res);
1329 res = self.z_axis.mul(rhs.zzzz()).add(res);
1330 res = self.w_axis.add(res);
1331 Vec3A::from_vec4(res)
1332 }
1333
1334 #[inline]
1338 #[must_use]
1339 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1340 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1341 let mut res = self.x_axis.mul(rhs.xxxx());
1342 res = self.y_axis.mul(rhs.yyyy()).add(res);
1343 res = self.z_axis.mul(rhs.zzzz()).add(res);
1344 Vec3A::from_vec4(res)
1345 }
1346
1347 #[inline]
1349 #[must_use]
1350 pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1351 let mut res = self.x_axis.mul(rhs.xxxx());
1352 res = res.add(self.y_axis.mul(rhs.yyyy()));
1353 res = res.add(self.z_axis.mul(rhs.zzzz()));
1354 res = res.add(self.w_axis.mul(rhs.wwww()));
1355 res
1356 }
1357
1358 #[inline]
1360 #[must_use]
1361 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1362 self.mul(rhs)
1363 }
1364
1365 #[inline]
1367 #[must_use]
1368 pub fn add_mat4(&self, rhs: &Self) -> Self {
1369 self.add(rhs)
1370 }
1371
1372 #[inline]
1374 #[must_use]
1375 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1376 self.sub(rhs)
1377 }
1378
1379 #[inline]
1381 #[must_use]
1382 pub fn mul_scalar(&self, rhs: f32) -> Self {
1383 Self::from_cols(
1384 self.x_axis.mul(rhs),
1385 self.y_axis.mul(rhs),
1386 self.z_axis.mul(rhs),
1387 self.w_axis.mul(rhs),
1388 )
1389 }
1390
1391 #[inline]
1393 #[must_use]
1394 pub fn div_scalar(&self, rhs: f32) -> Self {
1395 let rhs = Vec4::splat(rhs);
1396 Self::from_cols(
1397 self.x_axis.div(rhs),
1398 self.y_axis.div(rhs),
1399 self.z_axis.div(rhs),
1400 self.w_axis.div(rhs),
1401 )
1402 }
1403
1404 #[inline]
1414 #[must_use]
1415 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1416 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1417 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1418 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1419 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1420 }
1421
1422 #[inline]
1424 #[must_use]
1425 pub fn abs(&self) -> Self {
1426 Self::from_cols(
1427 self.x_axis.abs(),
1428 self.y_axis.abs(),
1429 self.z_axis.abs(),
1430 self.w_axis.abs(),
1431 )
1432 }
1433
1434 #[inline]
1435 pub fn as_dmat4(&self) -> DMat4 {
1436 DMat4::from_cols(
1437 self.x_axis.as_dvec4(),
1438 self.y_axis.as_dvec4(),
1439 self.z_axis.as_dvec4(),
1440 self.w_axis.as_dvec4(),
1441 )
1442 }
1443}
1444
1445impl Default for Mat4 {
1446 #[inline]
1447 fn default() -> Self {
1448 Self::IDENTITY
1449 }
1450}
1451
1452impl Add for Mat4 {
1453 type Output = Self;
1454 #[inline]
1455 fn add(self, rhs: Self) -> Self {
1456 Self::from_cols(
1457 self.x_axis.add(rhs.x_axis),
1458 self.y_axis.add(rhs.y_axis),
1459 self.z_axis.add(rhs.z_axis),
1460 self.w_axis.add(rhs.w_axis),
1461 )
1462 }
1463}
1464
1465impl Add<&Self> for Mat4 {
1466 type Output = Self;
1467 #[inline]
1468 fn add(self, rhs: &Self) -> Self {
1469 self.add(*rhs)
1470 }
1471}
1472
1473impl Add<&Mat4> for &Mat4 {
1474 type Output = Mat4;
1475 #[inline]
1476 fn add(self, rhs: &Mat4) -> Mat4 {
1477 (*self).add(*rhs)
1478 }
1479}
1480
1481impl Add<Mat4> for &Mat4 {
1482 type Output = Mat4;
1483 #[inline]
1484 fn add(self, rhs: Mat4) -> Mat4 {
1485 (*self).add(rhs)
1486 }
1487}
1488
1489impl AddAssign for Mat4 {
1490 #[inline]
1491 fn add_assign(&mut self, rhs: Self) {
1492 *self = self.add(rhs);
1493 }
1494}
1495
1496impl AddAssign<&Self> for Mat4 {
1497 #[inline]
1498 fn add_assign(&mut self, rhs: &Self) {
1499 self.add_assign(*rhs);
1500 }
1501}
1502
1503impl Sub for Mat4 {
1504 type Output = Self;
1505 #[inline]
1506 fn sub(self, rhs: Self) -> Self {
1507 Self::from_cols(
1508 self.x_axis.sub(rhs.x_axis),
1509 self.y_axis.sub(rhs.y_axis),
1510 self.z_axis.sub(rhs.z_axis),
1511 self.w_axis.sub(rhs.w_axis),
1512 )
1513 }
1514}
1515
1516impl Sub<&Self> for Mat4 {
1517 type Output = Self;
1518 #[inline]
1519 fn sub(self, rhs: &Self) -> Self {
1520 self.sub(*rhs)
1521 }
1522}
1523
1524impl Sub<&Mat4> for &Mat4 {
1525 type Output = Mat4;
1526 #[inline]
1527 fn sub(self, rhs: &Mat4) -> Mat4 {
1528 (*self).sub(*rhs)
1529 }
1530}
1531
1532impl Sub<Mat4> for &Mat4 {
1533 type Output = Mat4;
1534 #[inline]
1535 fn sub(self, rhs: Mat4) -> Mat4 {
1536 (*self).sub(rhs)
1537 }
1538}
1539
1540impl SubAssign for Mat4 {
1541 #[inline]
1542 fn sub_assign(&mut self, rhs: Self) {
1543 *self = self.sub(rhs);
1544 }
1545}
1546
1547impl SubAssign<&Self> for Mat4 {
1548 #[inline]
1549 fn sub_assign(&mut self, rhs: &Self) {
1550 self.sub_assign(*rhs);
1551 }
1552}
1553
1554impl Neg for Mat4 {
1555 type Output = Self;
1556 #[inline]
1557 fn neg(self) -> Self::Output {
1558 Self::from_cols(
1559 self.x_axis.neg(),
1560 self.y_axis.neg(),
1561 self.z_axis.neg(),
1562 self.w_axis.neg(),
1563 )
1564 }
1565}
1566
1567impl Neg for &Mat4 {
1568 type Output = Mat4;
1569 #[inline]
1570 fn neg(self) -> Mat4 {
1571 (*self).neg()
1572 }
1573}
1574
1575impl Mul for Mat4 {
1576 type Output = Self;
1577 #[inline]
1578 fn mul(self, rhs: Self) -> Self {
1579 Self::from_cols(
1580 self.mul(rhs.x_axis),
1581 self.mul(rhs.y_axis),
1582 self.mul(rhs.z_axis),
1583 self.mul(rhs.w_axis),
1584 )
1585 }
1586}
1587
1588impl Mul<&Self> for Mat4 {
1589 type Output = Self;
1590 #[inline]
1591 fn mul(self, rhs: &Self) -> Self {
1592 self.mul(*rhs)
1593 }
1594}
1595
1596impl Mul<&Mat4> for &Mat4 {
1597 type Output = Mat4;
1598 #[inline]
1599 fn mul(self, rhs: &Mat4) -> Mat4 {
1600 (*self).mul(*rhs)
1601 }
1602}
1603
1604impl Mul<Mat4> for &Mat4 {
1605 type Output = Mat4;
1606 #[inline]
1607 fn mul(self, rhs: Mat4) -> Mat4 {
1608 (*self).mul(rhs)
1609 }
1610}
1611
1612impl MulAssign for Mat4 {
1613 #[inline]
1614 fn mul_assign(&mut self, rhs: Self) {
1615 *self = self.mul(rhs);
1616 }
1617}
1618
1619impl MulAssign<&Self> for Mat4 {
1620 #[inline]
1621 fn mul_assign(&mut self, rhs: &Self) {
1622 self.mul_assign(*rhs);
1623 }
1624}
1625
1626impl Mul<Vec4> for Mat4 {
1627 type Output = Vec4;
1628 #[inline]
1629 fn mul(self, rhs: Vec4) -> Self::Output {
1630 self.mul_vec4(rhs)
1631 }
1632}
1633
1634impl Mul<&Vec4> for Mat4 {
1635 type Output = Vec4;
1636 #[inline]
1637 fn mul(self, rhs: &Vec4) -> Vec4 {
1638 self.mul(*rhs)
1639 }
1640}
1641
1642impl Mul<&Vec4> for &Mat4 {
1643 type Output = Vec4;
1644 #[inline]
1645 fn mul(self, rhs: &Vec4) -> Vec4 {
1646 (*self).mul(*rhs)
1647 }
1648}
1649
1650impl Mul<Vec4> for &Mat4 {
1651 type Output = Vec4;
1652 #[inline]
1653 fn mul(self, rhs: Vec4) -> Vec4 {
1654 (*self).mul(rhs)
1655 }
1656}
1657
1658impl Mul<Mat4> for f32 {
1659 type Output = Mat4;
1660 #[inline]
1661 fn mul(self, rhs: Mat4) -> Self::Output {
1662 rhs.mul_scalar(self)
1663 }
1664}
1665
1666impl Mul<&Mat4> for f32 {
1667 type Output = Mat4;
1668 #[inline]
1669 fn mul(self, rhs: &Mat4) -> Mat4 {
1670 self.mul(*rhs)
1671 }
1672}
1673
1674impl Mul<&Mat4> for &f32 {
1675 type Output = Mat4;
1676 #[inline]
1677 fn mul(self, rhs: &Mat4) -> Mat4 {
1678 (*self).mul(*rhs)
1679 }
1680}
1681
1682impl Mul<Mat4> for &f32 {
1683 type Output = Mat4;
1684 #[inline]
1685 fn mul(self, rhs: Mat4) -> Mat4 {
1686 (*self).mul(rhs)
1687 }
1688}
1689
1690impl Mul<f32> for Mat4 {
1691 type Output = Self;
1692 #[inline]
1693 fn mul(self, rhs: f32) -> Self {
1694 self.mul_scalar(rhs)
1695 }
1696}
1697
1698impl Mul<&f32> for Mat4 {
1699 type Output = Self;
1700 #[inline]
1701 fn mul(self, rhs: &f32) -> Self {
1702 self.mul(*rhs)
1703 }
1704}
1705
1706impl Mul<&f32> for &Mat4 {
1707 type Output = Mat4;
1708 #[inline]
1709 fn mul(self, rhs: &f32) -> Mat4 {
1710 (*self).mul(*rhs)
1711 }
1712}
1713
1714impl Mul<f32> for &Mat4 {
1715 type Output = Mat4;
1716 #[inline]
1717 fn mul(self, rhs: f32) -> Mat4 {
1718 (*self).mul(rhs)
1719 }
1720}
1721
1722impl MulAssign<f32> for Mat4 {
1723 #[inline]
1724 fn mul_assign(&mut self, rhs: f32) {
1725 *self = self.mul(rhs);
1726 }
1727}
1728
1729impl MulAssign<&f32> for Mat4 {
1730 #[inline]
1731 fn mul_assign(&mut self, rhs: &f32) {
1732 self.mul_assign(*rhs);
1733 }
1734}
1735
1736impl Div<Mat4> for f32 {
1737 type Output = Mat4;
1738 #[inline]
1739 fn div(self, rhs: Mat4) -> Self::Output {
1740 rhs.div_scalar(self)
1741 }
1742}
1743
1744impl Div<&Mat4> for f32 {
1745 type Output = Mat4;
1746 #[inline]
1747 fn div(self, rhs: &Mat4) -> Mat4 {
1748 self.div(*rhs)
1749 }
1750}
1751
1752impl Div<&Mat4> for &f32 {
1753 type Output = Mat4;
1754 #[inline]
1755 fn div(self, rhs: &Mat4) -> Mat4 {
1756 (*self).div(*rhs)
1757 }
1758}
1759
1760impl Div<Mat4> for &f32 {
1761 type Output = Mat4;
1762 #[inline]
1763 fn div(self, rhs: Mat4) -> Mat4 {
1764 (*self).div(rhs)
1765 }
1766}
1767
1768impl Div<f32> for Mat4 {
1769 type Output = Self;
1770 #[inline]
1771 fn div(self, rhs: f32) -> Self {
1772 self.div_scalar(rhs)
1773 }
1774}
1775
1776impl Div<&f32> for Mat4 {
1777 type Output = Self;
1778 #[inline]
1779 fn div(self, rhs: &f32) -> Self {
1780 self.div(*rhs)
1781 }
1782}
1783
1784impl Div<&f32> for &Mat4 {
1785 type Output = Mat4;
1786 #[inline]
1787 fn div(self, rhs: &f32) -> Mat4 {
1788 (*self).div(*rhs)
1789 }
1790}
1791
1792impl Div<f32> for &Mat4 {
1793 type Output = Mat4;
1794 #[inline]
1795 fn div(self, rhs: f32) -> Mat4 {
1796 (*self).div(rhs)
1797 }
1798}
1799
1800impl DivAssign<f32> for Mat4 {
1801 #[inline]
1802 fn div_assign(&mut self, rhs: f32) {
1803 *self = self.div(rhs);
1804 }
1805}
1806
1807impl DivAssign<&f32> for Mat4 {
1808 #[inline]
1809 fn div_assign(&mut self, rhs: &f32) {
1810 self.div_assign(*rhs);
1811 }
1812}
1813
1814impl Sum<Self> for Mat4 {
1815 fn sum<I>(iter: I) -> Self
1816 where
1817 I: Iterator<Item = Self>,
1818 {
1819 iter.fold(Self::ZERO, Self::add)
1820 }
1821}
1822
1823impl<'a> Sum<&'a Self> for Mat4 {
1824 fn sum<I>(iter: I) -> Self
1825 where
1826 I: Iterator<Item = &'a Self>,
1827 {
1828 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1829 }
1830}
1831
1832impl Product for Mat4 {
1833 fn product<I>(iter: I) -> Self
1834 where
1835 I: Iterator<Item = Self>,
1836 {
1837 iter.fold(Self::IDENTITY, Self::mul)
1838 }
1839}
1840
1841impl<'a> Product<&'a Self> for Mat4 {
1842 fn product<I>(iter: I) -> Self
1843 where
1844 I: Iterator<Item = &'a Self>,
1845 {
1846 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1847 }
1848}
1849
1850impl PartialEq for Mat4 {
1851 #[inline]
1852 fn eq(&self, rhs: &Self) -> bool {
1853 self.x_axis.eq(&rhs.x_axis)
1854 && self.y_axis.eq(&rhs.y_axis)
1855 && self.z_axis.eq(&rhs.z_axis)
1856 && self.w_axis.eq(&rhs.w_axis)
1857 }
1858}
1859
1860impl AsRef<[f32; 16]> for Mat4 {
1861 #[inline]
1862 fn as_ref(&self) -> &[f32; 16] {
1863 unsafe { &*(self as *const Self as *const [f32; 16]) }
1864 }
1865}
1866
1867impl AsMut<[f32; 16]> for Mat4 {
1868 #[inline]
1869 fn as_mut(&mut self) -> &mut [f32; 16] {
1870 unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
1871 }
1872}
1873
1874impl fmt::Debug for Mat4 {
1875 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1876 fmt.debug_struct(stringify!(Mat4))
1877 .field("x_axis", &self.x_axis)
1878 .field("y_axis", &self.y_axis)
1879 .field("z_axis", &self.z_axis)
1880 .field("w_axis", &self.w_axis)
1881 .finish()
1882 }
1883}
1884
1885impl fmt::Display for Mat4 {
1886 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1887 if let Some(p) = f.precision() {
1888 write!(
1889 f,
1890 "[{:.*}, {:.*}, {:.*}, {:.*}]",
1891 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
1892 )
1893 } else {
1894 write!(
1895 f,
1896 "[{}, {}, {}, {}]",
1897 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1898 )
1899 }
1900 }
1901}