1 // Generated from mat.rs.tera template. Edit the template, not the generated file.
2
3 use crate::{
4 euler::{FromEuler, ToEuler},
5 f32::math,
6 swizzles::*,
7 wasm32::*,
8 DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4,
9 };
10 use core::fmt;
11 use core::iter::{Product, Sum};
12 use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
13
14 use core::arch::wasm32::*;
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 matrics from a 3x3 matrix (expressing scale, shear and
306 /// rotation) and a translation vector.
307 ///
308 /// Equivalent to `Mat4::from_translation(translation) * Mat4::from_mat3(mat3)`
309 #[inline]
310 #[must_use]
from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self311 pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
312 Self::from_cols(
313 Vec4::from((mat3.x_axis, 0.0)),
314 Vec4::from((mat3.y_axis, 0.0)),
315 Vec4::from((mat3.z_axis, 0.0)),
316 Vec4::from((translation, 1.0)),
317 )
318 }
319
320 /// Creates an affine transformation matrix from the given 3x3 linear transformation
321 /// matrix.
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_mat3a(m: Mat3A) -> Self327 pub fn from_mat3a(m: Mat3A) -> Self {
328 Self::from_cols(
329 Vec4::from((m.x_axis, 0.0)),
330 Vec4::from((m.y_axis, 0.0)),
331 Vec4::from((m.z_axis, 0.0)),
332 Vec4::W,
333 )
334 }
335
336 /// Creates an affine transformation matrix from the given 3D `translation`.
337 ///
338 /// The resulting matrix can be used to transform 3D points and vectors. See
339 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
340 #[inline]
341 #[must_use]
from_translation(translation: Vec3) -> Self342 pub fn from_translation(translation: Vec3) -> Self {
343 Self::from_cols(
344 Vec4::X,
345 Vec4::Y,
346 Vec4::Z,
347 Vec4::new(translation.x, translation.y, translation.z, 1.0),
348 )
349 }
350
351 /// Creates an affine transformation matrix containing a 3D rotation around a normalized
352 /// rotation `axis` of `angle` (in radians).
353 ///
354 /// The resulting matrix can be used to transform 3D points and vectors. See
355 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
356 ///
357 /// # Panics
358 ///
359 /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
360 #[inline]
361 #[must_use]
from_axis_angle(axis: Vec3, angle: f32) -> Self362 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
363 glam_assert!(axis.is_normalized());
364
365 let (sin, cos) = math::sin_cos(angle);
366 let axis_sin = axis.mul(sin);
367 let axis_sq = axis.mul(axis);
368 let omc = 1.0 - cos;
369 let xyomc = axis.x * axis.y * omc;
370 let xzomc = axis.x * axis.z * omc;
371 let yzomc = axis.y * axis.z * omc;
372 Self::from_cols(
373 Vec4::new(
374 axis_sq.x * omc + cos,
375 xyomc + axis_sin.z,
376 xzomc - axis_sin.y,
377 0.0,
378 ),
379 Vec4::new(
380 xyomc - axis_sin.z,
381 axis_sq.y * omc + cos,
382 yzomc + axis_sin.x,
383 0.0,
384 ),
385 Vec4::new(
386 xzomc + axis_sin.y,
387 yzomc - axis_sin.x,
388 axis_sq.z * omc + cos,
389 0.0,
390 ),
391 Vec4::W,
392 )
393 }
394
395 /// Creates a affine transformation matrix containing a rotation from the given euler
396 /// rotation sequence and angles (in radians).
397 ///
398 /// The resulting matrix can be used to transform 3D points and vectors. See
399 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
400 #[inline]
401 #[must_use]
from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self402 pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
403 Self::from_euler_angles(order, a, b, c)
404 }
405
406 /// Extract Euler angles with the given Euler rotation order.
407 ///
408 /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations
409 /// then the resulting Euler angles will be ill-defined.
410 ///
411 /// # Panics
412 ///
413 /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when
414 /// `glam_assert` is enabled.
415 #[inline]
416 #[must_use]
to_euler(&self, order: EulerRot) -> (f32, f32, f32)417 pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
418 glam_assert!(
419 self.x_axis.xyz().is_normalized()
420 && self.y_axis.xyz().is_normalized()
421 && self.z_axis.xyz().is_normalized()
422 );
423 self.to_euler_angles(order)
424 }
425
426 /// Creates an affine transformation matrix containing a 3D rotation around the x 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_x(angle: f32) -> Self433 pub fn from_rotation_x(angle: f32) -> Self {
434 let (sina, cosa) = math::sin_cos(angle);
435 Self::from_cols(
436 Vec4::X,
437 Vec4::new(0.0, cosa, sina, 0.0),
438 Vec4::new(0.0, -sina, cosa, 0.0),
439 Vec4::W,
440 )
441 }
442
443 /// Creates an affine transformation matrix containing a 3D rotation around the y axis of
444 /// `angle` (in radians).
445 ///
446 /// The resulting matrix can be used to transform 3D points and vectors. See
447 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
448 #[inline]
449 #[must_use]
from_rotation_y(angle: f32) -> Self450 pub fn from_rotation_y(angle: f32) -> Self {
451 let (sina, cosa) = math::sin_cos(angle);
452 Self::from_cols(
453 Vec4::new(cosa, 0.0, -sina, 0.0),
454 Vec4::Y,
455 Vec4::new(sina, 0.0, cosa, 0.0),
456 Vec4::W,
457 )
458 }
459
460 /// Creates an affine transformation matrix containing a 3D rotation around the z axis of
461 /// `angle` (in radians).
462 ///
463 /// The resulting matrix can be used to transform 3D points and vectors. See
464 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
465 #[inline]
466 #[must_use]
from_rotation_z(angle: f32) -> Self467 pub fn from_rotation_z(angle: f32) -> Self {
468 let (sina, cosa) = math::sin_cos(angle);
469 Self::from_cols(
470 Vec4::new(cosa, sina, 0.0, 0.0),
471 Vec4::new(-sina, cosa, 0.0, 0.0),
472 Vec4::Z,
473 Vec4::W,
474 )
475 }
476
477 /// Creates an affine transformation matrix containing the given 3D non-uniform `scale`.
478 ///
479 /// The resulting matrix can be used to transform 3D points and vectors. See
480 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
481 ///
482 /// # Panics
483 ///
484 /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
485 #[inline]
486 #[must_use]
from_scale(scale: Vec3) -> Self487 pub fn from_scale(scale: Vec3) -> Self {
488 // Do not panic as long as any component is non-zero
489 glam_assert!(scale.cmpne(Vec3::ZERO).any());
490
491 Self::from_cols(
492 Vec4::new(scale.x, 0.0, 0.0, 0.0),
493 Vec4::new(0.0, scale.y, 0.0, 0.0),
494 Vec4::new(0.0, 0.0, scale.z, 0.0),
495 Vec4::W,
496 )
497 }
498
499 /// Creates a 4x4 matrix from the first 16 values in `slice`.
500 ///
501 /// # Panics
502 ///
503 /// Panics if `slice` is less than 16 elements long.
504 #[inline]
505 #[must_use]
from_cols_slice(slice: &[f32]) -> Self506 pub const fn from_cols_slice(slice: &[f32]) -> Self {
507 Self::new(
508 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
509 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
510 )
511 }
512
513 /// Writes the columns of `self` to the first 16 elements in `slice`.
514 ///
515 /// # Panics
516 ///
517 /// Panics if `slice` is less than 16 elements long.
518 #[inline]
write_cols_to_slice(self, slice: &mut [f32])519 pub fn write_cols_to_slice(self, slice: &mut [f32]) {
520 slice[0] = self.x_axis.x;
521 slice[1] = self.x_axis.y;
522 slice[2] = self.x_axis.z;
523 slice[3] = self.x_axis.w;
524 slice[4] = self.y_axis.x;
525 slice[5] = self.y_axis.y;
526 slice[6] = self.y_axis.z;
527 slice[7] = self.y_axis.w;
528 slice[8] = self.z_axis.x;
529 slice[9] = self.z_axis.y;
530 slice[10] = self.z_axis.z;
531 slice[11] = self.z_axis.w;
532 slice[12] = self.w_axis.x;
533 slice[13] = self.w_axis.y;
534 slice[14] = self.w_axis.z;
535 slice[15] = self.w_axis.w;
536 }
537
538 /// Returns the matrix column for the given `index`.
539 ///
540 /// # Panics
541 ///
542 /// Panics if `index` is greater than 3.
543 #[inline]
544 #[must_use]
col(&self, index: usize) -> Vec4545 pub fn col(&self, index: usize) -> Vec4 {
546 match index {
547 0 => self.x_axis,
548 1 => self.y_axis,
549 2 => self.z_axis,
550 3 => self.w_axis,
551 _ => panic!("index out of bounds"),
552 }
553 }
554
555 /// Returns a mutable reference to the matrix column for the given `index`.
556 ///
557 /// # Panics
558 ///
559 /// Panics if `index` is greater than 3.
560 #[inline]
col_mut(&mut self, index: usize) -> &mut Vec4561 pub fn col_mut(&mut self, index: usize) -> &mut Vec4 {
562 match index {
563 0 => &mut self.x_axis,
564 1 => &mut self.y_axis,
565 2 => &mut self.z_axis,
566 3 => &mut self.w_axis,
567 _ => panic!("index out of bounds"),
568 }
569 }
570
571 /// Returns the matrix row for the given `index`.
572 ///
573 /// # Panics
574 ///
575 /// Panics if `index` is greater than 3.
576 #[inline]
577 #[must_use]
row(&self, index: usize) -> Vec4578 pub fn row(&self, index: usize) -> Vec4 {
579 match index {
580 0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
581 1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
582 2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
583 3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
584 _ => panic!("index out of bounds"),
585 }
586 }
587
588 /// Returns `true` if, and only if, all elements are finite.
589 /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
590 #[inline]
591 #[must_use]
is_finite(&self) -> bool592 pub fn is_finite(&self) -> bool {
593 self.x_axis.is_finite()
594 && self.y_axis.is_finite()
595 && self.z_axis.is_finite()
596 && self.w_axis.is_finite()
597 }
598
599 /// Returns `true` if any elements are `NaN`.
600 #[inline]
601 #[must_use]
is_nan(&self) -> bool602 pub fn is_nan(&self) -> bool {
603 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
604 }
605
606 /// Returns the transpose of `self`.
607 #[inline]
608 #[must_use]
transpose(&self) -> Self609 pub fn transpose(&self) -> Self {
610 // Based on https://github.com/microsoft/DirectXMath `XMMatrixTranspose`
611 let tmp0 = i32x4_shuffle::<0, 1, 4, 5>(self.x_axis.0, self.y_axis.0);
612 let tmp1 = i32x4_shuffle::<2, 3, 6, 7>(self.x_axis.0, self.y_axis.0);
613 let tmp2 = i32x4_shuffle::<0, 1, 4, 5>(self.z_axis.0, self.w_axis.0);
614 let tmp3 = i32x4_shuffle::<2, 3, 6, 7>(self.z_axis.0, self.w_axis.0);
615
616 Self {
617 x_axis: Vec4(i32x4_shuffle::<0, 2, 4, 6>(tmp0, tmp2)),
618 y_axis: Vec4(i32x4_shuffle::<1, 3, 5, 7>(tmp0, tmp2)),
619 z_axis: Vec4(i32x4_shuffle::<0, 2, 4, 6>(tmp1, tmp3)),
620 w_axis: Vec4(i32x4_shuffle::<1, 3, 5, 7>(tmp1, tmp3)),
621 }
622 }
623
624 /// Returns the determinant of `self`.
625 #[must_use]
determinant(&self) -> f32626 pub fn determinant(&self) -> f32 {
627 // Based on https://github.com/g-truc/glm `glm_mat4_determinant`
628 let swp2a = i32x4_shuffle::<2, 1, 1, 0>(self.z_axis.0, self.z_axis.0);
629 let swp3a = i32x4_shuffle::<3, 3, 2, 3>(self.w_axis.0, self.w_axis.0);
630 let swp2b = i32x4_shuffle::<3, 3, 2, 3>(self.z_axis.0, self.z_axis.0);
631 let swp3b = i32x4_shuffle::<2, 1, 1, 0>(self.w_axis.0, self.w_axis.0);
632 let swp2c = i32x4_shuffle::<2, 1, 0, 0>(self.z_axis.0, self.z_axis.0);
633 let swp3c = i32x4_shuffle::<0, 0, 2, 1>(self.w_axis.0, self.w_axis.0);
634
635 let mula = f32x4_mul(swp2a, swp3a);
636 let mulb = f32x4_mul(swp2b, swp3b);
637 let mulc = f32x4_mul(swp2c, swp3c);
638 let sube = f32x4_sub(mula, mulb);
639 let subf = f32x4_sub(i32x4_shuffle::<6, 7, 2, 3>(mulc, mulc), mulc);
640
641 let subfaca = i32x4_shuffle::<0, 0, 1, 2>(sube, sube);
642 let swpfaca = i32x4_shuffle::<1, 0, 0, 0>(self.y_axis.0, self.y_axis.0);
643 let mulfaca = f32x4_mul(swpfaca, subfaca);
644
645 let subtmpb = i32x4_shuffle::<1, 3, 4, 4>(sube, subf);
646 let subfacb = i32x4_shuffle::<0, 1, 1, 3>(subtmpb, subtmpb);
647 let swpfacb = i32x4_shuffle::<2, 2, 1, 1>(self.y_axis.0, self.y_axis.0);
648 let mulfacb = f32x4_mul(swpfacb, subfacb);
649
650 let subres = f32x4_sub(mulfaca, mulfacb);
651 let subtmpc = i32x4_shuffle::<2, 2, 4, 5>(sube, subf);
652 let subfacc = i32x4_shuffle::<0, 2, 3, 3>(subtmpc, subtmpc);
653 let swpfacc = i32x4_shuffle::<3, 3, 3, 2>(self.y_axis.0, self.y_axis.0);
654 let mulfacc = f32x4_mul(swpfacc, subfacc);
655
656 let addres = f32x4_add(subres, mulfacc);
657 let detcof = f32x4_mul(addres, f32x4(1.0, -1.0, 1.0, -1.0));
658
659 dot4(self.x_axis.0, detcof)
660 }
661
662 /// Returns the inverse of `self`.
663 ///
664 /// If the matrix is not invertible the returned matrix will be invalid.
665 ///
666 /// # Panics
667 ///
668 /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
669 #[must_use]
inverse(&self) -> Self670 pub fn inverse(&self) -> Self {
671 // Based on https://github.com/g-truc/glm `glm_mat4_inverse`
672 let fac0 = {
673 let swp0a = i32x4_shuffle::<3, 3, 7, 7>(self.w_axis.0, self.z_axis.0);
674 let swp0b = i32x4_shuffle::<2, 2, 6, 6>(self.w_axis.0, self.z_axis.0);
675
676 let swp00 = i32x4_shuffle::<2, 2, 6, 6>(self.z_axis.0, self.y_axis.0);
677 let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
678 let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
679 let swp03 = i32x4_shuffle::<3, 3, 7, 7>(self.z_axis.0, self.y_axis.0);
680
681 let mul00 = f32x4_mul(swp00, swp01);
682 let mul01 = f32x4_mul(swp02, swp03);
683 f32x4_sub(mul00, mul01)
684 };
685 let fac1 = {
686 let swp0a = i32x4_shuffle::<3, 3, 7, 7>(self.w_axis.0, self.z_axis.0);
687 let swp0b = i32x4_shuffle::<1, 1, 5, 5>(self.w_axis.0, self.z_axis.0);
688
689 let swp00 = i32x4_shuffle::<1, 1, 5, 5>(self.z_axis.0, self.y_axis.0);
690 let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
691 let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
692 let swp03 = i32x4_shuffle::<3, 3, 7, 7>(self.z_axis.0, self.y_axis.0);
693
694 let mul00 = f32x4_mul(swp00, swp01);
695 let mul01 = f32x4_mul(swp02, swp03);
696 f32x4_sub(mul00, mul01)
697 };
698 let fac2 = {
699 let swp0a = i32x4_shuffle::<2, 2, 6, 6>(self.w_axis.0, self.z_axis.0);
700 let swp0b = i32x4_shuffle::<1, 1, 5, 5>(self.w_axis.0, self.z_axis.0);
701
702 let swp00 = i32x4_shuffle::<1, 1, 5, 5>(self.z_axis.0, self.y_axis.0);
703 let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
704 let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
705 let swp03 = i32x4_shuffle::<2, 2, 6, 6>(self.z_axis.0, self.y_axis.0);
706
707 let mul00 = f32x4_mul(swp00, swp01);
708 let mul01 = f32x4_mul(swp02, swp03);
709 f32x4_sub(mul00, mul01)
710 };
711 let fac3 = {
712 let swp0a = i32x4_shuffle::<3, 3, 7, 7>(self.w_axis.0, self.z_axis.0);
713 let swp0b = i32x4_shuffle::<0, 0, 4, 4>(self.w_axis.0, self.z_axis.0);
714
715 let swp00 = i32x4_shuffle::<0, 0, 4, 4>(self.z_axis.0, self.y_axis.0);
716 let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
717 let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
718 let swp03 = i32x4_shuffle::<3, 3, 7, 7>(self.z_axis.0, self.y_axis.0);
719
720 let mul00 = f32x4_mul(swp00, swp01);
721 let mul01 = f32x4_mul(swp02, swp03);
722 f32x4_sub(mul00, mul01)
723 };
724 let fac4 = {
725 let swp0a = i32x4_shuffle::<2, 2, 6, 6>(self.w_axis.0, self.z_axis.0);
726 let swp0b = i32x4_shuffle::<0, 0, 4, 4>(self.w_axis.0, self.z_axis.0);
727
728 let swp00 = i32x4_shuffle::<0, 0, 4, 4>(self.z_axis.0, self.y_axis.0);
729 let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
730 let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
731 let swp03 = i32x4_shuffle::<2, 2, 6, 6>(self.z_axis.0, self.y_axis.0);
732
733 let mul00 = f32x4_mul(swp00, swp01);
734 let mul01 = f32x4_mul(swp02, swp03);
735 f32x4_sub(mul00, mul01)
736 };
737 let fac5 = {
738 let swp0a = i32x4_shuffle::<1, 1, 5, 5>(self.w_axis.0, self.z_axis.0);
739 let swp0b = i32x4_shuffle::<0, 0, 4, 4>(self.w_axis.0, self.z_axis.0);
740
741 let swp00 = i32x4_shuffle::<0, 0, 4, 4>(self.z_axis.0, self.y_axis.0);
742 let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a);
743 let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b);
744 let swp03 = i32x4_shuffle::<1, 1, 5, 5>(self.z_axis.0, self.y_axis.0);
745
746 let mul00 = f32x4_mul(swp00, swp01);
747 let mul01 = f32x4_mul(swp02, swp03);
748 f32x4_sub(mul00, mul01)
749 };
750 let sign_a = f32x4(-1.0, 1.0, -1.0, 1.0);
751 let sign_b = f32x4(1.0, -1.0, 1.0, -1.0);
752
753 let temp0 = i32x4_shuffle::<0, 0, 4, 4>(self.y_axis.0, self.x_axis.0);
754 let vec0 = i32x4_shuffle::<0, 2, 6, 6>(temp0, temp0);
755
756 let temp1 = i32x4_shuffle::<1, 1, 5, 5>(self.y_axis.0, self.x_axis.0);
757 let vec1 = i32x4_shuffle::<0, 2, 6, 6>(temp1, temp1);
758
759 let temp2 = i32x4_shuffle::<2, 2, 6, 6>(self.y_axis.0, self.x_axis.0);
760 let vec2 = i32x4_shuffle::<0, 2, 6, 6>(temp2, temp2);
761
762 let temp3 = i32x4_shuffle::<3, 3, 7, 7>(self.y_axis.0, self.x_axis.0);
763 let vec3 = i32x4_shuffle::<0, 2, 6, 6>(temp3, temp3);
764
765 let mul00 = f32x4_mul(vec1, fac0);
766 let mul01 = f32x4_mul(vec2, fac1);
767 let mul02 = f32x4_mul(vec3, fac2);
768 let sub00 = f32x4_sub(mul00, mul01);
769 let add00 = f32x4_add(sub00, mul02);
770 let inv0 = f32x4_mul(sign_b, add00);
771
772 let mul03 = f32x4_mul(vec0, fac0);
773 let mul04 = f32x4_mul(vec2, fac3);
774 let mul05 = f32x4_mul(vec3, fac4);
775 let sub01 = f32x4_sub(mul03, mul04);
776 let add01 = f32x4_add(sub01, mul05);
777 let inv1 = f32x4_mul(sign_a, add01);
778
779 let mul06 = f32x4_mul(vec0, fac1);
780 let mul07 = f32x4_mul(vec1, fac3);
781 let mul08 = f32x4_mul(vec3, fac5);
782 let sub02 = f32x4_sub(mul06, mul07);
783 let add02 = f32x4_add(sub02, mul08);
784 let inv2 = f32x4_mul(sign_b, add02);
785
786 let mul09 = f32x4_mul(vec0, fac2);
787 let mul10 = f32x4_mul(vec1, fac4);
788 let mul11 = f32x4_mul(vec2, fac5);
789 let sub03 = f32x4_sub(mul09, mul10);
790 let add03 = f32x4_add(sub03, mul11);
791 let inv3 = f32x4_mul(sign_a, add03);
792
793 let row0 = i32x4_shuffle::<0, 0, 4, 4>(inv0, inv1);
794 let row1 = i32x4_shuffle::<0, 0, 4, 4>(inv2, inv3);
795 let row2 = i32x4_shuffle::<0, 2, 4, 6>(row0, row1);
796
797 let dot0 = dot4(self.x_axis.0, row2);
798 glam_assert!(dot0 != 0.0);
799
800 let rcp0 = f32x4_splat(dot0.recip());
801
802 Self {
803 x_axis: Vec4(f32x4_mul(inv0, rcp0)),
804 y_axis: Vec4(f32x4_mul(inv1, rcp0)),
805 z_axis: Vec4(f32x4_mul(inv2, rcp0)),
806 w_axis: Vec4(f32x4_mul(inv3, rcp0)),
807 }
808 }
809
810 /// Creates a left-handed view matrix using a camera position, a facing direction and an up
811 /// direction
812 ///
813 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
814 ///
815 /// # Panics
816 ///
817 /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled.
818 #[inline]
819 #[must_use]
look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self820 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
821 Self::look_to_rh(eye, -dir, up)
822 }
823
824 /// Creates a right-handed view matrix using a camera position, a facing direction, and an up
825 /// direction.
826 ///
827 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
828 ///
829 /// # Panics
830 ///
831 /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled.
832 #[inline]
833 #[must_use]
look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self834 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
835 glam_assert!(dir.is_normalized());
836 glam_assert!(up.is_normalized());
837 let f = dir;
838 let s = f.cross(up).normalize();
839 let u = s.cross(f);
840
841 Self::from_cols(
842 Vec4::new(s.x, u.x, -f.x, 0.0),
843 Vec4::new(s.y, u.y, -f.y, 0.0),
844 Vec4::new(s.z, u.z, -f.z, 0.0),
845 Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
846 )
847 }
848
849 /// Creates a left-handed view matrix using a camera position, a focal points and an up
850 /// direction.
851 ///
852 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
853 ///
854 /// # Panics
855 ///
856 /// Will panic if `up` is not normalized when `glam_assert` is enabled.
857 #[inline]
858 #[must_use]
look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self859 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
860 Self::look_to_lh(eye, center.sub(eye).normalize(), up)
861 }
862
863 /// Creates a right-handed view matrix using a camera position, a focal point, and an up
864 /// direction.
865 ///
866 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
867 ///
868 /// # Panics
869 ///
870 /// Will panic if `up` is not normalized when `glam_assert` is enabled.
871 #[inline]
look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self872 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
873 Self::look_to_rh(eye, center.sub(eye).normalize(), up)
874 }
875
876 /// Creates a right-handed perspective projection matrix with `[-1,1]` depth range.
877 ///
878 /// Useful to map the standard right-handed coordinate system into what OpenGL expects.
879 ///
880 /// This is the same as the OpenGL `gluPerspective` function.
881 /// See <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml>
882 #[inline]
883 #[must_use]
perspective_rh_gl( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32, ) -> Self884 pub fn perspective_rh_gl(
885 fov_y_radians: f32,
886 aspect_ratio: f32,
887 z_near: f32,
888 z_far: f32,
889 ) -> Self {
890 let inv_length = 1.0 / (z_near - z_far);
891 let f = 1.0 / math::tan(0.5 * fov_y_radians);
892 let a = f / aspect_ratio;
893 let b = (z_near + z_far) * inv_length;
894 let c = (2.0 * z_near * z_far) * inv_length;
895 Self::from_cols(
896 Vec4::new(a, 0.0, 0.0, 0.0),
897 Vec4::new(0.0, f, 0.0, 0.0),
898 Vec4::new(0.0, 0.0, b, -1.0),
899 Vec4::new(0.0, 0.0, c, 0.0),
900 )
901 }
902
903 /// Creates a left-handed perspective projection matrix with `[0,1]` depth range.
904 ///
905 /// Useful to map the standard left-handed coordinate system into what WebGPU/Metal/Direct3D expect.
906 ///
907 /// # Panics
908 ///
909 /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
910 /// enabled.
911 #[inline]
912 #[must_use]
perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self913 pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
914 glam_assert!(z_near > 0.0 && z_far > 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 let r = z_far / (z_far - z_near);
919 Self::from_cols(
920 Vec4::new(w, 0.0, 0.0, 0.0),
921 Vec4::new(0.0, h, 0.0, 0.0),
922 Vec4::new(0.0, 0.0, r, 1.0),
923 Vec4::new(0.0, 0.0, -r * z_near, 0.0),
924 )
925 }
926
927 /// Creates a right-handed perspective projection matrix with `[0,1]` depth range.
928 ///
929 /// Useful to map the standard right-handed coordinate system into what WebGPU/Metal/Direct3D expect.
930 ///
931 /// # Panics
932 ///
933 /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
934 /// enabled.
935 #[inline]
936 #[must_use]
perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self937 pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
938 glam_assert!(z_near > 0.0 && z_far > 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 let r = z_far / (z_near - z_far);
943 Self::from_cols(
944 Vec4::new(w, 0.0, 0.0, 0.0),
945 Vec4::new(0.0, h, 0.0, 0.0),
946 Vec4::new(0.0, 0.0, r, -1.0),
947 Vec4::new(0.0, 0.0, r * z_near, 0.0),
948 )
949 }
950
951 /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range.
952 ///
953 /// Like `perspective_lh`, but with an infinite value for `z_far`.
954 /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`.
955 ///
956 /// # Panics
957 ///
958 /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
959 /// enabled.
960 #[inline]
961 #[must_use]
perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self962 pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
963 glam_assert!(z_near > 0.0);
964 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
965 let h = cos_fov / sin_fov;
966 let w = h / aspect_ratio;
967 Self::from_cols(
968 Vec4::new(w, 0.0, 0.0, 0.0),
969 Vec4::new(0.0, h, 0.0, 0.0),
970 Vec4::new(0.0, 0.0, 1.0, 1.0),
971 Vec4::new(0.0, 0.0, -z_near, 0.0),
972 )
973 }
974
975 /// Creates an infinite reverse left-handed perspective projection matrix with `[0,1]` depth range.
976 ///
977 /// Similar to `perspective_infinite_lh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`.
978 ///
979 /// # Panics
980 ///
981 /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
982 #[inline]
983 #[must_use]
perspective_infinite_reverse_lh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self984 pub fn perspective_infinite_reverse_lh(
985 fov_y_radians: f32,
986 aspect_ratio: f32,
987 z_near: f32,
988 ) -> Self {
989 glam_assert!(z_near > 0.0);
990 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
991 let h = cos_fov / sin_fov;
992 let w = h / aspect_ratio;
993 Self::from_cols(
994 Vec4::new(w, 0.0, 0.0, 0.0),
995 Vec4::new(0.0, h, 0.0, 0.0),
996 Vec4::new(0.0, 0.0, 0.0, 1.0),
997 Vec4::new(0.0, 0.0, z_near, 0.0),
998 )
999 }
1000
1001 /// Creates an infinite right-handed perspective projection matrix with `[0,1]` depth range.
1002 ///
1003 /// Like `perspective_rh`, but with an infinite value for `z_far`.
1004 /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`.
1005 ///
1006 /// # Panics
1007 ///
1008 /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
1009 /// enabled.
1010 #[inline]
1011 #[must_use]
perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self1012 pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
1013 glam_assert!(z_near > 0.0);
1014 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1015 Self::from_cols(
1016 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1017 Vec4::new(0.0, f, 0.0, 0.0),
1018 Vec4::new(0.0, 0.0, -1.0, -1.0),
1019 Vec4::new(0.0, 0.0, -z_near, 0.0),
1020 )
1021 }
1022
1023 /// Creates an infinite reverse right-handed perspective projection matrix with `[0,1]` depth range.
1024 ///
1025 /// Similar to `perspective_infinite_rh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`.
1026 ///
1027 /// # Panics
1028 ///
1029 /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
1030 #[inline]
1031 #[must_use]
perspective_infinite_reverse_rh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self1032 pub fn perspective_infinite_reverse_rh(
1033 fov_y_radians: f32,
1034 aspect_ratio: f32,
1035 z_near: f32,
1036 ) -> Self {
1037 glam_assert!(z_near > 0.0);
1038 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1039 Self::from_cols(
1040 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1041 Vec4::new(0.0, f, 0.0, 0.0),
1042 Vec4::new(0.0, 0.0, 0.0, -1.0),
1043 Vec4::new(0.0, 0.0, z_near, 0.0),
1044 )
1045 }
1046
1047 /// Creates a right-handed orthographic projection matrix with `[-1,1]` depth
1048 /// range. This is the same as the OpenGL `glOrtho` function in OpenGL.
1049 /// See
1050 /// <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml>
1051 ///
1052 /// Useful to map a right-handed coordinate system to the normalized device coordinates that OpenGL expects.
1053 #[inline]
1054 #[must_use]
orthographic_rh_gl( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self1055 pub fn orthographic_rh_gl(
1056 left: f32,
1057 right: f32,
1058 bottom: f32,
1059 top: f32,
1060 near: f32,
1061 far: f32,
1062 ) -> Self {
1063 let a = 2.0 / (right - left);
1064 let b = 2.0 / (top - bottom);
1065 let c = -2.0 / (far - near);
1066 let tx = -(right + left) / (right - left);
1067 let ty = -(top + bottom) / (top - bottom);
1068 let tz = -(far + near) / (far - near);
1069
1070 Self::from_cols(
1071 Vec4::new(a, 0.0, 0.0, 0.0),
1072 Vec4::new(0.0, b, 0.0, 0.0),
1073 Vec4::new(0.0, 0.0, c, 0.0),
1074 Vec4::new(tx, ty, tz, 1.0),
1075 )
1076 }
1077
1078 /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range.
1079 ///
1080 /// Useful to map a left-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect.
1081 #[inline]
1082 #[must_use]
orthographic_lh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self1083 pub fn orthographic_lh(
1084 left: f32,
1085 right: f32,
1086 bottom: f32,
1087 top: f32,
1088 near: f32,
1089 far: f32,
1090 ) -> Self {
1091 let rcp_width = 1.0 / (right - left);
1092 let rcp_height = 1.0 / (top - bottom);
1093 let r = 1.0 / (far - near);
1094 Self::from_cols(
1095 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1096 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1097 Vec4::new(0.0, 0.0, r, 0.0),
1098 Vec4::new(
1099 -(left + right) * rcp_width,
1100 -(top + bottom) * rcp_height,
1101 -r * near,
1102 1.0,
1103 ),
1104 )
1105 }
1106
1107 /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range.
1108 ///
1109 /// Useful to map a right-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect.
1110 #[inline]
1111 #[must_use]
orthographic_rh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self1112 pub fn orthographic_rh(
1113 left: f32,
1114 right: f32,
1115 bottom: f32,
1116 top: f32,
1117 near: f32,
1118 far: f32,
1119 ) -> Self {
1120 let rcp_width = 1.0 / (right - left);
1121 let rcp_height = 1.0 / (top - bottom);
1122 let r = 1.0 / (near - far);
1123 Self::from_cols(
1124 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1125 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1126 Vec4::new(0.0, 0.0, r, 0.0),
1127 Vec4::new(
1128 -(left + right) * rcp_width,
1129 -(top + bottom) * rcp_height,
1130 r * near,
1131 1.0,
1132 ),
1133 )
1134 }
1135
1136 /// Transforms the given 3D vector as a point, applying perspective correction.
1137 ///
1138 /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is `1.0`.
1139 /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
1140 ///
1141 /// This method assumes that `self` contains a projective transform.
1142 #[inline]
1143 #[must_use]
project_point3(&self, rhs: Vec3) -> Vec31144 pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
1145 let mut res = self.x_axis.mul(rhs.x);
1146 res = self.y_axis.mul(rhs.y).add(res);
1147 res = self.z_axis.mul(rhs.z).add(res);
1148 res = self.w_axis.add(res);
1149 res = res.div(res.w);
1150 res.xyz()
1151 }
1152
1153 /// Transforms the given 3D vector as a point.
1154 ///
1155 /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
1156 /// `1.0`.
1157 ///
1158 /// This method assumes that `self` contains a valid affine transform. It does not perform
1159 /// a perspective divide, if `self` contains a perspective transform, or if you are unsure,
1160 /// the [`Self::project_point3()`] method should be used instead.
1161 ///
1162 /// # Panics
1163 ///
1164 /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1165 #[inline]
1166 #[must_use]
transform_point3(&self, rhs: Vec3) -> Vec31167 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1168 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1169 let mut res = self.x_axis.mul(rhs.x);
1170 res = self.y_axis.mul(rhs.y).add(res);
1171 res = self.z_axis.mul(rhs.z).add(res);
1172 res = self.w_axis.add(res);
1173 res.xyz()
1174 }
1175
1176 /// Transforms the give 3D vector as a direction.
1177 ///
1178 /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
1179 /// `0.0`.
1180 ///
1181 /// This method assumes that `self` contains a valid affine transform.
1182 ///
1183 /// # Panics
1184 ///
1185 /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1186 #[inline]
1187 #[must_use]
transform_vector3(&self, rhs: Vec3) -> Vec31188 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1189 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1190 let mut res = self.x_axis.mul(rhs.x);
1191 res = self.y_axis.mul(rhs.y).add(res);
1192 res = self.z_axis.mul(rhs.z).add(res);
1193 res.xyz()
1194 }
1195
1196 /// Transforms the given [`Vec3A`] as a 3D point, applying perspective correction.
1197 ///
1198 /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
1199 /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
1200 ///
1201 /// This method assumes that `self` contains a projective transform.
1202 #[inline]
1203 #[must_use]
project_point3a(&self, rhs: Vec3A) -> Vec3A1204 pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
1205 let mut res = self.x_axis.mul(rhs.xxxx());
1206 res = self.y_axis.mul(rhs.yyyy()).add(res);
1207 res = self.z_axis.mul(rhs.zzzz()).add(res);
1208 res = self.w_axis.add(res);
1209 res = res.div(res.wwww());
1210 Vec3A::from_vec4(res)
1211 }
1212
1213 /// Transforms the given [`Vec3A`] as 3D point.
1214 ///
1215 /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
1216 #[inline]
1217 #[must_use]
transform_point3a(&self, rhs: Vec3A) -> Vec3A1218 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1219 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1220 let mut res = self.x_axis.mul(rhs.xxxx());
1221 res = self.y_axis.mul(rhs.yyyy()).add(res);
1222 res = self.z_axis.mul(rhs.zzzz()).add(res);
1223 res = self.w_axis.add(res);
1224 Vec3A::from_vec4(res)
1225 }
1226
1227 /// Transforms the give [`Vec3A`] as 3D vector.
1228 ///
1229 /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `0.0`.
1230 #[inline]
1231 #[must_use]
transform_vector3a(&self, rhs: Vec3A) -> Vec3A1232 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1233 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1234 let mut res = self.x_axis.mul(rhs.xxxx());
1235 res = self.y_axis.mul(rhs.yyyy()).add(res);
1236 res = self.z_axis.mul(rhs.zzzz()).add(res);
1237 Vec3A::from_vec4(res)
1238 }
1239
1240 /// Transforms a 4D vector.
1241 #[inline]
1242 #[must_use]
mul_vec4(&self, rhs: Vec4) -> Vec41243 pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1244 let mut res = self.x_axis.mul(rhs.xxxx());
1245 res = res.add(self.y_axis.mul(rhs.yyyy()));
1246 res = res.add(self.z_axis.mul(rhs.zzzz()));
1247 res = res.add(self.w_axis.mul(rhs.wwww()));
1248 res
1249 }
1250
1251 /// Multiplies two 4x4 matrices.
1252 #[inline]
1253 #[must_use]
mul_mat4(&self, rhs: &Self) -> Self1254 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1255 Self::from_cols(
1256 self.mul(rhs.x_axis),
1257 self.mul(rhs.y_axis),
1258 self.mul(rhs.z_axis),
1259 self.mul(rhs.w_axis),
1260 )
1261 }
1262
1263 /// Adds two 4x4 matrices.
1264 #[inline]
1265 #[must_use]
add_mat4(&self, rhs: &Self) -> Self1266 pub fn add_mat4(&self, rhs: &Self) -> Self {
1267 Self::from_cols(
1268 self.x_axis.add(rhs.x_axis),
1269 self.y_axis.add(rhs.y_axis),
1270 self.z_axis.add(rhs.z_axis),
1271 self.w_axis.add(rhs.w_axis),
1272 )
1273 }
1274
1275 /// Subtracts two 4x4 matrices.
1276 #[inline]
1277 #[must_use]
sub_mat4(&self, rhs: &Self) -> Self1278 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1279 Self::from_cols(
1280 self.x_axis.sub(rhs.x_axis),
1281 self.y_axis.sub(rhs.y_axis),
1282 self.z_axis.sub(rhs.z_axis),
1283 self.w_axis.sub(rhs.w_axis),
1284 )
1285 }
1286
1287 /// Multiplies a 4x4 matrix by a scalar.
1288 #[inline]
1289 #[must_use]
mul_scalar(&self, rhs: f32) -> Self1290 pub fn mul_scalar(&self, rhs: f32) -> Self {
1291 Self::from_cols(
1292 self.x_axis.mul(rhs),
1293 self.y_axis.mul(rhs),
1294 self.z_axis.mul(rhs),
1295 self.w_axis.mul(rhs),
1296 )
1297 }
1298
1299 /// Divides a 4x4 matrix by a scalar.
1300 #[inline]
1301 #[must_use]
div_scalar(&self, rhs: f32) -> Self1302 pub fn div_scalar(&self, rhs: f32) -> Self {
1303 let rhs = Vec4::splat(rhs);
1304 Self::from_cols(
1305 self.x_axis.div(rhs),
1306 self.y_axis.div(rhs),
1307 self.z_axis.div(rhs),
1308 self.w_axis.div(rhs),
1309 )
1310 }
1311
1312 /// Returns true if the absolute difference of all elements between `self` and `rhs`
1313 /// is less than or equal to `max_abs_diff`.
1314 ///
1315 /// This can be used to compare if two matrices contain similar elements. It works best
1316 /// when comparing with a known value. The `max_abs_diff` that should be used used
1317 /// depends on the values being compared against.
1318 ///
1319 /// For more see
1320 /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
1321 #[inline]
1322 #[must_use]
abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool1323 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1324 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1325 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1326 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1327 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1328 }
1329
1330 /// Takes the absolute value of each element in `self`
1331 #[inline]
1332 #[must_use]
abs(&self) -> Self1333 pub fn abs(&self) -> Self {
1334 Self::from_cols(
1335 self.x_axis.abs(),
1336 self.y_axis.abs(),
1337 self.z_axis.abs(),
1338 self.w_axis.abs(),
1339 )
1340 }
1341
1342 #[inline]
as_dmat4(&self) -> DMat41343 pub fn as_dmat4(&self) -> DMat4 {
1344 DMat4::from_cols(
1345 self.x_axis.as_dvec4(),
1346 self.y_axis.as_dvec4(),
1347 self.z_axis.as_dvec4(),
1348 self.w_axis.as_dvec4(),
1349 )
1350 }
1351 }
1352
1353 impl Default for Mat4 {
1354 #[inline]
default() -> Self1355 fn default() -> Self {
1356 Self::IDENTITY
1357 }
1358 }
1359
1360 impl Add<Mat4> for Mat4 {
1361 type Output = Self;
1362 #[inline]
add(self, rhs: Self) -> Self::Output1363 fn add(self, rhs: Self) -> Self::Output {
1364 self.add_mat4(&rhs)
1365 }
1366 }
1367
1368 impl AddAssign<Mat4> for Mat4 {
1369 #[inline]
add_assign(&mut self, rhs: Self)1370 fn add_assign(&mut self, rhs: Self) {
1371 *self = self.add_mat4(&rhs);
1372 }
1373 }
1374
1375 impl Sub<Mat4> for Mat4 {
1376 type Output = Self;
1377 #[inline]
sub(self, rhs: Self) -> Self::Output1378 fn sub(self, rhs: Self) -> Self::Output {
1379 self.sub_mat4(&rhs)
1380 }
1381 }
1382
1383 impl SubAssign<Mat4> for Mat4 {
1384 #[inline]
sub_assign(&mut self, rhs: Self)1385 fn sub_assign(&mut self, rhs: Self) {
1386 *self = self.sub_mat4(&rhs);
1387 }
1388 }
1389
1390 impl Neg for Mat4 {
1391 type Output = Self;
1392 #[inline]
neg(self) -> Self::Output1393 fn neg(self) -> Self::Output {
1394 Self::from_cols(
1395 self.x_axis.neg(),
1396 self.y_axis.neg(),
1397 self.z_axis.neg(),
1398 self.w_axis.neg(),
1399 )
1400 }
1401 }
1402
1403 impl Mul<Mat4> for Mat4 {
1404 type Output = Self;
1405 #[inline]
mul(self, rhs: Self) -> Self::Output1406 fn mul(self, rhs: Self) -> Self::Output {
1407 self.mul_mat4(&rhs)
1408 }
1409 }
1410
1411 impl MulAssign<Mat4> for Mat4 {
1412 #[inline]
mul_assign(&mut self, rhs: Self)1413 fn mul_assign(&mut self, rhs: Self) {
1414 *self = self.mul_mat4(&rhs);
1415 }
1416 }
1417
1418 impl Mul<Vec4> for Mat4 {
1419 type Output = Vec4;
1420 #[inline]
mul(self, rhs: Vec4) -> Self::Output1421 fn mul(self, rhs: Vec4) -> Self::Output {
1422 self.mul_vec4(rhs)
1423 }
1424 }
1425
1426 impl Mul<Mat4> for f32 {
1427 type Output = Mat4;
1428 #[inline]
mul(self, rhs: Mat4) -> Self::Output1429 fn mul(self, rhs: Mat4) -> Self::Output {
1430 rhs.mul_scalar(self)
1431 }
1432 }
1433
1434 impl Mul<f32> for Mat4 {
1435 type Output = Self;
1436 #[inline]
mul(self, rhs: f32) -> Self::Output1437 fn mul(self, rhs: f32) -> Self::Output {
1438 self.mul_scalar(rhs)
1439 }
1440 }
1441
1442 impl MulAssign<f32> for Mat4 {
1443 #[inline]
mul_assign(&mut self, rhs: f32)1444 fn mul_assign(&mut self, rhs: f32) {
1445 *self = self.mul_scalar(rhs);
1446 }
1447 }
1448
1449 impl Div<Mat4> for f32 {
1450 type Output = Mat4;
1451 #[inline]
div(self, rhs: Mat4) -> Self::Output1452 fn div(self, rhs: Mat4) -> Self::Output {
1453 rhs.div_scalar(self)
1454 }
1455 }
1456
1457 impl Div<f32> for Mat4 {
1458 type Output = Self;
1459 #[inline]
div(self, rhs: f32) -> Self::Output1460 fn div(self, rhs: f32) -> Self::Output {
1461 self.div_scalar(rhs)
1462 }
1463 }
1464
1465 impl DivAssign<f32> for Mat4 {
1466 #[inline]
div_assign(&mut self, rhs: f32)1467 fn div_assign(&mut self, rhs: f32) {
1468 *self = self.div_scalar(rhs);
1469 }
1470 }
1471
1472 impl Sum<Self> for Mat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,1473 fn sum<I>(iter: I) -> Self
1474 where
1475 I: Iterator<Item = Self>,
1476 {
1477 iter.fold(Self::ZERO, Self::add)
1478 }
1479 }
1480
1481 impl<'a> Sum<&'a Self> for Mat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,1482 fn sum<I>(iter: I) -> Self
1483 where
1484 I: Iterator<Item = &'a Self>,
1485 {
1486 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1487 }
1488 }
1489
1490 impl Product for Mat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,1491 fn product<I>(iter: I) -> Self
1492 where
1493 I: Iterator<Item = Self>,
1494 {
1495 iter.fold(Self::IDENTITY, Self::mul)
1496 }
1497 }
1498
1499 impl<'a> Product<&'a Self> for Mat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,1500 fn product<I>(iter: I) -> Self
1501 where
1502 I: Iterator<Item = &'a Self>,
1503 {
1504 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1505 }
1506 }
1507
1508 impl PartialEq for Mat4 {
1509 #[inline]
eq(&self, rhs: &Self) -> bool1510 fn eq(&self, rhs: &Self) -> bool {
1511 self.x_axis.eq(&rhs.x_axis)
1512 && self.y_axis.eq(&rhs.y_axis)
1513 && self.z_axis.eq(&rhs.z_axis)
1514 && self.w_axis.eq(&rhs.w_axis)
1515 }
1516 }
1517
1518 #[cfg(not(target_arch = "spirv"))]
1519 impl AsRef<[f32; 16]> for Mat4 {
1520 #[inline]
as_ref(&self) -> &[f32; 16]1521 fn as_ref(&self) -> &[f32; 16] {
1522 unsafe { &*(self as *const Self as *const [f32; 16]) }
1523 }
1524 }
1525
1526 #[cfg(not(target_arch = "spirv"))]
1527 impl AsMut<[f32; 16]> for Mat4 {
1528 #[inline]
as_mut(&mut self) -> &mut [f32; 16]1529 fn as_mut(&mut self) -> &mut [f32; 16] {
1530 unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
1531 }
1532 }
1533
1534 impl fmt::Debug for Mat4 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result1535 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1536 fmt.debug_struct(stringify!(Mat4))
1537 .field("x_axis", &self.x_axis)
1538 .field("y_axis", &self.y_axis)
1539 .field("z_axis", &self.z_axis)
1540 .field("w_axis", &self.w_axis)
1541 .finish()
1542 }
1543 }
1544
1545 impl fmt::Display for Mat4 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1546 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1547 if let Some(p) = f.precision() {
1548 write!(
1549 f,
1550 "[{:.*}, {:.*}, {:.*}, {:.*}]",
1551 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
1552 )
1553 } else {
1554 write!(
1555 f,
1556 "[{}, {}, {}, {}]",
1557 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1558 )
1559 }
1560 }
1561 }
1562