1#[cfg(feature = "f64")]
4use crate::DMat4;
5
6use crate::{
7 euler::{FromEuler, ToEuler},
8 f32::math,
9 neon::*,
10 swizzles::*,
11 EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4,
12};
13use core::fmt;
14use core::iter::{Product, Sum};
15use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
16
17use core::arch::aarch64::*;
18
19#[cfg(feature = "zerocopy")]
20use zerocopy_derive::*;
21
22#[inline(always)]
24#[must_use]
25pub const fn mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat4 {
26 Mat4::from_cols(x_axis, y_axis, z_axis, w_axis)
27}
28
29#[derive(Clone, Copy)]
45#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
46#[cfg_attr(
47 feature = "zerocopy",
48 derive(FromBytes, Immutable, IntoBytes, KnownLayout)
49)]
50#[repr(C)]
51pub struct Mat4 {
52 pub x_axis: Vec4,
53 pub y_axis: Vec4,
54 pub z_axis: Vec4,
55 pub w_axis: Vec4,
56}
57
58impl Mat4 {
59 pub const ZERO: Self = Self::from_cols(Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO);
61
62 pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W);
64
65 pub const NAN: Self = Self::from_cols(Vec4::NAN, Vec4::NAN, Vec4::NAN, Vec4::NAN);
67
68 #[allow(clippy::too_many_arguments)]
69 #[inline(always)]
70 #[must_use]
71 const fn new(
72 m00: f32,
73 m01: f32,
74 m02: f32,
75 m03: f32,
76 m10: f32,
77 m11: f32,
78 m12: f32,
79 m13: f32,
80 m20: f32,
81 m21: f32,
82 m22: f32,
83 m23: f32,
84 m30: f32,
85 m31: f32,
86 m32: f32,
87 m33: f32,
88 ) -> Self {
89 Self {
90 x_axis: Vec4::new(m00, m01, m02, m03),
91 y_axis: Vec4::new(m10, m11, m12, m13),
92 z_axis: Vec4::new(m20, m21, m22, m23),
93 w_axis: Vec4::new(m30, m31, m32, m33),
94 }
95 }
96
97 #[inline(always)]
99 #[must_use]
100 pub const fn from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self {
101 Self {
102 x_axis,
103 y_axis,
104 z_axis,
105 w_axis,
106 }
107 }
108
109 #[inline]
113 #[must_use]
114 pub const fn from_cols_array(m: &[f32; 16]) -> Self {
115 Self::new(
116 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],
117 m[14], m[15],
118 )
119 }
120
121 #[inline]
124 #[must_use]
125 pub const fn to_cols_array(&self) -> [f32; 16] {
126 let [x_axis_x, x_axis_y, x_axis_z, x_axis_w] = self.x_axis.to_array();
127 let [y_axis_x, y_axis_y, y_axis_z, y_axis_w] = self.y_axis.to_array();
128 let [z_axis_x, z_axis_y, z_axis_z, z_axis_w] = self.z_axis.to_array();
129 let [w_axis_x, w_axis_y, w_axis_z, w_axis_w] = self.w_axis.to_array();
130
131 [
132 x_axis_x, x_axis_y, x_axis_z, x_axis_w, y_axis_x, y_axis_y, y_axis_z, y_axis_w,
133 z_axis_x, z_axis_y, z_axis_z, z_axis_w, w_axis_x, w_axis_y, w_axis_z, w_axis_w,
134 ]
135 }
136
137 #[inline]
141 #[must_use]
142 pub const fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self {
143 Self::from_cols(
144 Vec4::from_array(m[0]),
145 Vec4::from_array(m[1]),
146 Vec4::from_array(m[2]),
147 Vec4::from_array(m[3]),
148 )
149 }
150
151 #[inline]
154 #[must_use]
155 pub const fn to_cols_array_2d(&self) -> [[f32; 4]; 4] {
156 [
157 self.x_axis.to_array(),
158 self.y_axis.to_array(),
159 self.z_axis.to_array(),
160 self.w_axis.to_array(),
161 ]
162 }
163
164 #[doc(alias = "scale")]
166 #[inline]
167 #[must_use]
168 pub const fn from_diagonal(diagonal: Vec4) -> Self {
169 let [x, y, z, w] = diagonal.to_array();
171 Self::new(
172 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,
173 )
174 }
175
176 #[inline]
177 #[must_use]
178 fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) {
179 glam_assert!(rotation.is_normalized());
180
181 let (x, y, z, w) = rotation.into();
182 let x2 = x + x;
183 let y2 = y + y;
184 let z2 = z + z;
185 let xx = x * x2;
186 let xy = x * y2;
187 let xz = x * z2;
188 let yy = y * y2;
189 let yz = y * z2;
190 let zz = z * z2;
191 let wx = w * x2;
192 let wy = w * y2;
193 let wz = w * z2;
194
195 let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
196 let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
197 let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
198 (x_axis, y_axis, z_axis)
199 }
200
201 #[inline]
211 #[must_use]
212 pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
213 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
214 Self::from_cols(
215 x_axis.mul(scale.x),
216 y_axis.mul(scale.y),
217 z_axis.mul(scale.z),
218 Vec4::from((translation, 1.0)),
219 )
220 }
221
222 #[inline]
231 #[must_use]
232 pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
233 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
234 Self::from_cols(x_axis, y_axis, z_axis, Vec4::from((translation, 1.0)))
235 }
236
237 #[inline]
245 #[must_use]
246 pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
247 let det = self.determinant();
248 glam_assert!(det != 0.0);
249
250 let scale = Vec3::new(
251 self.x_axis.length() * math::signum(det),
252 self.y_axis.length(),
253 self.z_axis.length(),
254 );
255
256 glam_assert!(scale.cmpne(Vec3::ZERO).all());
257
258 let inv_scale = scale.recip();
259
260 let rotation = Quat::from_rotation_axes(
261 self.x_axis.mul(inv_scale.x).xyz(),
262 self.y_axis.mul(inv_scale.y).xyz(),
263 self.z_axis.mul(inv_scale.z).xyz(),
264 );
265
266 let translation = self.w_axis.xyz();
267
268 (scale, rotation, translation)
269 }
270
271 #[inline]
280 #[must_use]
281 pub fn from_quat(rotation: Quat) -> Self {
282 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
283 Self::from_cols(x_axis, y_axis, z_axis, Vec4::W)
284 }
285
286 #[inline]
292 #[must_use]
293 pub fn from_mat3(m: Mat3) -> Self {
294 Self::from_cols(
295 Vec4::from((m.x_axis, 0.0)),
296 Vec4::from((m.y_axis, 0.0)),
297 Vec4::from((m.z_axis, 0.0)),
298 Vec4::W,
299 )
300 }
301
302 #[inline]
307 #[must_use]
308 pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
309 Self::from_cols(
310 Vec4::from((mat3.x_axis, 0.0)),
311 Vec4::from((mat3.y_axis, 0.0)),
312 Vec4::from((mat3.z_axis, 0.0)),
313 Vec4::from((translation, 1.0)),
314 )
315 }
316
317 #[inline]
323 #[must_use]
324 pub fn from_mat3a(m: Mat3A) -> Self {
325 Self::from_cols(
326 Vec4::from((m.x_axis, 0.0)),
327 Vec4::from((m.y_axis, 0.0)),
328 Vec4::from((m.z_axis, 0.0)),
329 Vec4::W,
330 )
331 }
332
333 #[inline]
338 #[must_use]
339 pub fn from_translation(translation: Vec3) -> Self {
340 Self::from_cols(
341 Vec4::X,
342 Vec4::Y,
343 Vec4::Z,
344 Vec4::new(translation.x, translation.y, translation.z, 1.0),
345 )
346 }
347
348 #[inline]
358 #[must_use]
359 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
360 glam_assert!(axis.is_normalized());
361
362 let (sin, cos) = math::sin_cos(angle);
363 let axis_sin = axis.mul(sin);
364 let axis_sq = axis.mul(axis);
365 let omc = 1.0 - cos;
366 let xyomc = axis.x * axis.y * omc;
367 let xzomc = axis.x * axis.z * omc;
368 let yzomc = axis.y * axis.z * omc;
369 Self::from_cols(
370 Vec4::new(
371 axis_sq.x * omc + cos,
372 xyomc + axis_sin.z,
373 xzomc - axis_sin.y,
374 0.0,
375 ),
376 Vec4::new(
377 xyomc - axis_sin.z,
378 axis_sq.y * omc + cos,
379 yzomc + axis_sin.x,
380 0.0,
381 ),
382 Vec4::new(
383 xzomc + axis_sin.y,
384 yzomc - axis_sin.x,
385 axis_sq.z * omc + cos,
386 0.0,
387 ),
388 Vec4::W,
389 )
390 }
391
392 #[inline]
398 #[must_use]
399 pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
400 Self::from_euler_angles(order, a, b, c)
401 }
402
403 #[inline]
413 #[must_use]
414 pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
415 glam_assert!(
416 self.x_axis.xyz().is_normalized()
417 && self.y_axis.xyz().is_normalized()
418 && self.z_axis.xyz().is_normalized()
419 );
420 self.to_euler_angles(order)
421 }
422
423 #[inline]
429 #[must_use]
430 pub fn from_rotation_x(angle: f32) -> Self {
431 let (sina, cosa) = math::sin_cos(angle);
432 Self::from_cols(
433 Vec4::X,
434 Vec4::new(0.0, cosa, sina, 0.0),
435 Vec4::new(0.0, -sina, cosa, 0.0),
436 Vec4::W,
437 )
438 }
439
440 #[inline]
446 #[must_use]
447 pub fn from_rotation_y(angle: f32) -> Self {
448 let (sina, cosa) = math::sin_cos(angle);
449 Self::from_cols(
450 Vec4::new(cosa, 0.0, -sina, 0.0),
451 Vec4::Y,
452 Vec4::new(sina, 0.0, cosa, 0.0),
453 Vec4::W,
454 )
455 }
456
457 #[inline]
463 #[must_use]
464 pub fn from_rotation_z(angle: f32) -> Self {
465 let (sina, cosa) = math::sin_cos(angle);
466 Self::from_cols(
467 Vec4::new(cosa, sina, 0.0, 0.0),
468 Vec4::new(-sina, cosa, 0.0, 0.0),
469 Vec4::Z,
470 Vec4::W,
471 )
472 }
473
474 #[inline]
483 #[must_use]
484 pub fn from_scale(scale: Vec3) -> Self {
485 glam_assert!(scale.cmpne(Vec3::ZERO).any());
487
488 Self::from_cols(
489 Vec4::new(scale.x, 0.0, 0.0, 0.0),
490 Vec4::new(0.0, scale.y, 0.0, 0.0),
491 Vec4::new(0.0, 0.0, scale.z, 0.0),
492 Vec4::W,
493 )
494 }
495
496 #[inline]
502 #[must_use]
503 pub const fn from_cols_slice(slice: &[f32]) -> Self {
504 Self::new(
505 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
506 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
507 )
508 }
509
510 #[inline]
516 pub fn write_cols_to_slice(&self, slice: &mut [f32]) {
517 slice[0] = self.x_axis.x;
518 slice[1] = self.x_axis.y;
519 slice[2] = self.x_axis.z;
520 slice[3] = self.x_axis.w;
521 slice[4] = self.y_axis.x;
522 slice[5] = self.y_axis.y;
523 slice[6] = self.y_axis.z;
524 slice[7] = self.y_axis.w;
525 slice[8] = self.z_axis.x;
526 slice[9] = self.z_axis.y;
527 slice[10] = self.z_axis.z;
528 slice[11] = self.z_axis.w;
529 slice[12] = self.w_axis.x;
530 slice[13] = self.w_axis.y;
531 slice[14] = self.w_axis.z;
532 slice[15] = self.w_axis.w;
533 }
534
535 #[inline]
541 #[must_use]
542 pub fn col(&self, index: usize) -> Vec4 {
543 match index {
544 0 => self.x_axis,
545 1 => self.y_axis,
546 2 => self.z_axis,
547 3 => self.w_axis,
548 _ => panic!("index out of bounds"),
549 }
550 }
551
552 #[inline]
558 pub fn col_mut(&mut self, index: usize) -> &mut Vec4 {
559 match index {
560 0 => &mut self.x_axis,
561 1 => &mut self.y_axis,
562 2 => &mut self.z_axis,
563 3 => &mut self.w_axis,
564 _ => panic!("index out of bounds"),
565 }
566 }
567
568 #[inline]
574 #[must_use]
575 pub fn row(&self, index: usize) -> Vec4 {
576 match index {
577 0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
578 1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
579 2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
580 3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
581 _ => panic!("index out of bounds"),
582 }
583 }
584
585 #[inline]
588 #[must_use]
589 pub fn is_finite(&self) -> bool {
590 self.x_axis.is_finite()
591 && self.y_axis.is_finite()
592 && self.z_axis.is_finite()
593 && self.w_axis.is_finite()
594 }
595
596 #[inline]
598 #[must_use]
599 pub fn is_nan(&self) -> bool {
600 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
601 }
602
603 #[inline]
605 #[must_use]
606 pub fn transpose(&self) -> Self {
607 Self {
608 x_axis: Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
609 y_axis: Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
610 z_axis: Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
611 w_axis: Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
612 }
613 }
614
615 #[inline]
617 #[must_use]
618 pub fn diagonal(&self) -> Vec4 {
619 Vec4::new(self.x_axis.x, self.y_axis.y, self.z_axis.z, self.w_axis.w)
620 }
621
622 #[must_use]
624 pub fn determinant(&self) -> f32 {
625 let (m00, m01, m02, m03) = self.x_axis.into();
626 let (m10, m11, m12, m13) = self.y_axis.into();
627 let (m20, m21, m22, m23) = self.z_axis.into();
628 let (m30, m31, m32, m33) = self.w_axis.into();
629
630 let a2323 = m22 * m33 - m23 * m32;
631 let a1323 = m21 * m33 - m23 * m31;
632 let a1223 = m21 * m32 - m22 * m31;
633 let a0323 = m20 * m33 - m23 * m30;
634 let a0223 = m20 * m32 - m22 * m30;
635 let a0123 = m20 * m31 - m21 * m30;
636
637 m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223)
638 - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223)
639 + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123)
640 - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123)
641 }
642
643 #[inline(always)]
655 #[must_use]
656 fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
657 unsafe {
658 let swizzle3377 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
660 let r = vuzp2q_f32(a, b);
661 vtrn2q_f32(r, r)
662 };
663 let swizzle2266 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
664 let r = vuzp1q_f32(a, b);
665 vtrn2q_f32(r, r)
666 };
667 let swizzle0046 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
668 let r = vuzp1q_f32(a, a);
669 vuzp1q_f32(r, b)
670 };
671 let swizzle1155 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
672 let r = vzip1q_f32(a, b);
673 vzip2q_f32(r, r)
674 };
675 let swizzle0044 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
676 let r = vuzp1q_f32(a, b);
677 vtrn1q_f32(r, r)
678 };
679 let swizzle0266 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
680 let r = vuzp1q_f32(a, b);
681 vsetq_lane_f32(vgetq_lane_f32(b, 2), r, 2)
682 };
683 let swizzle0246 = |a: float32x4_t, b: float32x4_t| -> float32x4_t { vuzp1q_f32(a, b) };
684 let fac0 = {
685 let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0);
686 let swp0b = swizzle2266(self.w_axis.0, self.z_axis.0);
687
688 let swp00 = swizzle2266(self.z_axis.0, self.y_axis.0);
689 let swp01 = swizzle0046(swp0a, swp0a);
690 let swp02 = swizzle0046(swp0b, swp0b);
691 let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0);
692
693 let mul00 = vmulq_f32(swp00, swp01);
694 let mul01 = vmulq_f32(swp02, swp03);
695 vsubq_f32(mul00, mul01)
696 };
697 let fac1 = {
698 let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0);
699 let swp0b = swizzle1155(self.w_axis.0, self.z_axis.0);
700
701 let swp00 = swizzle1155(self.z_axis.0, self.y_axis.0);
702 let swp01 = swizzle0046(swp0a, swp0a);
703 let swp02 = swizzle0046(swp0b, swp0b);
704 let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0);
705
706 let mul00 = vmulq_f32(swp00, swp01);
707 let mul01 = vmulq_f32(swp02, swp03);
708 vsubq_f32(mul00, mul01)
709 };
710 let fac2 = {
711 let swp0a = swizzle2266(self.w_axis.0, self.z_axis.0);
712 let swp0b = swizzle1155(self.w_axis.0, self.z_axis.0);
713
714 let swp00 = swizzle1155(self.z_axis.0, self.y_axis.0);
715 let swp01 = swizzle0046(swp0a, swp0a);
716 let swp02 = swizzle0046(swp0b, swp0b);
717 let swp03 = swizzle2266(self.z_axis.0, self.y_axis.0);
718
719 let mul00 = vmulq_f32(swp00, swp01);
720 let mul01 = vmulq_f32(swp02, swp03);
721 vsubq_f32(mul00, mul01)
722 };
723 let fac3 = {
724 let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0);
725 let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0);
726
727 let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0);
728 let swp01 = swizzle0046(swp0a, swp0a);
729 let swp02 = swizzle0046(swp0b, swp0b);
730 let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0);
731
732 let mul00 = vmulq_f32(swp00, swp01);
733 let mul01 = vmulq_f32(swp02, swp03);
734 vsubq_f32(mul00, mul01)
735 };
736 let fac4 = {
737 let swp0a = swizzle2266(self.w_axis.0, self.z_axis.0);
738 let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0);
739
740 let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0);
741 let swp01 = swizzle0046(swp0a, swp0a);
742 let swp02 = swizzle0046(swp0b, swp0b);
743 let swp03 = swizzle2266(self.z_axis.0, self.y_axis.0);
744
745 let mul00 = vmulq_f32(swp00, swp01);
746 let mul01 = vmulq_f32(swp02, swp03);
747 vsubq_f32(mul00, mul01)
748 };
749 let fac5 = {
750 let swp0a = swizzle1155(self.w_axis.0, self.z_axis.0);
751 let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0);
752
753 let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0);
754 let swp01 = swizzle0046(swp0a, swp0a);
755 let swp02 = swizzle0046(swp0b, swp0b);
756 let swp03 = swizzle1155(self.z_axis.0, self.y_axis.0);
757
758 let mul00 = vmulq_f32(swp00, swp01);
759 let mul01 = vmulq_f32(swp02, swp03);
760 vsubq_f32(mul00, mul01)
761 };
762
763 const SIGN_A: float32x4_t = Vec4::new(-1.0, 1.0, -1.0, 1.0).0;
764 const SIGN_B: float32x4_t = Vec4::new(1.0, -1.0, 1.0, -1.0).0;
765
766 let temp0 = swizzle0044(self.y_axis.0, self.x_axis.0);
767 let vec0 = swizzle0266(temp0, temp0);
768
769 let temp1 = swizzle1155(self.y_axis.0, self.x_axis.0);
770 let vec1 = swizzle0266(temp1, temp1);
771
772 let temp2 = swizzle2266(self.y_axis.0, self.x_axis.0);
773 let vec2 = swizzle0266(temp2, temp2);
774
775 let temp3 = swizzle3377(self.y_axis.0, self.x_axis.0);
776 let vec3 = swizzle0266(temp3, temp3);
777
778 let mul00 = vmulq_f32(vec1, fac0);
779 let mul01 = vmulq_f32(vec2, fac1);
780 let mul02 = vmulq_f32(vec3, fac2);
781 let sub00 = vsubq_f32(mul00, mul01);
782 let add00 = vaddq_f32(sub00, mul02);
783 let inv0 = vmulq_f32(SIGN_B, add00);
784
785 let mul03 = vmulq_f32(vec0, fac0);
786 let mul04 = vmulq_f32(vec2, fac3);
787 let mul05 = vmulq_f32(vec3, fac4);
788 let sub01 = vsubq_f32(mul03, mul04);
789 let add01 = vaddq_f32(sub01, mul05);
790 let inv1 = vmulq_f32(SIGN_A, add01);
791
792 let mul06 = vmulq_f32(vec0, fac1);
793 let mul07 = vmulq_f32(vec1, fac3);
794 let mul08 = vmulq_f32(vec3, fac5);
795 let sub02 = vsubq_f32(mul06, mul07);
796 let add02 = vaddq_f32(sub02, mul08);
797 let inv2 = vmulq_f32(SIGN_B, add02);
798
799 let mul09 = vmulq_f32(vec0, fac2);
800 let mul10 = vmulq_f32(vec1, fac4);
801 let mul11 = vmulq_f32(vec2, fac5);
802 let sub03 = vsubq_f32(mul09, mul10);
803 let add03 = vaddq_f32(sub03, mul11);
804 let inv3 = vmulq_f32(SIGN_A, add03);
805
806 let row0 = swizzle0044(inv0, inv1);
807 let row1 = swizzle0044(inv2, inv3);
808 let row2 = swizzle0246(row0, row1);
809
810 let dot0 = dot4(self.x_axis.0, row2);
811
812 if CHECKED {
813 if dot0 == 0.0 {
814 return (Self::ZERO, false);
815 }
816 } else {
817 glam_assert!(dot0 != 0.0);
818 }
819
820 let rcp0 = dot0.recip();
821
822 (
823 Self {
824 x_axis: Vec4(vmulq_n_f32(inv0, rcp0)),
825 y_axis: Vec4(vmulq_n_f32(inv1, rcp0)),
826 z_axis: Vec4(vmulq_n_f32(inv2, rcp0)),
827 w_axis: Vec4(vmulq_n_f32(inv3, rcp0)),
828 },
829 true,
830 )
831 }
832 }
833
834 #[must_use]
842 pub fn inverse(&self) -> Self {
843 self.inverse_checked::<false>().0
844 }
845
846 #[must_use]
848 pub fn try_inverse(&self) -> Option<Self> {
849 let (m, is_valid) = self.inverse_checked::<true>();
850 if is_valid {
851 Some(m)
852 } else {
853 None
854 }
855 }
856
857 #[must_use]
859 pub fn inverse_or_zero(&self) -> Self {
860 self.inverse_checked::<true>().0
861 }
862
863 #[deprecated(
872 since = "0.33.1",
873 note = "use the `glam::camera::lh::view::look_to_mat4` function instead"
874 )]
875 #[inline]
876 #[must_use]
877 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
878 #[allow(deprecated)]
879 Self::look_to_rh(eye, -dir, up)
880 }
881
882 #[deprecated(
891 since = "0.33.1",
892 note = "use the `glam::camera::rh::view::look_to_mat4` function instead"
893 )]
894 #[inline]
895 #[must_use]
896 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
897 glam_assert!(dir.is_normalized());
898 glam_assert!(up.is_normalized());
899 let f = dir;
900 let s = f.cross(up).normalize();
901 let u = s.cross(f);
902
903 Self::from_cols(
904 Vec4::new(s.x, u.x, -f.x, 0.0),
905 Vec4::new(s.y, u.y, -f.y, 0.0),
906 Vec4::new(s.z, u.z, -f.z, 0.0),
907 Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
908 )
909 }
910
911 #[deprecated(
920 since = "0.33.1",
921 note = "use the `glam::camera::lh::view::look_at_mat4` function instead"
922 )]
923 #[inline]
924 #[must_use]
925 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
926 #[allow(deprecated)]
927 Self::look_to_lh(eye, center.sub(eye).normalize(), up)
928 }
929
930 #[deprecated(
939 since = "0.33.1",
940 note = "use the `glam::camera::rh::view::look_at_mat4` function instead"
941 )]
942 #[inline]
943 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
944 #[allow(deprecated)]
945 Self::look_to_rh(eye, center.sub(eye).normalize(), up)
946 }
947
948 #[deprecated(
954 since = "0.33.1",
955 note = "use the `glam::camera::rh::proj::opengl::frustum` function instead"
956 )]
957 #[inline]
958 #[must_use]
959 pub fn frustum_rh_gl(
960 left: f32,
961 right: f32,
962 bottom: f32,
963 top: f32,
964 z_near: f32,
965 z_far: f32,
966 ) -> Self {
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 + z_near) * inv_depth;
973 let d = -(2.0 * 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 #[deprecated(
990 since = "0.33.1",
991 note = "use the `glam::camera::lh::proj::directx::frustum` function instead"
992 )]
993 #[inline]
994 #[must_use]
995 pub fn frustum_lh(
996 left: f32,
997 right: f32,
998 bottom: f32,
999 top: f32,
1000 z_near: f32,
1001 z_far: f32,
1002 ) -> Self {
1003 glam_assert!(z_near > 0.0 && z_far > 0.0);
1004 let inv_width = 1.0 / (right - left);
1005 let inv_height = 1.0 / (top - bottom);
1006 let inv_depth = 1.0 / (z_far - z_near);
1007 let a = (right + left) * inv_width;
1008 let b = (top + bottom) * inv_height;
1009 let c = z_far * inv_depth;
1010 let d = -(z_far * z_near) * inv_depth;
1011 let two_z_near = 2.0 * z_near;
1012 Self::from_cols(
1013 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
1014 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
1015 Vec4::new(a, b, c, 1.0),
1016 Vec4::new(0.0, 0.0, d, 0.0),
1017 )
1018 }
1019
1020 #[deprecated(
1027 since = "0.33.1",
1028 note = "use the `glam::camera::rh::proj::directx::frustum` function instead"
1029 )]
1030 #[inline]
1031 #[must_use]
1032 pub fn frustum_rh(
1033 left: f32,
1034 right: f32,
1035 bottom: f32,
1036 top: f32,
1037 z_near: f32,
1038 z_far: f32,
1039 ) -> Self {
1040 glam_assert!(z_near > 0.0 && z_far > 0.0);
1041 let inv_width = 1.0 / (right - left);
1042 let inv_height = 1.0 / (top - bottom);
1043 let inv_depth = 1.0 / (z_far - z_near);
1044 let a = (right + left) * inv_width;
1045 let b = (top + bottom) * inv_height;
1046 let c = -z_far * inv_depth;
1047 let d = -(z_far * z_near) * inv_depth;
1048 let two_z_near = 2.0 * z_near;
1049 Self::from_cols(
1050 Vec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
1051 Vec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
1052 Vec4::new(a, b, c, -1.0),
1053 Vec4::new(0.0, 0.0, d, 0.0),
1054 )
1055 }
1056
1057 #[deprecated(
1064 since = "0.33.1",
1065 note = "use the `glam::camera::rh::proj::opengl::perspective` function instead"
1066 )]
1067 #[inline]
1068 #[must_use]
1069 pub fn perspective_rh_gl(
1070 fov_y_radians: f32,
1071 aspect_ratio: f32,
1072 z_near: f32,
1073 z_far: f32,
1074 ) -> Self {
1075 let inv_length = 1.0 / (z_near - z_far);
1076 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1077 let a = f / aspect_ratio;
1078 let b = (z_near + z_far) * inv_length;
1079 let c = (2.0 * z_near * z_far) * inv_length;
1080 Self::from_cols(
1081 Vec4::new(a, 0.0, 0.0, 0.0),
1082 Vec4::new(0.0, f, 0.0, 0.0),
1083 Vec4::new(0.0, 0.0, b, -1.0),
1084 Vec4::new(0.0, 0.0, c, 0.0),
1085 )
1086 }
1087
1088 #[deprecated(
1097 since = "0.33.1",
1098 note = "use the `glam::camera::lh::proj::directx::perspective` function instead"
1099 )]
1100 #[inline]
1101 #[must_use]
1102 pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
1103 glam_assert!(z_near > 0.0 && z_far > 0.0);
1104 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1105 let h = cos_fov / sin_fov;
1106 let w = h / aspect_ratio;
1107 let r = z_far / (z_far - z_near);
1108 Self::from_cols(
1109 Vec4::new(w, 0.0, 0.0, 0.0),
1110 Vec4::new(0.0, h, 0.0, 0.0),
1111 Vec4::new(0.0, 0.0, r, 1.0),
1112 Vec4::new(0.0, 0.0, -r * z_near, 0.0),
1113 )
1114 }
1115
1116 #[deprecated(
1125 since = "0.33.1",
1126 note = "use the `glam::camera::rh::proj::directx::perspective` function instead"
1127 )]
1128 #[inline]
1129 #[must_use]
1130 pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
1131 glam_assert!(z_near > 0.0 && z_far > 0.0);
1132 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1133 let h = cos_fov / sin_fov;
1134 let w = h / aspect_ratio;
1135 let r = z_far / (z_near - z_far);
1136 Self::from_cols(
1137 Vec4::new(w, 0.0, 0.0, 0.0),
1138 Vec4::new(0.0, h, 0.0, 0.0),
1139 Vec4::new(0.0, 0.0, r, -1.0),
1140 Vec4::new(0.0, 0.0, r * z_near, 0.0),
1141 )
1142 }
1143
1144 #[deprecated(
1154 since = "0.33.1",
1155 note = "use the `glam::camera::lh::proj::directx::perspective_infinite` function instead"
1156 )]
1157 #[inline]
1158 #[must_use]
1159 pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1160 glam_assert!(z_near > 0.0);
1161 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1162 let h = cos_fov / sin_fov;
1163 let w = h / aspect_ratio;
1164 Self::from_cols(
1165 Vec4::new(w, 0.0, 0.0, 0.0),
1166 Vec4::new(0.0, h, 0.0, 0.0),
1167 Vec4::new(0.0, 0.0, 1.0, 1.0),
1168 Vec4::new(0.0, 0.0, -z_near, 0.0),
1169 )
1170 }
1171
1172 #[deprecated(
1180 since = "0.33.1",
1181 note = "use the `glam::camera::lh::proj::directx::perspective_infinite_reverse` function instead"
1182 )]
1183 #[inline]
1184 #[must_use]
1185 pub fn perspective_infinite_reverse_lh(
1186 fov_y_radians: f32,
1187 aspect_ratio: f32,
1188 z_near: f32,
1189 ) -> Self {
1190 glam_assert!(z_near > 0.0);
1191 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1192 let h = cos_fov / sin_fov;
1193 let w = h / aspect_ratio;
1194 Self::from_cols(
1195 Vec4::new(w, 0.0, 0.0, 0.0),
1196 Vec4::new(0.0, h, 0.0, 0.0),
1197 Vec4::new(0.0, 0.0, 0.0, 1.0),
1198 Vec4::new(0.0, 0.0, z_near, 0.0),
1199 )
1200 }
1201
1202 #[deprecated(
1212 since = "0.33.1",
1213 note = "use the `glam::camera::rh::proj::directx::perspective_infinite` function instead"
1214 )]
1215 #[inline]
1216 #[must_use]
1217 pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1218 glam_assert!(z_near > 0.0);
1219 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1220 Self::from_cols(
1221 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1222 Vec4::new(0.0, f, 0.0, 0.0),
1223 Vec4::new(0.0, 0.0, -1.0, -1.0),
1224 Vec4::new(0.0, 0.0, -z_near, 0.0),
1225 )
1226 }
1227
1228 #[deprecated(
1236 since = "0.33.1",
1237 note = "use the `glam::camera::rh::proj::directx::perspective_infinite_reverse` function instead"
1238 )]
1239 #[inline]
1240 #[must_use]
1241 pub fn perspective_infinite_reverse_rh(
1242 fov_y_radians: f32,
1243 aspect_ratio: f32,
1244 z_near: f32,
1245 ) -> Self {
1246 glam_assert!(z_near > 0.0);
1247 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1248 Self::from_cols(
1249 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1250 Vec4::new(0.0, f, 0.0, 0.0),
1251 Vec4::new(0.0, 0.0, 0.0, -1.0),
1252 Vec4::new(0.0, 0.0, z_near, 0.0),
1253 )
1254 }
1255
1256 #[deprecated(
1263 since = "0.33.1",
1264 note = "use the `glam::camera::rh::proj::opengl::orthographic` function instead"
1265 )]
1266 #[inline]
1267 #[must_use]
1268 pub fn orthographic_rh_gl(
1269 left: f32,
1270 right: f32,
1271 bottom: f32,
1272 top: f32,
1273 near: f32,
1274 far: f32,
1275 ) -> Self {
1276 let a = 2.0 / (right - left);
1277 let b = 2.0 / (top - bottom);
1278 let c = 2.0 / (near - far);
1279 let tx = -(right + left) / (right - left);
1280 let ty = -(top + bottom) / (top - bottom);
1281 let tz = -(far + near) / (far - near);
1282
1283 Self::from_cols(
1284 Vec4::new(a, 0.0, 0.0, 0.0),
1285 Vec4::new(0.0, b, 0.0, 0.0),
1286 Vec4::new(0.0, 0.0, c, 0.0),
1287 Vec4::new(tx, ty, tz, 1.0),
1288 )
1289 }
1290
1291 #[deprecated(
1295 since = "0.33.1",
1296 note = "use the `glam::camera::lh::proj::directx::orthographic` function instead"
1297 )]
1298 #[inline]
1299 #[must_use]
1300 pub fn orthographic_lh(
1301 left: f32,
1302 right: f32,
1303 bottom: f32,
1304 top: f32,
1305 near: f32,
1306 far: f32,
1307 ) -> Self {
1308 let rcp_width = 1.0 / (right - left);
1309 let rcp_height = 1.0 / (top - bottom);
1310 let r = 1.0 / (far - near);
1311 Self::from_cols(
1312 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1313 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1314 Vec4::new(0.0, 0.0, r, 0.0),
1315 Vec4::new(
1316 -(left + right) * rcp_width,
1317 -(top + bottom) * rcp_height,
1318 -r * near,
1319 1.0,
1320 ),
1321 )
1322 }
1323
1324 #[deprecated(
1328 since = "0.33.1",
1329 note = "use the `glam::camera::rh::proj::directx::orthographic` function instead"
1330 )]
1331 #[inline]
1332 #[must_use]
1333 pub fn orthographic_rh(
1334 left: f32,
1335 right: f32,
1336 bottom: f32,
1337 top: f32,
1338 near: f32,
1339 far: f32,
1340 ) -> Self {
1341 let rcp_width = 1.0 / (right - left);
1342 let rcp_height = 1.0 / (top - bottom);
1343 let r = 1.0 / (near - far);
1344 Self::from_cols(
1345 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1346 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1347 Vec4::new(0.0, 0.0, r, 0.0),
1348 Vec4::new(
1349 -(left + right) * rcp_width,
1350 -(top + bottom) * rcp_height,
1351 r * near,
1352 1.0,
1353 ),
1354 )
1355 }
1356
1357 #[inline]
1364 #[must_use]
1365 pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
1366 let mut res = self.x_axis.mul(rhs.x);
1367 res = self.y_axis.mul(rhs.y).add(res);
1368 res = self.z_axis.mul(rhs.z).add(res);
1369 res = self.w_axis.add(res);
1370 res = res.div(res.w);
1371 res.xyz()
1372 }
1373
1374 #[inline]
1387 #[must_use]
1388 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1389 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1390 let mut res = self.x_axis.mul(rhs.x);
1391 res = self.y_axis.mul(rhs.y).add(res);
1392 res = self.z_axis.mul(rhs.z).add(res);
1393 res = self.w_axis.add(res);
1394 res.xyz()
1395 }
1396
1397 #[inline]
1408 #[must_use]
1409 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1410 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1411 let mut res = self.x_axis.mul(rhs.x);
1412 res = self.y_axis.mul(rhs.y).add(res);
1413 res = self.z_axis.mul(rhs.z).add(res);
1414 res.xyz()
1415 }
1416
1417 #[inline]
1424 #[must_use]
1425 pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
1426 let mut res = self.x_axis.mul(rhs.xxxx());
1427 res = self.y_axis.mul(rhs.yyyy()).add(res);
1428 res = self.z_axis.mul(rhs.zzzz()).add(res);
1429 res = self.w_axis.add(res);
1430 res = res.div(res.wwww());
1431 Vec3A::from_vec4(res)
1432 }
1433
1434 #[inline]
1438 #[must_use]
1439 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1440 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1441 let mut res = self.x_axis.mul(rhs.xxxx());
1442 res = self.y_axis.mul(rhs.yyyy()).add(res);
1443 res = self.z_axis.mul(rhs.zzzz()).add(res);
1444 res = self.w_axis.add(res);
1445 Vec3A::from_vec4(res)
1446 }
1447
1448 #[inline]
1452 #[must_use]
1453 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1454 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1455 let mut res = self.x_axis.mul(rhs.xxxx());
1456 res = self.y_axis.mul(rhs.yyyy()).add(res);
1457 res = self.z_axis.mul(rhs.zzzz()).add(res);
1458 Vec3A::from_vec4(res)
1459 }
1460
1461 #[inline]
1463 #[must_use]
1464 pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1465 let mut res = self.x_axis.mul(rhs.xxxx());
1466 res = res.add(self.y_axis.mul(rhs.yyyy()));
1467 res = res.add(self.z_axis.mul(rhs.zzzz()));
1468 res = res.add(self.w_axis.mul(rhs.wwww()));
1469 res
1470 }
1471
1472 #[inline]
1474 #[must_use]
1475 pub fn mul_transpose_vec4(&self, rhs: Vec4) -> Vec4 {
1476 Vec4::new(
1477 self.x_axis.dot(rhs),
1478 self.y_axis.dot(rhs),
1479 self.z_axis.dot(rhs),
1480 self.w_axis.dot(rhs),
1481 )
1482 }
1483
1484 #[inline]
1486 #[must_use]
1487 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1488 self.mul(rhs)
1489 }
1490
1491 #[inline]
1493 #[must_use]
1494 pub fn add_mat4(&self, rhs: &Self) -> Self {
1495 self.add(rhs)
1496 }
1497
1498 #[inline]
1500 #[must_use]
1501 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1502 self.sub(rhs)
1503 }
1504
1505 #[inline]
1507 #[must_use]
1508 pub fn mul_scalar(&self, rhs: f32) -> Self {
1509 Self::from_cols(
1510 self.x_axis.mul(rhs),
1511 self.y_axis.mul(rhs),
1512 self.z_axis.mul(rhs),
1513 self.w_axis.mul(rhs),
1514 )
1515 }
1516
1517 #[inline]
1521 #[must_use]
1522 pub fn mul_diagonal_scale(&self, scale: Vec4) -> Self {
1523 Self::from_cols(
1524 self.x_axis * scale.x,
1525 self.y_axis * scale.y,
1526 self.z_axis * scale.z,
1527 self.w_axis * scale.w,
1528 )
1529 }
1530
1531 #[inline]
1533 #[must_use]
1534 pub fn div_scalar(&self, rhs: f32) -> Self {
1535 let rhs = Vec4::splat(rhs);
1536 Self::from_cols(
1537 self.x_axis.div(rhs),
1538 self.y_axis.div(rhs),
1539 self.z_axis.div(rhs),
1540 self.w_axis.div(rhs),
1541 )
1542 }
1543
1544 #[inline]
1546 #[must_use]
1547 pub fn recip(&self) -> Self {
1548 Self::from_cols(
1549 self.x_axis.recip(),
1550 self.y_axis.recip(),
1551 self.z_axis.recip(),
1552 self.w_axis.recip(),
1553 )
1554 }
1555
1556 #[inline]
1566 #[must_use]
1567 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1568 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1569 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1570 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1571 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1572 }
1573
1574 #[inline]
1576 #[must_use]
1577 pub fn abs(&self) -> Self {
1578 Self::from_cols(
1579 self.x_axis.abs(),
1580 self.y_axis.abs(),
1581 self.z_axis.abs(),
1582 self.w_axis.abs(),
1583 )
1584 }
1585
1586 #[cfg(feature = "f64")]
1587 #[inline]
1588 #[must_use]
1589 pub fn as_dmat4(&self) -> DMat4 {
1590 DMat4::from_cols(
1591 self.x_axis.as_dvec4(),
1592 self.y_axis.as_dvec4(),
1593 self.z_axis.as_dvec4(),
1594 self.w_axis.as_dvec4(),
1595 )
1596 }
1597}
1598
1599impl Default for Mat4 {
1600 #[inline]
1601 fn default() -> Self {
1602 Self::IDENTITY
1603 }
1604}
1605
1606impl Add for Mat4 {
1607 type Output = Self;
1608 #[inline]
1609 fn add(self, rhs: Self) -> Self {
1610 Self::from_cols(
1611 self.x_axis.add(rhs.x_axis),
1612 self.y_axis.add(rhs.y_axis),
1613 self.z_axis.add(rhs.z_axis),
1614 self.w_axis.add(rhs.w_axis),
1615 )
1616 }
1617}
1618
1619impl Add<&Self> for Mat4 {
1620 type Output = Self;
1621 #[inline]
1622 fn add(self, rhs: &Self) -> Self {
1623 self.add(*rhs)
1624 }
1625}
1626
1627impl Add<&Mat4> for &Mat4 {
1628 type Output = Mat4;
1629 #[inline]
1630 fn add(self, rhs: &Mat4) -> Mat4 {
1631 (*self).add(*rhs)
1632 }
1633}
1634
1635impl Add<Mat4> for &Mat4 {
1636 type Output = Mat4;
1637 #[inline]
1638 fn add(self, rhs: Mat4) -> Mat4 {
1639 (*self).add(rhs)
1640 }
1641}
1642
1643impl AddAssign for Mat4 {
1644 #[inline]
1645 fn add_assign(&mut self, rhs: Self) {
1646 *self = self.add(rhs);
1647 }
1648}
1649
1650impl AddAssign<&Self> for Mat4 {
1651 #[inline]
1652 fn add_assign(&mut self, rhs: &Self) {
1653 self.add_assign(*rhs);
1654 }
1655}
1656
1657impl Sub for Mat4 {
1658 type Output = Self;
1659 #[inline]
1660 fn sub(self, rhs: Self) -> Self {
1661 Self::from_cols(
1662 self.x_axis.sub(rhs.x_axis),
1663 self.y_axis.sub(rhs.y_axis),
1664 self.z_axis.sub(rhs.z_axis),
1665 self.w_axis.sub(rhs.w_axis),
1666 )
1667 }
1668}
1669
1670impl Sub<&Self> for Mat4 {
1671 type Output = Self;
1672 #[inline]
1673 fn sub(self, rhs: &Self) -> Self {
1674 self.sub(*rhs)
1675 }
1676}
1677
1678impl Sub<&Mat4> for &Mat4 {
1679 type Output = Mat4;
1680 #[inline]
1681 fn sub(self, rhs: &Mat4) -> Mat4 {
1682 (*self).sub(*rhs)
1683 }
1684}
1685
1686impl Sub<Mat4> for &Mat4 {
1687 type Output = Mat4;
1688 #[inline]
1689 fn sub(self, rhs: Mat4) -> Mat4 {
1690 (*self).sub(rhs)
1691 }
1692}
1693
1694impl SubAssign for Mat4 {
1695 #[inline]
1696 fn sub_assign(&mut self, rhs: Self) {
1697 *self = self.sub(rhs);
1698 }
1699}
1700
1701impl SubAssign<&Self> for Mat4 {
1702 #[inline]
1703 fn sub_assign(&mut self, rhs: &Self) {
1704 self.sub_assign(*rhs);
1705 }
1706}
1707
1708impl Neg for Mat4 {
1709 type Output = Self;
1710 #[inline]
1711 fn neg(self) -> Self::Output {
1712 Self::from_cols(
1713 self.x_axis.neg(),
1714 self.y_axis.neg(),
1715 self.z_axis.neg(),
1716 self.w_axis.neg(),
1717 )
1718 }
1719}
1720
1721impl Neg for &Mat4 {
1722 type Output = Mat4;
1723 #[inline]
1724 fn neg(self) -> Mat4 {
1725 (*self).neg()
1726 }
1727}
1728
1729impl Mul for Mat4 {
1730 type Output = Self;
1731 #[inline]
1732 fn mul(self, rhs: Self) -> Self {
1733 Self::from_cols(
1734 self.mul(rhs.x_axis),
1735 self.mul(rhs.y_axis),
1736 self.mul(rhs.z_axis),
1737 self.mul(rhs.w_axis),
1738 )
1739 }
1740}
1741
1742impl Mul<&Self> for Mat4 {
1743 type Output = Self;
1744 #[inline]
1745 fn mul(self, rhs: &Self) -> Self {
1746 self.mul(*rhs)
1747 }
1748}
1749
1750impl Mul<&Mat4> for &Mat4 {
1751 type Output = Mat4;
1752 #[inline]
1753 fn mul(self, rhs: &Mat4) -> Mat4 {
1754 (*self).mul(*rhs)
1755 }
1756}
1757
1758impl Mul<Mat4> for &Mat4 {
1759 type Output = Mat4;
1760 #[inline]
1761 fn mul(self, rhs: Mat4) -> Mat4 {
1762 (*self).mul(rhs)
1763 }
1764}
1765
1766impl MulAssign for Mat4 {
1767 #[inline]
1768 fn mul_assign(&mut self, rhs: Self) {
1769 *self = self.mul(rhs);
1770 }
1771}
1772
1773impl MulAssign<&Self> for Mat4 {
1774 #[inline]
1775 fn mul_assign(&mut self, rhs: &Self) {
1776 self.mul_assign(*rhs);
1777 }
1778}
1779
1780impl Mul<Vec4> for Mat4 {
1781 type Output = Vec4;
1782 #[inline]
1783 fn mul(self, rhs: Vec4) -> Self::Output {
1784 self.mul_vec4(rhs)
1785 }
1786}
1787
1788impl Mul<&Vec4> for Mat4 {
1789 type Output = Vec4;
1790 #[inline]
1791 fn mul(self, rhs: &Vec4) -> Vec4 {
1792 self.mul(*rhs)
1793 }
1794}
1795
1796impl Mul<&Vec4> for &Mat4 {
1797 type Output = Vec4;
1798 #[inline]
1799 fn mul(self, rhs: &Vec4) -> Vec4 {
1800 (*self).mul(*rhs)
1801 }
1802}
1803
1804impl Mul<Vec4> for &Mat4 {
1805 type Output = Vec4;
1806 #[inline]
1807 fn mul(self, rhs: Vec4) -> Vec4 {
1808 (*self).mul(rhs)
1809 }
1810}
1811
1812impl Mul<Mat4> for f32 {
1813 type Output = Mat4;
1814 #[inline]
1815 fn mul(self, rhs: Mat4) -> Self::Output {
1816 rhs.mul_scalar(self)
1817 }
1818}
1819
1820impl Mul<&Mat4> for f32 {
1821 type Output = Mat4;
1822 #[inline]
1823 fn mul(self, rhs: &Mat4) -> Mat4 {
1824 self.mul(*rhs)
1825 }
1826}
1827
1828impl Mul<&Mat4> for &f32 {
1829 type Output = Mat4;
1830 #[inline]
1831 fn mul(self, rhs: &Mat4) -> Mat4 {
1832 (*self).mul(*rhs)
1833 }
1834}
1835
1836impl Mul<Mat4> for &f32 {
1837 type Output = Mat4;
1838 #[inline]
1839 fn mul(self, rhs: Mat4) -> Mat4 {
1840 (*self).mul(rhs)
1841 }
1842}
1843
1844impl Mul<f32> for Mat4 {
1845 type Output = Self;
1846 #[inline]
1847 fn mul(self, rhs: f32) -> Self {
1848 self.mul_scalar(rhs)
1849 }
1850}
1851
1852impl Mul<&f32> for Mat4 {
1853 type Output = Self;
1854 #[inline]
1855 fn mul(self, rhs: &f32) -> Self {
1856 self.mul(*rhs)
1857 }
1858}
1859
1860impl Mul<&f32> for &Mat4 {
1861 type Output = Mat4;
1862 #[inline]
1863 fn mul(self, rhs: &f32) -> Mat4 {
1864 (*self).mul(*rhs)
1865 }
1866}
1867
1868impl Mul<f32> for &Mat4 {
1869 type Output = Mat4;
1870 #[inline]
1871 fn mul(self, rhs: f32) -> Mat4 {
1872 (*self).mul(rhs)
1873 }
1874}
1875
1876impl MulAssign<f32> for Mat4 {
1877 #[inline]
1878 fn mul_assign(&mut self, rhs: f32) {
1879 *self = self.mul(rhs);
1880 }
1881}
1882
1883impl MulAssign<&f32> for Mat4 {
1884 #[inline]
1885 fn mul_assign(&mut self, rhs: &f32) {
1886 self.mul_assign(*rhs);
1887 }
1888}
1889
1890impl Div<Mat4> for f32 {
1891 type Output = Mat4;
1892 #[inline]
1893 fn div(self, rhs: Mat4) -> Self::Output {
1894 Mat4::from_cols(
1895 self.div(rhs.x_axis),
1896 self.div(rhs.y_axis),
1897 self.div(rhs.z_axis),
1898 self.div(rhs.w_axis),
1899 )
1900 }
1901}
1902
1903impl Div<&Mat4> for f32 {
1904 type Output = Mat4;
1905 #[inline]
1906 fn div(self, rhs: &Mat4) -> Mat4 {
1907 self.div(*rhs)
1908 }
1909}
1910
1911impl Div<&Mat4> for &f32 {
1912 type Output = Mat4;
1913 #[inline]
1914 fn div(self, rhs: &Mat4) -> Mat4 {
1915 (*self).div(*rhs)
1916 }
1917}
1918
1919impl Div<Mat4> for &f32 {
1920 type Output = Mat4;
1921 #[inline]
1922 fn div(self, rhs: Mat4) -> Mat4 {
1923 (*self).div(rhs)
1924 }
1925}
1926
1927impl Div<f32> for Mat4 {
1928 type Output = Self;
1929 #[inline]
1930 fn div(self, rhs: f32) -> Self {
1931 self.div_scalar(rhs)
1932 }
1933}
1934
1935impl Div<&f32> for Mat4 {
1936 type Output = Self;
1937 #[inline]
1938 fn div(self, rhs: &f32) -> Self {
1939 self.div(*rhs)
1940 }
1941}
1942
1943impl Div<&f32> for &Mat4 {
1944 type Output = Mat4;
1945 #[inline]
1946 fn div(self, rhs: &f32) -> Mat4 {
1947 (*self).div(*rhs)
1948 }
1949}
1950
1951impl Div<f32> for &Mat4 {
1952 type Output = Mat4;
1953 #[inline]
1954 fn div(self, rhs: f32) -> Mat4 {
1955 (*self).div(rhs)
1956 }
1957}
1958
1959impl DivAssign<f32> for Mat4 {
1960 #[inline]
1961 fn div_assign(&mut self, rhs: f32) {
1962 *self = self.div(rhs);
1963 }
1964}
1965
1966impl DivAssign<&f32> for Mat4 {
1967 #[inline]
1968 fn div_assign(&mut self, rhs: &f32) {
1969 self.div_assign(*rhs);
1970 }
1971}
1972
1973impl Sum<Self> for Mat4 {
1974 fn sum<I>(iter: I) -> Self
1975 where
1976 I: Iterator<Item = Self>,
1977 {
1978 iter.fold(Self::ZERO, Self::add)
1979 }
1980}
1981
1982impl<'a> Sum<&'a Self> for Mat4 {
1983 fn sum<I>(iter: I) -> Self
1984 where
1985 I: Iterator<Item = &'a Self>,
1986 {
1987 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1988 }
1989}
1990
1991impl Product for Mat4 {
1992 fn product<I>(iter: I) -> Self
1993 where
1994 I: Iterator<Item = Self>,
1995 {
1996 iter.fold(Self::IDENTITY, Self::mul)
1997 }
1998}
1999
2000impl<'a> Product<&'a Self> for Mat4 {
2001 fn product<I>(iter: I) -> Self
2002 where
2003 I: Iterator<Item = &'a Self>,
2004 {
2005 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
2006 }
2007}
2008
2009impl PartialEq for Mat4 {
2010 #[inline]
2011 fn eq(&self, rhs: &Self) -> bool {
2012 self.x_axis.eq(&rhs.x_axis)
2013 && self.y_axis.eq(&rhs.y_axis)
2014 && self.z_axis.eq(&rhs.z_axis)
2015 && self.w_axis.eq(&rhs.w_axis)
2016 }
2017}
2018
2019impl AsRef<[f32; 16]> for Mat4 {
2020 #[inline]
2021 fn as_ref(&self) -> &[f32; 16] {
2022 unsafe { &*(self as *const Self as *const [f32; 16]) }
2023 }
2024}
2025
2026impl AsMut<[f32; 16]> for Mat4 {
2027 #[inline]
2028 fn as_mut(&mut self) -> &mut [f32; 16] {
2029 unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
2030 }
2031}
2032
2033impl fmt::Debug for Mat4 {
2034 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2035 fmt.debug_struct(stringify!(Mat4))
2036 .field("x_axis", &self.x_axis)
2037 .field("y_axis", &self.y_axis)
2038 .field("z_axis", &self.z_axis)
2039 .field("w_axis", &self.w_axis)
2040 .finish()
2041 }
2042}
2043
2044impl fmt::Display for Mat4 {
2045 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2046 if let Some(p) = f.precision() {
2047 write!(
2048 f,
2049 "[{:.*}, {:.*}, {:.*}, {:.*}]",
2050 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
2051 )
2052 } else {
2053 write!(
2054 f,
2055 "[{}, {}, {}, {}]",
2056 self.x_axis, self.y_axis, self.z_axis, self.w_axis
2057 )
2058 }
2059 }
2060}