1 // Generated from mat.rs.tera template. Edit the template, not the generated file.
2
3 use crate::{
4 f32::math, sse2::*, swizzles::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4,
5 };
6 #[cfg(not(target_arch = "spirv"))]
7 use core::fmt;
8 use core::iter::{Product, Sum};
9 use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
10
11 #[cfg(target_arch = "x86")]
12 use core::arch::x86::*;
13 #[cfg(target_arch = "x86_64")]
14 use core::arch::x86_64::*;
15
16 /// Creates a 4x4 matrix from four column vectors.
17 #[inline(always)]
18 #[must_use]
mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat419 pub 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 /// A 4x4 column major matrix.
24 ///
25 /// This 4x4 matrix type features convenience methods for creating and using affine transforms and
26 /// perspective projections. If you are primarily dealing with 3D affine transformations
27 /// considering using [`Affine3A`](crate::Affine3A) which is faster than a 4x4 matrix
28 /// for some affine operations.
29 ///
30 /// Affine transformations including 3D translation, rotation and scale can be created
31 /// using methods such as [`Self::from_translation()`], [`Self::from_quat()`],
32 /// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`].
33 ///
34 /// Orthographic projections can be created using the methods [`Self::orthographic_lh()`] for
35 /// left-handed coordinate systems and [`Self::orthographic_rh()`] for right-handed
36 /// systems. The resulting matrix is also an affine transformation.
37 ///
38 /// The [`Self::transform_point3()`] and [`Self::transform_vector3()`] convenience methods
39 /// are provided for performing affine transformations on 3D vectors and points. These
40 /// multiply 3D inputs as 4D vectors with an implicit `w` value of `1` for points and `0`
41 /// for vectors respectively. These methods assume that `Self` contains a valid affine
42 /// transform.
43 ///
44 /// Perspective projections can be created using methods such as
45 /// [`Self::perspective_lh()`], [`Self::perspective_infinite_lh()`] and
46 /// [`Self::perspective_infinite_reverse_lh()`] for left-handed co-ordinate systems and
47 /// [`Self::perspective_rh()`], [`Self::perspective_infinite_rh()`] and
48 /// [`Self::perspective_infinite_reverse_rh()`] for right-handed co-ordinate systems.
49 ///
50 /// The resulting perspective project can be use to transform 3D vectors as points with
51 /// perspective correction using the [`Self::project_point3()`] convenience method.
52 #[derive(Clone, Copy)]
53 #[repr(C)]
54 pub struct Mat4 {
55 pub x_axis: Vec4,
56 pub y_axis: Vec4,
57 pub z_axis: Vec4,
58 pub w_axis: Vec4,
59 }
60
61 impl Mat4 {
62 /// A 4x4 matrix with all elements set to `0.0`.
63 pub const ZERO: Self = Self::from_cols(Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO);
64
65 /// A 4x4 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
66 pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W);
67
68 /// All NAN:s.
69 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]
new( m00: f32, m01: f32, m02: f32, m03: f32, m10: f32, m11: f32, m12: f32, m13: f32, m20: f32, m21: f32, m22: f32, m23: f32, m30: f32, m31: f32, m32: f32, m33: f32, ) -> Self74 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 /// Creates a 4x4 matrix from four column vectors.
101 #[inline(always)]
102 #[must_use]
from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self103 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 /// Creates a 4x4 matrix from a `[f32; 16]` array stored in column major order.
113 /// If your data is stored in row major you will need to `transpose` the returned
114 /// matrix.
115 #[inline]
116 #[must_use]
from_cols_array(m: &[f32; 16]) -> Self117 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 /// Creates a `[f32; 16]` array storing data in column major order.
125 /// If you require data in row major order `transpose` the matrix first.
126 #[inline]
127 #[must_use]
to_cols_array(&self) -> [f32; 16]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 /// Creates a 4x4 matrix from a `[[f32; 4]; 4]` 4D array stored in column major order.
141 /// If your data is in row major order you will need to `transpose` the returned
142 /// matrix.
143 #[inline]
144 #[must_use]
from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self145 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 /// Creates a `[[f32; 4]; 4]` 4D array storing data in column major order.
155 /// If you require data in row major order `transpose` the matrix first.
156 #[inline]
157 #[must_use]
to_cols_array_2d(&self) -> [[f32; 4]; 4]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 /// Creates a 4x4 matrix with its diagonal set to `diagonal` and all other entries set to 0.
168 #[doc(alias = "scale")]
169 #[inline]
170 #[must_use]
from_diagonal(diagonal: Vec4) -> Self171 pub const fn from_diagonal(diagonal: Vec4) -> Self {
172 // diagonal.x, diagonal.y etc can't be done in a const-context
173 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]
quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4)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 /// Creates an affine transformation matrix from the given 3D `scale`, `rotation` and
205 /// `translation`.
206 ///
207 /// The resulting matrix can be used to transform 3D points and vectors. See
208 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
209 ///
210 /// # Panics
211 ///
212 /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
213 #[inline]
214 #[must_use]
from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self215 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 /// Creates an affine transformation matrix from the given 3D `translation`.
226 ///
227 /// The resulting matrix can be used to transform 3D points and vectors. See
228 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
229 ///
230 /// # Panics
231 ///
232 /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
233 #[inline]
234 #[must_use]
from_rotation_translation(rotation: Quat, translation: Vec3) -> Self235 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 /// Extracts `scale`, `rotation` and `translation` from `self`. The input matrix is
241 /// expected to be a 3D affine transformation matrix otherwise the output will be invalid.
242 ///
243 /// # Panics
244 ///
245 /// Will panic if the determinant of `self` is zero or if the resulting scale vector
246 /// contains any zero elements when `glam_assert` is enabled.
247 #[inline]
248 #[must_use]
to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3)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 /// Creates an affine transformation matrix from the given `rotation` quaternion.
275 ///
276 /// The resulting matrix can be used to transform 3D points and vectors. See
277 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
278 ///
279 /// # Panics
280 ///
281 /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
282 #[inline]
283 #[must_use]
from_quat(rotation: Quat) -> Self284 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 /// Creates an affine transformation matrix from the given 3x3 linear transformation
290 /// matrix.
291 ///
292 /// The resulting matrix can be used to transform 3D points and vectors. See
293 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
294 #[inline]
295 #[must_use]
from_mat3(m: Mat3) -> Self296 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 /// Creates an affine transformation matrix from the given 3x3 linear transformation
306 /// matrix.
307 ///
308 /// The resulting matrix can be used to transform 3D points and vectors. See
309 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
310 #[inline]
311 #[must_use]
from_mat3a(m: Mat3A) -> Self312 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 /// Creates an affine transformation matrix from the given 3D `translation`.
322 ///
323 /// The resulting matrix can be used to transform 3D points and vectors. See
324 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
325 #[inline]
326 #[must_use]
from_translation(translation: Vec3) -> Self327 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 /// Creates an affine transformation matrix containing a 3D rotation around a normalized
337 /// rotation `axis` of `angle` (in radians).
338 ///
339 /// The resulting matrix can be used to transform 3D points and vectors. See
340 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
341 ///
342 /// # Panics
343 ///
344 /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
345 #[inline]
346 #[must_use]
from_axis_angle(axis: Vec3, angle: f32) -> Self347 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 /// Creates a affine transformation matrix containing a rotation from the given euler
381 /// rotation sequence and angles (in radians).
382 ///
383 /// The resulting matrix can be used to transform 3D points and vectors. See
384 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
385 #[inline]
386 #[must_use]
from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self387 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 /// Creates an affine transformation matrix containing a 3D rotation around the x axis of
393 /// `angle` (in radians).
394 ///
395 /// The resulting matrix can be used to transform 3D points and vectors. See
396 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
397 #[inline]
398 #[must_use]
from_rotation_x(angle: f32) -> Self399 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 /// Creates an affine transformation matrix containing a 3D rotation around the y axis of
410 /// `angle` (in radians).
411 ///
412 /// The resulting matrix can be used to transform 3D points and vectors. See
413 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
414 #[inline]
415 #[must_use]
from_rotation_y(angle: f32) -> Self416 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 /// Creates an affine transformation matrix containing a 3D rotation around the z axis of
427 /// `angle` (in radians).
428 ///
429 /// The resulting matrix can be used to transform 3D points and vectors. See
430 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
431 #[inline]
432 #[must_use]
from_rotation_z(angle: f32) -> Self433 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 /// Creates an affine transformation matrix containing the given 3D non-uniform `scale`.
444 ///
445 /// The resulting matrix can be used to transform 3D points and vectors. See
446 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
447 ///
448 /// # Panics
449 ///
450 /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
451 #[inline]
452 #[must_use]
from_scale(scale: Vec3) -> Self453 pub fn from_scale(scale: Vec3) -> Self {
454 // Do not panic as long as any component is non-zero
455 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 /// Creates a 4x4 matrix from the first 16 values in `slice`.
466 ///
467 /// # Panics
468 ///
469 /// Panics if `slice` is less than 16 elements long.
470 #[inline]
471 #[must_use]
from_cols_slice(slice: &[f32]) -> Self472 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 /// Writes the columns of `self` to the first 16 elements in `slice`.
480 ///
481 /// # Panics
482 ///
483 /// Panics if `slice` is less than 16 elements long.
484 #[inline]
write_cols_to_slice(self, slice: &mut [f32])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 /// Returns the matrix column for the given `index`.
505 ///
506 /// # Panics
507 ///
508 /// Panics if `index` is greater than 3.
509 #[inline]
510 #[must_use]
col(&self, index: usize) -> Vec4511 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 /// Returns a mutable reference to the matrix column for the given `index`.
522 ///
523 /// # Panics
524 ///
525 /// Panics if `index` is greater than 3.
526 #[inline]
col_mut(&mut self, index: usize) -> &mut Vec4527 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 /// Returns the matrix row for the given `index`.
538 ///
539 /// # Panics
540 ///
541 /// Panics if `index` is greater than 3.
542 #[inline]
543 #[must_use]
row(&self, index: usize) -> Vec4544 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 /// Returns `true` if, and only if, all elements are finite.
555 /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
556 #[inline]
557 #[must_use]
is_finite(&self) -> bool558 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 /// Returns `true` if any elements are `NaN`.
566 #[inline]
567 #[must_use]
is_nan(&self) -> bool568 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 /// Returns the transpose of `self`.
573 #[inline]
574 #[must_use]
transpose(&self) -> Self575 pub fn transpose(&self) -> Self {
576 unsafe {
577 // Based on https://github.com/microsoft/DirectXMath `XMMatrixTranspose`
578 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 /// Returns the determinant of `self`.
593 #[must_use]
determinant(&self) -> f32594 pub fn determinant(&self) -> f32 {
595 unsafe {
596 // Based on https://github.com/g-truc/glm `glm_mat4_determinant_lowp`
597 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 /// Returns the inverse of `self`.
633 ///
634 /// If the matrix is not invertible the returned matrix will be invalid.
635 ///
636 /// # Panics
637 ///
638 /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
639 #[must_use]
inverse(&self) -> Self640 pub fn inverse(&self) -> Self {
641 unsafe {
642 // Based on https://github.com/g-truc/glm `glm_mat4_inverse`
643 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 /// Creates a left-handed view matrix using a camera position, an up direction, and a facing
783 /// direction.
784 ///
785 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
786 #[inline]
787 #[must_use]
look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self788 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
789 Self::look_to_rh(eye, -dir, up)
790 }
791
792 /// Creates a right-handed view matrix using a camera position, an up direction, and a facing
793 /// direction.
794 ///
795 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
796 #[inline]
797 #[must_use]
look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self798 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 /// Creates a left-handed view matrix using a camera position, an up direction, and a focal
812 /// point.
813 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
814 ///
815 /// # Panics
816 ///
817 /// Will panic if `up` is not normalized when `glam_assert` is enabled.
818 #[inline]
819 #[must_use]
look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self820 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 /// Creates a right-handed view matrix using a camera position, an up direction, and a focal
826 /// point.
827 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
828 ///
829 /// # Panics
830 ///
831 /// Will panic if `up` is not normalized when `glam_assert` is enabled.
832 #[inline]
look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self833 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 /// Creates a right-handed perspective projection matrix with [-1,1] depth range.
839 /// This is the same as the OpenGL `gluPerspective` function.
840 /// See <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml>
841 #[inline]
842 #[must_use]
perspective_rh_gl( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32, ) -> Self843 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 /// Creates a left-handed perspective projection matrix with `[0,1]` depth range.
863 ///
864 /// # Panics
865 ///
866 /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
867 /// enabled.
868 #[inline]
869 #[must_use]
perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self870 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 /// Creates a right-handed perspective projection matrix with `[0,1]` depth range.
885 ///
886 /// # Panics
887 ///
888 /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
889 /// enabled.
890 #[inline]
891 #[must_use]
perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self892 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 /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range.
907 ///
908 /// # Panics
909 ///
910 /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
911 #[inline]
912 #[must_use]
perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self913 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 /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range.
927 ///
928 /// # Panics
929 ///
930 /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
931 #[inline]
932 #[must_use]
perspective_infinite_reverse_lh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self933 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 /// Creates an infinite right-handed perspective projection matrix with
951 /// `[0,1]` depth range.
952 #[inline]
953 #[must_use]
perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self954 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 /// Creates an infinite reverse right-handed perspective projection matrix
966 /// with `[0,1]` depth range.
967 #[inline]
968 #[must_use]
perspective_infinite_reverse_rh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self969 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 /// Creates a right-handed orthographic projection matrix with `[-1,1]` depth
985 /// range. This is the same as the OpenGL `glOrtho` function in OpenGL.
986 /// See
987 /// <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml>
988 #[inline]
989 #[must_use]
orthographic_rh_gl( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self990 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 /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range.
1014 #[inline]
1015 #[must_use]
orthographic_lh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self1016 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 /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range.
1041 #[inline]
1042 #[must_use]
orthographic_rh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self1043 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 /// Transforms the given 3D vector as a point, applying perspective correction.
1068 ///
1069 /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is `1.0`.
1070 /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
1071 ///
1072 /// This method assumes that `self` contains a projective transform.
1073 #[inline]
1074 #[must_use]
project_point3(&self, rhs: Vec3) -> Vec31075 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 /// Transforms the given 3D vector as a point.
1085 ///
1086 /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
1087 /// `1.0`.
1088 ///
1089 /// This method assumes that `self` contains a valid affine transform. It does not perform
1090 /// a persective divide, if `self` contains a perspective transform, or if you are unsure,
1091 /// the [`Self::project_point3()`] method should be used instead.
1092 ///
1093 /// # Panics
1094 ///
1095 /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1096 #[inline]
1097 #[must_use]
transform_point3(&self, rhs: Vec3) -> Vec31098 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 /// Transforms the give 3D vector as a direction.
1108 ///
1109 /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
1110 /// `0.0`.
1111 ///
1112 /// This method assumes that `self` contains a valid affine transform.
1113 ///
1114 /// # Panics
1115 ///
1116 /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1117 #[inline]
1118 #[must_use]
transform_vector3(&self, rhs: Vec3) -> Vec31119 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 /// Transforms the given [`Vec3A`] as 3D point.
1128 ///
1129 /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
1130 #[inline]
1131 #[must_use]
transform_point3a(&self, rhs: Vec3A) -> Vec3A1132 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 /// Transforms the give [`Vec3A`] as 3D vector.
1142 ///
1143 /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `0.0`.
1144 #[inline]
1145 #[must_use]
transform_vector3a(&self, rhs: Vec3A) -> Vec3A1146 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 /// Transforms a 4D vector.
1155 #[inline]
1156 #[must_use]
mul_vec4(&self, rhs: Vec4) -> Vec41157 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 /// Multiplies two 4x4 matrices.
1166 #[inline]
1167 #[must_use]
mul_mat4(&self, rhs: &Self) -> Self1168 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 /// Adds two 4x4 matrices.
1178 #[inline]
1179 #[must_use]
add_mat4(&self, rhs: &Self) -> Self1180 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 /// Subtracts two 4x4 matrices.
1190 #[inline]
1191 #[must_use]
sub_mat4(&self, rhs: &Self) -> Self1192 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 /// Multiplies a 4x4 matrix by a scalar.
1202 #[inline]
1203 #[must_use]
mul_scalar(&self, rhs: f32) -> Self1204 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 /// Returns true if the absolute difference of all elements between `self` and `rhs`
1214 /// is less than or equal to `max_abs_diff`.
1215 ///
1216 /// This can be used to compare if two matrices contain similar elements. It works best
1217 /// when comparing with a known value. The `max_abs_diff` that should be used used
1218 /// depends on the values being compared against.
1219 ///
1220 /// For more see
1221 /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
1222 #[inline]
1223 #[must_use]
abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool1224 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]
as_dmat4(&self) -> DMat41232 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
1242 impl Default for Mat4 {
1243 #[inline]
default() -> Self1244 fn default() -> Self {
1245 Self::IDENTITY
1246 }
1247 }
1248
1249 impl Add<Mat4> for Mat4 {
1250 type Output = Self;
1251 #[inline]
add(self, rhs: Self) -> Self::Output1252 fn add(self, rhs: Self) -> Self::Output {
1253 self.add_mat4(&rhs)
1254 }
1255 }
1256
1257 impl AddAssign<Mat4> for Mat4 {
1258 #[inline]
add_assign(&mut self, rhs: Self)1259 fn add_assign(&mut self, rhs: Self) {
1260 *self = self.add_mat4(&rhs);
1261 }
1262 }
1263
1264 impl Sub<Mat4> for Mat4 {
1265 type Output = Self;
1266 #[inline]
sub(self, rhs: Self) -> Self::Output1267 fn sub(self, rhs: Self) -> Self::Output {
1268 self.sub_mat4(&rhs)
1269 }
1270 }
1271
1272 impl SubAssign<Mat4> for Mat4 {
1273 #[inline]
sub_assign(&mut self, rhs: Self)1274 fn sub_assign(&mut self, rhs: Self) {
1275 *self = self.sub_mat4(&rhs);
1276 }
1277 }
1278
1279 impl Neg for Mat4 {
1280 type Output = Self;
1281 #[inline]
neg(self) -> Self::Output1282 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
1292 impl Mul<Mat4> for Mat4 {
1293 type Output = Self;
1294 #[inline]
mul(self, rhs: Self) -> Self::Output1295 fn mul(self, rhs: Self) -> Self::Output {
1296 self.mul_mat4(&rhs)
1297 }
1298 }
1299
1300 impl MulAssign<Mat4> for Mat4 {
1301 #[inline]
mul_assign(&mut self, rhs: Self)1302 fn mul_assign(&mut self, rhs: Self) {
1303 *self = self.mul_mat4(&rhs);
1304 }
1305 }
1306
1307 impl Mul<Vec4> for Mat4 {
1308 type Output = Vec4;
1309 #[inline]
mul(self, rhs: Vec4) -> Self::Output1310 fn mul(self, rhs: Vec4) -> Self::Output {
1311 self.mul_vec4(rhs)
1312 }
1313 }
1314
1315 impl Mul<Mat4> for f32 {
1316 type Output = Mat4;
1317 #[inline]
mul(self, rhs: Mat4) -> Self::Output1318 fn mul(self, rhs: Mat4) -> Self::Output {
1319 rhs.mul_scalar(self)
1320 }
1321 }
1322
1323 impl Mul<f32> for Mat4 {
1324 type Output = Self;
1325 #[inline]
mul(self, rhs: f32) -> Self::Output1326 fn mul(self, rhs: f32) -> Self::Output {
1327 self.mul_scalar(rhs)
1328 }
1329 }
1330
1331 impl MulAssign<f32> for Mat4 {
1332 #[inline]
mul_assign(&mut self, rhs: f32)1333 fn mul_assign(&mut self, rhs: f32) {
1334 *self = self.mul_scalar(rhs);
1335 }
1336 }
1337
1338 impl Sum<Self> for Mat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,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
1347 impl<'a> Sum<&'a Self> for Mat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,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
1356 impl Product for Mat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,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
1365 impl<'a> Product<&'a Self> for Mat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,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
1374 impl PartialEq for Mat4 {
1375 #[inline]
eq(&self, rhs: &Self) -> bool1376 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"))]
1385 impl AsRef<[f32; 16]> for Mat4 {
1386 #[inline]
as_ref(&self) -> &[f32; 16]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"))]
1393 impl AsMut<[f32; 16]> for Mat4 {
1394 #[inline]
as_mut(&mut self) -> &mut [f32; 16]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"))]
1401 impl fmt::Debug for Mat4 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result1402 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"))]
1413 impl fmt::Display for Mat4 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1414 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 }
1422