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)]
18pub const fn mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat4 {
19 Mat4::from_cols(x_axis, y_axis, z_axis, w_axis)
20}
21
22#[derive(Clone, Copy)]
52#[repr(C)]
53pub struct Mat4 {
54 pub x_axis: Vec4,
55 pub y_axis: Vec4,
56 pub z_axis: Vec4,
57 pub w_axis: Vec4,
58}
59
60impl Mat4 {
61 pub const ZERO: Self = Self::from_cols(Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO);
63
64 pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W);
66
67 pub const NAN: Self = Self::from_cols(Vec4::NAN, Vec4::NAN, Vec4::NAN, Vec4::NAN);
69
70 #[allow(clippy::too_many_arguments)]
71 #[inline(always)]
72 const fn new(
73 m00: f32,
74 m01: f32,
75 m02: f32,
76 m03: f32,
77 m10: f32,
78 m11: f32,
79 m12: f32,
80 m13: f32,
81 m20: f32,
82 m21: f32,
83 m22: f32,
84 m23: f32,
85 m30: f32,
86 m31: f32,
87 m32: f32,
88 m33: f32,
89 ) -> Self {
90 Self {
91 x_axis: Vec4::new(m00, m01, m02, m03),
92 y_axis: Vec4::new(m10, m11, m12, m13),
93 z_axis: Vec4::new(m20, m21, m22, m23),
94 w_axis: Vec4::new(m30, m31, m32, m33),
95 }
96 }
97
98 #[inline(always)]
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 pub const fn from_cols_array(m: &[f32; 16]) -> Self {
114 Self::new(
115 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],
116 m[14], m[15],
117 )
118 }
119
120 #[inline]
123 pub const fn to_cols_array(&self) -> [f32; 16] {
124 let [x_axis_x, x_axis_y, x_axis_z, x_axis_w] = self.x_axis.to_array();
125 let [y_axis_x, y_axis_y, y_axis_z, y_axis_w] = self.y_axis.to_array();
126 let [z_axis_x, z_axis_y, z_axis_z, z_axis_w] = self.z_axis.to_array();
127 let [w_axis_x, w_axis_y, w_axis_z, w_axis_w] = self.w_axis.to_array();
128
129 [
130 x_axis_x, x_axis_y, x_axis_z, x_axis_w, y_axis_x, y_axis_y, y_axis_z, y_axis_w,
131 z_axis_x, z_axis_y, z_axis_z, z_axis_w, w_axis_x, w_axis_y, w_axis_z, w_axis_w,
132 ]
133 }
134
135 #[inline]
139 pub const fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self {
140 Self::from_cols(
141 Vec4::from_array(m[0]),
142 Vec4::from_array(m[1]),
143 Vec4::from_array(m[2]),
144 Vec4::from_array(m[3]),
145 )
146 }
147
148 #[inline]
151 pub const fn to_cols_array_2d(&self) -> [[f32; 4]; 4] {
152 [
153 self.x_axis.to_array(),
154 self.y_axis.to_array(),
155 self.z_axis.to_array(),
156 self.w_axis.to_array(),
157 ]
158 }
159
160 #[doc(alias = "scale")]
162 #[inline]
163 pub const fn from_diagonal(diagonal: Vec4) -> Self {
164 let [x, y, z, w] = diagonal.to_array();
166 Self::new(
167 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,
168 )
169 }
170
171 #[inline]
172 fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) {
173 glam_assert!(rotation.is_normalized());
174
175 let (x, y, z, w) = rotation.into();
176 let x2 = x + x;
177 let y2 = y + y;
178 let z2 = z + z;
179 let xx = x * x2;
180 let xy = x * y2;
181 let xz = x * z2;
182 let yy = y * y2;
183 let yz = y * z2;
184 let zz = z * z2;
185 let wx = w * x2;
186 let wy = w * y2;
187 let wz = w * z2;
188
189 let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
190 let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
191 let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
192 (x_axis, y_axis, z_axis)
193 }
194
195 #[inline]
205 pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
206 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
207 Self::from_cols(
208 x_axis.mul(scale.x),
209 y_axis.mul(scale.y),
210 z_axis.mul(scale.z),
211 Vec4::from((translation, 1.0)),
212 )
213 }
214
215 #[inline]
224 pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
225 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
226 Self::from_cols(x_axis, y_axis, z_axis, Vec4::from((translation, 1.0)))
227 }
228
229 #[inline]
237 pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
238 let det = self.determinant();
239 glam_assert!(det != 0.0);
240
241 let scale = Vec3::new(
242 self.x_axis.length() * math::signum(det),
243 self.y_axis.length(),
244 self.z_axis.length(),
245 );
246
247 glam_assert!(scale.cmpne(Vec3::ZERO).all());
248
249 let inv_scale = scale.recip();
250
251 let rotation = Quat::from_rotation_axes(
252 self.x_axis.mul(inv_scale.x).xyz(),
253 self.y_axis.mul(inv_scale.y).xyz(),
254 self.z_axis.mul(inv_scale.z).xyz(),
255 );
256
257 let translation = self.w_axis.xyz();
258
259 (scale, rotation, translation)
260 }
261
262 #[inline]
271 pub fn from_quat(rotation: Quat) -> Self {
272 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
273 Self::from_cols(x_axis, y_axis, z_axis, Vec4::W)
274 }
275
276 #[inline]
282 pub fn from_mat3(m: Mat3) -> Self {
283 Self::from_cols(
284 Vec4::from((m.x_axis, 0.0)),
285 Vec4::from((m.y_axis, 0.0)),
286 Vec4::from((m.z_axis, 0.0)),
287 Vec4::W,
288 )
289 }
290
291 #[inline]
297 pub fn from_mat3a(m: Mat3A) -> Self {
298 Self::from_cols(
299 Vec4::from((m.x_axis, 0.0)),
300 Vec4::from((m.y_axis, 0.0)),
301 Vec4::from((m.z_axis, 0.0)),
302 Vec4::W,
303 )
304 }
305
306 #[inline]
311 pub fn from_translation(translation: Vec3) -> Self {
312 Self::from_cols(
313 Vec4::X,
314 Vec4::Y,
315 Vec4::Z,
316 Vec4::new(translation.x, translation.y, translation.z, 1.0),
317 )
318 }
319
320 #[inline]
330 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
331 glam_assert!(axis.is_normalized());
332
333 let (sin, cos) = math::sin_cos(angle);
334 let axis_sin = axis.mul(sin);
335 let axis_sq = axis.mul(axis);
336 let omc = 1.0 - cos;
337 let xyomc = axis.x * axis.y * omc;
338 let xzomc = axis.x * axis.z * omc;
339 let yzomc = axis.y * axis.z * omc;
340 Self::from_cols(
341 Vec4::new(
342 axis_sq.x * omc + cos,
343 xyomc + axis_sin.z,
344 xzomc - axis_sin.y,
345 0.0,
346 ),
347 Vec4::new(
348 xyomc - axis_sin.z,
349 axis_sq.y * omc + cos,
350 yzomc + axis_sin.x,
351 0.0,
352 ),
353 Vec4::new(
354 xzomc + axis_sin.y,
355 yzomc - axis_sin.x,
356 axis_sq.z * omc + cos,
357 0.0,
358 ),
359 Vec4::W,
360 )
361 }
362
363 #[inline]
364 pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
370 let quat = Quat::from_euler(order, a, b, c);
371 Self::from_quat(quat)
372 }
373
374 #[inline]
380 pub fn from_rotation_x(angle: f32) -> Self {
381 let (sina, cosa) = math::sin_cos(angle);
382 Self::from_cols(
383 Vec4::X,
384 Vec4::new(0.0, cosa, sina, 0.0),
385 Vec4::new(0.0, -sina, cosa, 0.0),
386 Vec4::W,
387 )
388 }
389
390 #[inline]
396 pub fn from_rotation_y(angle: f32) -> Self {
397 let (sina, cosa) = math::sin_cos(angle);
398 Self::from_cols(
399 Vec4::new(cosa, 0.0, -sina, 0.0),
400 Vec4::Y,
401 Vec4::new(sina, 0.0, cosa, 0.0),
402 Vec4::W,
403 )
404 }
405
406 #[inline]
412 pub fn from_rotation_z(angle: f32) -> Self {
413 let (sina, cosa) = math::sin_cos(angle);
414 Self::from_cols(
415 Vec4::new(cosa, sina, 0.0, 0.0),
416 Vec4::new(-sina, cosa, 0.0, 0.0),
417 Vec4::Z,
418 Vec4::W,
419 )
420 }
421
422 #[inline]
431 pub fn from_scale(scale: Vec3) -> Self {
432 glam_assert!(scale.cmpne(Vec3::ZERO).any());
434
435 Self::from_cols(
436 Vec4::new(scale.x, 0.0, 0.0, 0.0),
437 Vec4::new(0.0, scale.y, 0.0, 0.0),
438 Vec4::new(0.0, 0.0, scale.z, 0.0),
439 Vec4::W,
440 )
441 }
442
443 #[inline]
449 pub const fn from_cols_slice(slice: &[f32]) -> Self {
450 Self::new(
451 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
452 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
453 )
454 }
455
456 #[inline]
462 pub fn write_cols_to_slice(self, slice: &mut [f32]) {
463 slice[0] = self.x_axis.x;
464 slice[1] = self.x_axis.y;
465 slice[2] = self.x_axis.z;
466 slice[3] = self.x_axis.w;
467 slice[4] = self.y_axis.x;
468 slice[5] = self.y_axis.y;
469 slice[6] = self.y_axis.z;
470 slice[7] = self.y_axis.w;
471 slice[8] = self.z_axis.x;
472 slice[9] = self.z_axis.y;
473 slice[10] = self.z_axis.z;
474 slice[11] = self.z_axis.w;
475 slice[12] = self.w_axis.x;
476 slice[13] = self.w_axis.y;
477 slice[14] = self.w_axis.z;
478 slice[15] = self.w_axis.w;
479 }
480
481 #[inline]
487 pub fn col(&self, index: usize) -> Vec4 {
488 match index {
489 0 => self.x_axis,
490 1 => self.y_axis,
491 2 => self.z_axis,
492 3 => self.w_axis,
493 _ => panic!("index out of bounds"),
494 }
495 }
496
497 #[inline]
503 pub fn col_mut(&mut self, index: usize) -> &mut Vec4 {
504 match index {
505 0 => &mut self.x_axis,
506 1 => &mut self.y_axis,
507 2 => &mut self.z_axis,
508 3 => &mut self.w_axis,
509 _ => panic!("index out of bounds"),
510 }
511 }
512
513 #[inline]
519 pub fn row(&self, index: usize) -> Vec4 {
520 match index {
521 0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
522 1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
523 2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
524 3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
525 _ => panic!("index out of bounds"),
526 }
527 }
528
529 #[inline]
532 pub fn is_finite(&self) -> bool {
533 self.x_axis.is_finite()
534 && self.y_axis.is_finite()
535 && self.z_axis.is_finite()
536 && self.w_axis.is_finite()
537 }
538
539 #[inline]
541 pub fn is_nan(&self) -> bool {
542 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
543 }
544
545 #[must_use]
547 #[inline]
548 pub fn transpose(&self) -> Self {
549 unsafe {
550 let tmp0 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b01_00_01_00);
552 let tmp1 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b11_10_11_10);
553 let tmp2 = _mm_shuffle_ps(self.z_axis.0, self.w_axis.0, 0b01_00_01_00);
554 let tmp3 = _mm_shuffle_ps(self.z_axis.0, self.w_axis.0, 0b11_10_11_10);
555
556 Self {
557 x_axis: Vec4(_mm_shuffle_ps(tmp0, tmp2, 0b10_00_10_00)),
558 y_axis: Vec4(_mm_shuffle_ps(tmp0, tmp2, 0b11_01_11_01)),
559 z_axis: Vec4(_mm_shuffle_ps(tmp1, tmp3, 0b10_00_10_00)),
560 w_axis: Vec4(_mm_shuffle_ps(tmp1, tmp3, 0b11_01_11_01)),
561 }
562 }
563 }
564
565 pub fn determinant(&self) -> f32 {
567 unsafe {
568 let swp2a = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_01_01_10);
570 let swp3a = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b11_10_11_11);
571 let swp2b = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b11_10_11_11);
572 let swp3b = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b00_01_01_10);
573 let swp2c = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_00_01_10);
574 let swp3c = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b01_10_00_00);
575
576 let mula = _mm_mul_ps(swp2a, swp3a);
577 let mulb = _mm_mul_ps(swp2b, swp3b);
578 let mulc = _mm_mul_ps(swp2c, swp3c);
579 let sube = _mm_sub_ps(mula, mulb);
580 let subf = _mm_sub_ps(_mm_movehl_ps(mulc, mulc), mulc);
581
582 let subfaca = _mm_shuffle_ps(sube, sube, 0b10_01_00_00);
583 let swpfaca = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b00_00_00_01);
584 let mulfaca = _mm_mul_ps(swpfaca, subfaca);
585
586 let subtmpb = _mm_shuffle_ps(sube, subf, 0b00_00_11_01);
587 let subfacb = _mm_shuffle_ps(subtmpb, subtmpb, 0b11_01_01_00);
588 let swpfacb = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b01_01_10_10);
589 let mulfacb = _mm_mul_ps(swpfacb, subfacb);
590
591 let subres = _mm_sub_ps(mulfaca, mulfacb);
592 let subtmpc = _mm_shuffle_ps(sube, subf, 0b01_00_10_10);
593 let subfacc = _mm_shuffle_ps(subtmpc, subtmpc, 0b11_11_10_00);
594 let swpfacc = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b10_11_11_11);
595 let mulfacc = _mm_mul_ps(swpfacc, subfacc);
596
597 let addres = _mm_add_ps(subres, mulfacc);
598 let detcof = _mm_mul_ps(addres, _mm_setr_ps(1.0, -1.0, 1.0, -1.0));
599
600 dot4(self.x_axis.0, detcof)
601 }
602 }
603
604 #[must_use]
612 pub fn inverse(&self) -> Self {
613 unsafe {
614 let fac0 = {
616 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
617 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
618
619 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
620 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
621 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
622 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
623
624 let mul00 = _mm_mul_ps(swp00, swp01);
625 let mul01 = _mm_mul_ps(swp02, swp03);
626 _mm_sub_ps(mul00, mul01)
627 };
628 let fac1 = {
629 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
630 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
631
632 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
633 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
634 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
635 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
636
637 let mul00 = _mm_mul_ps(swp00, swp01);
638 let mul01 = _mm_mul_ps(swp02, swp03);
639 _mm_sub_ps(mul00, mul01)
640 };
641 let fac2 = {
642 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
643 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
644
645 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
646 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
647 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
648 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
649
650 let mul00 = _mm_mul_ps(swp00, swp01);
651 let mul01 = _mm_mul_ps(swp02, swp03);
652 _mm_sub_ps(mul00, mul01)
653 };
654 let fac3 = {
655 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11);
656 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
657
658 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
659 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
660 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
661 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11);
662
663 let mul00 = _mm_mul_ps(swp00, swp01);
664 let mul01 = _mm_mul_ps(swp02, swp03);
665 _mm_sub_ps(mul00, mul01)
666 };
667 let fac4 = {
668 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10);
669 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
670
671 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
672 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
673 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
674 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10);
675
676 let mul00 = _mm_mul_ps(swp00, swp01);
677 let mul01 = _mm_mul_ps(swp02, swp03);
678 _mm_sub_ps(mul00, mul01)
679 };
680 let fac5 = {
681 let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01);
682 let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00);
683
684 let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00);
685 let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00);
686 let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00);
687 let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01);
688
689 let mul00 = _mm_mul_ps(swp00, swp01);
690 let mul01 = _mm_mul_ps(swp02, swp03);
691 _mm_sub_ps(mul00, mul01)
692 };
693 let sign_a = _mm_set_ps(1.0, -1.0, 1.0, -1.0);
694 let sign_b = _mm_set_ps(-1.0, 1.0, -1.0, 1.0);
695
696 let temp0 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b00_00_00_00);
697 let vec0 = _mm_shuffle_ps(temp0, temp0, 0b10_10_10_00);
698
699 let temp1 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b01_01_01_01);
700 let vec1 = _mm_shuffle_ps(temp1, temp1, 0b10_10_10_00);
701
702 let temp2 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b10_10_10_10);
703 let vec2 = _mm_shuffle_ps(temp2, temp2, 0b10_10_10_00);
704
705 let temp3 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b11_11_11_11);
706 let vec3 = _mm_shuffle_ps(temp3, temp3, 0b10_10_10_00);
707
708 let mul00 = _mm_mul_ps(vec1, fac0);
709 let mul01 = _mm_mul_ps(vec2, fac1);
710 let mul02 = _mm_mul_ps(vec3, fac2);
711 let sub00 = _mm_sub_ps(mul00, mul01);
712 let add00 = _mm_add_ps(sub00, mul02);
713 let inv0 = _mm_mul_ps(sign_b, add00);
714
715 let mul03 = _mm_mul_ps(vec0, fac0);
716 let mul04 = _mm_mul_ps(vec2, fac3);
717 let mul05 = _mm_mul_ps(vec3, fac4);
718 let sub01 = _mm_sub_ps(mul03, mul04);
719 let add01 = _mm_add_ps(sub01, mul05);
720 let inv1 = _mm_mul_ps(sign_a, add01);
721
722 let mul06 = _mm_mul_ps(vec0, fac1);
723 let mul07 = _mm_mul_ps(vec1, fac3);
724 let mul08 = _mm_mul_ps(vec3, fac5);
725 let sub02 = _mm_sub_ps(mul06, mul07);
726 let add02 = _mm_add_ps(sub02, mul08);
727 let inv2 = _mm_mul_ps(sign_b, add02);
728
729 let mul09 = _mm_mul_ps(vec0, fac2);
730 let mul10 = _mm_mul_ps(vec1, fac4);
731 let mul11 = _mm_mul_ps(vec2, fac5);
732 let sub03 = _mm_sub_ps(mul09, mul10);
733 let add03 = _mm_add_ps(sub03, mul11);
734 let inv3 = _mm_mul_ps(sign_a, add03);
735
736 let row0 = _mm_shuffle_ps(inv0, inv1, 0b00_00_00_00);
737 let row1 = _mm_shuffle_ps(inv2, inv3, 0b00_00_00_00);
738 let row2 = _mm_shuffle_ps(row0, row1, 0b10_00_10_00);
739
740 let dot0 = dot4(self.x_axis.0, row2);
741 glam_assert!(dot0 != 0.0);
742
743 let rcp0 = _mm_set1_ps(dot0.recip());
744
745 Self {
746 x_axis: Vec4(_mm_mul_ps(inv0, rcp0)),
747 y_axis: Vec4(_mm_mul_ps(inv1, rcp0)),
748 z_axis: Vec4(_mm_mul_ps(inv2, rcp0)),
749 w_axis: Vec4(_mm_mul_ps(inv3, rcp0)),
750 }
751 }
752 }
753
754 #[inline]
759 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
760 Self::look_to_rh(eye, -dir, up)
761 }
762
763 #[inline]
768 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
769 let f = dir.normalize();
770 let s = f.cross(up).normalize();
771 let u = s.cross(f);
772
773 Self::from_cols(
774 Vec4::new(s.x, u.x, -f.x, 0.0),
775 Vec4::new(s.y, u.y, -f.y, 0.0),
776 Vec4::new(s.z, u.z, -f.z, 0.0),
777 Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
778 )
779 }
780
781 #[inline]
789 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
790 glam_assert!(up.is_normalized());
791 Self::look_to_lh(eye, center.sub(eye), up)
792 }
793
794 #[inline]
802 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
803 glam_assert!(up.is_normalized());
804 Self::look_to_rh(eye, center.sub(eye), up)
805 }
806
807 #[inline]
811 pub fn perspective_rh_gl(
812 fov_y_radians: f32,
813 aspect_ratio: f32,
814 z_near: f32,
815 z_far: f32,
816 ) -> Self {
817 let inv_length = 1.0 / (z_near - z_far);
818 let f = 1.0 / math::tan(0.5 * fov_y_radians);
819 let a = f / aspect_ratio;
820 let b = (z_near + z_far) * inv_length;
821 let c = (2.0 * z_near * z_far) * inv_length;
822 Self::from_cols(
823 Vec4::new(a, 0.0, 0.0, 0.0),
824 Vec4::new(0.0, f, 0.0, 0.0),
825 Vec4::new(0.0, 0.0, b, -1.0),
826 Vec4::new(0.0, 0.0, c, 0.0),
827 )
828 }
829
830 #[inline]
837 pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
838 glam_assert!(z_near > 0.0 && z_far > 0.0);
839 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
840 let h = cos_fov / sin_fov;
841 let w = h / aspect_ratio;
842 let r = z_far / (z_far - z_near);
843 Self::from_cols(
844 Vec4::new(w, 0.0, 0.0, 0.0),
845 Vec4::new(0.0, h, 0.0, 0.0),
846 Vec4::new(0.0, 0.0, r, 1.0),
847 Vec4::new(0.0, 0.0, -r * z_near, 0.0),
848 )
849 }
850
851 #[inline]
858 pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
859 glam_assert!(z_near > 0.0 && z_far > 0.0);
860 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
861 let h = cos_fov / sin_fov;
862 let w = h / aspect_ratio;
863 let r = z_far / (z_near - z_far);
864 Self::from_cols(
865 Vec4::new(w, 0.0, 0.0, 0.0),
866 Vec4::new(0.0, h, 0.0, 0.0),
867 Vec4::new(0.0, 0.0, r, -1.0),
868 Vec4::new(0.0, 0.0, r * z_near, 0.0),
869 )
870 }
871
872 #[inline]
878 pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
879 glam_assert!(z_near > 0.0);
880 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
881 let h = cos_fov / sin_fov;
882 let w = h / aspect_ratio;
883 Self::from_cols(
884 Vec4::new(w, 0.0, 0.0, 0.0),
885 Vec4::new(0.0, h, 0.0, 0.0),
886 Vec4::new(0.0, 0.0, 1.0, 1.0),
887 Vec4::new(0.0, 0.0, -z_near, 0.0),
888 )
889 }
890
891 #[inline]
897 pub fn perspective_infinite_reverse_lh(
898 fov_y_radians: f32,
899 aspect_ratio: f32,
900 z_near: f32,
901 ) -> Self {
902 glam_assert!(z_near > 0.0);
903 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
904 let h = cos_fov / sin_fov;
905 let w = h / aspect_ratio;
906 Self::from_cols(
907 Vec4::new(w, 0.0, 0.0, 0.0),
908 Vec4::new(0.0, h, 0.0, 0.0),
909 Vec4::new(0.0, 0.0, 0.0, 1.0),
910 Vec4::new(0.0, 0.0, z_near, 0.0),
911 )
912 }
913
914 #[inline]
917 pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
918 glam_assert!(z_near > 0.0);
919 let f = 1.0 / math::tan(0.5 * fov_y_radians);
920 Self::from_cols(
921 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
922 Vec4::new(0.0, f, 0.0, 0.0),
923 Vec4::new(0.0, 0.0, -1.0, -1.0),
924 Vec4::new(0.0, 0.0, -z_near, 0.0),
925 )
926 }
927
928 #[inline]
931 pub fn perspective_infinite_reverse_rh(
932 fov_y_radians: f32,
933 aspect_ratio: f32,
934 z_near: f32,
935 ) -> Self {
936 glam_assert!(z_near > 0.0);
937 let f = 1.0 / math::tan(0.5 * fov_y_radians);
938 Self::from_cols(
939 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
940 Vec4::new(0.0, f, 0.0, 0.0),
941 Vec4::new(0.0, 0.0, 0.0, -1.0),
942 Vec4::new(0.0, 0.0, z_near, 0.0),
943 )
944 }
945
946 #[inline]
951 pub fn orthographic_rh_gl(
952 left: f32,
953 right: f32,
954 bottom: f32,
955 top: f32,
956 near: f32,
957 far: f32,
958 ) -> Self {
959 let a = 2.0 / (right - left);
960 let b = 2.0 / (top - bottom);
961 let c = -2.0 / (far - near);
962 let tx = -(right + left) / (right - left);
963 let ty = -(top + bottom) / (top - bottom);
964 let tz = -(far + near) / (far - near);
965
966 Self::from_cols(
967 Vec4::new(a, 0.0, 0.0, 0.0),
968 Vec4::new(0.0, b, 0.0, 0.0),
969 Vec4::new(0.0, 0.0, c, 0.0),
970 Vec4::new(tx, ty, tz, 1.0),
971 )
972 }
973
974 #[inline]
976 pub fn orthographic_lh(
977 left: f32,
978 right: f32,
979 bottom: f32,
980 top: f32,
981 near: f32,
982 far: f32,
983 ) -> Self {
984 let rcp_width = 1.0 / (right - left);
985 let rcp_height = 1.0 / (top - bottom);
986 let r = 1.0 / (far - near);
987 Self::from_cols(
988 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
989 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
990 Vec4::new(0.0, 0.0, r, 0.0),
991 Vec4::new(
992 -(left + right) * rcp_width,
993 -(top + bottom) * rcp_height,
994 -r * near,
995 1.0,
996 ),
997 )
998 }
999
1000 #[inline]
1002 pub fn orthographic_rh(
1003 left: f32,
1004 right: f32,
1005 bottom: f32,
1006 top: f32,
1007 near: f32,
1008 far: f32,
1009 ) -> Self {
1010 let rcp_width = 1.0 / (right - left);
1011 let rcp_height = 1.0 / (top - bottom);
1012 let r = 1.0 / (near - far);
1013 Self::from_cols(
1014 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1015 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1016 Vec4::new(0.0, 0.0, r, 0.0),
1017 Vec4::new(
1018 -(left + right) * rcp_width,
1019 -(top + bottom) * rcp_height,
1020 r * near,
1021 1.0,
1022 ),
1023 )
1024 }
1025
1026 #[inline]
1033 pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
1034 let mut res = self.x_axis.mul(rhs.x);
1035 res = self.y_axis.mul(rhs.y).add(res);
1036 res = self.z_axis.mul(rhs.z).add(res);
1037 res = self.w_axis.add(res);
1038 res = res.mul(res.wwww().recip());
1039 res.xyz()
1040 }
1041
1042 #[inline]
1055 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1056 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1057 let mut res = self.x_axis.mul(rhs.x);
1058 res = self.y_axis.mul(rhs.y).add(res);
1059 res = self.z_axis.mul(rhs.z).add(res);
1060 res = self.w_axis.add(res);
1061 res.xyz()
1062 }
1063
1064 #[inline]
1075 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1076 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1077 let mut res = self.x_axis.mul(rhs.x);
1078 res = self.y_axis.mul(rhs.y).add(res);
1079 res = self.z_axis.mul(rhs.z).add(res);
1080 res.xyz()
1081 }
1082
1083 #[inline]
1087 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1088 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1089 let mut res = self.x_axis.mul(rhs.xxxx());
1090 res = self.y_axis.mul(rhs.yyyy()).add(res);
1091 res = self.z_axis.mul(rhs.zzzz()).add(res);
1092 res = self.w_axis.add(res);
1093 res.into()
1094 }
1095
1096 #[inline]
1100 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1101 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1102 let mut res = self.x_axis.mul(rhs.xxxx());
1103 res = self.y_axis.mul(rhs.yyyy()).add(res);
1104 res = self.z_axis.mul(rhs.zzzz()).add(res);
1105 res.into()
1106 }
1107
1108 #[inline]
1110 pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1111 let mut res = self.x_axis.mul(rhs.xxxx());
1112 res = res.add(self.y_axis.mul(rhs.yyyy()));
1113 res = res.add(self.z_axis.mul(rhs.zzzz()));
1114 res = res.add(self.w_axis.mul(rhs.wwww()));
1115 res
1116 }
1117
1118 #[inline]
1120 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1121 Self::from_cols(
1122 self.mul(rhs.x_axis),
1123 self.mul(rhs.y_axis),
1124 self.mul(rhs.z_axis),
1125 self.mul(rhs.w_axis),
1126 )
1127 }
1128
1129 #[inline]
1131 pub fn add_mat4(&self, rhs: &Self) -> Self {
1132 Self::from_cols(
1133 self.x_axis.add(rhs.x_axis),
1134 self.y_axis.add(rhs.y_axis),
1135 self.z_axis.add(rhs.z_axis),
1136 self.w_axis.add(rhs.w_axis),
1137 )
1138 }
1139
1140 #[inline]
1142 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1143 Self::from_cols(
1144 self.x_axis.sub(rhs.x_axis),
1145 self.y_axis.sub(rhs.y_axis),
1146 self.z_axis.sub(rhs.z_axis),
1147 self.w_axis.sub(rhs.w_axis),
1148 )
1149 }
1150
1151 #[inline]
1153 pub fn mul_scalar(&self, rhs: f32) -> Self {
1154 Self::from_cols(
1155 self.x_axis.mul(rhs),
1156 self.y_axis.mul(rhs),
1157 self.z_axis.mul(rhs),
1158 self.w_axis.mul(rhs),
1159 )
1160 }
1161
1162 #[inline]
1172 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1173 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1174 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1175 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1176 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1177 }
1178
1179 #[inline]
1180 pub fn as_dmat4(&self) -> DMat4 {
1181 DMat4::from_cols(
1182 self.x_axis.as_dvec4(),
1183 self.y_axis.as_dvec4(),
1184 self.z_axis.as_dvec4(),
1185 self.w_axis.as_dvec4(),
1186 )
1187 }
1188}
1189
1190impl Default for Mat4 {
1191 #[inline]
1192 fn default() -> Self {
1193 Self::IDENTITY
1194 }
1195}
1196
1197impl Add<Mat4> for Mat4 {
1198 type Output = Self;
1199 #[inline]
1200 fn add(self, rhs: Self) -> Self::Output {
1201 self.add_mat4(&rhs)
1202 }
1203}
1204
1205impl AddAssign<Mat4> for Mat4 {
1206 #[inline]
1207 fn add_assign(&mut self, rhs: Self) {
1208 *self = self.add_mat4(&rhs);
1209 }
1210}
1211
1212impl Sub<Mat4> for Mat4 {
1213 type Output = Self;
1214 #[inline]
1215 fn sub(self, rhs: Self) -> Self::Output {
1216 self.sub_mat4(&rhs)
1217 }
1218}
1219
1220impl SubAssign<Mat4> for Mat4 {
1221 #[inline]
1222 fn sub_assign(&mut self, rhs: Self) {
1223 *self = self.sub_mat4(&rhs);
1224 }
1225}
1226
1227impl Neg for Mat4 {
1228 type Output = Self;
1229 #[inline]
1230 fn neg(self) -> Self::Output {
1231 Self::from_cols(
1232 self.x_axis.neg(),
1233 self.y_axis.neg(),
1234 self.z_axis.neg(),
1235 self.w_axis.neg(),
1236 )
1237 }
1238}
1239
1240impl Mul<Mat4> for Mat4 {
1241 type Output = Self;
1242 #[inline]
1243 fn mul(self, rhs: Self) -> Self::Output {
1244 self.mul_mat4(&rhs)
1245 }
1246}
1247
1248impl MulAssign<Mat4> for Mat4 {
1249 #[inline]
1250 fn mul_assign(&mut self, rhs: Self) {
1251 *self = self.mul_mat4(&rhs);
1252 }
1253}
1254
1255impl Mul<Vec4> for Mat4 {
1256 type Output = Vec4;
1257 #[inline]
1258 fn mul(self, rhs: Vec4) -> Self::Output {
1259 self.mul_vec4(rhs)
1260 }
1261}
1262
1263impl Mul<Mat4> for f32 {
1264 type Output = Mat4;
1265 #[inline]
1266 fn mul(self, rhs: Mat4) -> Self::Output {
1267 rhs.mul_scalar(self)
1268 }
1269}
1270
1271impl Mul<f32> for Mat4 {
1272 type Output = Self;
1273 #[inline]
1274 fn mul(self, rhs: f32) -> Self::Output {
1275 self.mul_scalar(rhs)
1276 }
1277}
1278
1279impl MulAssign<f32> for Mat4 {
1280 #[inline]
1281 fn mul_assign(&mut self, rhs: f32) {
1282 *self = self.mul_scalar(rhs);
1283 }
1284}
1285
1286impl Sum<Self> for Mat4 {
1287 fn sum<I>(iter: I) -> Self
1288 where
1289 I: Iterator<Item = Self>,
1290 {
1291 iter.fold(Self::ZERO, Self::add)
1292 }
1293}
1294
1295impl<'a> Sum<&'a Self> for Mat4 {
1296 fn sum<I>(iter: I) -> Self
1297 where
1298 I: Iterator<Item = &'a Self>,
1299 {
1300 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1301 }
1302}
1303
1304impl Product for Mat4 {
1305 fn product<I>(iter: I) -> Self
1306 where
1307 I: Iterator<Item = Self>,
1308 {
1309 iter.fold(Self::IDENTITY, Self::mul)
1310 }
1311}
1312
1313impl<'a> Product<&'a Self> for Mat4 {
1314 fn product<I>(iter: I) -> Self
1315 where
1316 I: Iterator<Item = &'a Self>,
1317 {
1318 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1319 }
1320}
1321
1322impl PartialEq for Mat4 {
1323 #[inline]
1324 fn eq(&self, rhs: &Self) -> bool {
1325 self.x_axis.eq(&rhs.x_axis)
1326 && self.y_axis.eq(&rhs.y_axis)
1327 && self.z_axis.eq(&rhs.z_axis)
1328 && self.w_axis.eq(&rhs.w_axis)
1329 }
1330}
1331
1332#[cfg(not(target_arch = "spirv"))]
1333impl AsRef<[f32; 16]> for Mat4 {
1334 #[inline]
1335 fn as_ref(&self) -> &[f32; 16] {
1336 unsafe { &*(self as *const Self as *const [f32; 16]) }
1337 }
1338}
1339
1340#[cfg(not(target_arch = "spirv"))]
1341impl AsMut<[f32; 16]> for Mat4 {
1342 #[inline]
1343 fn as_mut(&mut self) -> &mut [f32; 16] {
1344 unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
1345 }
1346}
1347
1348#[cfg(not(target_arch = "spirv"))]
1349impl fmt::Debug for Mat4 {
1350 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1351 fmt.debug_struct(stringify!(Mat4))
1352 .field("x_axis", &self.x_axis)
1353 .field("y_axis", &self.y_axis)
1354 .field("z_axis", &self.z_axis)
1355 .field("w_axis", &self.w_axis)
1356 .finish()
1357 }
1358}
1359
1360#[cfg(not(target_arch = "spirv"))]
1361impl fmt::Display for Mat4 {
1362 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1363 write!(
1364 f,
1365 "[{}, {}, {}, {}]",
1366 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1367 )
1368 }
1369}