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 #[must_use]
628 pub fn determinant(&self) -> f32 {
629 let (m00, m01, m02, m03) = self.x_axis.into();
630 let (m10, m11, m12, m13) = self.y_axis.into();
631 let (m20, m21, m22, m23) = self.z_axis.into();
632 let (m30, m31, m32, m33) = self.w_axis.into();
633
634 let a2323 = m22 * m33 - m23 * m32;
635 let a1323 = m21 * m33 - m23 * m31;
636 let a1223 = m21 * m32 - m22 * m31;
637 let a0323 = m20 * m33 - m23 * m30;
638 let a0223 = m20 * m32 - m22 * m30;
639 let a0123 = m20 * m31 - m21 * m30;
640
641 m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223)
642 - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223)
643 + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123)
644 - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123)
645 }
646
647 #[must_use]
655 pub fn inverse(&self) -> Self {
656 unsafe {
657 let swizzle3377 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
659 let r = vuzp2q_f32(a, b);
660 vtrn2q_f32(r, r)
661 };
662 let swizzle2266 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
663 let r = vuzp1q_f32(a, b);
664 vtrn2q_f32(r, r)
665 };
666 let swizzle0046 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
667 let r = vuzp1q_f32(a, a);
668 vuzp1q_f32(r, b)
669 };
670 let swizzle1155 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
671 let r = vzip1q_f32(a, b);
672 vzip2q_f32(r, r)
673 };
674 let swizzle0044 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
675 let r = vuzp1q_f32(a, b);
676 vtrn1q_f32(r, r)
677 };
678 let swizzle0266 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
679 let r = vuzp1q_f32(a, b);
680 vsetq_lane_f32(vgetq_lane_f32(b, 2), r, 2)
681 };
682 let swizzle0246 = |a: float32x4_t, b: float32x4_t| -> float32x4_t { vuzp1q_f32(a, b) };
683 let fac0 = {
684 let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0);
685 let swp0b = swizzle2266(self.w_axis.0, self.z_axis.0);
686
687 let swp00 = swizzle2266(self.z_axis.0, self.y_axis.0);
688 let swp01 = swizzle0046(swp0a, swp0a);
689 let swp02 = swizzle0046(swp0b, swp0b);
690 let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0);
691
692 let mul00 = vmulq_f32(swp00, swp01);
693 let mul01 = vmulq_f32(swp02, swp03);
694 vsubq_f32(mul00, mul01)
695 };
696 let fac1 = {
697 let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0);
698 let swp0b = swizzle1155(self.w_axis.0, self.z_axis.0);
699
700 let swp00 = swizzle1155(self.z_axis.0, self.y_axis.0);
701 let swp01 = swizzle0046(swp0a, swp0a);
702 let swp02 = swizzle0046(swp0b, swp0b);
703 let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0);
704
705 let mul00 = vmulq_f32(swp00, swp01);
706 let mul01 = vmulq_f32(swp02, swp03);
707 vsubq_f32(mul00, mul01)
708 };
709 let fac2 = {
710 let swp0a = swizzle2266(self.w_axis.0, self.z_axis.0);
711 let swp0b = swizzle1155(self.w_axis.0, self.z_axis.0);
712
713 let swp00 = swizzle1155(self.z_axis.0, self.y_axis.0);
714 let swp01 = swizzle0046(swp0a, swp0a);
715 let swp02 = swizzle0046(swp0b, swp0b);
716 let swp03 = swizzle2266(self.z_axis.0, self.y_axis.0);
717
718 let mul00 = vmulq_f32(swp00, swp01);
719 let mul01 = vmulq_f32(swp02, swp03);
720 vsubq_f32(mul00, mul01)
721 };
722 let fac3 = {
723 let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0);
724 let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0);
725
726 let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0);
727 let swp01 = swizzle0046(swp0a, swp0a);
728 let swp02 = swizzle0046(swp0b, swp0b);
729 let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0);
730
731 let mul00 = vmulq_f32(swp00, swp01);
732 let mul01 = vmulq_f32(swp02, swp03);
733 vsubq_f32(mul00, mul01)
734 };
735 let fac4 = {
736 let swp0a = swizzle2266(self.w_axis.0, self.z_axis.0);
737 let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0);
738
739 let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0);
740 let swp01 = swizzle0046(swp0a, swp0a);
741 let swp02 = swizzle0046(swp0b, swp0b);
742 let swp03 = swizzle2266(self.z_axis.0, self.y_axis.0);
743
744 let mul00 = vmulq_f32(swp00, swp01);
745 let mul01 = vmulq_f32(swp02, swp03);
746 vsubq_f32(mul00, mul01)
747 };
748 let fac5 = {
749 let swp0a = swizzle1155(self.w_axis.0, self.z_axis.0);
750 let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0);
751
752 let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0);
753 let swp01 = swizzle0046(swp0a, swp0a);
754 let swp02 = swizzle0046(swp0b, swp0b);
755 let swp03 = swizzle1155(self.z_axis.0, self.y_axis.0);
756
757 let mul00 = vmulq_f32(swp00, swp01);
758 let mul01 = vmulq_f32(swp02, swp03);
759 vsubq_f32(mul00, mul01)
760 };
761
762 const SIGN_A: float32x4_t = Vec4::new(-1.0, 1.0, -1.0, 1.0).0;
763 const SIGN_B: float32x4_t = Vec4::new(1.0, -1.0, 1.0, -1.0).0;
764
765 let temp0 = swizzle0044(self.y_axis.0, self.x_axis.0);
766 let vec0 = swizzle0266(temp0, temp0);
767
768 let temp1 = swizzle1155(self.y_axis.0, self.x_axis.0);
769 let vec1 = swizzle0266(temp1, temp1);
770
771 let temp2 = swizzle2266(self.y_axis.0, self.x_axis.0);
772 let vec2 = swizzle0266(temp2, temp2);
773
774 let temp3 = swizzle3377(self.y_axis.0, self.x_axis.0);
775 let vec3 = swizzle0266(temp3, temp3);
776
777 let mul00 = vmulq_f32(vec1, fac0);
778 let mul01 = vmulq_f32(vec2, fac1);
779 let mul02 = vmulq_f32(vec3, fac2);
780 let sub00 = vsubq_f32(mul00, mul01);
781 let add00 = vaddq_f32(sub00, mul02);
782 let inv0 = vmulq_f32(SIGN_B, add00);
783
784 let mul03 = vmulq_f32(vec0, fac0);
785 let mul04 = vmulq_f32(vec2, fac3);
786 let mul05 = vmulq_f32(vec3, fac4);
787 let sub01 = vsubq_f32(mul03, mul04);
788 let add01 = vaddq_f32(sub01, mul05);
789 let inv1 = vmulq_f32(SIGN_A, add01);
790
791 let mul06 = vmulq_f32(vec0, fac1);
792 let mul07 = vmulq_f32(vec1, fac3);
793 let mul08 = vmulq_f32(vec3, fac5);
794 let sub02 = vsubq_f32(mul06, mul07);
795 let add02 = vaddq_f32(sub02, mul08);
796 let inv2 = vmulq_f32(SIGN_B, add02);
797
798 let mul09 = vmulq_f32(vec0, fac2);
799 let mul10 = vmulq_f32(vec1, fac4);
800 let mul11 = vmulq_f32(vec2, fac5);
801 let sub03 = vsubq_f32(mul09, mul10);
802 let add03 = vaddq_f32(sub03, mul11);
803 let inv3 = vmulq_f32(SIGN_A, add03);
804
805 let row0 = swizzle0044(inv0, inv1);
806 let row1 = swizzle0044(inv2, inv3);
807 let row2 = swizzle0246(row0, row1);
808
809 let dot0 = dot4(self.x_axis.0, row2);
810 glam_assert!(dot0 != 0.0);
811
812 let rcp0 = dot0.recip();
813
814 Self {
815 x_axis: Vec4(vmulq_n_f32(inv0, rcp0)),
816 y_axis: Vec4(vmulq_n_f32(inv1, rcp0)),
817 z_axis: Vec4(vmulq_n_f32(inv2, rcp0)),
818 w_axis: Vec4(vmulq_n_f32(inv3, rcp0)),
819 }
820 }
821 }
822
823 #[inline]
832 #[must_use]
833 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
834 Self::look_to_rh(eye, -dir, up)
835 }
836
837 #[inline]
846 #[must_use]
847 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
848 glam_assert!(dir.is_normalized());
849 glam_assert!(up.is_normalized());
850 let f = dir;
851 let s = f.cross(up).normalize();
852 let u = s.cross(f);
853
854 Self::from_cols(
855 Vec4::new(s.x, u.x, -f.x, 0.0),
856 Vec4::new(s.y, u.y, -f.y, 0.0),
857 Vec4::new(s.z, u.z, -f.z, 0.0),
858 Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
859 )
860 }
861
862 #[inline]
871 #[must_use]
872 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
873 Self::look_to_lh(eye, center.sub(eye).normalize(), up)
874 }
875
876 #[inline]
885 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
886 Self::look_to_rh(eye, center.sub(eye).normalize(), up)
887 }
888
889 #[inline]
895 #[must_use]
896 pub fn frustum_rh_gl(
897 left: f32,
898 right: f32,
899 bottom: f32,
900 top: f32,
901 z_near: f32,
902 z_far: f32,
903 ) -> Self {
904 let inv_width = 1.0 / (right - left);
905 let inv_height = 1.0 / (top - bottom);
906 let inv_depth = 1.0 / (z_far - z_near);
907 let a = (right + left) * inv_width;
908 let b = (top + bottom) * inv_height;
909 let c = -(z_far + z_near) * inv_depth;
910 let d = -(2.0 * z_far * z_near) * inv_depth;
911 let two_z_near = 2.0 * z_near;
912 Self::from_cols(
913 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
914 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
915 Vec4::new(a, b, c, -1.0),
916 Vec4::new(0.0, 0.0, d, 0.0),
917 )
918 }
919
920 #[inline]
927 #[must_use]
928 pub fn frustum_lh(
929 left: f32,
930 right: f32,
931 bottom: f32,
932 top: f32,
933 z_near: f32,
934 z_far: f32,
935 ) -> Self {
936 glam_assert!(z_near > 0.0 && z_far > 0.0);
937 let inv_width = 1.0 / (right - left);
938 let inv_height = 1.0 / (top - bottom);
939 let inv_depth = 1.0 / (z_far - z_near);
940 let a = (right + left) * inv_width;
941 let b = (top + bottom) * inv_height;
942 let c = z_far * inv_depth;
943 let d = -(z_far * z_near) * inv_depth;
944 let two_z_near = 2.0 * z_near;
945 Self::from_cols(
946 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
947 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
948 Vec4::new(a, b, c, 1.0),
949 Vec4::new(0.0, 0.0, d, 0.0),
950 )
951 }
952
953 #[inline]
960 #[must_use]
961 pub fn frustum_rh(
962 left: f32,
963 right: f32,
964 bottom: f32,
965 top: f32,
966 z_near: f32,
967 z_far: f32,
968 ) -> Self {
969 glam_assert!(z_near > 0.0 && z_far > 0.0);
970 let inv_width = 1.0 / (right - left);
971 let inv_height = 1.0 / (top - bottom);
972 let inv_depth = 1.0 / (z_far - z_near);
973 let a = (right + left) * inv_width;
974 let b = (top + bottom) * inv_height;
975 let c = -z_far * inv_depth;
976 let d = -(z_far * z_near) * inv_depth;
977 let two_z_near = 2.0 * z_near;
978 Self::from_cols(
979 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
980 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
981 Vec4::new(a, b, c, -1.0),
982 Vec4::new(0.0, 0.0, d, 0.0),
983 )
984 }
985
986 #[inline]
993 #[must_use]
994 pub fn perspective_rh_gl(
995 fov_y_radians: f32,
996 aspect_ratio: f32,
997 z_near: f32,
998 z_far: f32,
999 ) -> Self {
1000 let inv_length = 1.0 / (z_near - z_far);
1001 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1002 let a = f / aspect_ratio;
1003 let b = (z_near + z_far) * inv_length;
1004 let c = (2.0 * z_near * z_far) * inv_length;
1005 Self::from_cols(
1006 Vec4::new(a, 0.0, 0.0, 0.0),
1007 Vec4::new(0.0, f, 0.0, 0.0),
1008 Vec4::new(0.0, 0.0, b, -1.0),
1009 Vec4::new(0.0, 0.0, c, 0.0),
1010 )
1011 }
1012
1013 #[inline]
1022 #[must_use]
1023 pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
1024 glam_assert!(z_near > 0.0 && z_far > 0.0);
1025 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1026 let h = cos_fov / sin_fov;
1027 let w = h / aspect_ratio;
1028 let r = z_far / (z_far - z_near);
1029 Self::from_cols(
1030 Vec4::new(w, 0.0, 0.0, 0.0),
1031 Vec4::new(0.0, h, 0.0, 0.0),
1032 Vec4::new(0.0, 0.0, r, 1.0),
1033 Vec4::new(0.0, 0.0, -r * z_near, 0.0),
1034 )
1035 }
1036
1037 #[inline]
1046 #[must_use]
1047 pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
1048 glam_assert!(z_near > 0.0 && z_far > 0.0);
1049 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1050 let h = cos_fov / sin_fov;
1051 let w = h / aspect_ratio;
1052 let r = z_far / (z_near - z_far);
1053 Self::from_cols(
1054 Vec4::new(w, 0.0, 0.0, 0.0),
1055 Vec4::new(0.0, h, 0.0, 0.0),
1056 Vec4::new(0.0, 0.0, r, -1.0),
1057 Vec4::new(0.0, 0.0, r * z_near, 0.0),
1058 )
1059 }
1060
1061 #[inline]
1071 #[must_use]
1072 pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1073 glam_assert!(z_near > 0.0);
1074 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1075 let h = cos_fov / sin_fov;
1076 let w = h / aspect_ratio;
1077 Self::from_cols(
1078 Vec4::new(w, 0.0, 0.0, 0.0),
1079 Vec4::new(0.0, h, 0.0, 0.0),
1080 Vec4::new(0.0, 0.0, 1.0, 1.0),
1081 Vec4::new(0.0, 0.0, -z_near, 0.0),
1082 )
1083 }
1084
1085 #[inline]
1093 #[must_use]
1094 pub fn perspective_infinite_reverse_lh(
1095 fov_y_radians: f32,
1096 aspect_ratio: f32,
1097 z_near: f32,
1098 ) -> Self {
1099 glam_assert!(z_near > 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 Self::from_cols(
1104 Vec4::new(w, 0.0, 0.0, 0.0),
1105 Vec4::new(0.0, h, 0.0, 0.0),
1106 Vec4::new(0.0, 0.0, 0.0, 1.0),
1107 Vec4::new(0.0, 0.0, z_near, 0.0),
1108 )
1109 }
1110
1111 #[inline]
1121 #[must_use]
1122 pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1123 glam_assert!(z_near > 0.0);
1124 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1125 Self::from_cols(
1126 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1127 Vec4::new(0.0, f, 0.0, 0.0),
1128 Vec4::new(0.0, 0.0, -1.0, -1.0),
1129 Vec4::new(0.0, 0.0, -z_near, 0.0),
1130 )
1131 }
1132
1133 #[inline]
1141 #[must_use]
1142 pub fn perspective_infinite_reverse_rh(
1143 fov_y_radians: f32,
1144 aspect_ratio: f32,
1145 z_near: f32,
1146 ) -> Self {
1147 glam_assert!(z_near > 0.0);
1148 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1149 Self::from_cols(
1150 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1151 Vec4::new(0.0, f, 0.0, 0.0),
1152 Vec4::new(0.0, 0.0, 0.0, -1.0),
1153 Vec4::new(0.0, 0.0, z_near, 0.0),
1154 )
1155 }
1156
1157 #[inline]
1164 #[must_use]
1165 pub fn orthographic_rh_gl(
1166 left: f32,
1167 right: f32,
1168 bottom: f32,
1169 top: f32,
1170 near: f32,
1171 far: f32,
1172 ) -> Self {
1173 let a = 2.0 / (right - left);
1174 let b = 2.0 / (top - bottom);
1175 let c = -2.0 / (far - near);
1176 let tx = -(right + left) / (right - left);
1177 let ty = -(top + bottom) / (top - bottom);
1178 let tz = -(far + near) / (far - near);
1179
1180 Self::from_cols(
1181 Vec4::new(a, 0.0, 0.0, 0.0),
1182 Vec4::new(0.0, b, 0.0, 0.0),
1183 Vec4::new(0.0, 0.0, c, 0.0),
1184 Vec4::new(tx, ty, tz, 1.0),
1185 )
1186 }
1187
1188 #[inline]
1192 #[must_use]
1193 pub fn orthographic_lh(
1194 left: f32,
1195 right: f32,
1196 bottom: f32,
1197 top: f32,
1198 near: f32,
1199 far: f32,
1200 ) -> Self {
1201 let rcp_width = 1.0 / (right - left);
1202 let rcp_height = 1.0 / (top - bottom);
1203 let r = 1.0 / (far - near);
1204 Self::from_cols(
1205 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1206 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1207 Vec4::new(0.0, 0.0, r, 0.0),
1208 Vec4::new(
1209 -(left + right) * rcp_width,
1210 -(top + bottom) * rcp_height,
1211 -r * near,
1212 1.0,
1213 ),
1214 )
1215 }
1216
1217 #[inline]
1221 #[must_use]
1222 pub fn orthographic_rh(
1223 left: f32,
1224 right: f32,
1225 bottom: f32,
1226 top: f32,
1227 near: f32,
1228 far: f32,
1229 ) -> Self {
1230 let rcp_width = 1.0 / (right - left);
1231 let rcp_height = 1.0 / (top - bottom);
1232 let r = 1.0 / (near - far);
1233 Self::from_cols(
1234 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1235 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1236 Vec4::new(0.0, 0.0, r, 0.0),
1237 Vec4::new(
1238 -(left + right) * rcp_width,
1239 -(top + bottom) * rcp_height,
1240 r * near,
1241 1.0,
1242 ),
1243 )
1244 }
1245
1246 #[inline]
1253 #[must_use]
1254 pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
1255 let mut res = self.x_axis.mul(rhs.x);
1256 res = self.y_axis.mul(rhs.y).add(res);
1257 res = self.z_axis.mul(rhs.z).add(res);
1258 res = self.w_axis.add(res);
1259 res = res.div(res.w);
1260 res.xyz()
1261 }
1262
1263 #[inline]
1276 #[must_use]
1277 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1278 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1279 let mut res = self.x_axis.mul(rhs.x);
1280 res = self.y_axis.mul(rhs.y).add(res);
1281 res = self.z_axis.mul(rhs.z).add(res);
1282 res = self.w_axis.add(res);
1283 res.xyz()
1284 }
1285
1286 #[inline]
1297 #[must_use]
1298 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1299 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1300 let mut res = self.x_axis.mul(rhs.x);
1301 res = self.y_axis.mul(rhs.y).add(res);
1302 res = self.z_axis.mul(rhs.z).add(res);
1303 res.xyz()
1304 }
1305
1306 #[inline]
1313 #[must_use]
1314 pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
1315 let mut res = self.x_axis.mul(rhs.xxxx());
1316 res = self.y_axis.mul(rhs.yyyy()).add(res);
1317 res = self.z_axis.mul(rhs.zzzz()).add(res);
1318 res = self.w_axis.add(res);
1319 res = res.div(res.wwww());
1320 Vec3A::from_vec4(res)
1321 }
1322
1323 #[inline]
1327 #[must_use]
1328 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1329 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1330 let mut res = self.x_axis.mul(rhs.xxxx());
1331 res = self.y_axis.mul(rhs.yyyy()).add(res);
1332 res = self.z_axis.mul(rhs.zzzz()).add(res);
1333 res = self.w_axis.add(res);
1334 Vec3A::from_vec4(res)
1335 }
1336
1337 #[inline]
1341 #[must_use]
1342 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1343 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1344 let mut res = self.x_axis.mul(rhs.xxxx());
1345 res = self.y_axis.mul(rhs.yyyy()).add(res);
1346 res = self.z_axis.mul(rhs.zzzz()).add(res);
1347 Vec3A::from_vec4(res)
1348 }
1349
1350 #[inline]
1352 #[must_use]
1353 pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1354 let mut res = self.x_axis.mul(rhs.xxxx());
1355 res = res.add(self.y_axis.mul(rhs.yyyy()));
1356 res = res.add(self.z_axis.mul(rhs.zzzz()));
1357 res = res.add(self.w_axis.mul(rhs.wwww()));
1358 res
1359 }
1360
1361 #[inline]
1363 #[must_use]
1364 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1365 self.mul(rhs)
1366 }
1367
1368 #[inline]
1370 #[must_use]
1371 pub fn add_mat4(&self, rhs: &Self) -> Self {
1372 self.add(rhs)
1373 }
1374
1375 #[inline]
1377 #[must_use]
1378 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1379 self.sub(rhs)
1380 }
1381
1382 #[inline]
1384 #[must_use]
1385 pub fn mul_scalar(&self, rhs: f32) -> Self {
1386 Self::from_cols(
1387 self.x_axis.mul(rhs),
1388 self.y_axis.mul(rhs),
1389 self.z_axis.mul(rhs),
1390 self.w_axis.mul(rhs),
1391 )
1392 }
1393
1394 #[inline]
1396 #[must_use]
1397 pub fn div_scalar(&self, rhs: f32) -> Self {
1398 let rhs = Vec4::splat(rhs);
1399 Self::from_cols(
1400 self.x_axis.div(rhs),
1401 self.y_axis.div(rhs),
1402 self.z_axis.div(rhs),
1403 self.w_axis.div(rhs),
1404 )
1405 }
1406
1407 #[inline]
1417 #[must_use]
1418 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1419 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1420 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1421 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1422 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1423 }
1424
1425 #[inline]
1427 #[must_use]
1428 pub fn abs(&self) -> Self {
1429 Self::from_cols(
1430 self.x_axis.abs(),
1431 self.y_axis.abs(),
1432 self.z_axis.abs(),
1433 self.w_axis.abs(),
1434 )
1435 }
1436
1437 #[inline]
1438 pub fn as_dmat4(&self) -> DMat4 {
1439 DMat4::from_cols(
1440 self.x_axis.as_dvec4(),
1441 self.y_axis.as_dvec4(),
1442 self.z_axis.as_dvec4(),
1443 self.w_axis.as_dvec4(),
1444 )
1445 }
1446}
1447
1448impl Default for Mat4 {
1449 #[inline]
1450 fn default() -> Self {
1451 Self::IDENTITY
1452 }
1453}
1454
1455impl Add for Mat4 {
1456 type Output = Self;
1457 #[inline]
1458 fn add(self, rhs: Self) -> Self {
1459 Self::from_cols(
1460 self.x_axis.add(rhs.x_axis),
1461 self.y_axis.add(rhs.y_axis),
1462 self.z_axis.add(rhs.z_axis),
1463 self.w_axis.add(rhs.w_axis),
1464 )
1465 }
1466}
1467
1468impl Add<&Self> for Mat4 {
1469 type Output = Self;
1470 #[inline]
1471 fn add(self, rhs: &Self) -> Self {
1472 self.add(*rhs)
1473 }
1474}
1475
1476impl Add<&Mat4> for &Mat4 {
1477 type Output = Mat4;
1478 #[inline]
1479 fn add(self, rhs: &Mat4) -> Mat4 {
1480 (*self).add(*rhs)
1481 }
1482}
1483
1484impl Add<Mat4> for &Mat4 {
1485 type Output = Mat4;
1486 #[inline]
1487 fn add(self, rhs: Mat4) -> Mat4 {
1488 (*self).add(rhs)
1489 }
1490}
1491
1492impl AddAssign for Mat4 {
1493 #[inline]
1494 fn add_assign(&mut self, rhs: Self) {
1495 *self = self.add(rhs);
1496 }
1497}
1498
1499impl AddAssign<&Self> for Mat4 {
1500 #[inline]
1501 fn add_assign(&mut self, rhs: &Self) {
1502 self.add_assign(*rhs);
1503 }
1504}
1505
1506impl Sub for Mat4 {
1507 type Output = Self;
1508 #[inline]
1509 fn sub(self, rhs: Self) -> Self {
1510 Self::from_cols(
1511 self.x_axis.sub(rhs.x_axis),
1512 self.y_axis.sub(rhs.y_axis),
1513 self.z_axis.sub(rhs.z_axis),
1514 self.w_axis.sub(rhs.w_axis),
1515 )
1516 }
1517}
1518
1519impl Sub<&Self> for Mat4 {
1520 type Output = Self;
1521 #[inline]
1522 fn sub(self, rhs: &Self) -> Self {
1523 self.sub(*rhs)
1524 }
1525}
1526
1527impl Sub<&Mat4> for &Mat4 {
1528 type Output = Mat4;
1529 #[inline]
1530 fn sub(self, rhs: &Mat4) -> Mat4 {
1531 (*self).sub(*rhs)
1532 }
1533}
1534
1535impl Sub<Mat4> for &Mat4 {
1536 type Output = Mat4;
1537 #[inline]
1538 fn sub(self, rhs: Mat4) -> Mat4 {
1539 (*self).sub(rhs)
1540 }
1541}
1542
1543impl SubAssign for Mat4 {
1544 #[inline]
1545 fn sub_assign(&mut self, rhs: Self) {
1546 *self = self.sub(rhs);
1547 }
1548}
1549
1550impl SubAssign<&Self> for Mat4 {
1551 #[inline]
1552 fn sub_assign(&mut self, rhs: &Self) {
1553 self.sub_assign(*rhs);
1554 }
1555}
1556
1557impl Neg for Mat4 {
1558 type Output = Self;
1559 #[inline]
1560 fn neg(self) -> Self::Output {
1561 Self::from_cols(
1562 self.x_axis.neg(),
1563 self.y_axis.neg(),
1564 self.z_axis.neg(),
1565 self.w_axis.neg(),
1566 )
1567 }
1568}
1569
1570impl Neg for &Mat4 {
1571 type Output = Mat4;
1572 #[inline]
1573 fn neg(self) -> Mat4 {
1574 (*self).neg()
1575 }
1576}
1577
1578impl Mul for Mat4 {
1579 type Output = Self;
1580 #[inline]
1581 fn mul(self, rhs: Self) -> Self {
1582 Self::from_cols(
1583 self.mul(rhs.x_axis),
1584 self.mul(rhs.y_axis),
1585 self.mul(rhs.z_axis),
1586 self.mul(rhs.w_axis),
1587 )
1588 }
1589}
1590
1591impl Mul<&Self> for Mat4 {
1592 type Output = Self;
1593 #[inline]
1594 fn mul(self, rhs: &Self) -> Self {
1595 self.mul(*rhs)
1596 }
1597}
1598
1599impl Mul<&Mat4> for &Mat4 {
1600 type Output = Mat4;
1601 #[inline]
1602 fn mul(self, rhs: &Mat4) -> Mat4 {
1603 (*self).mul(*rhs)
1604 }
1605}
1606
1607impl Mul<Mat4> for &Mat4 {
1608 type Output = Mat4;
1609 #[inline]
1610 fn mul(self, rhs: Mat4) -> Mat4 {
1611 (*self).mul(rhs)
1612 }
1613}
1614
1615impl MulAssign for Mat4 {
1616 #[inline]
1617 fn mul_assign(&mut self, rhs: Self) {
1618 *self = self.mul(rhs);
1619 }
1620}
1621
1622impl MulAssign<&Self> for Mat4 {
1623 #[inline]
1624 fn mul_assign(&mut self, rhs: &Self) {
1625 self.mul_assign(*rhs);
1626 }
1627}
1628
1629impl Mul<Vec4> for Mat4 {
1630 type Output = Vec4;
1631 #[inline]
1632 fn mul(self, rhs: Vec4) -> Self::Output {
1633 self.mul_vec4(rhs)
1634 }
1635}
1636
1637impl Mul<&Vec4> for Mat4 {
1638 type Output = Vec4;
1639 #[inline]
1640 fn mul(self, rhs: &Vec4) -> Vec4 {
1641 self.mul(*rhs)
1642 }
1643}
1644
1645impl Mul<&Vec4> for &Mat4 {
1646 type Output = Vec4;
1647 #[inline]
1648 fn mul(self, rhs: &Vec4) -> Vec4 {
1649 (*self).mul(*rhs)
1650 }
1651}
1652
1653impl Mul<Vec4> for &Mat4 {
1654 type Output = Vec4;
1655 #[inline]
1656 fn mul(self, rhs: Vec4) -> Vec4 {
1657 (*self).mul(rhs)
1658 }
1659}
1660
1661impl Mul<Mat4> for f32 {
1662 type Output = Mat4;
1663 #[inline]
1664 fn mul(self, rhs: Mat4) -> Self::Output {
1665 rhs.mul_scalar(self)
1666 }
1667}
1668
1669impl Mul<&Mat4> for f32 {
1670 type Output = Mat4;
1671 #[inline]
1672 fn mul(self, rhs: &Mat4) -> Mat4 {
1673 self.mul(*rhs)
1674 }
1675}
1676
1677impl Mul<&Mat4> for &f32 {
1678 type Output = Mat4;
1679 #[inline]
1680 fn mul(self, rhs: &Mat4) -> Mat4 {
1681 (*self).mul(*rhs)
1682 }
1683}
1684
1685impl Mul<Mat4> for &f32 {
1686 type Output = Mat4;
1687 #[inline]
1688 fn mul(self, rhs: Mat4) -> Mat4 {
1689 (*self).mul(rhs)
1690 }
1691}
1692
1693impl Mul<f32> for Mat4 {
1694 type Output = Self;
1695 #[inline]
1696 fn mul(self, rhs: f32) -> Self {
1697 self.mul_scalar(rhs)
1698 }
1699}
1700
1701impl Mul<&f32> for Mat4 {
1702 type Output = Self;
1703 #[inline]
1704 fn mul(self, rhs: &f32) -> Self {
1705 self.mul(*rhs)
1706 }
1707}
1708
1709impl Mul<&f32> for &Mat4 {
1710 type Output = Mat4;
1711 #[inline]
1712 fn mul(self, rhs: &f32) -> Mat4 {
1713 (*self).mul(*rhs)
1714 }
1715}
1716
1717impl Mul<f32> for &Mat4 {
1718 type Output = Mat4;
1719 #[inline]
1720 fn mul(self, rhs: f32) -> Mat4 {
1721 (*self).mul(rhs)
1722 }
1723}
1724
1725impl MulAssign<f32> for Mat4 {
1726 #[inline]
1727 fn mul_assign(&mut self, rhs: f32) {
1728 *self = self.mul(rhs);
1729 }
1730}
1731
1732impl MulAssign<&f32> for Mat4 {
1733 #[inline]
1734 fn mul_assign(&mut self, rhs: &f32) {
1735 self.mul_assign(*rhs);
1736 }
1737}
1738
1739impl Div<Mat4> for f32 {
1740 type Output = Mat4;
1741 #[inline]
1742 fn div(self, rhs: Mat4) -> Self::Output {
1743 rhs.div_scalar(self)
1744 }
1745}
1746
1747impl Div<&Mat4> for f32 {
1748 type Output = Mat4;
1749 #[inline]
1750 fn div(self, rhs: &Mat4) -> Mat4 {
1751 self.div(*rhs)
1752 }
1753}
1754
1755impl Div<&Mat4> for &f32 {
1756 type Output = Mat4;
1757 #[inline]
1758 fn div(self, rhs: &Mat4) -> Mat4 {
1759 (*self).div(*rhs)
1760 }
1761}
1762
1763impl Div<Mat4> for &f32 {
1764 type Output = Mat4;
1765 #[inline]
1766 fn div(self, rhs: Mat4) -> Mat4 {
1767 (*self).div(rhs)
1768 }
1769}
1770
1771impl Div<f32> for Mat4 {
1772 type Output = Self;
1773 #[inline]
1774 fn div(self, rhs: f32) -> Self {
1775 self.div_scalar(rhs)
1776 }
1777}
1778
1779impl Div<&f32> for Mat4 {
1780 type Output = Self;
1781 #[inline]
1782 fn div(self, rhs: &f32) -> Self {
1783 self.div(*rhs)
1784 }
1785}
1786
1787impl Div<&f32> for &Mat4 {
1788 type Output = Mat4;
1789 #[inline]
1790 fn div(self, rhs: &f32) -> Mat4 {
1791 (*self).div(*rhs)
1792 }
1793}
1794
1795impl Div<f32> for &Mat4 {
1796 type Output = Mat4;
1797 #[inline]
1798 fn div(self, rhs: f32) -> Mat4 {
1799 (*self).div(rhs)
1800 }
1801}
1802
1803impl DivAssign<f32> for Mat4 {
1804 #[inline]
1805 fn div_assign(&mut self, rhs: f32) {
1806 *self = self.div(rhs);
1807 }
1808}
1809
1810impl DivAssign<&f32> for Mat4 {
1811 #[inline]
1812 fn div_assign(&mut self, rhs: &f32) {
1813 self.div_assign(*rhs);
1814 }
1815}
1816
1817impl Sum<Self> for Mat4 {
1818 fn sum<I>(iter: I) -> Self
1819 where
1820 I: Iterator<Item = Self>,
1821 {
1822 iter.fold(Self::ZERO, Self::add)
1823 }
1824}
1825
1826impl<'a> Sum<&'a Self> for Mat4 {
1827 fn sum<I>(iter: I) -> Self
1828 where
1829 I: Iterator<Item = &'a Self>,
1830 {
1831 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1832 }
1833}
1834
1835impl Product for Mat4 {
1836 fn product<I>(iter: I) -> Self
1837 where
1838 I: Iterator<Item = Self>,
1839 {
1840 iter.fold(Self::IDENTITY, Self::mul)
1841 }
1842}
1843
1844impl<'a> Product<&'a Self> for Mat4 {
1845 fn product<I>(iter: I) -> Self
1846 where
1847 I: Iterator<Item = &'a Self>,
1848 {
1849 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1850 }
1851}
1852
1853impl PartialEq for Mat4 {
1854 #[inline]
1855 fn eq(&self, rhs: &Self) -> bool {
1856 self.x_axis.eq(&rhs.x_axis)
1857 && self.y_axis.eq(&rhs.y_axis)
1858 && self.z_axis.eq(&rhs.z_axis)
1859 && self.w_axis.eq(&rhs.w_axis)
1860 }
1861}
1862
1863impl AsRef<[f32; 16]> for Mat4 {
1864 #[inline]
1865 fn as_ref(&self) -> &[f32; 16] {
1866 unsafe { &*(self as *const Self as *const [f32; 16]) }
1867 }
1868}
1869
1870impl AsMut<[f32; 16]> for Mat4 {
1871 #[inline]
1872 fn as_mut(&mut self) -> &mut [f32; 16] {
1873 unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
1874 }
1875}
1876
1877impl fmt::Debug for Mat4 {
1878 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1879 fmt.debug_struct(stringify!(Mat4))
1880 .field("x_axis", &self.x_axis)
1881 .field("y_axis", &self.y_axis)
1882 .field("z_axis", &self.z_axis)
1883 .field("w_axis", &self.w_axis)
1884 .finish()
1885 }
1886}
1887
1888impl fmt::Display for Mat4 {
1889 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1890 if let Some(p) = f.precision() {
1891 write!(
1892 f,
1893 "[{:.*}, {:.*}, {:.*}, {:.*}]",
1894 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
1895 )
1896 } else {
1897 write!(
1898 f,
1899 "[{}, {}, {}, {}]",
1900 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1901 )
1902 }
1903 }
1904}