1 // Generated from mat.rs.tera template. Edit the template, not the generated file.
2
3 use crate::{
4 f32::math, swizzles::*, wasm32::*, 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 use core::arch::wasm32::*;
12
13 /// Creates a 4x4 matrix from four column vectors.
14 #[inline(always)]
15 #[must_use]
mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat416 pub const fn mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat4 {
17 Mat4::from_cols(x_axis, y_axis, z_axis, w_axis)
18 }
19
20 /// A 4x4 column major matrix.
21 ///
22 /// This 4x4 matrix type features convenience methods for creating and using affine transforms and
23 /// perspective projections. If you are primarily dealing with 3D affine transformations
24 /// considering using [`Affine3A`](crate::Affine3A) which is faster than a 4x4 matrix
25 /// for some affine operations.
26 ///
27 /// Affine transformations including 3D translation, rotation and scale can be created
28 /// using methods such as [`Self::from_translation()`], [`Self::from_quat()`],
29 /// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`].
30 ///
31 /// Orthographic projections can be created using the methods [`Self::orthographic_lh()`] for
32 /// left-handed coordinate systems and [`Self::orthographic_rh()`] for right-handed
33 /// systems. The resulting matrix is also an affine transformation.
34 ///
35 /// The [`Self::transform_point3()`] and [`Self::transform_vector3()`] convenience methods
36 /// are provided for performing affine transformations on 3D vectors and points. These
37 /// multiply 3D inputs as 4D vectors with an implicit `w` value of `1` for points and `0`
38 /// for vectors respectively. These methods assume that `Self` contains a valid affine
39 /// transform.
40 ///
41 /// Perspective projections can be created using methods such as
42 /// [`Self::perspective_lh()`], [`Self::perspective_infinite_lh()`] and
43 /// [`Self::perspective_infinite_reverse_lh()`] for left-handed co-ordinate systems and
44 /// [`Self::perspective_rh()`], [`Self::perspective_infinite_rh()`] and
45 /// [`Self::perspective_infinite_reverse_rh()`] for right-handed co-ordinate systems.
46 ///
47 /// The resulting perspective project can be use to transform 3D vectors as points with
48 /// perspective correction using the [`Self::project_point3()`] convenience method.
49 #[derive(Clone, Copy)]
50 #[repr(C)]
51 pub struct Mat4 {
52 pub x_axis: Vec4,
53 pub y_axis: Vec4,
54 pub z_axis: Vec4,
55 pub w_axis: Vec4,
56 }
57
58 impl Mat4 {
59 /// A 4x4 matrix with all elements set to `0.0`.
60 pub const ZERO: Self = Self::from_cols(Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO);
61
62 /// A 4x4 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
63 pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W);
64
65 /// All NAN:s.
66 pub const NAN: Self = Self::from_cols(Vec4::NAN, Vec4::NAN, Vec4::NAN, Vec4::NAN);
67
68 #[allow(clippy::too_many_arguments)]
69 #[inline(always)]
70 #[must_use]
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, ) -> Self71 const fn new(
72 m00: f32,
73 m01: f32,
74 m02: f32,
75 m03: f32,
76 m10: f32,
77 m11: f32,
78 m12: f32,
79 m13: f32,
80 m20: f32,
81 m21: f32,
82 m22: f32,
83 m23: f32,
84 m30: f32,
85 m31: f32,
86 m32: f32,
87 m33: f32,
88 ) -> Self {
89 Self {
90 x_axis: Vec4::new(m00, m01, m02, m03),
91 y_axis: Vec4::new(m10, m11, m12, m13),
92 z_axis: Vec4::new(m20, m21, m22, m23),
93 w_axis: Vec4::new(m30, m31, m32, m33),
94 }
95 }
96
97 /// Creates a 4x4 matrix from four column vectors.
98 #[inline(always)]
99 #[must_use]
from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self100 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 /// Creates a 4x4 matrix from a `[f32; 16]` array stored in column major order.
110 /// If your data is stored in row major you will need to `transpose` the returned
111 /// matrix.
112 #[inline]
113 #[must_use]
from_cols_array(m: &[f32; 16]) -> Self114 pub const fn from_cols_array(m: &[f32; 16]) -> Self {
115 Self::new(
116 m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13],
117 m[14], m[15],
118 )
119 }
120
121 /// Creates a `[f32; 16]` array storing data in column major order.
122 /// If you require data in row major order `transpose` the matrix first.
123 #[inline]
124 #[must_use]
to_cols_array(&self) -> [f32; 16]125 pub const fn to_cols_array(&self) -> [f32; 16] {
126 let [x_axis_x, x_axis_y, x_axis_z, x_axis_w] = self.x_axis.to_array();
127 let [y_axis_x, y_axis_y, y_axis_z, y_axis_w] = self.y_axis.to_array();
128 let [z_axis_x, z_axis_y, z_axis_z, z_axis_w] = self.z_axis.to_array();
129 let [w_axis_x, w_axis_y, w_axis_z, w_axis_w] = self.w_axis.to_array();
130
131 [
132 x_axis_x, x_axis_y, x_axis_z, x_axis_w, y_axis_x, y_axis_y, y_axis_z, y_axis_w,
133 z_axis_x, z_axis_y, z_axis_z, z_axis_w, w_axis_x, w_axis_y, w_axis_z, w_axis_w,
134 ]
135 }
136
137 /// Creates a 4x4 matrix from a `[[f32; 4]; 4]` 4D array stored in column major order.
138 /// If your data is in row major order you will need to `transpose` the returned
139 /// matrix.
140 #[inline]
141 #[must_use]
from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self142 pub const fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self {
143 Self::from_cols(
144 Vec4::from_array(m[0]),
145 Vec4::from_array(m[1]),
146 Vec4::from_array(m[2]),
147 Vec4::from_array(m[3]),
148 )
149 }
150
151 /// Creates a `[[f32; 4]; 4]` 4D array storing data in column major order.
152 /// If you require data in row major order `transpose` the matrix first.
153 #[inline]
154 #[must_use]
to_cols_array_2d(&self) -> [[f32; 4]; 4]155 pub const fn to_cols_array_2d(&self) -> [[f32; 4]; 4] {
156 [
157 self.x_axis.to_array(),
158 self.y_axis.to_array(),
159 self.z_axis.to_array(),
160 self.w_axis.to_array(),
161 ]
162 }
163
164 /// Creates a 4x4 matrix with its diagonal set to `diagonal` and all other entries set to 0.
165 #[doc(alias = "scale")]
166 #[inline]
167 #[must_use]
from_diagonal(diagonal: Vec4) -> Self168 pub const fn from_diagonal(diagonal: Vec4) -> Self {
169 // diagonal.x, diagonal.y etc can't be done in a const-context
170 let [x, y, z, w] = diagonal.to_array();
171 Self::new(
172 x, 0.0, 0.0, 0.0, 0.0, y, 0.0, 0.0, 0.0, 0.0, z, 0.0, 0.0, 0.0, 0.0, w,
173 )
174 }
175
176 #[inline]
177 #[must_use]
quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4)178 fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) {
179 glam_assert!(rotation.is_normalized());
180
181 let (x, y, z, w) = rotation.into();
182 let x2 = x + x;
183 let y2 = y + y;
184 let z2 = z + z;
185 let xx = x * x2;
186 let xy = x * y2;
187 let xz = x * z2;
188 let yy = y * y2;
189 let yz = y * z2;
190 let zz = z * z2;
191 let wx = w * x2;
192 let wy = w * y2;
193 let wz = w * z2;
194
195 let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
196 let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
197 let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
198 (x_axis, y_axis, z_axis)
199 }
200
201 /// Creates an affine transformation matrix from the given 3D `scale`, `rotation` and
202 /// `translation`.
203 ///
204 /// The resulting matrix can be used to transform 3D points and vectors. See
205 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
206 ///
207 /// # Panics
208 ///
209 /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
210 #[inline]
211 #[must_use]
from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self212 pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
213 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
214 Self::from_cols(
215 x_axis.mul(scale.x),
216 y_axis.mul(scale.y),
217 z_axis.mul(scale.z),
218 Vec4::from((translation, 1.0)),
219 )
220 }
221
222 /// Creates an affine transformation matrix from the given 3D `translation`.
223 ///
224 /// The resulting matrix can be used to transform 3D points and vectors. See
225 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
226 ///
227 /// # Panics
228 ///
229 /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
230 #[inline]
231 #[must_use]
from_rotation_translation(rotation: Quat, translation: Vec3) -> Self232 pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
233 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
234 Self::from_cols(x_axis, y_axis, z_axis, Vec4::from((translation, 1.0)))
235 }
236
237 /// Extracts `scale`, `rotation` and `translation` from `self`. The input matrix is
238 /// expected to be a 3D affine transformation matrix otherwise the output will be invalid.
239 ///
240 /// # Panics
241 ///
242 /// Will panic if the determinant of `self` is zero or if the resulting scale vector
243 /// contains any zero elements when `glam_assert` is enabled.
244 #[inline]
245 #[must_use]
to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3)246 pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
247 let det = self.determinant();
248 glam_assert!(det != 0.0);
249
250 let scale = Vec3::new(
251 self.x_axis.length() * math::signum(det),
252 self.y_axis.length(),
253 self.z_axis.length(),
254 );
255
256 glam_assert!(scale.cmpne(Vec3::ZERO).all());
257
258 let inv_scale = scale.recip();
259
260 let rotation = Quat::from_rotation_axes(
261 self.x_axis.mul(inv_scale.x).xyz(),
262 self.y_axis.mul(inv_scale.y).xyz(),
263 self.z_axis.mul(inv_scale.z).xyz(),
264 );
265
266 let translation = self.w_axis.xyz();
267
268 (scale, rotation, translation)
269 }
270
271 /// Creates an affine transformation matrix from the given `rotation` quaternion.
272 ///
273 /// The resulting matrix can be used to transform 3D points and vectors. See
274 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
275 ///
276 /// # Panics
277 ///
278 /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
279 #[inline]
280 #[must_use]
from_quat(rotation: Quat) -> Self281 pub fn from_quat(rotation: Quat) -> Self {
282 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
283 Self::from_cols(x_axis, y_axis, z_axis, Vec4::W)
284 }
285
286 /// Creates an affine transformation matrix from the given 3x3 linear transformation
287 /// matrix.
288 ///
289 /// The resulting matrix can be used to transform 3D points and vectors. See
290 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
291 #[inline]
292 #[must_use]
from_mat3(m: Mat3) -> Self293 pub fn from_mat3(m: Mat3) -> Self {
294 Self::from_cols(
295 Vec4::from((m.x_axis, 0.0)),
296 Vec4::from((m.y_axis, 0.0)),
297 Vec4::from((m.z_axis, 0.0)),
298 Vec4::W,
299 )
300 }
301
302 /// Creates an affine transformation matrix from the given 3x3 linear transformation
303 /// matrix.
304 ///
305 /// The resulting matrix can be used to transform 3D points and vectors. See
306 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
307 #[inline]
308 #[must_use]
from_mat3a(m: Mat3A) -> Self309 pub fn from_mat3a(m: Mat3A) -> Self {
310 Self::from_cols(
311 Vec4::from((m.x_axis, 0.0)),
312 Vec4::from((m.y_axis, 0.0)),
313 Vec4::from((m.z_axis, 0.0)),
314 Vec4::W,
315 )
316 }
317
318 /// Creates an affine transformation matrix from the given 3D `translation`.
319 ///
320 /// The resulting matrix can be used to transform 3D points and vectors. See
321 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
322 #[inline]
323 #[must_use]
from_translation(translation: Vec3) -> Self324 pub fn from_translation(translation: Vec3) -> Self {
325 Self::from_cols(
326 Vec4::X,
327 Vec4::Y,
328 Vec4::Z,
329 Vec4::new(translation.x, translation.y, translation.z, 1.0),
330 )
331 }
332
333 /// Creates an affine transformation matrix containing a 3D rotation around a normalized
334 /// rotation `axis` of `angle` (in radians).
335 ///
336 /// The resulting matrix can be used to transform 3D points and vectors. See
337 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
338 ///
339 /// # Panics
340 ///
341 /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
342 #[inline]
343 #[must_use]
from_axis_angle(axis: Vec3, angle: f32) -> Self344 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
345 glam_assert!(axis.is_normalized());
346
347 let (sin, cos) = math::sin_cos(angle);
348 let axis_sin = axis.mul(sin);
349 let axis_sq = axis.mul(axis);
350 let omc = 1.0 - cos;
351 let xyomc = axis.x * axis.y * omc;
352 let xzomc = axis.x * axis.z * omc;
353 let yzomc = axis.y * axis.z * omc;
354 Self::from_cols(
355 Vec4::new(
356 axis_sq.x * omc + cos,
357 xyomc + axis_sin.z,
358 xzomc - axis_sin.y,
359 0.0,
360 ),
361 Vec4::new(
362 xyomc - axis_sin.z,
363 axis_sq.y * omc + cos,
364 yzomc + axis_sin.x,
365 0.0,
366 ),
367 Vec4::new(
368 xzomc + axis_sin.y,
369 yzomc - axis_sin.x,
370 axis_sq.z * omc + cos,
371 0.0,
372 ),
373 Vec4::W,
374 )
375 }
376
377 /// Creates a affine transformation matrix containing a rotation from the given euler
378 /// rotation sequence and angles (in radians).
379 ///
380 /// The resulting matrix can be used to transform 3D points and vectors. See
381 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
382 #[inline]
383 #[must_use]
from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self384 pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
385 let quat = Quat::from_euler(order, a, b, c);
386 Self::from_quat(quat)
387 }
388
389 /// Creates an affine transformation matrix containing a 3D rotation around the x axis of
390 /// `angle` (in radians).
391 ///
392 /// The resulting matrix can be used to transform 3D points and vectors. See
393 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
394 #[inline]
395 #[must_use]
from_rotation_x(angle: f32) -> Self396 pub fn from_rotation_x(angle: f32) -> Self {
397 let (sina, cosa) = math::sin_cos(angle);
398 Self::from_cols(
399 Vec4::X,
400 Vec4::new(0.0, cosa, sina, 0.0),
401 Vec4::new(0.0, -sina, cosa, 0.0),
402 Vec4::W,
403 )
404 }
405
406 /// Creates an affine transformation matrix containing a 3D rotation around the y axis of
407 /// `angle` (in radians).
408 ///
409 /// The resulting matrix can be used to transform 3D points and vectors. See
410 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
411 #[inline]
412 #[must_use]
from_rotation_y(angle: f32) -> Self413 pub fn from_rotation_y(angle: f32) -> Self {
414 let (sina, cosa) = math::sin_cos(angle);
415 Self::from_cols(
416 Vec4::new(cosa, 0.0, -sina, 0.0),
417 Vec4::Y,
418 Vec4::new(sina, 0.0, cosa, 0.0),
419 Vec4::W,
420 )
421 }
422
423 /// Creates an affine transformation matrix containing a 3D rotation around the z axis of
424 /// `angle` (in radians).
425 ///
426 /// The resulting matrix can be used to transform 3D points and vectors. See
427 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
428 #[inline]
429 #[must_use]
from_rotation_z(angle: f32) -> Self430 pub fn from_rotation_z(angle: f32) -> Self {
431 let (sina, cosa) = math::sin_cos(angle);
432 Self::from_cols(
433 Vec4::new(cosa, sina, 0.0, 0.0),
434 Vec4::new(-sina, cosa, 0.0, 0.0),
435 Vec4::Z,
436 Vec4::W,
437 )
438 }
439
440 /// Creates an affine transformation matrix containing the given 3D non-uniform `scale`.
441 ///
442 /// The resulting matrix can be used to transform 3D points and vectors. See
443 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
444 ///
445 /// # Panics
446 ///
447 /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
448 #[inline]
449 #[must_use]
from_scale(scale: Vec3) -> Self450 pub fn from_scale(scale: Vec3) -> Self {
451 // Do not panic as long as any component is non-zero
452 glam_assert!(scale.cmpne(Vec3::ZERO).any());
453
454 Self::from_cols(
455 Vec4::new(scale.x, 0.0, 0.0, 0.0),
456 Vec4::new(0.0, scale.y, 0.0, 0.0),
457 Vec4::new(0.0, 0.0, scale.z, 0.0),
458 Vec4::W,
459 )
460 }
461
462 /// Creates a 4x4 matrix from the first 16 values in `slice`.
463 ///
464 /// # Panics
465 ///
466 /// Panics if `slice` is less than 16 elements long.
467 #[inline]
468 #[must_use]
from_cols_slice(slice: &[f32]) -> Self469 pub const fn from_cols_slice(slice: &[f32]) -> Self {
470 Self::new(
471 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
472 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
473 )
474 }
475
476 /// Writes the columns of `self` to the first 16 elements in `slice`.
477 ///
478 /// # Panics
479 ///
480 /// Panics if `slice` is less than 16 elements long.
481 #[inline]
write_cols_to_slice(self, slice: &mut [f32])482 pub fn write_cols_to_slice(self, slice: &mut [f32]) {
483 slice[0] = self.x_axis.x;
484 slice[1] = self.x_axis.y;
485 slice[2] = self.x_axis.z;
486 slice[3] = self.x_axis.w;
487 slice[4] = self.y_axis.x;
488 slice[5] = self.y_axis.y;
489 slice[6] = self.y_axis.z;
490 slice[7] = self.y_axis.w;
491 slice[8] = self.z_axis.x;
492 slice[9] = self.z_axis.y;
493 slice[10] = self.z_axis.z;
494 slice[11] = self.z_axis.w;
495 slice[12] = self.w_axis.x;
496 slice[13] = self.w_axis.y;
497 slice[14] = self.w_axis.z;
498 slice[15] = self.w_axis.w;
499 }
500
501 /// Returns the matrix column for the given `index`.
502 ///
503 /// # Panics
504 ///
505 /// Panics if `index` is greater than 3.
506 #[inline]
507 #[must_use]
col(&self, index: usize) -> Vec4508 pub fn col(&self, index: usize) -> Vec4 {
509 match index {
510 0 => self.x_axis,
511 1 => self.y_axis,
512 2 => self.z_axis,
513 3 => self.w_axis,
514 _ => panic!("index out of bounds"),
515 }
516 }
517
518 /// Returns a mutable reference to the matrix column for the given `index`.
519 ///
520 /// # Panics
521 ///
522 /// Panics if `index` is greater than 3.
523 #[inline]
col_mut(&mut self, index: usize) -> &mut Vec4524 pub fn col_mut(&mut self, index: usize) -> &mut Vec4 {
525 match index {
526 0 => &mut self.x_axis,
527 1 => &mut self.y_axis,
528 2 => &mut self.z_axis,
529 3 => &mut self.w_axis,
530 _ => panic!("index out of bounds"),
531 }
532 }
533
534 /// Returns the matrix row for the given `index`.
535 ///
536 /// # Panics
537 ///
538 /// Panics if `index` is greater than 3.
539 #[inline]
540 #[must_use]
row(&self, index: usize) -> Vec4541 pub fn row(&self, index: usize) -> Vec4 {
542 match index {
543 0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
544 1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
545 2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
546 3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
547 _ => panic!("index out of bounds"),
548 }
549 }
550
551 /// Returns `true` if, and only if, all elements are finite.
552 /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
553 #[inline]
554 #[must_use]
is_finite(&self) -> bool555 pub fn is_finite(&self) -> bool {
556 self.x_axis.is_finite()
557 && self.y_axis.is_finite()
558 && self.z_axis.is_finite()
559 && self.w_axis.is_finite()
560 }
561
562 /// Returns `true` if any elements are `NaN`.
563 #[inline]
564 #[must_use]
is_nan(&self) -> bool565 pub fn is_nan(&self) -> bool {
566 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
567 }
568
569 /// Returns the transpose of `self`.
570 #[inline]
571 #[must_use]
transpose(&self) -> Self572 pub fn transpose(&self) -> Self {
573 // Based on https://github.com/microsoft/DirectXMath `XMMatrixTranspose`
574 let tmp0 = i32x4_shuffle::<0, 1, 4, 5>(self.x_axis.0, self.y_axis.0);
575 let tmp1 = i32x4_shuffle::<2, 3, 6, 7>(self.x_axis.0, self.y_axis.0);
576 let tmp2 = i32x4_shuffle::<0, 1, 4, 5>(self.z_axis.0, self.w_axis.0);
577 let tmp3 = i32x4_shuffle::<2, 3, 6, 7>(self.z_axis.0, self.w_axis.0);
578
579 Self {
580 x_axis: Vec4(i32x4_shuffle::<0, 2, 4, 6>(tmp0, tmp2)),
581 y_axis: Vec4(i32x4_shuffle::<1, 3, 5, 7>(tmp0, tmp2)),
582 z_axis: Vec4(i32x4_shuffle::<0, 2, 4, 6>(tmp1, tmp3)),
583 w_axis: Vec4(i32x4_shuffle::<1, 3, 5, 7>(tmp1, tmp3)),
584 }
585 }
586
587 /// Returns the determinant of `self`.
588 #[must_use]
determinant(&self) -> f32589 pub fn determinant(&self) -> f32 {
590 // Based on https://github.com/g-truc/glm `glm_mat4_determinant`
591 let swp2a = i32x4_shuffle::<2, 1, 1, 0>(self.z_axis.0, self.z_axis.0);
592 let swp3a = i32x4_shuffle::<3, 3, 2, 3>(self.w_axis.0, self.w_axis.0);
593 let swp2b = i32x4_shuffle::<3, 3, 2, 3>(self.z_axis.0, self.z_axis.0);
594 let swp3b = i32x4_shuffle::<2, 1, 1, 0>(self.w_axis.0, self.w_axis.0);
595 let swp2c = i32x4_shuffle::<2, 1, 0, 0>(self.z_axis.0, self.z_axis.0);
596 let swp3c = i32x4_shuffle::<0, 0, 2, 1>(self.w_axis.0, self.w_axis.0);
597
598 let mula = f32x4_mul(swp2a, swp3a);
599 let mulb = f32x4_mul(swp2b, swp3b);
600 let mulc = f32x4_mul(swp2c, swp3c);
601 let sube = f32x4_sub(mula, mulb);
602 let subf = f32x4_sub(i32x4_shuffle::<6, 7, 2, 3>(mulc, mulc), mulc);
603
604 let subfaca = i32x4_shuffle::<0, 0, 1, 2>(sube, sube);
605 let swpfaca = i32x4_shuffle::<1, 0, 0, 0>(self.y_axis.0, self.y_axis.0);
606 let mulfaca = f32x4_mul(swpfaca, subfaca);
607
608 let subtmpb = i32x4_shuffle::<1, 3, 4, 4>(sube, subf);
609 let subfacb = i32x4_shuffle::<0, 1, 1, 3>(subtmpb, subtmpb);
610 let swpfacb = i32x4_shuffle::<2, 2, 1, 1>(self.y_axis.0, self.y_axis.0);
611 let mulfacb = f32x4_mul(swpfacb, subfacb);
612
613 let subres = f32x4_sub(mulfaca, mulfacb);
614 let subtmpc = i32x4_shuffle::<2, 2, 4, 5>(sube, subf);
615 let subfacc = i32x4_shuffle::<0, 2, 3, 3>(subtmpc, subtmpc);
616 let swpfacc = i32x4_shuffle::<3, 3, 3, 2>(self.y_axis.0, self.y_axis.0);
617 let mulfacc = f32x4_mul(swpfacc, subfacc);
618
619 let addres = f32x4_add(subres, mulfacc);
620 let detcof = f32x4_mul(addres, f32x4(1.0, -1.0, 1.0, -1.0));
621
622 dot4(self.x_axis.0, detcof)
623 }
624
625 /// Returns the inverse of `self`.
626 ///
627 /// If the matrix is not invertible the returned matrix will be invalid.
628 ///
629 /// # Panics
630 ///
631 /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
632 #[must_use]
inverse(&self) -> Self633 pub fn inverse(&self) -> Self {
634 // Based on https://github.com/g-truc/glm `glm_mat4_inverse`
635 let fac0 = {
636 let swp0a = i32x4_shuffle::<3, 3, 7, 7>(self.w_axis.0, self.z_axis.0);
637 let swp0b = i32x4_shuffle::<2, 2, 6, 6>(self.w_axis.0, self.z_axis.0);
638
639 let swp00 = i32x4_shuffle::<2, 2, 6, 6>(self.z_axis.0, self.y_axis.0);
640 let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
641 let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
642 let swp03 = i32x4_shuffle::<3, 3, 7, 7>(self.z_axis.0, self.y_axis.0);
643
644 let mul00 = f32x4_mul(swp00, swp01);
645 let mul01 = f32x4_mul(swp02, swp03);
646 f32x4_sub(mul00, mul01)
647 };
648 let fac1 = {
649 let swp0a = i32x4_shuffle::<3, 3, 7, 7>(self.w_axis.0, self.z_axis.0);
650 let swp0b = i32x4_shuffle::<1, 1, 5, 5>(self.w_axis.0, self.z_axis.0);
651
652 let swp00 = i32x4_shuffle::<1, 1, 5, 5>(self.z_axis.0, self.y_axis.0);
653 let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
654 let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
655 let swp03 = i32x4_shuffle::<3, 3, 7, 7>(self.z_axis.0, self.y_axis.0);
656
657 let mul00 = f32x4_mul(swp00, swp01);
658 let mul01 = f32x4_mul(swp02, swp03);
659 f32x4_sub(mul00, mul01)
660 };
661 let fac2 = {
662 let swp0a = i32x4_shuffle::<2, 2, 6, 6>(self.w_axis.0, self.z_axis.0);
663 let swp0b = i32x4_shuffle::<1, 1, 5, 5>(self.w_axis.0, self.z_axis.0);
664
665 let swp00 = i32x4_shuffle::<1, 1, 5, 5>(self.z_axis.0, self.y_axis.0);
666 let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
667 let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
668 let swp03 = i32x4_shuffle::<2, 2, 6, 6>(self.z_axis.0, self.y_axis.0);
669
670 let mul00 = f32x4_mul(swp00, swp01);
671 let mul01 = f32x4_mul(swp02, swp03);
672 f32x4_sub(mul00, mul01)
673 };
674 let fac3 = {
675 let swp0a = i32x4_shuffle::<3, 3, 7, 7>(self.w_axis.0, self.z_axis.0);
676 let swp0b = i32x4_shuffle::<0, 0, 4, 4>(self.w_axis.0, self.z_axis.0);
677
678 let swp00 = i32x4_shuffle::<0, 0, 4, 4>(self.z_axis.0, self.y_axis.0);
679 let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
680 let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
681 let swp03 = i32x4_shuffle::<3, 3, 7, 7>(self.z_axis.0, self.y_axis.0);
682
683 let mul00 = f32x4_mul(swp00, swp01);
684 let mul01 = f32x4_mul(swp02, swp03);
685 f32x4_sub(mul00, mul01)
686 };
687 let fac4 = {
688 let swp0a = i32x4_shuffle::<2, 2, 6, 6>(self.w_axis.0, self.z_axis.0);
689 let swp0b = i32x4_shuffle::<0, 0, 4, 4>(self.w_axis.0, self.z_axis.0);
690
691 let swp00 = i32x4_shuffle::<0, 0, 4, 4>(self.z_axis.0, self.y_axis.0);
692 let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
693 let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
694 let swp03 = i32x4_shuffle::<2, 2, 6, 6>(self.z_axis.0, self.y_axis.0);
695
696 let mul00 = f32x4_mul(swp00, swp01);
697 let mul01 = f32x4_mul(swp02, swp03);
698 f32x4_sub(mul00, mul01)
699 };
700 let fac5 = {
701 let swp0a = i32x4_shuffle::<1, 1, 5, 5>(self.w_axis.0, self.z_axis.0);
702 let swp0b = i32x4_shuffle::<0, 0, 4, 4>(self.w_axis.0, self.z_axis.0);
703
704 let swp00 = i32x4_shuffle::<0, 0, 4, 4>(self.z_axis.0, self.y_axis.0);
705 let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
706 let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
707 let swp03 = i32x4_shuffle::<1, 1, 5, 5>(self.z_axis.0, self.y_axis.0);
708
709 let mul00 = f32x4_mul(swp00, swp01);
710 let mul01 = f32x4_mul(swp02, swp03);
711 f32x4_sub(mul00, mul01)
712 };
713 let sign_a = f32x4(-1.0, 1.0, -1.0, 1.0);
714 let sign_b = f32x4(1.0, -1.0, 1.0, -1.0);
715
716 let temp0 = i32x4_shuffle::<0, 0, 4, 4>(self.y_axis.0, self.x_axis.0);
717 let vec0 = i32x4_shuffle::<0, 2, 6, 6>(temp0, temp0);
718
719 let temp1 = i32x4_shuffle::<1, 1, 5, 5>(self.y_axis.0, self.x_axis.0);
720 let vec1 = i32x4_shuffle::<0, 2, 6, 6>(temp1, temp1);
721
722 let temp2 = i32x4_shuffle::<2, 2, 6, 6>(self.y_axis.0, self.x_axis.0);
723 let vec2 = i32x4_shuffle::<0, 2, 6, 6>(temp2, temp2);
724
725 let temp3 = i32x4_shuffle::<3, 3, 7, 7>(self.y_axis.0, self.x_axis.0);
726 let vec3 = i32x4_shuffle::<0, 2, 6, 6>(temp3, temp3);
727
728 let mul00 = f32x4_mul(vec1, fac0);
729 let mul01 = f32x4_mul(vec2, fac1);
730 let mul02 = f32x4_mul(vec3, fac2);
731 let sub00 = f32x4_sub(mul00, mul01);
732 let add00 = f32x4_add(sub00, mul02);
733 let inv0 = f32x4_mul(sign_b, add00);
734
735 let mul03 = f32x4_mul(vec0, fac0);
736 let mul04 = f32x4_mul(vec2, fac3);
737 let mul05 = f32x4_mul(vec3, fac4);
738 let sub01 = f32x4_sub(mul03, mul04);
739 let add01 = f32x4_add(sub01, mul05);
740 let inv1 = f32x4_mul(sign_a, add01);
741
742 let mul06 = f32x4_mul(vec0, fac1);
743 let mul07 = f32x4_mul(vec1, fac3);
744 let mul08 = f32x4_mul(vec3, fac5);
745 let sub02 = f32x4_sub(mul06, mul07);
746 let add02 = f32x4_add(sub02, mul08);
747 let inv2 = f32x4_mul(sign_b, add02);
748
749 let mul09 = f32x4_mul(vec0, fac2);
750 let mul10 = f32x4_mul(vec1, fac4);
751 let mul11 = f32x4_mul(vec2, fac5);
752 let sub03 = f32x4_sub(mul09, mul10);
753 let add03 = f32x4_add(sub03, mul11);
754 let inv3 = f32x4_mul(sign_a, add03);
755
756 let row0 = i32x4_shuffle::<0, 0, 4, 4>(inv0, inv1);
757 let row1 = i32x4_shuffle::<0, 0, 4, 4>(inv2, inv3);
758 let row2 = i32x4_shuffle::<0, 2, 4, 6>(row0, row1);
759
760 let dot0 = dot4(self.x_axis.0, row2);
761 glam_assert!(dot0 != 0.0);
762
763 let rcp0 = f32x4_splat(dot0.recip());
764
765 Self {
766 x_axis: Vec4(f32x4_mul(inv0, rcp0)),
767 y_axis: Vec4(f32x4_mul(inv1, rcp0)),
768 z_axis: Vec4(f32x4_mul(inv2, rcp0)),
769 w_axis: Vec4(f32x4_mul(inv3, rcp0)),
770 }
771 }
772
773 /// Creates a left-handed view matrix using a camera position, an up direction, and a facing
774 /// direction.
775 ///
776 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
777 #[inline]
778 #[must_use]
look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self779 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
780 Self::look_to_rh(eye, -dir, up)
781 }
782
783 /// Creates a right-handed view matrix using a camera position, an up direction, and a facing
784 /// direction.
785 ///
786 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
787 #[inline]
788 #[must_use]
look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self789 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
790 let f = dir.normalize();
791 let s = f.cross(up).normalize();
792 let u = s.cross(f);
793
794 Self::from_cols(
795 Vec4::new(s.x, u.x, -f.x, 0.0),
796 Vec4::new(s.y, u.y, -f.y, 0.0),
797 Vec4::new(s.z, u.z, -f.z, 0.0),
798 Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
799 )
800 }
801
802 /// Creates a left-handed view matrix using a camera position, an up direction, and a focal
803 /// point.
804 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
805 ///
806 /// # Panics
807 ///
808 /// Will panic if `up` is not normalized when `glam_assert` is enabled.
809 #[inline]
810 #[must_use]
look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self811 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
812 glam_assert!(up.is_normalized());
813 Self::look_to_lh(eye, center.sub(eye), up)
814 }
815
816 /// Creates a right-handed view matrix using a camera position, an up direction, and a focal
817 /// point.
818 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
819 ///
820 /// # Panics
821 ///
822 /// Will panic if `up` is not normalized when `glam_assert` is enabled.
823 #[inline]
look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self824 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
825 glam_assert!(up.is_normalized());
826 Self::look_to_rh(eye, center.sub(eye), up)
827 }
828
829 /// Creates a right-handed perspective projection matrix with [-1,1] depth range.
830 /// This is the same as the OpenGL `gluPerspective` function.
831 /// See <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml>
832 #[inline]
833 #[must_use]
perspective_rh_gl( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32, ) -> Self834 pub fn perspective_rh_gl(
835 fov_y_radians: f32,
836 aspect_ratio: f32,
837 z_near: f32,
838 z_far: f32,
839 ) -> Self {
840 let inv_length = 1.0 / (z_near - z_far);
841 let f = 1.0 / math::tan(0.5 * fov_y_radians);
842 let a = f / aspect_ratio;
843 let b = (z_near + z_far) * inv_length;
844 let c = (2.0 * z_near * z_far) * inv_length;
845 Self::from_cols(
846 Vec4::new(a, 0.0, 0.0, 0.0),
847 Vec4::new(0.0, f, 0.0, 0.0),
848 Vec4::new(0.0, 0.0, b, -1.0),
849 Vec4::new(0.0, 0.0, c, 0.0),
850 )
851 }
852
853 /// Creates a left-handed perspective projection matrix with `[0,1]` depth range.
854 ///
855 /// # Panics
856 ///
857 /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
858 /// enabled.
859 #[inline]
860 #[must_use]
perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self861 pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
862 glam_assert!(z_near > 0.0 && z_far > 0.0);
863 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
864 let h = cos_fov / sin_fov;
865 let w = h / aspect_ratio;
866 let r = z_far / (z_far - z_near);
867 Self::from_cols(
868 Vec4::new(w, 0.0, 0.0, 0.0),
869 Vec4::new(0.0, h, 0.0, 0.0),
870 Vec4::new(0.0, 0.0, r, 1.0),
871 Vec4::new(0.0, 0.0, -r * z_near, 0.0),
872 )
873 }
874
875 /// Creates a right-handed perspective projection matrix with `[0,1]` depth range.
876 ///
877 /// # Panics
878 ///
879 /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
880 /// enabled.
881 #[inline]
882 #[must_use]
perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self883 pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
884 glam_assert!(z_near > 0.0 && z_far > 0.0);
885 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
886 let h = cos_fov / sin_fov;
887 let w = h / aspect_ratio;
888 let r = z_far / (z_near - z_far);
889 Self::from_cols(
890 Vec4::new(w, 0.0, 0.0, 0.0),
891 Vec4::new(0.0, h, 0.0, 0.0),
892 Vec4::new(0.0, 0.0, r, -1.0),
893 Vec4::new(0.0, 0.0, r * z_near, 0.0),
894 )
895 }
896
897 /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range.
898 ///
899 /// # Panics
900 ///
901 /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
902 #[inline]
903 #[must_use]
perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self904 pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
905 glam_assert!(z_near > 0.0);
906 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
907 let h = cos_fov / sin_fov;
908 let w = h / aspect_ratio;
909 Self::from_cols(
910 Vec4::new(w, 0.0, 0.0, 0.0),
911 Vec4::new(0.0, h, 0.0, 0.0),
912 Vec4::new(0.0, 0.0, 1.0, 1.0),
913 Vec4::new(0.0, 0.0, -z_near, 0.0),
914 )
915 }
916
917 /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range.
918 ///
919 /// # Panics
920 ///
921 /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
922 #[inline]
923 #[must_use]
perspective_infinite_reverse_lh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self924 pub fn perspective_infinite_reverse_lh(
925 fov_y_radians: f32,
926 aspect_ratio: f32,
927 z_near: f32,
928 ) -> Self {
929 glam_assert!(z_near > 0.0);
930 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
931 let h = cos_fov / sin_fov;
932 let w = h / aspect_ratio;
933 Self::from_cols(
934 Vec4::new(w, 0.0, 0.0, 0.0),
935 Vec4::new(0.0, h, 0.0, 0.0),
936 Vec4::new(0.0, 0.0, 0.0, 1.0),
937 Vec4::new(0.0, 0.0, z_near, 0.0),
938 )
939 }
940
941 /// Creates an infinite right-handed perspective projection matrix with
942 /// `[0,1]` depth range.
943 #[inline]
944 #[must_use]
perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self945 pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
946 glam_assert!(z_near > 0.0);
947 let f = 1.0 / math::tan(0.5 * fov_y_radians);
948 Self::from_cols(
949 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
950 Vec4::new(0.0, f, 0.0, 0.0),
951 Vec4::new(0.0, 0.0, -1.0, -1.0),
952 Vec4::new(0.0, 0.0, -z_near, 0.0),
953 )
954 }
955
956 /// Creates an infinite reverse right-handed perspective projection matrix
957 /// with `[0,1]` depth range.
958 #[inline]
959 #[must_use]
perspective_infinite_reverse_rh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self960 pub fn perspective_infinite_reverse_rh(
961 fov_y_radians: f32,
962 aspect_ratio: f32,
963 z_near: f32,
964 ) -> Self {
965 glam_assert!(z_near > 0.0);
966 let f = 1.0 / math::tan(0.5 * fov_y_radians);
967 Self::from_cols(
968 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
969 Vec4::new(0.0, f, 0.0, 0.0),
970 Vec4::new(0.0, 0.0, 0.0, -1.0),
971 Vec4::new(0.0, 0.0, z_near, 0.0),
972 )
973 }
974
975 /// Creates a right-handed orthographic projection matrix with `[-1,1]` depth
976 /// range. This is the same as the OpenGL `glOrtho` function in OpenGL.
977 /// See
978 /// <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml>
979 #[inline]
980 #[must_use]
orthographic_rh_gl( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self981 pub fn orthographic_rh_gl(
982 left: f32,
983 right: f32,
984 bottom: f32,
985 top: f32,
986 near: f32,
987 far: f32,
988 ) -> Self {
989 let a = 2.0 / (right - left);
990 let b = 2.0 / (top - bottom);
991 let c = -2.0 / (far - near);
992 let tx = -(right + left) / (right - left);
993 let ty = -(top + bottom) / (top - bottom);
994 let tz = -(far + near) / (far - near);
995
996 Self::from_cols(
997 Vec4::new(a, 0.0, 0.0, 0.0),
998 Vec4::new(0.0, b, 0.0, 0.0),
999 Vec4::new(0.0, 0.0, c, 0.0),
1000 Vec4::new(tx, ty, tz, 1.0),
1001 )
1002 }
1003
1004 /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range.
1005 #[inline]
1006 #[must_use]
orthographic_lh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self1007 pub fn orthographic_lh(
1008 left: f32,
1009 right: f32,
1010 bottom: f32,
1011 top: f32,
1012 near: f32,
1013 far: f32,
1014 ) -> Self {
1015 let rcp_width = 1.0 / (right - left);
1016 let rcp_height = 1.0 / (top - bottom);
1017 let r = 1.0 / (far - near);
1018 Self::from_cols(
1019 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1020 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1021 Vec4::new(0.0, 0.0, r, 0.0),
1022 Vec4::new(
1023 -(left + right) * rcp_width,
1024 -(top + bottom) * rcp_height,
1025 -r * near,
1026 1.0,
1027 ),
1028 )
1029 }
1030
1031 /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range.
1032 #[inline]
1033 #[must_use]
orthographic_rh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self1034 pub fn orthographic_rh(
1035 left: f32,
1036 right: f32,
1037 bottom: f32,
1038 top: f32,
1039 near: f32,
1040 far: f32,
1041 ) -> Self {
1042 let rcp_width = 1.0 / (right - left);
1043 let rcp_height = 1.0 / (top - bottom);
1044 let r = 1.0 / (near - far);
1045 Self::from_cols(
1046 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1047 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1048 Vec4::new(0.0, 0.0, r, 0.0),
1049 Vec4::new(
1050 -(left + right) * rcp_width,
1051 -(top + bottom) * rcp_height,
1052 r * near,
1053 1.0,
1054 ),
1055 )
1056 }
1057
1058 /// Transforms the given 3D vector as a point, applying perspective correction.
1059 ///
1060 /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is `1.0`.
1061 /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
1062 ///
1063 /// This method assumes that `self` contains a projective transform.
1064 #[inline]
1065 #[must_use]
project_point3(&self, rhs: Vec3) -> Vec31066 pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
1067 let mut res = self.x_axis.mul(rhs.x);
1068 res = self.y_axis.mul(rhs.y).add(res);
1069 res = self.z_axis.mul(rhs.z).add(res);
1070 res = self.w_axis.add(res);
1071 res = res.mul(res.wwww().recip());
1072 res.xyz()
1073 }
1074
1075 /// Transforms the given 3D vector as a point.
1076 ///
1077 /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
1078 /// `1.0`.
1079 ///
1080 /// This method assumes that `self` contains a valid affine transform. It does not perform
1081 /// a persective divide, if `self` contains a perspective transform, or if you are unsure,
1082 /// the [`Self::project_point3()`] method should be used instead.
1083 ///
1084 /// # Panics
1085 ///
1086 /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1087 #[inline]
1088 #[must_use]
transform_point3(&self, rhs: Vec3) -> Vec31089 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1090 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1091 let mut res = self.x_axis.mul(rhs.x);
1092 res = self.y_axis.mul(rhs.y).add(res);
1093 res = self.z_axis.mul(rhs.z).add(res);
1094 res = self.w_axis.add(res);
1095 res.xyz()
1096 }
1097
1098 /// Transforms the give 3D vector as a direction.
1099 ///
1100 /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
1101 /// `0.0`.
1102 ///
1103 /// This method assumes that `self` contains a valid affine transform.
1104 ///
1105 /// # Panics
1106 ///
1107 /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1108 #[inline]
1109 #[must_use]
transform_vector3(&self, rhs: Vec3) -> Vec31110 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1111 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1112 let mut res = self.x_axis.mul(rhs.x);
1113 res = self.y_axis.mul(rhs.y).add(res);
1114 res = self.z_axis.mul(rhs.z).add(res);
1115 res.xyz()
1116 }
1117
1118 /// Transforms the given [`Vec3A`] as 3D point.
1119 ///
1120 /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
1121 #[inline]
1122 #[must_use]
transform_point3a(&self, rhs: Vec3A) -> Vec3A1123 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1124 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1125 let mut res = self.x_axis.mul(rhs.xxxx());
1126 res = self.y_axis.mul(rhs.yyyy()).add(res);
1127 res = self.z_axis.mul(rhs.zzzz()).add(res);
1128 res = self.w_axis.add(res);
1129 res.into()
1130 }
1131
1132 /// Transforms the give [`Vec3A`] as 3D vector.
1133 ///
1134 /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `0.0`.
1135 #[inline]
1136 #[must_use]
transform_vector3a(&self, rhs: Vec3A) -> Vec3A1137 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1138 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1139 let mut res = self.x_axis.mul(rhs.xxxx());
1140 res = self.y_axis.mul(rhs.yyyy()).add(res);
1141 res = self.z_axis.mul(rhs.zzzz()).add(res);
1142 res.into()
1143 }
1144
1145 /// Transforms a 4D vector.
1146 #[inline]
1147 #[must_use]
mul_vec4(&self, rhs: Vec4) -> Vec41148 pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1149 let mut res = self.x_axis.mul(rhs.xxxx());
1150 res = res.add(self.y_axis.mul(rhs.yyyy()));
1151 res = res.add(self.z_axis.mul(rhs.zzzz()));
1152 res = res.add(self.w_axis.mul(rhs.wwww()));
1153 res
1154 }
1155
1156 /// Multiplies two 4x4 matrices.
1157 #[inline]
1158 #[must_use]
mul_mat4(&self, rhs: &Self) -> Self1159 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1160 Self::from_cols(
1161 self.mul(rhs.x_axis),
1162 self.mul(rhs.y_axis),
1163 self.mul(rhs.z_axis),
1164 self.mul(rhs.w_axis),
1165 )
1166 }
1167
1168 /// Adds two 4x4 matrices.
1169 #[inline]
1170 #[must_use]
add_mat4(&self, rhs: &Self) -> Self1171 pub fn add_mat4(&self, rhs: &Self) -> Self {
1172 Self::from_cols(
1173 self.x_axis.add(rhs.x_axis),
1174 self.y_axis.add(rhs.y_axis),
1175 self.z_axis.add(rhs.z_axis),
1176 self.w_axis.add(rhs.w_axis),
1177 )
1178 }
1179
1180 /// Subtracts two 4x4 matrices.
1181 #[inline]
1182 #[must_use]
sub_mat4(&self, rhs: &Self) -> Self1183 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1184 Self::from_cols(
1185 self.x_axis.sub(rhs.x_axis),
1186 self.y_axis.sub(rhs.y_axis),
1187 self.z_axis.sub(rhs.z_axis),
1188 self.w_axis.sub(rhs.w_axis),
1189 )
1190 }
1191
1192 /// Multiplies a 4x4 matrix by a scalar.
1193 #[inline]
1194 #[must_use]
mul_scalar(&self, rhs: f32) -> Self1195 pub fn mul_scalar(&self, rhs: f32) -> Self {
1196 Self::from_cols(
1197 self.x_axis.mul(rhs),
1198 self.y_axis.mul(rhs),
1199 self.z_axis.mul(rhs),
1200 self.w_axis.mul(rhs),
1201 )
1202 }
1203
1204 /// Returns true if the absolute difference of all elements between `self` and `rhs`
1205 /// is less than or equal to `max_abs_diff`.
1206 ///
1207 /// This can be used to compare if two matrices contain similar elements. It works best
1208 /// when comparing with a known value. The `max_abs_diff` that should be used used
1209 /// depends on the values being compared against.
1210 ///
1211 /// For more see
1212 /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
1213 #[inline]
1214 #[must_use]
abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool1215 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1216 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1217 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1218 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1219 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1220 }
1221
1222 #[inline]
as_dmat4(&self) -> DMat41223 pub fn as_dmat4(&self) -> DMat4 {
1224 DMat4::from_cols(
1225 self.x_axis.as_dvec4(),
1226 self.y_axis.as_dvec4(),
1227 self.z_axis.as_dvec4(),
1228 self.w_axis.as_dvec4(),
1229 )
1230 }
1231 }
1232
1233 impl Default for Mat4 {
1234 #[inline]
default() -> Self1235 fn default() -> Self {
1236 Self::IDENTITY
1237 }
1238 }
1239
1240 impl Add<Mat4> for Mat4 {
1241 type Output = Self;
1242 #[inline]
add(self, rhs: Self) -> Self::Output1243 fn add(self, rhs: Self) -> Self::Output {
1244 self.add_mat4(&rhs)
1245 }
1246 }
1247
1248 impl AddAssign<Mat4> for Mat4 {
1249 #[inline]
add_assign(&mut self, rhs: Self)1250 fn add_assign(&mut self, rhs: Self) {
1251 *self = self.add_mat4(&rhs);
1252 }
1253 }
1254
1255 impl Sub<Mat4> for Mat4 {
1256 type Output = Self;
1257 #[inline]
sub(self, rhs: Self) -> Self::Output1258 fn sub(self, rhs: Self) -> Self::Output {
1259 self.sub_mat4(&rhs)
1260 }
1261 }
1262
1263 impl SubAssign<Mat4> for Mat4 {
1264 #[inline]
sub_assign(&mut self, rhs: Self)1265 fn sub_assign(&mut self, rhs: Self) {
1266 *self = self.sub_mat4(&rhs);
1267 }
1268 }
1269
1270 impl Neg for Mat4 {
1271 type Output = Self;
1272 #[inline]
neg(self) -> Self::Output1273 fn neg(self) -> Self::Output {
1274 Self::from_cols(
1275 self.x_axis.neg(),
1276 self.y_axis.neg(),
1277 self.z_axis.neg(),
1278 self.w_axis.neg(),
1279 )
1280 }
1281 }
1282
1283 impl Mul<Mat4> for Mat4 {
1284 type Output = Self;
1285 #[inline]
mul(self, rhs: Self) -> Self::Output1286 fn mul(self, rhs: Self) -> Self::Output {
1287 self.mul_mat4(&rhs)
1288 }
1289 }
1290
1291 impl MulAssign<Mat4> for Mat4 {
1292 #[inline]
mul_assign(&mut self, rhs: Self)1293 fn mul_assign(&mut self, rhs: Self) {
1294 *self = self.mul_mat4(&rhs);
1295 }
1296 }
1297
1298 impl Mul<Vec4> for Mat4 {
1299 type Output = Vec4;
1300 #[inline]
mul(self, rhs: Vec4) -> Self::Output1301 fn mul(self, rhs: Vec4) -> Self::Output {
1302 self.mul_vec4(rhs)
1303 }
1304 }
1305
1306 impl Mul<Mat4> for f32 {
1307 type Output = Mat4;
1308 #[inline]
mul(self, rhs: Mat4) -> Self::Output1309 fn mul(self, rhs: Mat4) -> Self::Output {
1310 rhs.mul_scalar(self)
1311 }
1312 }
1313
1314 impl Mul<f32> for Mat4 {
1315 type Output = Self;
1316 #[inline]
mul(self, rhs: f32) -> Self::Output1317 fn mul(self, rhs: f32) -> Self::Output {
1318 self.mul_scalar(rhs)
1319 }
1320 }
1321
1322 impl MulAssign<f32> for Mat4 {
1323 #[inline]
mul_assign(&mut self, rhs: f32)1324 fn mul_assign(&mut self, rhs: f32) {
1325 *self = self.mul_scalar(rhs);
1326 }
1327 }
1328
1329 impl Sum<Self> for Mat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,1330 fn sum<I>(iter: I) -> Self
1331 where
1332 I: Iterator<Item = Self>,
1333 {
1334 iter.fold(Self::ZERO, Self::add)
1335 }
1336 }
1337
1338 impl<'a> Sum<&'a Self> for Mat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,1339 fn sum<I>(iter: I) -> Self
1340 where
1341 I: Iterator<Item = &'a Self>,
1342 {
1343 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1344 }
1345 }
1346
1347 impl Product for Mat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,1348 fn product<I>(iter: I) -> Self
1349 where
1350 I: Iterator<Item = Self>,
1351 {
1352 iter.fold(Self::IDENTITY, Self::mul)
1353 }
1354 }
1355
1356 impl<'a> Product<&'a Self> for Mat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,1357 fn product<I>(iter: I) -> Self
1358 where
1359 I: Iterator<Item = &'a Self>,
1360 {
1361 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1362 }
1363 }
1364
1365 impl PartialEq for Mat4 {
1366 #[inline]
eq(&self, rhs: &Self) -> bool1367 fn eq(&self, rhs: &Self) -> bool {
1368 self.x_axis.eq(&rhs.x_axis)
1369 && self.y_axis.eq(&rhs.y_axis)
1370 && self.z_axis.eq(&rhs.z_axis)
1371 && self.w_axis.eq(&rhs.w_axis)
1372 }
1373 }
1374
1375 #[cfg(not(target_arch = "spirv"))]
1376 impl AsRef<[f32; 16]> for Mat4 {
1377 #[inline]
as_ref(&self) -> &[f32; 16]1378 fn as_ref(&self) -> &[f32; 16] {
1379 unsafe { &*(self as *const Self as *const [f32; 16]) }
1380 }
1381 }
1382
1383 #[cfg(not(target_arch = "spirv"))]
1384 impl AsMut<[f32; 16]> for Mat4 {
1385 #[inline]
as_mut(&mut self) -> &mut [f32; 16]1386 fn as_mut(&mut self) -> &mut [f32; 16] {
1387 unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
1388 }
1389 }
1390
1391 #[cfg(not(target_arch = "spirv"))]
1392 impl fmt::Debug for Mat4 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result1393 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1394 fmt.debug_struct(stringify!(Mat4))
1395 .field("x_axis", &self.x_axis)
1396 .field("y_axis", &self.y_axis)
1397 .field("z_axis", &self.z_axis)
1398 .field("w_axis", &self.w_axis)
1399 .finish()
1400 }
1401 }
1402
1403 #[cfg(not(target_arch = "spirv"))]
1404 impl fmt::Display for Mat4 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1405 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1406 write!(
1407 f,
1408 "[{}, {}, {}, {}]",
1409 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1410 )
1411 }
1412 }
1413