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#[inline(always)]
18#[must_use]
19pub const fn mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat4 {
20 Mat4::from_cols(x_axis, y_axis, z_axis, w_axis)
21}
22
23#[derive(Clone, Copy)]
53#[repr(C)]
54pub struct Mat4 {
55 pub x_axis: Vec4,
56 pub y_axis: Vec4,
57 pub z_axis: Vec4,
58 pub w_axis: Vec4,
59}
60
61impl Mat4 {
62 pub const ZERO: Self = Self::from_cols(Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO);
64
65 pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W);
67
68 pub const NAN: Self = Self::from_cols(Vec4::NAN, Vec4::NAN, Vec4::NAN, Vec4::NAN);
70
71 #[allow(clippy::too_many_arguments)]
72 #[inline(always)]
73 #[must_use]
74 const fn new(
75 m00: f32,
76 m01: f32,
77 m02: f32,
78 m03: f32,
79 m10: f32,
80 m11: f32,
81 m12: f32,
82 m13: f32,
83 m20: f32,
84 m21: f32,
85 m22: f32,
86 m23: f32,
87 m30: f32,
88 m31: f32,
89 m32: f32,
90 m33: f32,
91 ) -> Self {
92 Self {
93 x_axis: Vec4::new(m00, m01, m02, m03),
94 y_axis: Vec4::new(m10, m11, m12, m13),
95 z_axis: Vec4::new(m20, m21, m22, m23),
96 w_axis: Vec4::new(m30, m31, m32, m33),
97 }
98 }
99
100 #[inline(always)]
102 #[must_use]
103 pub const fn from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self {
104 Self {
105 x_axis,
106 y_axis,
107 z_axis,
108 w_axis,
109 }
110 }
111
112 #[inline]
116 #[must_use]
117 pub const fn from_cols_array(m: &[f32; 16]) -> Self {
118 Self::new(
119 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],
120 m[14], m[15],
121 )
122 }
123
124 #[inline]
127 #[must_use]
128 pub const fn to_cols_array(&self) -> [f32; 16] {
129 let [x_axis_x, x_axis_y, x_axis_z, x_axis_w] = self.x_axis.to_array();
130 let [y_axis_x, y_axis_y, y_axis_z, y_axis_w] = self.y_axis.to_array();
131 let [z_axis_x, z_axis_y, z_axis_z, z_axis_w] = self.z_axis.to_array();
132 let [w_axis_x, w_axis_y, w_axis_z, w_axis_w] = self.w_axis.to_array();
133
134 [
135 x_axis_x, x_axis_y, x_axis_z, x_axis_w, y_axis_x, y_axis_y, y_axis_z, y_axis_w,
136 z_axis_x, z_axis_y, z_axis_z, z_axis_w, w_axis_x, w_axis_y, w_axis_z, w_axis_w,
137 ]
138 }
139
140 #[inline]
144 #[must_use]
145 pub const fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self {
146 Self::from_cols(
147 Vec4::from_array(m[0]),
148 Vec4::from_array(m[1]),
149 Vec4::from_array(m[2]),
150 Vec4::from_array(m[3]),
151 )
152 }
153
154 #[inline]
157 #[must_use]
158 pub const fn to_cols_array_2d(&self) -> [[f32; 4]; 4] {
159 [
160 self.x_axis.to_array(),
161 self.y_axis.to_array(),
162 self.z_axis.to_array(),
163 self.w_axis.to_array(),
164 ]
165 }
166
167 #[doc(alias = "scale")]
169 #[inline]
170 #[must_use]
171 pub const fn from_diagonal(diagonal: Vec4) -> Self {
172 let [x, y, z, w] = diagonal.to_array();
174 Self::new(
175 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,
176 )
177 }
178
179 #[inline]
180 #[must_use]
181 fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) {
182 glam_assert!(rotation.is_normalized());
183
184 let (x, y, z, w) = rotation.into();
185 let x2 = x + x;
186 let y2 = y + y;
187 let z2 = z + z;
188 let xx = x * x2;
189 let xy = x * y2;
190 let xz = x * z2;
191 let yy = y * y2;
192 let yz = y * z2;
193 let zz = z * z2;
194 let wx = w * x2;
195 let wy = w * y2;
196 let wz = w * z2;
197
198 let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
199 let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
200 let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
201 (x_axis, y_axis, z_axis)
202 }
203
204 #[inline]
214 #[must_use]
215 pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
216 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
217 Self::from_cols(
218 x_axis.mul(scale.x),
219 y_axis.mul(scale.y),
220 z_axis.mul(scale.z),
221 Vec4::from((translation, 1.0)),
222 )
223 }
224
225 #[inline]
234 #[must_use]
235 pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
236 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
237 Self::from_cols(x_axis, y_axis, z_axis, Vec4::from((translation, 1.0)))
238 }
239
240 #[inline]
248 #[must_use]
249 pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
250 let det = self.determinant();
251 glam_assert!(det != 0.0);
252
253 let scale = Vec3::new(
254 self.x_axis.length() * math::signum(det),
255 self.y_axis.length(),
256 self.z_axis.length(),
257 );
258
259 glam_assert!(scale.cmpne(Vec3::ZERO).all());
260
261 let inv_scale = scale.recip();
262
263 let rotation = Quat::from_rotation_axes(
264 self.x_axis.mul(inv_scale.x).xyz(),
265 self.y_axis.mul(inv_scale.y).xyz(),
266 self.z_axis.mul(inv_scale.z).xyz(),
267 );
268
269 let translation = self.w_axis.xyz();
270
271 (scale, rotation, translation)
272 }
273
274 #[inline]
283 #[must_use]
284 pub fn from_quat(rotation: Quat) -> Self {
285 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
286 Self::from_cols(x_axis, y_axis, z_axis, Vec4::W)
287 }
288
289 #[inline]
295 #[must_use]
296 pub fn from_mat3(m: Mat3) -> Self {
297 Self::from_cols(
298 Vec4::from((m.x_axis, 0.0)),
299 Vec4::from((m.y_axis, 0.0)),
300 Vec4::from((m.z_axis, 0.0)),
301 Vec4::W,
302 )
303 }
304
305 #[inline]
310 #[must_use]
311 pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
312 Self::from_cols(
313 Vec4::from((mat3.x_axis, 0.0)),
314 Vec4::from((mat3.y_axis, 0.0)),
315 Vec4::from((mat3.z_axis, 0.0)),
316 Vec4::from((translation, 1.0)),
317 )
318 }
319
320 #[inline]
326 #[must_use]
327 pub fn from_mat3a(m: Mat3A) -> Self {
328 Self::from_cols(
329 Vec4::from((m.x_axis, 0.0)),
330 Vec4::from((m.y_axis, 0.0)),
331 Vec4::from((m.z_axis, 0.0)),
332 Vec4::W,
333 )
334 }
335
336 #[inline]
341 #[must_use]
342 pub fn from_translation(translation: Vec3) -> Self {
343 Self::from_cols(
344 Vec4::X,
345 Vec4::Y,
346 Vec4::Z,
347 Vec4::new(translation.x, translation.y, translation.z, 1.0),
348 )
349 }
350
351 #[inline]
361 #[must_use]
362 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
363 glam_assert!(axis.is_normalized());
364
365 let (sin, cos) = math::sin_cos(angle);
366 let axis_sin = axis.mul(sin);
367 let axis_sq = axis.mul(axis);
368 let omc = 1.0 - cos;
369 let xyomc = axis.x * axis.y * omc;
370 let xzomc = axis.x * axis.z * omc;
371 let yzomc = axis.y * axis.z * omc;
372 Self::from_cols(
373 Vec4::new(
374 axis_sq.x * omc + cos,
375 xyomc + axis_sin.z,
376 xzomc - axis_sin.y,
377 0.0,
378 ),
379 Vec4::new(
380 xyomc - axis_sin.z,
381 axis_sq.y * omc + cos,
382 yzomc + axis_sin.x,
383 0.0,
384 ),
385 Vec4::new(
386 xzomc + axis_sin.y,
387 yzomc - axis_sin.x,
388 axis_sq.z * omc + cos,
389 0.0,
390 ),
391 Vec4::W,
392 )
393 }
394
395 #[inline]
401 #[must_use]
402 pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
403 Self::from_euler_angles(order, a, b, c)
404 }
405
406 #[inline]
416 #[must_use]
417 pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
418 glam_assert!(
419 self.x_axis.xyz().is_normalized()
420 && self.y_axis.xyz().is_normalized()
421 && self.z_axis.xyz().is_normalized()
422 );
423 self.to_euler_angles(order)
424 }
425
426 #[inline]
432 #[must_use]
433 pub fn from_rotation_x(angle: f32) -> Self {
434 let (sina, cosa) = math::sin_cos(angle);
435 Self::from_cols(
436 Vec4::X,
437 Vec4::new(0.0, cosa, sina, 0.0),
438 Vec4::new(0.0, -sina, cosa, 0.0),
439 Vec4::W,
440 )
441 }
442
443 #[inline]
449 #[must_use]
450 pub fn from_rotation_y(angle: f32) -> Self {
451 let (sina, cosa) = math::sin_cos(angle);
452 Self::from_cols(
453 Vec4::new(cosa, 0.0, -sina, 0.0),
454 Vec4::Y,
455 Vec4::new(sina, 0.0, cosa, 0.0),
456 Vec4::W,
457 )
458 }
459
460 #[inline]
466 #[must_use]
467 pub fn from_rotation_z(angle: f32) -> Self {
468 let (sina, cosa) = math::sin_cos(angle);
469 Self::from_cols(
470 Vec4::new(cosa, sina, 0.0, 0.0),
471 Vec4::new(-sina, cosa, 0.0, 0.0),
472 Vec4::Z,
473 Vec4::W,
474 )
475 }
476
477 #[inline]
486 #[must_use]
487 pub fn from_scale(scale: Vec3) -> Self {
488 glam_assert!(scale.cmpne(Vec3::ZERO).any());
490
491 Self::from_cols(
492 Vec4::new(scale.x, 0.0, 0.0, 0.0),
493 Vec4::new(0.0, scale.y, 0.0, 0.0),
494 Vec4::new(0.0, 0.0, scale.z, 0.0),
495 Vec4::W,
496 )
497 }
498
499 #[inline]
505 #[must_use]
506 pub const fn from_cols_slice(slice: &[f32]) -> Self {
507 Self::new(
508 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
509 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
510 )
511 }
512
513 #[inline]
519 pub fn write_cols_to_slice(self, slice: &mut [f32]) {
520 slice[0] = self.x_axis.x;
521 slice[1] = self.x_axis.y;
522 slice[2] = self.x_axis.z;
523 slice[3] = self.x_axis.w;
524 slice[4] = self.y_axis.x;
525 slice[5] = self.y_axis.y;
526 slice[6] = self.y_axis.z;
527 slice[7] = self.y_axis.w;
528 slice[8] = self.z_axis.x;
529 slice[9] = self.z_axis.y;
530 slice[10] = self.z_axis.z;
531 slice[11] = self.z_axis.w;
532 slice[12] = self.w_axis.x;
533 slice[13] = self.w_axis.y;
534 slice[14] = self.w_axis.z;
535 slice[15] = self.w_axis.w;
536 }
537
538 #[inline]
544 #[must_use]
545 pub fn col(&self, index: usize) -> Vec4 {
546 match index {
547 0 => self.x_axis,
548 1 => self.y_axis,
549 2 => self.z_axis,
550 3 => self.w_axis,
551 _ => panic!("index out of bounds"),
552 }
553 }
554
555 #[inline]
561 pub fn col_mut(&mut self, index: usize) -> &mut Vec4 {
562 match index {
563 0 => &mut self.x_axis,
564 1 => &mut self.y_axis,
565 2 => &mut self.z_axis,
566 3 => &mut self.w_axis,
567 _ => panic!("index out of bounds"),
568 }
569 }
570
571 #[inline]
577 #[must_use]
578 pub fn row(&self, index: usize) -> Vec4 {
579 match index {
580 0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
581 1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
582 2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
583 3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
584 _ => panic!("index out of bounds"),
585 }
586 }
587
588 #[inline]
591 #[must_use]
592 pub fn is_finite(&self) -> bool {
593 self.x_axis.is_finite()
594 && self.y_axis.is_finite()
595 && self.z_axis.is_finite()
596 && self.w_axis.is_finite()
597 }
598
599 #[inline]
601 #[must_use]
602 pub fn is_nan(&self) -> bool {
603 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
604 }
605
606 #[inline]
608 #[must_use]
609 pub fn transpose(&self) -> Self {
610 Self {
611 x_axis: Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
612 y_axis: Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
613 z_axis: Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
614 w_axis: Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
615 }
616 }
617
618 #[must_use]
620 pub fn determinant(&self) -> f32 {
621 let (m00, m01, m02, m03) = self.x_axis.into();
622 let (m10, m11, m12, m13) = self.y_axis.into();
623 let (m20, m21, m22, m23) = self.z_axis.into();
624 let (m30, m31, m32, m33) = self.w_axis.into();
625
626 let a2323 = m22 * m33 - m23 * m32;
627 let a1323 = m21 * m33 - m23 * m31;
628 let a1223 = m21 * m32 - m22 * m31;
629 let a0323 = m20 * m33 - m23 * m30;
630 let a0223 = m20 * m32 - m22 * m30;
631 let a0123 = m20 * m31 - m21 * m30;
632
633 m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223)
634 - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223)
635 + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123)
636 - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123)
637 }
638
639 #[must_use]
647 pub fn inverse(&self) -> Self {
648 unsafe {
649 let swizzle3377 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
651 let r = vuzp2q_f32(a, b);
652 vtrn2q_f32(r, r)
653 };
654 let swizzle2266 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
655 let r = vuzp1q_f32(a, b);
656 vtrn2q_f32(r, r)
657 };
658 let swizzle0046 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
659 let r = vuzp1q_f32(a, a);
660 vuzp1q_f32(r, b)
661 };
662 let swizzle1155 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
663 let r = vzip1q_f32(a, b);
664 vzip2q_f32(r, r)
665 };
666 let swizzle0044 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
667 let r = vuzp1q_f32(a, b);
668 vtrn1q_f32(r, r)
669 };
670 let swizzle0266 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
671 let r = vuzp1q_f32(a, b);
672 vsetq_lane_f32(vgetq_lane_f32(b, 2), r, 2)
673 };
674 let swizzle0246 = |a: float32x4_t, b: float32x4_t| -> float32x4_t { vuzp1q_f32(a, b) };
675 let fac0 = {
676 let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0);
677 let swp0b = swizzle2266(self.w_axis.0, self.z_axis.0);
678
679 let swp00 = swizzle2266(self.z_axis.0, self.y_axis.0);
680 let swp01 = swizzle0046(swp0a, swp0a);
681 let swp02 = swizzle0046(swp0b, swp0b);
682 let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0);
683
684 let mul00 = vmulq_f32(swp00, swp01);
685 let mul01 = vmulq_f32(swp02, swp03);
686 vsubq_f32(mul00, mul01)
687 };
688 let fac1 = {
689 let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0);
690 let swp0b = swizzle1155(self.w_axis.0, self.z_axis.0);
691
692 let swp00 = swizzle1155(self.z_axis.0, self.y_axis.0);
693 let swp01 = swizzle0046(swp0a, swp0a);
694 let swp02 = swizzle0046(swp0b, swp0b);
695 let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0);
696
697 let mul00 = vmulq_f32(swp00, swp01);
698 let mul01 = vmulq_f32(swp02, swp03);
699 vsubq_f32(mul00, mul01)
700 };
701 let fac2 = {
702 let swp0a = swizzle2266(self.w_axis.0, self.z_axis.0);
703 let swp0b = swizzle1155(self.w_axis.0, self.z_axis.0);
704
705 let swp00 = swizzle1155(self.z_axis.0, self.y_axis.0);
706 let swp01 = swizzle0046(swp0a, swp0a);
707 let swp02 = swizzle0046(swp0b, swp0b);
708 let swp03 = swizzle2266(self.z_axis.0, self.y_axis.0);
709
710 let mul00 = vmulq_f32(swp00, swp01);
711 let mul01 = vmulq_f32(swp02, swp03);
712 vsubq_f32(mul00, mul01)
713 };
714 let fac3 = {
715 let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0);
716 let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0);
717
718 let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0);
719 let swp01 = swizzle0046(swp0a, swp0a);
720 let swp02 = swizzle0046(swp0b, swp0b);
721 let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0);
722
723 let mul00 = vmulq_f32(swp00, swp01);
724 let mul01 = vmulq_f32(swp02, swp03);
725 vsubq_f32(mul00, mul01)
726 };
727 let fac4 = {
728 let swp0a = swizzle2266(self.w_axis.0, self.z_axis.0);
729 let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0);
730
731 let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0);
732 let swp01 = swizzle0046(swp0a, swp0a);
733 let swp02 = swizzle0046(swp0b, swp0b);
734 let swp03 = swizzle2266(self.z_axis.0, self.y_axis.0);
735
736 let mul00 = vmulq_f32(swp00, swp01);
737 let mul01 = vmulq_f32(swp02, swp03);
738 vsubq_f32(mul00, mul01)
739 };
740 let fac5 = {
741 let swp0a = swizzle1155(self.w_axis.0, self.z_axis.0);
742 let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0);
743
744 let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0);
745 let swp01 = swizzle0046(swp0a, swp0a);
746 let swp02 = swizzle0046(swp0b, swp0b);
747 let swp03 = swizzle1155(self.z_axis.0, self.y_axis.0);
748
749 let mul00 = vmulq_f32(swp00, swp01);
750 let mul01 = vmulq_f32(swp02, swp03);
751 vsubq_f32(mul00, mul01)
752 };
753
754 const SIGN_A: float32x4_t = Vec4::new(-1.0, 1.0, -1.0, 1.0).0;
755 const SIGN_B: float32x4_t = Vec4::new(1.0, -1.0, 1.0, -1.0).0;
756
757 let temp0 = swizzle0044(self.y_axis.0, self.x_axis.0);
758 let vec0 = swizzle0266(temp0, temp0);
759
760 let temp1 = swizzle1155(self.y_axis.0, self.x_axis.0);
761 let vec1 = swizzle0266(temp1, temp1);
762
763 let temp2 = swizzle2266(self.y_axis.0, self.x_axis.0);
764 let vec2 = swizzle0266(temp2, temp2);
765
766 let temp3 = swizzle3377(self.y_axis.0, self.x_axis.0);
767 let vec3 = swizzle0266(temp3, temp3);
768
769 let mul00 = vmulq_f32(vec1, fac0);
770 let mul01 = vmulq_f32(vec2, fac1);
771 let mul02 = vmulq_f32(vec3, fac2);
772 let sub00 = vsubq_f32(mul00, mul01);
773 let add00 = vaddq_f32(sub00, mul02);
774 let inv0 = vmulq_f32(SIGN_B, add00);
775
776 let mul03 = vmulq_f32(vec0, fac0);
777 let mul04 = vmulq_f32(vec2, fac3);
778 let mul05 = vmulq_f32(vec3, fac4);
779 let sub01 = vsubq_f32(mul03, mul04);
780 let add01 = vaddq_f32(sub01, mul05);
781 let inv1 = vmulq_f32(SIGN_A, add01);
782
783 let mul06 = vmulq_f32(vec0, fac1);
784 let mul07 = vmulq_f32(vec1, fac3);
785 let mul08 = vmulq_f32(vec3, fac5);
786 let sub02 = vsubq_f32(mul06, mul07);
787 let add02 = vaddq_f32(sub02, mul08);
788 let inv2 = vmulq_f32(SIGN_B, add02);
789
790 let mul09 = vmulq_f32(vec0, fac2);
791 let mul10 = vmulq_f32(vec1, fac4);
792 let mul11 = vmulq_f32(vec2, fac5);
793 let sub03 = vsubq_f32(mul09, mul10);
794 let add03 = vaddq_f32(sub03, mul11);
795 let inv3 = vmulq_f32(SIGN_A, add03);
796
797 let row0 = swizzle0044(inv0, inv1);
798 let row1 = swizzle0044(inv2, inv3);
799 let row2 = swizzle0246(row0, row1);
800
801 let dot0 = dot4(self.x_axis.0, row2);
802 glam_assert!(dot0 != 0.0);
803
804 let rcp0 = dot0.recip();
805
806 Self {
807 x_axis: Vec4(vmulq_n_f32(inv0, rcp0)),
808 y_axis: Vec4(vmulq_n_f32(inv1, rcp0)),
809 z_axis: Vec4(vmulq_n_f32(inv2, rcp0)),
810 w_axis: Vec4(vmulq_n_f32(inv3, rcp0)),
811 }
812 }
813 }
814
815 #[inline]
824 #[must_use]
825 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
826 Self::look_to_rh(eye, -dir, up)
827 }
828
829 #[inline]
838 #[must_use]
839 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
840 glam_assert!(dir.is_normalized());
841 glam_assert!(up.is_normalized());
842 let f = dir;
843 let s = f.cross(up).normalize();
844 let u = s.cross(f);
845
846 Self::from_cols(
847 Vec4::new(s.x, u.x, -f.x, 0.0),
848 Vec4::new(s.y, u.y, -f.y, 0.0),
849 Vec4::new(s.z, u.z, -f.z, 0.0),
850 Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
851 )
852 }
853
854 #[inline]
863 #[must_use]
864 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
865 Self::look_to_lh(eye, center.sub(eye).normalize(), up)
866 }
867
868 #[inline]
877 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
878 Self::look_to_rh(eye, center.sub(eye).normalize(), up)
879 }
880
881 #[inline]
888 #[must_use]
889 pub fn perspective_rh_gl(
890 fov_y_radians: f32,
891 aspect_ratio: f32,
892 z_near: f32,
893 z_far: f32,
894 ) -> Self {
895 let inv_length = 1.0 / (z_near - z_far);
896 let f = 1.0 / math::tan(0.5 * fov_y_radians);
897 let a = f / aspect_ratio;
898 let b = (z_near + z_far) * inv_length;
899 let c = (2.0 * z_near * z_far) * inv_length;
900 Self::from_cols(
901 Vec4::new(a, 0.0, 0.0, 0.0),
902 Vec4::new(0.0, f, 0.0, 0.0),
903 Vec4::new(0.0, 0.0, b, -1.0),
904 Vec4::new(0.0, 0.0, c, 0.0),
905 )
906 }
907
908 #[inline]
917 #[must_use]
918 pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
919 glam_assert!(z_near > 0.0 && z_far > 0.0);
920 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
921 let h = cos_fov / sin_fov;
922 let w = h / aspect_ratio;
923 let r = z_far / (z_far - z_near);
924 Self::from_cols(
925 Vec4::new(w, 0.0, 0.0, 0.0),
926 Vec4::new(0.0, h, 0.0, 0.0),
927 Vec4::new(0.0, 0.0, r, 1.0),
928 Vec4::new(0.0, 0.0, -r * z_near, 0.0),
929 )
930 }
931
932 #[inline]
941 #[must_use]
942 pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
943 glam_assert!(z_near > 0.0 && z_far > 0.0);
944 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
945 let h = cos_fov / sin_fov;
946 let w = h / aspect_ratio;
947 let r = z_far / (z_near - z_far);
948 Self::from_cols(
949 Vec4::new(w, 0.0, 0.0, 0.0),
950 Vec4::new(0.0, h, 0.0, 0.0),
951 Vec4::new(0.0, 0.0, r, -1.0),
952 Vec4::new(0.0, 0.0, r * z_near, 0.0),
953 )
954 }
955
956 #[inline]
966 #[must_use]
967 pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
968 glam_assert!(z_near > 0.0);
969 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
970 let h = cos_fov / sin_fov;
971 let w = h / aspect_ratio;
972 Self::from_cols(
973 Vec4::new(w, 0.0, 0.0, 0.0),
974 Vec4::new(0.0, h, 0.0, 0.0),
975 Vec4::new(0.0, 0.0, 1.0, 1.0),
976 Vec4::new(0.0, 0.0, -z_near, 0.0),
977 )
978 }
979
980 #[inline]
988 #[must_use]
989 pub fn perspective_infinite_reverse_lh(
990 fov_y_radians: f32,
991 aspect_ratio: f32,
992 z_near: f32,
993 ) -> Self {
994 glam_assert!(z_near > 0.0);
995 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
996 let h = cos_fov / sin_fov;
997 let w = h / aspect_ratio;
998 Self::from_cols(
999 Vec4::new(w, 0.0, 0.0, 0.0),
1000 Vec4::new(0.0, h, 0.0, 0.0),
1001 Vec4::new(0.0, 0.0, 0.0, 1.0),
1002 Vec4::new(0.0, 0.0, z_near, 0.0),
1003 )
1004 }
1005
1006 #[inline]
1016 #[must_use]
1017 pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1018 glam_assert!(z_near > 0.0);
1019 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1020 Self::from_cols(
1021 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1022 Vec4::new(0.0, f, 0.0, 0.0),
1023 Vec4::new(0.0, 0.0, -1.0, -1.0),
1024 Vec4::new(0.0, 0.0, -z_near, 0.0),
1025 )
1026 }
1027
1028 #[inline]
1036 #[must_use]
1037 pub fn perspective_infinite_reverse_rh(
1038 fov_y_radians: f32,
1039 aspect_ratio: f32,
1040 z_near: f32,
1041 ) -> Self {
1042 glam_assert!(z_near > 0.0);
1043 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1044 Self::from_cols(
1045 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1046 Vec4::new(0.0, f, 0.0, 0.0),
1047 Vec4::new(0.0, 0.0, 0.0, -1.0),
1048 Vec4::new(0.0, 0.0, z_near, 0.0),
1049 )
1050 }
1051
1052 #[inline]
1059 #[must_use]
1060 pub fn orthographic_rh_gl(
1061 left: f32,
1062 right: f32,
1063 bottom: f32,
1064 top: f32,
1065 near: f32,
1066 far: f32,
1067 ) -> Self {
1068 let a = 2.0 / (right - left);
1069 let b = 2.0 / (top - bottom);
1070 let c = -2.0 / (far - near);
1071 let tx = -(right + left) / (right - left);
1072 let ty = -(top + bottom) / (top - bottom);
1073 let tz = -(far + near) / (far - near);
1074
1075 Self::from_cols(
1076 Vec4::new(a, 0.0, 0.0, 0.0),
1077 Vec4::new(0.0, b, 0.0, 0.0),
1078 Vec4::new(0.0, 0.0, c, 0.0),
1079 Vec4::new(tx, ty, tz, 1.0),
1080 )
1081 }
1082
1083 #[inline]
1087 #[must_use]
1088 pub fn orthographic_lh(
1089 left: f32,
1090 right: f32,
1091 bottom: f32,
1092 top: f32,
1093 near: f32,
1094 far: f32,
1095 ) -> Self {
1096 let rcp_width = 1.0 / (right - left);
1097 let rcp_height = 1.0 / (top - bottom);
1098 let r = 1.0 / (far - near);
1099 Self::from_cols(
1100 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1101 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1102 Vec4::new(0.0, 0.0, r, 0.0),
1103 Vec4::new(
1104 -(left + right) * rcp_width,
1105 -(top + bottom) * rcp_height,
1106 -r * near,
1107 1.0,
1108 ),
1109 )
1110 }
1111
1112 #[inline]
1116 #[must_use]
1117 pub fn orthographic_rh(
1118 left: f32,
1119 right: f32,
1120 bottom: f32,
1121 top: f32,
1122 near: f32,
1123 far: f32,
1124 ) -> Self {
1125 let rcp_width = 1.0 / (right - left);
1126 let rcp_height = 1.0 / (top - bottom);
1127 let r = 1.0 / (near - far);
1128 Self::from_cols(
1129 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1130 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1131 Vec4::new(0.0, 0.0, r, 0.0),
1132 Vec4::new(
1133 -(left + right) * rcp_width,
1134 -(top + bottom) * rcp_height,
1135 r * near,
1136 1.0,
1137 ),
1138 )
1139 }
1140
1141 #[inline]
1148 #[must_use]
1149 pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
1150 let mut res = self.x_axis.mul(rhs.x);
1151 res = self.y_axis.mul(rhs.y).add(res);
1152 res = self.z_axis.mul(rhs.z).add(res);
1153 res = self.w_axis.add(res);
1154 res = res.div(res.w);
1155 res.xyz()
1156 }
1157
1158 #[inline]
1171 #[must_use]
1172 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1173 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1174 let mut res = self.x_axis.mul(rhs.x);
1175 res = self.y_axis.mul(rhs.y).add(res);
1176 res = self.z_axis.mul(rhs.z).add(res);
1177 res = self.w_axis.add(res);
1178 res.xyz()
1179 }
1180
1181 #[inline]
1192 #[must_use]
1193 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1194 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1195 let mut res = self.x_axis.mul(rhs.x);
1196 res = self.y_axis.mul(rhs.y).add(res);
1197 res = self.z_axis.mul(rhs.z).add(res);
1198 res.xyz()
1199 }
1200
1201 #[inline]
1208 #[must_use]
1209 pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
1210 let mut res = self.x_axis.mul(rhs.xxxx());
1211 res = self.y_axis.mul(rhs.yyyy()).add(res);
1212 res = self.z_axis.mul(rhs.zzzz()).add(res);
1213 res = self.w_axis.add(res);
1214 res = res.div(res.wwww());
1215 Vec3A::from_vec4(res)
1216 }
1217
1218 #[inline]
1222 #[must_use]
1223 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1224 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1225 let mut res = self.x_axis.mul(rhs.xxxx());
1226 res = self.y_axis.mul(rhs.yyyy()).add(res);
1227 res = self.z_axis.mul(rhs.zzzz()).add(res);
1228 res = self.w_axis.add(res);
1229 Vec3A::from_vec4(res)
1230 }
1231
1232 #[inline]
1236 #[must_use]
1237 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1238 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1239 let mut res = self.x_axis.mul(rhs.xxxx());
1240 res = self.y_axis.mul(rhs.yyyy()).add(res);
1241 res = self.z_axis.mul(rhs.zzzz()).add(res);
1242 Vec3A::from_vec4(res)
1243 }
1244
1245 #[inline]
1247 #[must_use]
1248 pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1249 let mut res = self.x_axis.mul(rhs.xxxx());
1250 res = res.add(self.y_axis.mul(rhs.yyyy()));
1251 res = res.add(self.z_axis.mul(rhs.zzzz()));
1252 res = res.add(self.w_axis.mul(rhs.wwww()));
1253 res
1254 }
1255
1256 #[inline]
1258 #[must_use]
1259 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1260 Self::from_cols(
1261 self.mul(rhs.x_axis),
1262 self.mul(rhs.y_axis),
1263 self.mul(rhs.z_axis),
1264 self.mul(rhs.w_axis),
1265 )
1266 }
1267
1268 #[inline]
1270 #[must_use]
1271 pub fn add_mat4(&self, rhs: &Self) -> Self {
1272 Self::from_cols(
1273 self.x_axis.add(rhs.x_axis),
1274 self.y_axis.add(rhs.y_axis),
1275 self.z_axis.add(rhs.z_axis),
1276 self.w_axis.add(rhs.w_axis),
1277 )
1278 }
1279
1280 #[inline]
1282 #[must_use]
1283 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1284 Self::from_cols(
1285 self.x_axis.sub(rhs.x_axis),
1286 self.y_axis.sub(rhs.y_axis),
1287 self.z_axis.sub(rhs.z_axis),
1288 self.w_axis.sub(rhs.w_axis),
1289 )
1290 }
1291
1292 #[inline]
1294 #[must_use]
1295 pub fn mul_scalar(&self, rhs: f32) -> Self {
1296 Self::from_cols(
1297 self.x_axis.mul(rhs),
1298 self.y_axis.mul(rhs),
1299 self.z_axis.mul(rhs),
1300 self.w_axis.mul(rhs),
1301 )
1302 }
1303
1304 #[inline]
1306 #[must_use]
1307 pub fn div_scalar(&self, rhs: f32) -> Self {
1308 let rhs = Vec4::splat(rhs);
1309 Self::from_cols(
1310 self.x_axis.div(rhs),
1311 self.y_axis.div(rhs),
1312 self.z_axis.div(rhs),
1313 self.w_axis.div(rhs),
1314 )
1315 }
1316
1317 #[inline]
1327 #[must_use]
1328 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1329 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1330 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1331 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1332 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1333 }
1334
1335 #[inline]
1337 #[must_use]
1338 pub fn abs(&self) -> Self {
1339 Self::from_cols(
1340 self.x_axis.abs(),
1341 self.y_axis.abs(),
1342 self.z_axis.abs(),
1343 self.w_axis.abs(),
1344 )
1345 }
1346
1347 #[inline]
1348 pub fn as_dmat4(&self) -> DMat4 {
1349 DMat4::from_cols(
1350 self.x_axis.as_dvec4(),
1351 self.y_axis.as_dvec4(),
1352 self.z_axis.as_dvec4(),
1353 self.w_axis.as_dvec4(),
1354 )
1355 }
1356}
1357
1358impl Default for Mat4 {
1359 #[inline]
1360 fn default() -> Self {
1361 Self::IDENTITY
1362 }
1363}
1364
1365impl Add<Mat4> for Mat4 {
1366 type Output = Self;
1367 #[inline]
1368 fn add(self, rhs: Self) -> Self::Output {
1369 self.add_mat4(&rhs)
1370 }
1371}
1372
1373impl AddAssign<Mat4> for Mat4 {
1374 #[inline]
1375 fn add_assign(&mut self, rhs: Self) {
1376 *self = self.add_mat4(&rhs);
1377 }
1378}
1379
1380impl Sub<Mat4> for Mat4 {
1381 type Output = Self;
1382 #[inline]
1383 fn sub(self, rhs: Self) -> Self::Output {
1384 self.sub_mat4(&rhs)
1385 }
1386}
1387
1388impl SubAssign<Mat4> for Mat4 {
1389 #[inline]
1390 fn sub_assign(&mut self, rhs: Self) {
1391 *self = self.sub_mat4(&rhs);
1392 }
1393}
1394
1395impl Neg for Mat4 {
1396 type Output = Self;
1397 #[inline]
1398 fn neg(self) -> Self::Output {
1399 Self::from_cols(
1400 self.x_axis.neg(),
1401 self.y_axis.neg(),
1402 self.z_axis.neg(),
1403 self.w_axis.neg(),
1404 )
1405 }
1406}
1407
1408impl Mul<Mat4> for Mat4 {
1409 type Output = Self;
1410 #[inline]
1411 fn mul(self, rhs: Self) -> Self::Output {
1412 self.mul_mat4(&rhs)
1413 }
1414}
1415
1416impl MulAssign<Mat4> for Mat4 {
1417 #[inline]
1418 fn mul_assign(&mut self, rhs: Self) {
1419 *self = self.mul_mat4(&rhs);
1420 }
1421}
1422
1423impl Mul<Vec4> for Mat4 {
1424 type Output = Vec4;
1425 #[inline]
1426 fn mul(self, rhs: Vec4) -> Self::Output {
1427 self.mul_vec4(rhs)
1428 }
1429}
1430
1431impl Mul<Mat4> for f32 {
1432 type Output = Mat4;
1433 #[inline]
1434 fn mul(self, rhs: Mat4) -> Self::Output {
1435 rhs.mul_scalar(self)
1436 }
1437}
1438
1439impl Mul<f32> for Mat4 {
1440 type Output = Self;
1441 #[inline]
1442 fn mul(self, rhs: f32) -> Self::Output {
1443 self.mul_scalar(rhs)
1444 }
1445}
1446
1447impl MulAssign<f32> for Mat4 {
1448 #[inline]
1449 fn mul_assign(&mut self, rhs: f32) {
1450 *self = self.mul_scalar(rhs);
1451 }
1452}
1453
1454impl Div<Mat4> for f32 {
1455 type Output = Mat4;
1456 #[inline]
1457 fn div(self, rhs: Mat4) -> Self::Output {
1458 rhs.div_scalar(self)
1459 }
1460}
1461
1462impl Div<f32> for Mat4 {
1463 type Output = Self;
1464 #[inline]
1465 fn div(self, rhs: f32) -> Self::Output {
1466 self.div_scalar(rhs)
1467 }
1468}
1469
1470impl DivAssign<f32> for Mat4 {
1471 #[inline]
1472 fn div_assign(&mut self, rhs: f32) {
1473 *self = self.div_scalar(rhs);
1474 }
1475}
1476
1477impl Sum<Self> for Mat4 {
1478 fn sum<I>(iter: I) -> Self
1479 where
1480 I: Iterator<Item = Self>,
1481 {
1482 iter.fold(Self::ZERO, Self::add)
1483 }
1484}
1485
1486impl<'a> Sum<&'a Self> for Mat4 {
1487 fn sum<I>(iter: I) -> Self
1488 where
1489 I: Iterator<Item = &'a Self>,
1490 {
1491 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1492 }
1493}
1494
1495impl Product for Mat4 {
1496 fn product<I>(iter: I) -> Self
1497 where
1498 I: Iterator<Item = Self>,
1499 {
1500 iter.fold(Self::IDENTITY, Self::mul)
1501 }
1502}
1503
1504impl<'a> Product<&'a Self> for Mat4 {
1505 fn product<I>(iter: I) -> Self
1506 where
1507 I: Iterator<Item = &'a Self>,
1508 {
1509 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1510 }
1511}
1512
1513impl PartialEq for Mat4 {
1514 #[inline]
1515 fn eq(&self, rhs: &Self) -> bool {
1516 self.x_axis.eq(&rhs.x_axis)
1517 && self.y_axis.eq(&rhs.y_axis)
1518 && self.z_axis.eq(&rhs.z_axis)
1519 && self.w_axis.eq(&rhs.w_axis)
1520 }
1521}
1522
1523#[cfg(not(target_arch = "spirv"))]
1524impl AsRef<[f32; 16]> for Mat4 {
1525 #[inline]
1526 fn as_ref(&self) -> &[f32; 16] {
1527 unsafe { &*(self as *const Self as *const [f32; 16]) }
1528 }
1529}
1530
1531#[cfg(not(target_arch = "spirv"))]
1532impl AsMut<[f32; 16]> for Mat4 {
1533 #[inline]
1534 fn as_mut(&mut self) -> &mut [f32; 16] {
1535 unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
1536 }
1537}
1538
1539impl fmt::Debug for Mat4 {
1540 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1541 fmt.debug_struct(stringify!(Mat4))
1542 .field("x_axis", &self.x_axis)
1543 .field("y_axis", &self.y_axis)
1544 .field("z_axis", &self.z_axis)
1545 .field("w_axis", &self.w_axis)
1546 .finish()
1547 }
1548}
1549
1550impl fmt::Display for Mat4 {
1551 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1552 if let Some(p) = f.precision() {
1553 write!(
1554 f,
1555 "[{:.*}, {:.*}, {:.*}, {:.*}]",
1556 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
1557 )
1558 } else {
1559 write!(
1560 f,
1561 "[{}, {}, {}, {}]",
1562 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1563 )
1564 }
1565 }
1566}