1use crate::{
4 euler::{FromEuler, ToEuler},
5 f32::math,
6 neon::*,
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
14use core::arch::aarch64::*;
15
16#[cfg(feature = "zerocopy")]
17use zerocopy_derive::*;
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#[cfg_attr(
58 feature = "zerocopy",
59 derive(FromBytes, Immutable, IntoBytes, KnownLayout)
60)]
61#[repr(C)]
62pub struct Mat4 {
63 pub x_axis: Vec4,
64 pub y_axis: Vec4,
65 pub z_axis: Vec4,
66 pub w_axis: Vec4,
67}
68
69impl Mat4 {
70 pub const ZERO: Self = Self::from_cols(Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO);
72
73 pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W);
75
76 pub const NAN: Self = Self::from_cols(Vec4::NAN, Vec4::NAN, Vec4::NAN, Vec4::NAN);
78
79 #[allow(clippy::too_many_arguments)]
80 #[inline(always)]
81 #[must_use]
82 const fn new(
83 m00: f32,
84 m01: f32,
85 m02: f32,
86 m03: f32,
87 m10: f32,
88 m11: f32,
89 m12: f32,
90 m13: f32,
91 m20: f32,
92 m21: f32,
93 m22: f32,
94 m23: f32,
95 m30: f32,
96 m31: f32,
97 m32: f32,
98 m33: f32,
99 ) -> Self {
100 Self {
101 x_axis: Vec4::new(m00, m01, m02, m03),
102 y_axis: Vec4::new(m10, m11, m12, m13),
103 z_axis: Vec4::new(m20, m21, m22, m23),
104 w_axis: Vec4::new(m30, m31, m32, m33),
105 }
106 }
107
108 #[inline(always)]
110 #[must_use]
111 pub const fn from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self {
112 Self {
113 x_axis,
114 y_axis,
115 z_axis,
116 w_axis,
117 }
118 }
119
120 #[inline]
124 #[must_use]
125 pub const fn from_cols_array(m: &[f32; 16]) -> Self {
126 Self::new(
127 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],
128 m[14], m[15],
129 )
130 }
131
132 #[inline]
135 #[must_use]
136 pub const fn to_cols_array(&self) -> [f32; 16] {
137 let [x_axis_x, x_axis_y, x_axis_z, x_axis_w] = self.x_axis.to_array();
138 let [y_axis_x, y_axis_y, y_axis_z, y_axis_w] = self.y_axis.to_array();
139 let [z_axis_x, z_axis_y, z_axis_z, z_axis_w] = self.z_axis.to_array();
140 let [w_axis_x, w_axis_y, w_axis_z, w_axis_w] = self.w_axis.to_array();
141
142 [
143 x_axis_x, x_axis_y, x_axis_z, x_axis_w, y_axis_x, y_axis_y, y_axis_z, y_axis_w,
144 z_axis_x, z_axis_y, z_axis_z, z_axis_w, w_axis_x, w_axis_y, w_axis_z, w_axis_w,
145 ]
146 }
147
148 #[inline]
152 #[must_use]
153 pub const fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self {
154 Self::from_cols(
155 Vec4::from_array(m[0]),
156 Vec4::from_array(m[1]),
157 Vec4::from_array(m[2]),
158 Vec4::from_array(m[3]),
159 )
160 }
161
162 #[inline]
165 #[must_use]
166 pub const fn to_cols_array_2d(&self) -> [[f32; 4]; 4] {
167 [
168 self.x_axis.to_array(),
169 self.y_axis.to_array(),
170 self.z_axis.to_array(),
171 self.w_axis.to_array(),
172 ]
173 }
174
175 #[doc(alias = "scale")]
177 #[inline]
178 #[must_use]
179 pub const fn from_diagonal(diagonal: Vec4) -> Self {
180 let [x, y, z, w] = diagonal.to_array();
182 Self::new(
183 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,
184 )
185 }
186
187 #[inline]
188 #[must_use]
189 fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) {
190 glam_assert!(rotation.is_normalized());
191
192 let (x, y, z, w) = rotation.into();
193 let x2 = x + x;
194 let y2 = y + y;
195 let z2 = z + z;
196 let xx = x * x2;
197 let xy = x * y2;
198 let xz = x * z2;
199 let yy = y * y2;
200 let yz = y * z2;
201 let zz = z * z2;
202 let wx = w * x2;
203 let wy = w * y2;
204 let wz = w * z2;
205
206 let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
207 let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
208 let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
209 (x_axis, y_axis, z_axis)
210 }
211
212 #[inline]
222 #[must_use]
223 pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
224 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
225 Self::from_cols(
226 x_axis.mul(scale.x),
227 y_axis.mul(scale.y),
228 z_axis.mul(scale.z),
229 Vec4::from((translation, 1.0)),
230 )
231 }
232
233 #[inline]
242 #[must_use]
243 pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
244 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
245 Self::from_cols(x_axis, y_axis, z_axis, Vec4::from((translation, 1.0)))
246 }
247
248 #[inline]
256 #[must_use]
257 pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
258 let det = self.determinant();
259 glam_assert!(det != 0.0);
260
261 let scale = Vec3::new(
262 self.x_axis.length() * math::signum(det),
263 self.y_axis.length(),
264 self.z_axis.length(),
265 );
266
267 glam_assert!(scale.cmpne(Vec3::ZERO).all());
268
269 let inv_scale = scale.recip();
270
271 let rotation = Quat::from_rotation_axes(
272 self.x_axis.mul(inv_scale.x).xyz(),
273 self.y_axis.mul(inv_scale.y).xyz(),
274 self.z_axis.mul(inv_scale.z).xyz(),
275 );
276
277 let translation = self.w_axis.xyz();
278
279 (scale, rotation, translation)
280 }
281
282 #[inline]
291 #[must_use]
292 pub fn from_quat(rotation: Quat) -> Self {
293 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
294 Self::from_cols(x_axis, y_axis, z_axis, Vec4::W)
295 }
296
297 #[inline]
303 #[must_use]
304 pub fn from_mat3(m: Mat3) -> Self {
305 Self::from_cols(
306 Vec4::from((m.x_axis, 0.0)),
307 Vec4::from((m.y_axis, 0.0)),
308 Vec4::from((m.z_axis, 0.0)),
309 Vec4::W,
310 )
311 }
312
313 #[inline]
318 #[must_use]
319 pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
320 Self::from_cols(
321 Vec4::from((mat3.x_axis, 0.0)),
322 Vec4::from((mat3.y_axis, 0.0)),
323 Vec4::from((mat3.z_axis, 0.0)),
324 Vec4::from((translation, 1.0)),
325 )
326 }
327
328 #[inline]
334 #[must_use]
335 pub fn from_mat3a(m: Mat3A) -> Self {
336 Self::from_cols(
337 Vec4::from((m.x_axis, 0.0)),
338 Vec4::from((m.y_axis, 0.0)),
339 Vec4::from((m.z_axis, 0.0)),
340 Vec4::W,
341 )
342 }
343
344 #[inline]
349 #[must_use]
350 pub fn from_translation(translation: Vec3) -> Self {
351 Self::from_cols(
352 Vec4::X,
353 Vec4::Y,
354 Vec4::Z,
355 Vec4::new(translation.x, translation.y, translation.z, 1.0),
356 )
357 }
358
359 #[inline]
369 #[must_use]
370 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
371 glam_assert!(axis.is_normalized());
372
373 let (sin, cos) = math::sin_cos(angle);
374 let axis_sin = axis.mul(sin);
375 let axis_sq = axis.mul(axis);
376 let omc = 1.0 - cos;
377 let xyomc = axis.x * axis.y * omc;
378 let xzomc = axis.x * axis.z * omc;
379 let yzomc = axis.y * axis.z * omc;
380 Self::from_cols(
381 Vec4::new(
382 axis_sq.x * omc + cos,
383 xyomc + axis_sin.z,
384 xzomc - axis_sin.y,
385 0.0,
386 ),
387 Vec4::new(
388 xyomc - axis_sin.z,
389 axis_sq.y * omc + cos,
390 yzomc + axis_sin.x,
391 0.0,
392 ),
393 Vec4::new(
394 xzomc + axis_sin.y,
395 yzomc - axis_sin.x,
396 axis_sq.z * omc + cos,
397 0.0,
398 ),
399 Vec4::W,
400 )
401 }
402
403 #[inline]
409 #[must_use]
410 pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
411 Self::from_euler_angles(order, a, b, c)
412 }
413
414 #[inline]
424 #[must_use]
425 pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
426 glam_assert!(
427 self.x_axis.xyz().is_normalized()
428 && self.y_axis.xyz().is_normalized()
429 && self.z_axis.xyz().is_normalized()
430 );
431 self.to_euler_angles(order)
432 }
433
434 #[inline]
440 #[must_use]
441 pub fn from_rotation_x(angle: f32) -> Self {
442 let (sina, cosa) = math::sin_cos(angle);
443 Self::from_cols(
444 Vec4::X,
445 Vec4::new(0.0, cosa, sina, 0.0),
446 Vec4::new(0.0, -sina, cosa, 0.0),
447 Vec4::W,
448 )
449 }
450
451 #[inline]
457 #[must_use]
458 pub fn from_rotation_y(angle: f32) -> Self {
459 let (sina, cosa) = math::sin_cos(angle);
460 Self::from_cols(
461 Vec4::new(cosa, 0.0, -sina, 0.0),
462 Vec4::Y,
463 Vec4::new(sina, 0.0, cosa, 0.0),
464 Vec4::W,
465 )
466 }
467
468 #[inline]
474 #[must_use]
475 pub fn from_rotation_z(angle: f32) -> Self {
476 let (sina, cosa) = math::sin_cos(angle);
477 Self::from_cols(
478 Vec4::new(cosa, sina, 0.0, 0.0),
479 Vec4::new(-sina, cosa, 0.0, 0.0),
480 Vec4::Z,
481 Vec4::W,
482 )
483 }
484
485 #[inline]
494 #[must_use]
495 pub fn from_scale(scale: Vec3) -> Self {
496 glam_assert!(scale.cmpne(Vec3::ZERO).any());
498
499 Self::from_cols(
500 Vec4::new(scale.x, 0.0, 0.0, 0.0),
501 Vec4::new(0.0, scale.y, 0.0, 0.0),
502 Vec4::new(0.0, 0.0, scale.z, 0.0),
503 Vec4::W,
504 )
505 }
506
507 #[inline]
513 #[must_use]
514 pub const fn from_cols_slice(slice: &[f32]) -> Self {
515 Self::new(
516 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
517 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
518 )
519 }
520
521 #[inline]
527 pub fn write_cols_to_slice(&self, slice: &mut [f32]) {
528 slice[0] = self.x_axis.x;
529 slice[1] = self.x_axis.y;
530 slice[2] = self.x_axis.z;
531 slice[3] = self.x_axis.w;
532 slice[4] = self.y_axis.x;
533 slice[5] = self.y_axis.y;
534 slice[6] = self.y_axis.z;
535 slice[7] = self.y_axis.w;
536 slice[8] = self.z_axis.x;
537 slice[9] = self.z_axis.y;
538 slice[10] = self.z_axis.z;
539 slice[11] = self.z_axis.w;
540 slice[12] = self.w_axis.x;
541 slice[13] = self.w_axis.y;
542 slice[14] = self.w_axis.z;
543 slice[15] = self.w_axis.w;
544 }
545
546 #[inline]
552 #[must_use]
553 pub fn col(&self, index: usize) -> Vec4 {
554 match index {
555 0 => self.x_axis,
556 1 => self.y_axis,
557 2 => self.z_axis,
558 3 => self.w_axis,
559 _ => panic!("index out of bounds"),
560 }
561 }
562
563 #[inline]
569 pub fn col_mut(&mut self, index: usize) -> &mut Vec4 {
570 match index {
571 0 => &mut self.x_axis,
572 1 => &mut self.y_axis,
573 2 => &mut self.z_axis,
574 3 => &mut self.w_axis,
575 _ => panic!("index out of bounds"),
576 }
577 }
578
579 #[inline]
585 #[must_use]
586 pub fn row(&self, index: usize) -> Vec4 {
587 match index {
588 0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
589 1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
590 2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
591 3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
592 _ => panic!("index out of bounds"),
593 }
594 }
595
596 #[inline]
599 #[must_use]
600 pub fn is_finite(&self) -> bool {
601 self.x_axis.is_finite()
602 && self.y_axis.is_finite()
603 && self.z_axis.is_finite()
604 && self.w_axis.is_finite()
605 }
606
607 #[inline]
609 #[must_use]
610 pub fn is_nan(&self) -> bool {
611 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
612 }
613
614 #[inline]
616 #[must_use]
617 pub fn transpose(&self) -> Self {
618 Self {
619 x_axis: Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
620 y_axis: Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
621 z_axis: Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
622 w_axis: Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
623 }
624 }
625
626 #[inline]
628 #[must_use]
629 pub fn diagonal(&self) -> Vec4 {
630 Vec4::new(self.x_axis.x, self.y_axis.y, self.z_axis.z, self.w_axis.w)
631 }
632
633 #[must_use]
635 pub fn determinant(&self) -> f32 {
636 let (m00, m01, m02, m03) = self.x_axis.into();
637 let (m10, m11, m12, m13) = self.y_axis.into();
638 let (m20, m21, m22, m23) = self.z_axis.into();
639 let (m30, m31, m32, m33) = self.w_axis.into();
640
641 let a2323 = m22 * m33 - m23 * m32;
642 let a1323 = m21 * m33 - m23 * m31;
643 let a1223 = m21 * m32 - m22 * m31;
644 let a0323 = m20 * m33 - m23 * m30;
645 let a0223 = m20 * m32 - m22 * m30;
646 let a0123 = m20 * m31 - m21 * m30;
647
648 m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223)
649 - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223)
650 + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123)
651 - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123)
652 }
653
654 #[inline(always)]
666 #[must_use]
667 fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
668 unsafe {
669 let swizzle3377 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
671 let r = vuzp2q_f32(a, b);
672 vtrn2q_f32(r, r)
673 };
674 let swizzle2266 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
675 let r = vuzp1q_f32(a, b);
676 vtrn2q_f32(r, r)
677 };
678 let swizzle0046 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
679 let r = vuzp1q_f32(a, a);
680 vuzp1q_f32(r, b)
681 };
682 let swizzle1155 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
683 let r = vzip1q_f32(a, b);
684 vzip2q_f32(r, r)
685 };
686 let swizzle0044 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
687 let r = vuzp1q_f32(a, b);
688 vtrn1q_f32(r, r)
689 };
690 let swizzle0266 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
691 let r = vuzp1q_f32(a, b);
692 vsetq_lane_f32(vgetq_lane_f32(b, 2), r, 2)
693 };
694 let swizzle0246 = |a: float32x4_t, b: float32x4_t| -> float32x4_t { vuzp1q_f32(a, b) };
695 let fac0 = {
696 let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0);
697 let swp0b = swizzle2266(self.w_axis.0, self.z_axis.0);
698
699 let swp00 = swizzle2266(self.z_axis.0, self.y_axis.0);
700 let swp01 = swizzle0046(swp0a, swp0a);
701 let swp02 = swizzle0046(swp0b, swp0b);
702 let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0);
703
704 let mul00 = vmulq_f32(swp00, swp01);
705 let mul01 = vmulq_f32(swp02, swp03);
706 vsubq_f32(mul00, mul01)
707 };
708 let fac1 = {
709 let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0);
710 let swp0b = swizzle1155(self.w_axis.0, self.z_axis.0);
711
712 let swp00 = swizzle1155(self.z_axis.0, self.y_axis.0);
713 let swp01 = swizzle0046(swp0a, swp0a);
714 let swp02 = swizzle0046(swp0b, swp0b);
715 let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0);
716
717 let mul00 = vmulq_f32(swp00, swp01);
718 let mul01 = vmulq_f32(swp02, swp03);
719 vsubq_f32(mul00, mul01)
720 };
721 let fac2 = {
722 let swp0a = swizzle2266(self.w_axis.0, self.z_axis.0);
723 let swp0b = swizzle1155(self.w_axis.0, self.z_axis.0);
724
725 let swp00 = swizzle1155(self.z_axis.0, self.y_axis.0);
726 let swp01 = swizzle0046(swp0a, swp0a);
727 let swp02 = swizzle0046(swp0b, swp0b);
728 let swp03 = swizzle2266(self.z_axis.0, self.y_axis.0);
729
730 let mul00 = vmulq_f32(swp00, swp01);
731 let mul01 = vmulq_f32(swp02, swp03);
732 vsubq_f32(mul00, mul01)
733 };
734 let fac3 = {
735 let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0);
736 let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0);
737
738 let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0);
739 let swp01 = swizzle0046(swp0a, swp0a);
740 let swp02 = swizzle0046(swp0b, swp0b);
741 let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0);
742
743 let mul00 = vmulq_f32(swp00, swp01);
744 let mul01 = vmulq_f32(swp02, swp03);
745 vsubq_f32(mul00, mul01)
746 };
747 let fac4 = {
748 let swp0a = swizzle2266(self.w_axis.0, self.z_axis.0);
749 let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0);
750
751 let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0);
752 let swp01 = swizzle0046(swp0a, swp0a);
753 let swp02 = swizzle0046(swp0b, swp0b);
754 let swp03 = swizzle2266(self.z_axis.0, self.y_axis.0);
755
756 let mul00 = vmulq_f32(swp00, swp01);
757 let mul01 = vmulq_f32(swp02, swp03);
758 vsubq_f32(mul00, mul01)
759 };
760 let fac5 = {
761 let swp0a = swizzle1155(self.w_axis.0, self.z_axis.0);
762 let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0);
763
764 let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0);
765 let swp01 = swizzle0046(swp0a, swp0a);
766 let swp02 = swizzle0046(swp0b, swp0b);
767 let swp03 = swizzle1155(self.z_axis.0, self.y_axis.0);
768
769 let mul00 = vmulq_f32(swp00, swp01);
770 let mul01 = vmulq_f32(swp02, swp03);
771 vsubq_f32(mul00, mul01)
772 };
773
774 const SIGN_A: float32x4_t = Vec4::new(-1.0, 1.0, -1.0, 1.0).0;
775 const SIGN_B: float32x4_t = Vec4::new(1.0, -1.0, 1.0, -1.0).0;
776
777 let temp0 = swizzle0044(self.y_axis.0, self.x_axis.0);
778 let vec0 = swizzle0266(temp0, temp0);
779
780 let temp1 = swizzle1155(self.y_axis.0, self.x_axis.0);
781 let vec1 = swizzle0266(temp1, temp1);
782
783 let temp2 = swizzle2266(self.y_axis.0, self.x_axis.0);
784 let vec2 = swizzle0266(temp2, temp2);
785
786 let temp3 = swizzle3377(self.y_axis.0, self.x_axis.0);
787 let vec3 = swizzle0266(temp3, temp3);
788
789 let mul00 = vmulq_f32(vec1, fac0);
790 let mul01 = vmulq_f32(vec2, fac1);
791 let mul02 = vmulq_f32(vec3, fac2);
792 let sub00 = vsubq_f32(mul00, mul01);
793 let add00 = vaddq_f32(sub00, mul02);
794 let inv0 = vmulq_f32(SIGN_B, add00);
795
796 let mul03 = vmulq_f32(vec0, fac0);
797 let mul04 = vmulq_f32(vec2, fac3);
798 let mul05 = vmulq_f32(vec3, fac4);
799 let sub01 = vsubq_f32(mul03, mul04);
800 let add01 = vaddq_f32(sub01, mul05);
801 let inv1 = vmulq_f32(SIGN_A, add01);
802
803 let mul06 = vmulq_f32(vec0, fac1);
804 let mul07 = vmulq_f32(vec1, fac3);
805 let mul08 = vmulq_f32(vec3, fac5);
806 let sub02 = vsubq_f32(mul06, mul07);
807 let add02 = vaddq_f32(sub02, mul08);
808 let inv2 = vmulq_f32(SIGN_B, add02);
809
810 let mul09 = vmulq_f32(vec0, fac2);
811 let mul10 = vmulq_f32(vec1, fac4);
812 let mul11 = vmulq_f32(vec2, fac5);
813 let sub03 = vsubq_f32(mul09, mul10);
814 let add03 = vaddq_f32(sub03, mul11);
815 let inv3 = vmulq_f32(SIGN_A, add03);
816
817 let row0 = swizzle0044(inv0, inv1);
818 let row1 = swizzle0044(inv2, inv3);
819 let row2 = swizzle0246(row0, row1);
820
821 let dot0 = dot4(self.x_axis.0, row2);
822
823 if CHECKED {
824 if dot0 == 0.0 {
825 return (Self::ZERO, false);
826 }
827 } else {
828 glam_assert!(dot0 != 0.0);
829 }
830
831 let rcp0 = dot0.recip();
832
833 (
834 Self {
835 x_axis: Vec4(vmulq_n_f32(inv0, rcp0)),
836 y_axis: Vec4(vmulq_n_f32(inv1, rcp0)),
837 z_axis: Vec4(vmulq_n_f32(inv2, rcp0)),
838 w_axis: Vec4(vmulq_n_f32(inv3, rcp0)),
839 },
840 true,
841 )
842 }
843 }
844
845 #[must_use]
853 pub fn inverse(&self) -> Self {
854 self.inverse_checked::<false>().0
855 }
856
857 #[must_use]
859 pub fn try_inverse(&self) -> Option<Self> {
860 let (m, is_valid) = self.inverse_checked::<true>();
861 if is_valid {
862 Some(m)
863 } else {
864 None
865 }
866 }
867
868 #[must_use]
870 pub fn inverse_or_zero(&self) -> Self {
871 self.inverse_checked::<true>().0
872 }
873
874 #[inline]
883 #[must_use]
884 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
885 Self::look_to_rh(eye, -dir, up)
886 }
887
888 #[inline]
897 #[must_use]
898 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
899 glam_assert!(dir.is_normalized());
900 glam_assert!(up.is_normalized());
901 let f = dir;
902 let s = f.cross(up).normalize();
903 let u = s.cross(f);
904
905 Self::from_cols(
906 Vec4::new(s.x, u.x, -f.x, 0.0),
907 Vec4::new(s.y, u.y, -f.y, 0.0),
908 Vec4::new(s.z, u.z, -f.z, 0.0),
909 Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
910 )
911 }
912
913 #[inline]
922 #[must_use]
923 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
924 Self::look_to_lh(eye, center.sub(eye).normalize(), up)
925 }
926
927 #[inline]
936 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
937 Self::look_to_rh(eye, center.sub(eye).normalize(), up)
938 }
939
940 #[inline]
946 #[must_use]
947 pub fn frustum_rh_gl(
948 left: f32,
949 right: f32,
950 bottom: f32,
951 top: f32,
952 z_near: f32,
953 z_far: f32,
954 ) -> Self {
955 let inv_width = 1.0 / (right - left);
956 let inv_height = 1.0 / (top - bottom);
957 let inv_depth = 1.0 / (z_far - z_near);
958 let a = (right + left) * inv_width;
959 let b = (top + bottom) * inv_height;
960 let c = -(z_far + z_near) * inv_depth;
961 let d = -(2.0 * z_far * z_near) * inv_depth;
962 let two_z_near = 2.0 * z_near;
963 Self::from_cols(
964 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
965 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
966 Vec4::new(a, b, c, -1.0),
967 Vec4::new(0.0, 0.0, d, 0.0),
968 )
969 }
970
971 #[inline]
978 #[must_use]
979 pub fn frustum_lh(
980 left: f32,
981 right: f32,
982 bottom: f32,
983 top: f32,
984 z_near: f32,
985 z_far: f32,
986 ) -> Self {
987 glam_assert!(z_near > 0.0 && z_far > 0.0);
988 let inv_width = 1.0 / (right - left);
989 let inv_height = 1.0 / (top - bottom);
990 let inv_depth = 1.0 / (z_far - z_near);
991 let a = (right + left) * inv_width;
992 let b = (top + bottom) * inv_height;
993 let c = z_far * inv_depth;
994 let d = -(z_far * z_near) * inv_depth;
995 let two_z_near = 2.0 * z_near;
996 Self::from_cols(
997 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
998 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
999 Vec4::new(a, b, c, 1.0),
1000 Vec4::new(0.0, 0.0, d, 0.0),
1001 )
1002 }
1003
1004 #[inline]
1011 #[must_use]
1012 pub fn frustum_rh(
1013 left: f32,
1014 right: f32,
1015 bottom: f32,
1016 top: f32,
1017 z_near: f32,
1018 z_far: f32,
1019 ) -> Self {
1020 glam_assert!(z_near > 0.0 && z_far > 0.0);
1021 let inv_width = 1.0 / (right - left);
1022 let inv_height = 1.0 / (top - bottom);
1023 let inv_depth = 1.0 / (z_far - z_near);
1024 let a = (right + left) * inv_width;
1025 let b = (top + bottom) * inv_height;
1026 let c = -z_far * inv_depth;
1027 let d = -(z_far * z_near) * inv_depth;
1028 let two_z_near = 2.0 * z_near;
1029 Self::from_cols(
1030 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
1031 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
1032 Vec4::new(a, b, c, -1.0),
1033 Vec4::new(0.0, 0.0, d, 0.0),
1034 )
1035 }
1036
1037 #[inline]
1044 #[must_use]
1045 pub fn perspective_rh_gl(
1046 fov_y_radians: f32,
1047 aspect_ratio: f32,
1048 z_near: f32,
1049 z_far: f32,
1050 ) -> Self {
1051 let inv_length = 1.0 / (z_near - z_far);
1052 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1053 let a = f / aspect_ratio;
1054 let b = (z_near + z_far) * inv_length;
1055 let c = (2.0 * z_near * z_far) * inv_length;
1056 Self::from_cols(
1057 Vec4::new(a, 0.0, 0.0, 0.0),
1058 Vec4::new(0.0, f, 0.0, 0.0),
1059 Vec4::new(0.0, 0.0, b, -1.0),
1060 Vec4::new(0.0, 0.0, c, 0.0),
1061 )
1062 }
1063
1064 #[inline]
1073 #[must_use]
1074 pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
1075 glam_assert!(z_near > 0.0 && z_far > 0.0);
1076 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1077 let h = cos_fov / sin_fov;
1078 let w = h / aspect_ratio;
1079 let r = z_far / (z_far - z_near);
1080 Self::from_cols(
1081 Vec4::new(w, 0.0, 0.0, 0.0),
1082 Vec4::new(0.0, h, 0.0, 0.0),
1083 Vec4::new(0.0, 0.0, r, 1.0),
1084 Vec4::new(0.0, 0.0, -r * z_near, 0.0),
1085 )
1086 }
1087
1088 #[inline]
1097 #[must_use]
1098 pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
1099 glam_assert!(z_near > 0.0 && z_far > 0.0);
1100 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1101 let h = cos_fov / sin_fov;
1102 let w = h / aspect_ratio;
1103 let r = z_far / (z_near - z_far);
1104 Self::from_cols(
1105 Vec4::new(w, 0.0, 0.0, 0.0),
1106 Vec4::new(0.0, h, 0.0, 0.0),
1107 Vec4::new(0.0, 0.0, r, -1.0),
1108 Vec4::new(0.0, 0.0, r * z_near, 0.0),
1109 )
1110 }
1111
1112 #[inline]
1122 #[must_use]
1123 pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1124 glam_assert!(z_near > 0.0);
1125 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1126 let h = cos_fov / sin_fov;
1127 let w = h / aspect_ratio;
1128 Self::from_cols(
1129 Vec4::new(w, 0.0, 0.0, 0.0),
1130 Vec4::new(0.0, h, 0.0, 0.0),
1131 Vec4::new(0.0, 0.0, 1.0, 1.0),
1132 Vec4::new(0.0, 0.0, -z_near, 0.0),
1133 )
1134 }
1135
1136 #[inline]
1144 #[must_use]
1145 pub fn perspective_infinite_reverse_lh(
1146 fov_y_radians: f32,
1147 aspect_ratio: f32,
1148 z_near: f32,
1149 ) -> Self {
1150 glam_assert!(z_near > 0.0);
1151 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1152 let h = cos_fov / sin_fov;
1153 let w = h / aspect_ratio;
1154 Self::from_cols(
1155 Vec4::new(w, 0.0, 0.0, 0.0),
1156 Vec4::new(0.0, h, 0.0, 0.0),
1157 Vec4::new(0.0, 0.0, 0.0, 1.0),
1158 Vec4::new(0.0, 0.0, z_near, 0.0),
1159 )
1160 }
1161
1162 #[inline]
1172 #[must_use]
1173 pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1174 glam_assert!(z_near > 0.0);
1175 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1176 Self::from_cols(
1177 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1178 Vec4::new(0.0, f, 0.0, 0.0),
1179 Vec4::new(0.0, 0.0, -1.0, -1.0),
1180 Vec4::new(0.0, 0.0, -z_near, 0.0),
1181 )
1182 }
1183
1184 #[inline]
1192 #[must_use]
1193 pub fn perspective_infinite_reverse_rh(
1194 fov_y_radians: f32,
1195 aspect_ratio: f32,
1196 z_near: f32,
1197 ) -> Self {
1198 glam_assert!(z_near > 0.0);
1199 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1200 Self::from_cols(
1201 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1202 Vec4::new(0.0, f, 0.0, 0.0),
1203 Vec4::new(0.0, 0.0, 0.0, -1.0),
1204 Vec4::new(0.0, 0.0, z_near, 0.0),
1205 )
1206 }
1207
1208 #[inline]
1215 #[must_use]
1216 pub fn orthographic_rh_gl(
1217 left: f32,
1218 right: f32,
1219 bottom: f32,
1220 top: f32,
1221 near: f32,
1222 far: f32,
1223 ) -> Self {
1224 let a = 2.0 / (right - left);
1225 let b = 2.0 / (top - bottom);
1226 let c = -2.0 / (far - near);
1227 let tx = -(right + left) / (right - left);
1228 let ty = -(top + bottom) / (top - bottom);
1229 let tz = -(far + near) / (far - near);
1230
1231 Self::from_cols(
1232 Vec4::new(a, 0.0, 0.0, 0.0),
1233 Vec4::new(0.0, b, 0.0, 0.0),
1234 Vec4::new(0.0, 0.0, c, 0.0),
1235 Vec4::new(tx, ty, tz, 1.0),
1236 )
1237 }
1238
1239 #[inline]
1243 #[must_use]
1244 pub fn orthographic_lh(
1245 left: f32,
1246 right: f32,
1247 bottom: f32,
1248 top: f32,
1249 near: f32,
1250 far: f32,
1251 ) -> Self {
1252 let rcp_width = 1.0 / (right - left);
1253 let rcp_height = 1.0 / (top - bottom);
1254 let r = 1.0 / (far - near);
1255 Self::from_cols(
1256 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1257 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1258 Vec4::new(0.0, 0.0, r, 0.0),
1259 Vec4::new(
1260 -(left + right) * rcp_width,
1261 -(top + bottom) * rcp_height,
1262 -r * near,
1263 1.0,
1264 ),
1265 )
1266 }
1267
1268 #[inline]
1272 #[must_use]
1273 pub fn orthographic_rh(
1274 left: f32,
1275 right: f32,
1276 bottom: f32,
1277 top: f32,
1278 near: f32,
1279 far: f32,
1280 ) -> Self {
1281 let rcp_width = 1.0 / (right - left);
1282 let rcp_height = 1.0 / (top - bottom);
1283 let r = 1.0 / (near - far);
1284 Self::from_cols(
1285 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1286 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1287 Vec4::new(0.0, 0.0, r, 0.0),
1288 Vec4::new(
1289 -(left + right) * rcp_width,
1290 -(top + bottom) * rcp_height,
1291 r * near,
1292 1.0,
1293 ),
1294 )
1295 }
1296
1297 #[inline]
1304 #[must_use]
1305 pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
1306 let mut res = self.x_axis.mul(rhs.x);
1307 res = self.y_axis.mul(rhs.y).add(res);
1308 res = self.z_axis.mul(rhs.z).add(res);
1309 res = self.w_axis.add(res);
1310 res = res.div(res.w);
1311 res.xyz()
1312 }
1313
1314 #[inline]
1327 #[must_use]
1328 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1329 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1330 let mut res = self.x_axis.mul(rhs.x);
1331 res = self.y_axis.mul(rhs.y).add(res);
1332 res = self.z_axis.mul(rhs.z).add(res);
1333 res = self.w_axis.add(res);
1334 res.xyz()
1335 }
1336
1337 #[inline]
1348 #[must_use]
1349 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1350 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1351 let mut res = self.x_axis.mul(rhs.x);
1352 res = self.y_axis.mul(rhs.y).add(res);
1353 res = self.z_axis.mul(rhs.z).add(res);
1354 res.xyz()
1355 }
1356
1357 #[inline]
1364 #[must_use]
1365 pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
1366 let mut res = self.x_axis.mul(rhs.xxxx());
1367 res = self.y_axis.mul(rhs.yyyy()).add(res);
1368 res = self.z_axis.mul(rhs.zzzz()).add(res);
1369 res = self.w_axis.add(res);
1370 res = res.div(res.wwww());
1371 Vec3A::from_vec4(res)
1372 }
1373
1374 #[inline]
1378 #[must_use]
1379 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1380 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1381 let mut res = self.x_axis.mul(rhs.xxxx());
1382 res = self.y_axis.mul(rhs.yyyy()).add(res);
1383 res = self.z_axis.mul(rhs.zzzz()).add(res);
1384 res = self.w_axis.add(res);
1385 Vec3A::from_vec4(res)
1386 }
1387
1388 #[inline]
1392 #[must_use]
1393 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1394 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1395 let mut res = self.x_axis.mul(rhs.xxxx());
1396 res = self.y_axis.mul(rhs.yyyy()).add(res);
1397 res = self.z_axis.mul(rhs.zzzz()).add(res);
1398 Vec3A::from_vec4(res)
1399 }
1400
1401 #[inline]
1403 #[must_use]
1404 pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1405 let mut res = self.x_axis.mul(rhs.xxxx());
1406 res = res.add(self.y_axis.mul(rhs.yyyy()));
1407 res = res.add(self.z_axis.mul(rhs.zzzz()));
1408 res = res.add(self.w_axis.mul(rhs.wwww()));
1409 res
1410 }
1411
1412 #[inline]
1414 #[must_use]
1415 pub fn mul_transpose_vec4(&self, rhs: Vec4) -> Vec4 {
1416 Vec4::new(
1417 self.x_axis.dot(rhs),
1418 self.y_axis.dot(rhs),
1419 self.z_axis.dot(rhs),
1420 self.w_axis.dot(rhs),
1421 )
1422 }
1423
1424 #[inline]
1426 #[must_use]
1427 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1428 self.mul(rhs)
1429 }
1430
1431 #[inline]
1433 #[must_use]
1434 pub fn add_mat4(&self, rhs: &Self) -> Self {
1435 self.add(rhs)
1436 }
1437
1438 #[inline]
1440 #[must_use]
1441 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1442 self.sub(rhs)
1443 }
1444
1445 #[inline]
1447 #[must_use]
1448 pub fn mul_scalar(&self, rhs: f32) -> Self {
1449 Self::from_cols(
1450 self.x_axis.mul(rhs),
1451 self.y_axis.mul(rhs),
1452 self.z_axis.mul(rhs),
1453 self.w_axis.mul(rhs),
1454 )
1455 }
1456
1457 #[inline]
1461 #[must_use]
1462 pub fn mul_diagonal_scale(&self, scale: Vec4) -> Self {
1463 Self::from_cols(
1464 self.x_axis * scale.x,
1465 self.y_axis * scale.y,
1466 self.z_axis * scale.z,
1467 self.w_axis * scale.w,
1468 )
1469 }
1470
1471 #[inline]
1473 #[must_use]
1474 pub fn div_scalar(&self, rhs: f32) -> Self {
1475 let rhs = Vec4::splat(rhs);
1476 Self::from_cols(
1477 self.x_axis.div(rhs),
1478 self.y_axis.div(rhs),
1479 self.z_axis.div(rhs),
1480 self.w_axis.div(rhs),
1481 )
1482 }
1483
1484 #[inline]
1494 #[must_use]
1495 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1496 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1497 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1498 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1499 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1500 }
1501
1502 #[inline]
1504 #[must_use]
1505 pub fn abs(&self) -> Self {
1506 Self::from_cols(
1507 self.x_axis.abs(),
1508 self.y_axis.abs(),
1509 self.z_axis.abs(),
1510 self.w_axis.abs(),
1511 )
1512 }
1513
1514 #[inline]
1515 pub fn as_dmat4(&self) -> DMat4 {
1516 DMat4::from_cols(
1517 self.x_axis.as_dvec4(),
1518 self.y_axis.as_dvec4(),
1519 self.z_axis.as_dvec4(),
1520 self.w_axis.as_dvec4(),
1521 )
1522 }
1523}
1524
1525impl Default for Mat4 {
1526 #[inline]
1527 fn default() -> Self {
1528 Self::IDENTITY
1529 }
1530}
1531
1532impl Add for Mat4 {
1533 type Output = Self;
1534 #[inline]
1535 fn add(self, rhs: Self) -> Self {
1536 Self::from_cols(
1537 self.x_axis.add(rhs.x_axis),
1538 self.y_axis.add(rhs.y_axis),
1539 self.z_axis.add(rhs.z_axis),
1540 self.w_axis.add(rhs.w_axis),
1541 )
1542 }
1543}
1544
1545impl Add<&Self> for Mat4 {
1546 type Output = Self;
1547 #[inline]
1548 fn add(self, rhs: &Self) -> Self {
1549 self.add(*rhs)
1550 }
1551}
1552
1553impl Add<&Mat4> for &Mat4 {
1554 type Output = Mat4;
1555 #[inline]
1556 fn add(self, rhs: &Mat4) -> Mat4 {
1557 (*self).add(*rhs)
1558 }
1559}
1560
1561impl Add<Mat4> for &Mat4 {
1562 type Output = Mat4;
1563 #[inline]
1564 fn add(self, rhs: Mat4) -> Mat4 {
1565 (*self).add(rhs)
1566 }
1567}
1568
1569impl AddAssign for Mat4 {
1570 #[inline]
1571 fn add_assign(&mut self, rhs: Self) {
1572 *self = self.add(rhs);
1573 }
1574}
1575
1576impl AddAssign<&Self> for Mat4 {
1577 #[inline]
1578 fn add_assign(&mut self, rhs: &Self) {
1579 self.add_assign(*rhs);
1580 }
1581}
1582
1583impl Sub for Mat4 {
1584 type Output = Self;
1585 #[inline]
1586 fn sub(self, rhs: Self) -> Self {
1587 Self::from_cols(
1588 self.x_axis.sub(rhs.x_axis),
1589 self.y_axis.sub(rhs.y_axis),
1590 self.z_axis.sub(rhs.z_axis),
1591 self.w_axis.sub(rhs.w_axis),
1592 )
1593 }
1594}
1595
1596impl Sub<&Self> for Mat4 {
1597 type Output = Self;
1598 #[inline]
1599 fn sub(self, rhs: &Self) -> Self {
1600 self.sub(*rhs)
1601 }
1602}
1603
1604impl Sub<&Mat4> for &Mat4 {
1605 type Output = Mat4;
1606 #[inline]
1607 fn sub(self, rhs: &Mat4) -> Mat4 {
1608 (*self).sub(*rhs)
1609 }
1610}
1611
1612impl Sub<Mat4> for &Mat4 {
1613 type Output = Mat4;
1614 #[inline]
1615 fn sub(self, rhs: Mat4) -> Mat4 {
1616 (*self).sub(rhs)
1617 }
1618}
1619
1620impl SubAssign for Mat4 {
1621 #[inline]
1622 fn sub_assign(&mut self, rhs: Self) {
1623 *self = self.sub(rhs);
1624 }
1625}
1626
1627impl SubAssign<&Self> for Mat4 {
1628 #[inline]
1629 fn sub_assign(&mut self, rhs: &Self) {
1630 self.sub_assign(*rhs);
1631 }
1632}
1633
1634impl Neg for Mat4 {
1635 type Output = Self;
1636 #[inline]
1637 fn neg(self) -> Self::Output {
1638 Self::from_cols(
1639 self.x_axis.neg(),
1640 self.y_axis.neg(),
1641 self.z_axis.neg(),
1642 self.w_axis.neg(),
1643 )
1644 }
1645}
1646
1647impl Neg for &Mat4 {
1648 type Output = Mat4;
1649 #[inline]
1650 fn neg(self) -> Mat4 {
1651 (*self).neg()
1652 }
1653}
1654
1655impl Mul for Mat4 {
1656 type Output = Self;
1657 #[inline]
1658 fn mul(self, rhs: Self) -> Self {
1659 Self::from_cols(
1660 self.mul(rhs.x_axis),
1661 self.mul(rhs.y_axis),
1662 self.mul(rhs.z_axis),
1663 self.mul(rhs.w_axis),
1664 )
1665 }
1666}
1667
1668impl Mul<&Self> for Mat4 {
1669 type Output = Self;
1670 #[inline]
1671 fn mul(self, rhs: &Self) -> Self {
1672 self.mul(*rhs)
1673 }
1674}
1675
1676impl Mul<&Mat4> for &Mat4 {
1677 type Output = Mat4;
1678 #[inline]
1679 fn mul(self, rhs: &Mat4) -> Mat4 {
1680 (*self).mul(*rhs)
1681 }
1682}
1683
1684impl Mul<Mat4> for &Mat4 {
1685 type Output = Mat4;
1686 #[inline]
1687 fn mul(self, rhs: Mat4) -> Mat4 {
1688 (*self).mul(rhs)
1689 }
1690}
1691
1692impl MulAssign for Mat4 {
1693 #[inline]
1694 fn mul_assign(&mut self, rhs: Self) {
1695 *self = self.mul(rhs);
1696 }
1697}
1698
1699impl MulAssign<&Self> for Mat4 {
1700 #[inline]
1701 fn mul_assign(&mut self, rhs: &Self) {
1702 self.mul_assign(*rhs);
1703 }
1704}
1705
1706impl Mul<Vec4> for Mat4 {
1707 type Output = Vec4;
1708 #[inline]
1709 fn mul(self, rhs: Vec4) -> Self::Output {
1710 self.mul_vec4(rhs)
1711 }
1712}
1713
1714impl Mul<&Vec4> for Mat4 {
1715 type Output = Vec4;
1716 #[inline]
1717 fn mul(self, rhs: &Vec4) -> Vec4 {
1718 self.mul(*rhs)
1719 }
1720}
1721
1722impl Mul<&Vec4> for &Mat4 {
1723 type Output = Vec4;
1724 #[inline]
1725 fn mul(self, rhs: &Vec4) -> Vec4 {
1726 (*self).mul(*rhs)
1727 }
1728}
1729
1730impl Mul<Vec4> for &Mat4 {
1731 type Output = Vec4;
1732 #[inline]
1733 fn mul(self, rhs: Vec4) -> Vec4 {
1734 (*self).mul(rhs)
1735 }
1736}
1737
1738impl Mul<Mat4> for f32 {
1739 type Output = Mat4;
1740 #[inline]
1741 fn mul(self, rhs: Mat4) -> Self::Output {
1742 rhs.mul_scalar(self)
1743 }
1744}
1745
1746impl Mul<&Mat4> for f32 {
1747 type Output = Mat4;
1748 #[inline]
1749 fn mul(self, rhs: &Mat4) -> Mat4 {
1750 self.mul(*rhs)
1751 }
1752}
1753
1754impl Mul<&Mat4> for &f32 {
1755 type Output = Mat4;
1756 #[inline]
1757 fn mul(self, rhs: &Mat4) -> Mat4 {
1758 (*self).mul(*rhs)
1759 }
1760}
1761
1762impl Mul<Mat4> for &f32 {
1763 type Output = Mat4;
1764 #[inline]
1765 fn mul(self, rhs: Mat4) -> Mat4 {
1766 (*self).mul(rhs)
1767 }
1768}
1769
1770impl Mul<f32> for Mat4 {
1771 type Output = Self;
1772 #[inline]
1773 fn mul(self, rhs: f32) -> Self {
1774 self.mul_scalar(rhs)
1775 }
1776}
1777
1778impl Mul<&f32> for Mat4 {
1779 type Output = Self;
1780 #[inline]
1781 fn mul(self, rhs: &f32) -> Self {
1782 self.mul(*rhs)
1783 }
1784}
1785
1786impl Mul<&f32> for &Mat4 {
1787 type Output = Mat4;
1788 #[inline]
1789 fn mul(self, rhs: &f32) -> Mat4 {
1790 (*self).mul(*rhs)
1791 }
1792}
1793
1794impl Mul<f32> for &Mat4 {
1795 type Output = Mat4;
1796 #[inline]
1797 fn mul(self, rhs: f32) -> Mat4 {
1798 (*self).mul(rhs)
1799 }
1800}
1801
1802impl MulAssign<f32> for Mat4 {
1803 #[inline]
1804 fn mul_assign(&mut self, rhs: f32) {
1805 *self = self.mul(rhs);
1806 }
1807}
1808
1809impl MulAssign<&f32> for Mat4 {
1810 #[inline]
1811 fn mul_assign(&mut self, rhs: &f32) {
1812 self.mul_assign(*rhs);
1813 }
1814}
1815
1816impl Div<Mat4> for f32 {
1817 type Output = Mat4;
1818 #[inline]
1819 fn div(self, rhs: Mat4) -> Self::Output {
1820 rhs.div_scalar(self)
1821 }
1822}
1823
1824impl Div<&Mat4> for f32 {
1825 type Output = Mat4;
1826 #[inline]
1827 fn div(self, rhs: &Mat4) -> Mat4 {
1828 self.div(*rhs)
1829 }
1830}
1831
1832impl Div<&Mat4> for &f32 {
1833 type Output = Mat4;
1834 #[inline]
1835 fn div(self, rhs: &Mat4) -> Mat4 {
1836 (*self).div(*rhs)
1837 }
1838}
1839
1840impl Div<Mat4> for &f32 {
1841 type Output = Mat4;
1842 #[inline]
1843 fn div(self, rhs: Mat4) -> Mat4 {
1844 (*self).div(rhs)
1845 }
1846}
1847
1848impl Div<f32> for Mat4 {
1849 type Output = Self;
1850 #[inline]
1851 fn div(self, rhs: f32) -> Self {
1852 self.div_scalar(rhs)
1853 }
1854}
1855
1856impl Div<&f32> for Mat4 {
1857 type Output = Self;
1858 #[inline]
1859 fn div(self, rhs: &f32) -> Self {
1860 self.div(*rhs)
1861 }
1862}
1863
1864impl Div<&f32> for &Mat4 {
1865 type Output = Mat4;
1866 #[inline]
1867 fn div(self, rhs: &f32) -> Mat4 {
1868 (*self).div(*rhs)
1869 }
1870}
1871
1872impl Div<f32> for &Mat4 {
1873 type Output = Mat4;
1874 #[inline]
1875 fn div(self, rhs: f32) -> Mat4 {
1876 (*self).div(rhs)
1877 }
1878}
1879
1880impl DivAssign<f32> for Mat4 {
1881 #[inline]
1882 fn div_assign(&mut self, rhs: f32) {
1883 *self = self.div(rhs);
1884 }
1885}
1886
1887impl DivAssign<&f32> for Mat4 {
1888 #[inline]
1889 fn div_assign(&mut self, rhs: &f32) {
1890 self.div_assign(*rhs);
1891 }
1892}
1893
1894impl Sum<Self> for Mat4 {
1895 fn sum<I>(iter: I) -> Self
1896 where
1897 I: Iterator<Item = Self>,
1898 {
1899 iter.fold(Self::ZERO, Self::add)
1900 }
1901}
1902
1903impl<'a> Sum<&'a Self> for Mat4 {
1904 fn sum<I>(iter: I) -> Self
1905 where
1906 I: Iterator<Item = &'a Self>,
1907 {
1908 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1909 }
1910}
1911
1912impl Product for Mat4 {
1913 fn product<I>(iter: I) -> Self
1914 where
1915 I: Iterator<Item = Self>,
1916 {
1917 iter.fold(Self::IDENTITY, Self::mul)
1918 }
1919}
1920
1921impl<'a> Product<&'a Self> for Mat4 {
1922 fn product<I>(iter: I) -> Self
1923 where
1924 I: Iterator<Item = &'a Self>,
1925 {
1926 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1927 }
1928}
1929
1930impl PartialEq for Mat4 {
1931 #[inline]
1932 fn eq(&self, rhs: &Self) -> bool {
1933 self.x_axis.eq(&rhs.x_axis)
1934 && self.y_axis.eq(&rhs.y_axis)
1935 && self.z_axis.eq(&rhs.z_axis)
1936 && self.w_axis.eq(&rhs.w_axis)
1937 }
1938}
1939
1940impl AsRef<[f32; 16]> for Mat4 {
1941 #[inline]
1942 fn as_ref(&self) -> &[f32; 16] {
1943 unsafe { &*(self as *const Self as *const [f32; 16]) }
1944 }
1945}
1946
1947impl AsMut<[f32; 16]> for Mat4 {
1948 #[inline]
1949 fn as_mut(&mut self) -> &mut [f32; 16] {
1950 unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
1951 }
1952}
1953
1954impl fmt::Debug for Mat4 {
1955 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1956 fmt.debug_struct(stringify!(Mat4))
1957 .field("x_axis", &self.x_axis)
1958 .field("y_axis", &self.y_axis)
1959 .field("z_axis", &self.z_axis)
1960 .field("w_axis", &self.w_axis)
1961 .finish()
1962 }
1963}
1964
1965impl fmt::Display for Mat4 {
1966 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1967 if let Some(p) = f.precision() {
1968 write!(
1969 f,
1970 "[{:.*}, {:.*}, {:.*}, {:.*}]",
1971 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
1972 )
1973 } else {
1974 write!(
1975 f,
1976 "[{}, {}, {}, {}]",
1977 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1978 )
1979 }
1980 }
1981}