1use crate::{
4 f32::math, sse2::*, swizzles::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4,
5};
6#[cfg(not(target_arch = "spirv"))]
7use core::fmt;
8use core::iter::{Product, Sum};
9use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
10
11#[cfg(target_arch = "x86")]
12use core::arch::x86::*;
13#[cfg(target_arch = "x86_64")]
14use core::arch::x86_64::*;
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]
311 #[must_use]
312 pub fn from_mat3a(m: Mat3A) -> Self {
313 Self::from_cols(
314 Vec4::from((m.x_axis, 0.0)),
315 Vec4::from((m.y_axis, 0.0)),
316 Vec4::from((m.z_axis, 0.0)),
317 Vec4::W,
318 )
319 }
320
321 #[inline]
326 #[must_use]
327 pub fn from_translation(translation: Vec3) -> Self {
328 Self::from_cols(
329 Vec4::X,
330 Vec4::Y,
331 Vec4::Z,
332 Vec4::new(translation.x, translation.y, translation.z, 1.0),
333 )
334 }
335
336 #[inline]
346 #[must_use]
347 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
348 glam_assert!(axis.is_normalized());
349
350 let (sin, cos) = math::sin_cos(angle);
351 let axis_sin = axis.mul(sin);
352 let axis_sq = axis.mul(axis);
353 let omc = 1.0 - cos;
354 let xyomc = axis.x * axis.y * omc;
355 let xzomc = axis.x * axis.z * omc;
356 let yzomc = axis.y * axis.z * omc;
357 Self::from_cols(
358 Vec4::new(
359 axis_sq.x * omc + cos,
360 xyomc + axis_sin.z,
361 xzomc - axis_sin.y,
362 0.0,
363 ),
364 Vec4::new(
365 xyomc - axis_sin.z,
366 axis_sq.y * omc + cos,
367 yzomc + axis_sin.x,
368 0.0,
369 ),
370 Vec4::new(
371 xzomc + axis_sin.y,
372 yzomc - axis_sin.x,
373 axis_sq.z * omc + cos,
374 0.0,
375 ),
376 Vec4::W,
377 )
378 }
379
380 #[inline]
386 #[must_use]
387 pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
388 let quat = Quat::from_euler(order, a, b, c);
389 Self::from_quat(quat)
390 }
391
392 #[inline]
398 #[must_use]
399 pub fn from_rotation_x(angle: f32) -> Self {
400 let (sina, cosa) = math::sin_cos(angle);
401 Self::from_cols(
402 Vec4::X,
403 Vec4::new(0.0, cosa, sina, 0.0),
404 Vec4::new(0.0, -sina, cosa, 0.0),
405 Vec4::W,
406 )
407 }
408
409 #[inline]
415 #[must_use]
416 pub fn from_rotation_y(angle: f32) -> Self {
417 let (sina, cosa) = math::sin_cos(angle);
418 Self::from_cols(
419 Vec4::new(cosa, 0.0, -sina, 0.0),
420 Vec4::Y,
421 Vec4::new(sina, 0.0, cosa, 0.0),
422 Vec4::W,
423 )
424 }
425
426 #[inline]
432 #[must_use]
433 pub fn from_rotation_z(angle: f32) -> Self {
434 let (sina, cosa) = math::sin_cos(angle);
435 Self::from_cols(
436 Vec4::new(cosa, sina, 0.0, 0.0),
437 Vec4::new(-sina, cosa, 0.0, 0.0),
438 Vec4::Z,
439 Vec4::W,
440 )
441 }
442
443 #[inline]
452 #[must_use]
453 pub fn from_scale(scale: Vec3) -> Self {
454 glam_assert!(scale.cmpne(Vec3::ZERO).any());
456
457 Self::from_cols(
458 Vec4::new(scale.x, 0.0, 0.0, 0.0),
459 Vec4::new(0.0, scale.y, 0.0, 0.0),
460 Vec4::new(0.0, 0.0, scale.z, 0.0),
461 Vec4::W,
462 )
463 }
464
465 #[inline]
471 #[must_use]
472 pub const fn from_cols_slice(slice: &[f32]) -> Self {
473 Self::new(
474 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
475 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
476 )
477 }
478
479 #[inline]
485 pub fn write_cols_to_slice(self, slice: &mut [f32]) {
486 slice[0] = self.x_axis.x;
487 slice[1] = self.x_axis.y;
488 slice[2] = self.x_axis.z;
489 slice[3] = self.x_axis.w;
490 slice[4] = self.y_axis.x;
491 slice[5] = self.y_axis.y;
492 slice[6] = self.y_axis.z;
493 slice[7] = self.y_axis.w;
494 slice[8] = self.z_axis.x;
495 slice[9] = self.z_axis.y;
496 slice[10] = self.z_axis.z;
497 slice[11] = self.z_axis.w;
498 slice[12] = self.w_axis.x;
499 slice[13] = self.w_axis.y;
500 slice[14] = self.w_axis.z;
501 slice[15] = self.w_axis.w;
502 }
503
504 #[inline]
510 #[must_use]
511 pub fn col(&self, index: usize) -> Vec4 {
512 match index {
513 0 => self.x_axis,
514 1 => self.y_axis,
515 2 => self.z_axis,
516 3 => self.w_axis,
517 _ => panic!("index out of bounds"),
518 }
519 }
520
521 #[inline]
527 pub fn col_mut(&mut self, index: usize) -> &mut Vec4 {
528 match index {
529 0 => &mut self.x_axis,
530 1 => &mut self.y_axis,
531 2 => &mut self.z_axis,
532 3 => &mut self.w_axis,
533 _ => panic!("index out of bounds"),
534 }
535 }
536
537 #[inline]
543 #[must_use]
544 pub fn row(&self, index: usize) -> Vec4 {
545 match index {
546 0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
547 1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
548 2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
549 3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
550 _ => panic!("index out of bounds"),
551 }
552 }
553
554 #[inline]
557 #[must_use]
558 pub fn is_finite(&self) -> bool {
559 self.x_axis.is_finite()
560 && self.y_axis.is_finite()
561 && self.z_axis.is_finite()
562 && self.w_axis.is_finite()
563 }
564
565 #[inline]
567 #[must_use]
568 pub fn is_nan(&self) -> bool {
569 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
570 }
571
572 #[inline]
574 #[must_use]
575 pub fn transpose(&self) -> Self {
576 unsafe {
577 let tmp0 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b01_00_01_00);
579 let tmp1 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b11_10_11_10);
580 let tmp2 = _mm_shuffle_ps(self.z_axis.0, self.w_axis.0, 0b01_00_01_00);
581 let tmp3 = _mm_shuffle_ps(self.z_axis.0, self.w_axis.0, 0b11_10_11_10);
582
583 Self {
584 x_axis: Vec4(_mm_shuffle_ps(tmp0, tmp2, 0b10_00_10_00)),
585 y_axis: Vec4(_mm_shuffle_ps(tmp0, tmp2, 0b11_01_11_01)),
586 z_axis: Vec4(_mm_shuffle_ps(tmp1, tmp3, 0b10_00_10_00)),
587 w_axis: Vec4(_mm_shuffle_ps(tmp1, tmp3, 0b11_01_11_01)),
588 }
589 }
590 }
591
592 #[must_use]
594 pub fn determinant(&self) -> f32 {
595 unsafe {
596 let swp2a = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_01_01_10);
598 let swp3a = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b11_10_11_11);
599 let swp2b = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b11_10_11_11);
600 let swp3b = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b00_01_01_10);
601 let swp2c = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_00_01_10);
602 let swp3c = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b01_10_00_00);
603
604 let mula = _mm_mul_ps(swp2a, swp3a);
605 let mulb = _mm_mul_ps(swp2b, swp3b);
606 let mulc = _mm_mul_ps(swp2c, swp3c);
607 let sube = _mm_sub_ps(mula, mulb);
608 let subf = _mm_sub_ps(_mm_movehl_ps(mulc, mulc), mulc);
609
610 let subfaca = _mm_shuffle_ps(sube, sube, 0b10_01_00_00);
611 let swpfaca = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b00_00_00_01);
612 let mulfaca = _mm_mul_ps(swpfaca, subfaca);
613
614 let subtmpb = _mm_shuffle_ps(sube, subf, 0b00_00_11_01);
615 let subfacb = _mm_shuffle_ps(subtmpb, subtmpb, 0b11_01_01_00);
616 let swpfacb = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b01_01_10_10);
617 let mulfacb = _mm_mul_ps(swpfacb, subfacb);
618
619 let subres = _mm_sub_ps(mulfaca, mulfacb);
620 let subtmpc = _mm_shuffle_ps(sube, subf, 0b01_00_10_10);
621 let subfacc = _mm_shuffle_ps(subtmpc, subtmpc, 0b11_11_10_00);
622 let swpfacc = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b10_11_11_11);
623 let mulfacc = _mm_mul_ps(swpfacc, subfacc);
624
625 let addres = _mm_add_ps(subres, mulfacc);
626 let detcof = _mm_mul_ps(addres, _mm_setr_ps(1.0, -1.0, 1.0, -1.0));
627
628 dot4(self.x_axis.0, detcof)
629 }
630 }
631
632 #[must_use]
640 pub fn inverse(&self) -> Self {
641 unsafe {
642 let fac0 = {
644 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
645 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
646
647 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
648 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
649 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
650 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
651
652 let mul00 = _mm_mul_ps(swp00, swp01);
653 let mul01 = _mm_mul_ps(swp02, swp03);
654 _mm_sub_ps(mul00, mul01)
655 };
656 let fac1 = {
657 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
658 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
659
660 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
661 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
662 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
663 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
664
665 let mul00 = _mm_mul_ps(swp00, swp01);
666 let mul01 = _mm_mul_ps(swp02, swp03);
667 _mm_sub_ps(mul00, mul01)
668 };
669 let fac2 = {
670 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
671 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
672
673 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
674 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
675 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
676 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
677
678 let mul00 = _mm_mul_ps(swp00, swp01);
679 let mul01 = _mm_mul_ps(swp02, swp03);
680 _mm_sub_ps(mul00, mul01)
681 };
682 let fac3 = {
683 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
684 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
685
686 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
687 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
688 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
689 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
690
691 let mul00 = _mm_mul_ps(swp00, swp01);
692 let mul01 = _mm_mul_ps(swp02, swp03);
693 _mm_sub_ps(mul00, mul01)
694 };
695 let fac4 = {
696 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
697 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
698
699 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
700 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
701 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
702 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
703
704 let mul00 = _mm_mul_ps(swp00, swp01);
705 let mul01 = _mm_mul_ps(swp02, swp03);
706 _mm_sub_ps(mul00, mul01)
707 };
708 let fac5 = {
709 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
710 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
711
712 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
713 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
714 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
715 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
716
717 let mul00 = _mm_mul_ps(swp00, swp01);
718 let mul01 = _mm_mul_ps(swp02, swp03);
719 _mm_sub_ps(mul00, mul01)
720 };
721 let sign_a = _mm_set_ps(1.0, -1.0, 1.0, -1.0);
722 let sign_b = _mm_set_ps(-1.0, 1.0, -1.0, 1.0);
723
724 let temp0 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b00_00_00_00);
725 let vec0 = _mm_shuffle_ps(temp0, temp0, 0b10_10_10_00);
726
727 let temp1 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b01_01_01_01);
728 let vec1 = _mm_shuffle_ps(temp1, temp1, 0b10_10_10_00);
729
730 let temp2 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b10_10_10_10);
731 let vec2 = _mm_shuffle_ps(temp2, temp2, 0b10_10_10_00);
732
733 let temp3 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b11_11_11_11);
734 let vec3 = _mm_shuffle_ps(temp3, temp3, 0b10_10_10_00);
735
736 let mul00 = _mm_mul_ps(vec1, fac0);
737 let mul01 = _mm_mul_ps(vec2, fac1);
738 let mul02 = _mm_mul_ps(vec3, fac2);
739 let sub00 = _mm_sub_ps(mul00, mul01);
740 let add00 = _mm_add_ps(sub00, mul02);
741 let inv0 = _mm_mul_ps(sign_b, add00);
742
743 let mul03 = _mm_mul_ps(vec0, fac0);
744 let mul04 = _mm_mul_ps(vec2, fac3);
745 let mul05 = _mm_mul_ps(vec3, fac4);
746 let sub01 = _mm_sub_ps(mul03, mul04);
747 let add01 = _mm_add_ps(sub01, mul05);
748 let inv1 = _mm_mul_ps(sign_a, add01);
749
750 let mul06 = _mm_mul_ps(vec0, fac1);
751 let mul07 = _mm_mul_ps(vec1, fac3);
752 let mul08 = _mm_mul_ps(vec3, fac5);
753 let sub02 = _mm_sub_ps(mul06, mul07);
754 let add02 = _mm_add_ps(sub02, mul08);
755 let inv2 = _mm_mul_ps(sign_b, add02);
756
757 let mul09 = _mm_mul_ps(vec0, fac2);
758 let mul10 = _mm_mul_ps(vec1, fac4);
759 let mul11 = _mm_mul_ps(vec2, fac5);
760 let sub03 = _mm_sub_ps(mul09, mul10);
761 let add03 = _mm_add_ps(sub03, mul11);
762 let inv3 = _mm_mul_ps(sign_a, add03);
763
764 let row0 = _mm_shuffle_ps(inv0, inv1, 0b00_00_00_00);
765 let row1 = _mm_shuffle_ps(inv2, inv3, 0b00_00_00_00);
766 let row2 = _mm_shuffle_ps(row0, row1, 0b10_00_10_00);
767
768 let dot0 = dot4(self.x_axis.0, row2);
769 glam_assert!(dot0 != 0.0);
770
771 let rcp0 = _mm_set1_ps(dot0.recip());
772
773 Self {
774 x_axis: Vec4(_mm_mul_ps(inv0, rcp0)),
775 y_axis: Vec4(_mm_mul_ps(inv1, rcp0)),
776 z_axis: Vec4(_mm_mul_ps(inv2, rcp0)),
777 w_axis: Vec4(_mm_mul_ps(inv3, rcp0)),
778 }
779 }
780 }
781
782 #[inline]
787 #[must_use]
788 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
789 Self::look_to_rh(eye, -dir, up)
790 }
791
792 #[inline]
797 #[must_use]
798 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
799 let f = dir.normalize();
800 let s = f.cross(up).normalize();
801 let u = s.cross(f);
802
803 Self::from_cols(
804 Vec4::new(s.x, u.x, -f.x, 0.0),
805 Vec4::new(s.y, u.y, -f.y, 0.0),
806 Vec4::new(s.z, u.z, -f.z, 0.0),
807 Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
808 )
809 }
810
811 #[inline]
819 #[must_use]
820 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
821 glam_assert!(up.is_normalized());
822 Self::look_to_lh(eye, center.sub(eye), up)
823 }
824
825 #[inline]
833 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
834 glam_assert!(up.is_normalized());
835 Self::look_to_rh(eye, center.sub(eye), up)
836 }
837
838 #[inline]
842 #[must_use]
843 pub fn perspective_rh_gl(
844 fov_y_radians: f32,
845 aspect_ratio: f32,
846 z_near: f32,
847 z_far: f32,
848 ) -> Self {
849 let inv_length = 1.0 / (z_near - z_far);
850 let f = 1.0 / math::tan(0.5 * fov_y_radians);
851 let a = f / aspect_ratio;
852 let b = (z_near + z_far) * inv_length;
853 let c = (2.0 * z_near * z_far) * inv_length;
854 Self::from_cols(
855 Vec4::new(a, 0.0, 0.0, 0.0),
856 Vec4::new(0.0, f, 0.0, 0.0),
857 Vec4::new(0.0, 0.0, b, -1.0),
858 Vec4::new(0.0, 0.0, c, 0.0),
859 )
860 }
861
862 #[inline]
869 #[must_use]
870 pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
871 glam_assert!(z_near > 0.0 && z_far > 0.0);
872 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
873 let h = cos_fov / sin_fov;
874 let w = h / aspect_ratio;
875 let r = z_far / (z_far - z_near);
876 Self::from_cols(
877 Vec4::new(w, 0.0, 0.0, 0.0),
878 Vec4::new(0.0, h, 0.0, 0.0),
879 Vec4::new(0.0, 0.0, r, 1.0),
880 Vec4::new(0.0, 0.0, -r * z_near, 0.0),
881 )
882 }
883
884 #[inline]
891 #[must_use]
892 pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
893 glam_assert!(z_near > 0.0 && z_far > 0.0);
894 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
895 let h = cos_fov / sin_fov;
896 let w = h / aspect_ratio;
897 let r = z_far / (z_near - z_far);
898 Self::from_cols(
899 Vec4::new(w, 0.0, 0.0, 0.0),
900 Vec4::new(0.0, h, 0.0, 0.0),
901 Vec4::new(0.0, 0.0, r, -1.0),
902 Vec4::new(0.0, 0.0, r * z_near, 0.0),
903 )
904 }
905
906 #[inline]
912 #[must_use]
913 pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
914 glam_assert!(z_near > 0.0);
915 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
916 let h = cos_fov / sin_fov;
917 let w = h / aspect_ratio;
918 Self::from_cols(
919 Vec4::new(w, 0.0, 0.0, 0.0),
920 Vec4::new(0.0, h, 0.0, 0.0),
921 Vec4::new(0.0, 0.0, 1.0, 1.0),
922 Vec4::new(0.0, 0.0, -z_near, 0.0),
923 )
924 }
925
926 #[inline]
932 #[must_use]
933 pub fn perspective_infinite_reverse_lh(
934 fov_y_radians: f32,
935 aspect_ratio: f32,
936 z_near: f32,
937 ) -> Self {
938 glam_assert!(z_near > 0.0);
939 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
940 let h = cos_fov / sin_fov;
941 let w = h / aspect_ratio;
942 Self::from_cols(
943 Vec4::new(w, 0.0, 0.0, 0.0),
944 Vec4::new(0.0, h, 0.0, 0.0),
945 Vec4::new(0.0, 0.0, 0.0, 1.0),
946 Vec4::new(0.0, 0.0, z_near, 0.0),
947 )
948 }
949
950 #[inline]
953 #[must_use]
954 pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
955 glam_assert!(z_near > 0.0);
956 let f = 1.0 / math::tan(0.5 * fov_y_radians);
957 Self::from_cols(
958 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
959 Vec4::new(0.0, f, 0.0, 0.0),
960 Vec4::new(0.0, 0.0, -1.0, -1.0),
961 Vec4::new(0.0, 0.0, -z_near, 0.0),
962 )
963 }
964
965 #[inline]
968 #[must_use]
969 pub fn perspective_infinite_reverse_rh(
970 fov_y_radians: f32,
971 aspect_ratio: f32,
972 z_near: f32,
973 ) -> Self {
974 glam_assert!(z_near > 0.0);
975 let f = 1.0 / math::tan(0.5 * fov_y_radians);
976 Self::from_cols(
977 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
978 Vec4::new(0.0, f, 0.0, 0.0),
979 Vec4::new(0.0, 0.0, 0.0, -1.0),
980 Vec4::new(0.0, 0.0, z_near, 0.0),
981 )
982 }
983
984 #[inline]
989 #[must_use]
990 pub fn orthographic_rh_gl(
991 left: f32,
992 right: f32,
993 bottom: f32,
994 top: f32,
995 near: f32,
996 far: f32,
997 ) -> Self {
998 let a = 2.0 / (right - left);
999 let b = 2.0 / (top - bottom);
1000 let c = -2.0 / (far - near);
1001 let tx = -(right + left) / (right - left);
1002 let ty = -(top + bottom) / (top - bottom);
1003 let tz = -(far + near) / (far - near);
1004
1005 Self::from_cols(
1006 Vec4::new(a, 0.0, 0.0, 0.0),
1007 Vec4::new(0.0, b, 0.0, 0.0),
1008 Vec4::new(0.0, 0.0, c, 0.0),
1009 Vec4::new(tx, ty, tz, 1.0),
1010 )
1011 }
1012
1013 #[inline]
1015 #[must_use]
1016 pub fn orthographic_lh(
1017 left: f32,
1018 right: f32,
1019 bottom: f32,
1020 top: f32,
1021 near: f32,
1022 far: f32,
1023 ) -> Self {
1024 let rcp_width = 1.0 / (right - left);
1025 let rcp_height = 1.0 / (top - bottom);
1026 let r = 1.0 / (far - near);
1027 Self::from_cols(
1028 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1029 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1030 Vec4::new(0.0, 0.0, r, 0.0),
1031 Vec4::new(
1032 -(left + right) * rcp_width,
1033 -(top + bottom) * rcp_height,
1034 -r * near,
1035 1.0,
1036 ),
1037 )
1038 }
1039
1040 #[inline]
1042 #[must_use]
1043 pub fn orthographic_rh(
1044 left: f32,
1045 right: f32,
1046 bottom: f32,
1047 top: f32,
1048 near: f32,
1049 far: f32,
1050 ) -> Self {
1051 let rcp_width = 1.0 / (right - left);
1052 let rcp_height = 1.0 / (top - bottom);
1053 let r = 1.0 / (near - far);
1054 Self::from_cols(
1055 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1056 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1057 Vec4::new(0.0, 0.0, r, 0.0),
1058 Vec4::new(
1059 -(left + right) * rcp_width,
1060 -(top + bottom) * rcp_height,
1061 r * near,
1062 1.0,
1063 ),
1064 )
1065 }
1066
1067 #[inline]
1074 #[must_use]
1075 pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
1076 let mut res = self.x_axis.mul(rhs.x);
1077 res = self.y_axis.mul(rhs.y).add(res);
1078 res = self.z_axis.mul(rhs.z).add(res);
1079 res = self.w_axis.add(res);
1080 res = res.mul(res.wwww().recip());
1081 res.xyz()
1082 }
1083
1084 #[inline]
1097 #[must_use]
1098 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1099 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1100 let mut res = self.x_axis.mul(rhs.x);
1101 res = self.y_axis.mul(rhs.y).add(res);
1102 res = self.z_axis.mul(rhs.z).add(res);
1103 res = self.w_axis.add(res);
1104 res.xyz()
1105 }
1106
1107 #[inline]
1118 #[must_use]
1119 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1120 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1121 let mut res = self.x_axis.mul(rhs.x);
1122 res = self.y_axis.mul(rhs.y).add(res);
1123 res = self.z_axis.mul(rhs.z).add(res);
1124 res.xyz()
1125 }
1126
1127 #[inline]
1131 #[must_use]
1132 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1133 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1134 let mut res = self.x_axis.mul(rhs.xxxx());
1135 res = self.y_axis.mul(rhs.yyyy()).add(res);
1136 res = self.z_axis.mul(rhs.zzzz()).add(res);
1137 res = self.w_axis.add(res);
1138 res.into()
1139 }
1140
1141 #[inline]
1145 #[must_use]
1146 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1147 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1148 let mut res = self.x_axis.mul(rhs.xxxx());
1149 res = self.y_axis.mul(rhs.yyyy()).add(res);
1150 res = self.z_axis.mul(rhs.zzzz()).add(res);
1151 res.into()
1152 }
1153
1154 #[inline]
1156 #[must_use]
1157 pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1158 let mut res = self.x_axis.mul(rhs.xxxx());
1159 res = res.add(self.y_axis.mul(rhs.yyyy()));
1160 res = res.add(self.z_axis.mul(rhs.zzzz()));
1161 res = res.add(self.w_axis.mul(rhs.wwww()));
1162 res
1163 }
1164
1165 #[inline]
1167 #[must_use]
1168 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1169 Self::from_cols(
1170 self.mul(rhs.x_axis),
1171 self.mul(rhs.y_axis),
1172 self.mul(rhs.z_axis),
1173 self.mul(rhs.w_axis),
1174 )
1175 }
1176
1177 #[inline]
1179 #[must_use]
1180 pub fn add_mat4(&self, rhs: &Self) -> Self {
1181 Self::from_cols(
1182 self.x_axis.add(rhs.x_axis),
1183 self.y_axis.add(rhs.y_axis),
1184 self.z_axis.add(rhs.z_axis),
1185 self.w_axis.add(rhs.w_axis),
1186 )
1187 }
1188
1189 #[inline]
1191 #[must_use]
1192 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1193 Self::from_cols(
1194 self.x_axis.sub(rhs.x_axis),
1195 self.y_axis.sub(rhs.y_axis),
1196 self.z_axis.sub(rhs.z_axis),
1197 self.w_axis.sub(rhs.w_axis),
1198 )
1199 }
1200
1201 #[inline]
1203 #[must_use]
1204 pub fn mul_scalar(&self, rhs: f32) -> Self {
1205 Self::from_cols(
1206 self.x_axis.mul(rhs),
1207 self.y_axis.mul(rhs),
1208 self.z_axis.mul(rhs),
1209 self.w_axis.mul(rhs),
1210 )
1211 }
1212
1213 #[inline]
1223 #[must_use]
1224 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1225 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1226 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1227 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1228 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1229 }
1230
1231 #[inline]
1232 pub fn as_dmat4(&self) -> DMat4 {
1233 DMat4::from_cols(
1234 self.x_axis.as_dvec4(),
1235 self.y_axis.as_dvec4(),
1236 self.z_axis.as_dvec4(),
1237 self.w_axis.as_dvec4(),
1238 )
1239 }
1240}
1241
1242impl Default for Mat4 {
1243 #[inline]
1244 fn default() -> Self {
1245 Self::IDENTITY
1246 }
1247}
1248
1249impl Add<Mat4> for Mat4 {
1250 type Output = Self;
1251 #[inline]
1252 fn add(self, rhs: Self) -> Self::Output {
1253 self.add_mat4(&rhs)
1254 }
1255}
1256
1257impl AddAssign<Mat4> for Mat4 {
1258 #[inline]
1259 fn add_assign(&mut self, rhs: Self) {
1260 *self = self.add_mat4(&rhs);
1261 }
1262}
1263
1264impl Sub<Mat4> for Mat4 {
1265 type Output = Self;
1266 #[inline]
1267 fn sub(self, rhs: Self) -> Self::Output {
1268 self.sub_mat4(&rhs)
1269 }
1270}
1271
1272impl SubAssign<Mat4> for Mat4 {
1273 #[inline]
1274 fn sub_assign(&mut self, rhs: Self) {
1275 *self = self.sub_mat4(&rhs);
1276 }
1277}
1278
1279impl Neg for Mat4 {
1280 type Output = Self;
1281 #[inline]
1282 fn neg(self) -> Self::Output {
1283 Self::from_cols(
1284 self.x_axis.neg(),
1285 self.y_axis.neg(),
1286 self.z_axis.neg(),
1287 self.w_axis.neg(),
1288 )
1289 }
1290}
1291
1292impl Mul<Mat4> for Mat4 {
1293 type Output = Self;
1294 #[inline]
1295 fn mul(self, rhs: Self) -> Self::Output {
1296 self.mul_mat4(&rhs)
1297 }
1298}
1299
1300impl MulAssign<Mat4> for Mat4 {
1301 #[inline]
1302 fn mul_assign(&mut self, rhs: Self) {
1303 *self = self.mul_mat4(&rhs);
1304 }
1305}
1306
1307impl Mul<Vec4> for Mat4 {
1308 type Output = Vec4;
1309 #[inline]
1310 fn mul(self, rhs: Vec4) -> Self::Output {
1311 self.mul_vec4(rhs)
1312 }
1313}
1314
1315impl Mul<Mat4> for f32 {
1316 type Output = Mat4;
1317 #[inline]
1318 fn mul(self, rhs: Mat4) -> Self::Output {
1319 rhs.mul_scalar(self)
1320 }
1321}
1322
1323impl Mul<f32> for Mat4 {
1324 type Output = Self;
1325 #[inline]
1326 fn mul(self, rhs: f32) -> Self::Output {
1327 self.mul_scalar(rhs)
1328 }
1329}
1330
1331impl MulAssign<f32> for Mat4 {
1332 #[inline]
1333 fn mul_assign(&mut self, rhs: f32) {
1334 *self = self.mul_scalar(rhs);
1335 }
1336}
1337
1338impl Sum<Self> for Mat4 {
1339 fn sum<I>(iter: I) -> Self
1340 where
1341 I: Iterator<Item = Self>,
1342 {
1343 iter.fold(Self::ZERO, Self::add)
1344 }
1345}
1346
1347impl<'a> Sum<&'a Self> for Mat4 {
1348 fn sum<I>(iter: I) -> Self
1349 where
1350 I: Iterator<Item = &'a Self>,
1351 {
1352 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1353 }
1354}
1355
1356impl Product for Mat4 {
1357 fn product<I>(iter: I) -> Self
1358 where
1359 I: Iterator<Item = Self>,
1360 {
1361 iter.fold(Self::IDENTITY, Self::mul)
1362 }
1363}
1364
1365impl<'a> Product<&'a Self> for Mat4 {
1366 fn product<I>(iter: I) -> Self
1367 where
1368 I: Iterator<Item = &'a Self>,
1369 {
1370 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1371 }
1372}
1373
1374impl PartialEq for Mat4 {
1375 #[inline]
1376 fn eq(&self, rhs: &Self) -> bool {
1377 self.x_axis.eq(&rhs.x_axis)
1378 && self.y_axis.eq(&rhs.y_axis)
1379 && self.z_axis.eq(&rhs.z_axis)
1380 && self.w_axis.eq(&rhs.w_axis)
1381 }
1382}
1383
1384#[cfg(not(target_arch = "spirv"))]
1385impl AsRef<[f32; 16]> for Mat4 {
1386 #[inline]
1387 fn as_ref(&self) -> &[f32; 16] {
1388 unsafe { &*(self as *const Self as *const [f32; 16]) }
1389 }
1390}
1391
1392#[cfg(not(target_arch = "spirv"))]
1393impl AsMut<[f32; 16]> for Mat4 {
1394 #[inline]
1395 fn as_mut(&mut self) -> &mut [f32; 16] {
1396 unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
1397 }
1398}
1399
1400#[cfg(not(target_arch = "spirv"))]
1401impl fmt::Debug for Mat4 {
1402 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1403 fmt.debug_struct(stringify!(Mat4))
1404 .field("x_axis", &self.x_axis)
1405 .field("y_axis", &self.y_axis)
1406 .field("z_axis", &self.z_axis)
1407 .field("w_axis", &self.w_axis)
1408 .finish()
1409 }
1410}
1411
1412#[cfg(not(target_arch = "spirv"))]
1413impl fmt::Display for Mat4 {
1414 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1415 write!(
1416 f,
1417 "[{}, {}, {}, {}]",
1418 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1419 )
1420 }
1421}