1 // Generated from mat.rs.tera template. Edit the template, not the generated file.
2
3 use crate::{f32::math, swizzles::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4};
4 #[cfg(not(target_arch = "spirv"))]
5 use core::fmt;
6 use core::iter::{Product, Sum};
7 use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
8
9 /// Creates a 4x4 matrix from four column vectors.
10 #[inline(always)]
11 #[must_use]
mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat412 pub const fn mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat4 {
13 Mat4::from_cols(x_axis, y_axis, z_axis, w_axis)
14 }
15
16 /// A 4x4 column major matrix.
17 ///
18 /// This 4x4 matrix type features convenience methods for creating and using affine transforms and
19 /// perspective projections. If you are primarily dealing with 3D affine transformations
20 /// considering using [`Affine3A`](crate::Affine3A) which is faster than a 4x4 matrix
21 /// for some affine operations.
22 ///
23 /// Affine transformations including 3D translation, rotation and scale can be created
24 /// using methods such as [`Self::from_translation()`], [`Self::from_quat()`],
25 /// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`].
26 ///
27 /// Orthographic projections can be created using the methods [`Self::orthographic_lh()`] for
28 /// left-handed coordinate systems and [`Self::orthographic_rh()`] for right-handed
29 /// systems. The resulting matrix is also an affine transformation.
30 ///
31 /// The [`Self::transform_point3()`] and [`Self::transform_vector3()`] convenience methods
32 /// are provided for performing affine transformations on 3D vectors and points. These
33 /// multiply 3D inputs as 4D vectors with an implicit `w` value of `1` for points and `0`
34 /// for vectors respectively. These methods assume that `Self` contains a valid affine
35 /// transform.
36 ///
37 /// Perspective projections can be created using methods such as
38 /// [`Self::perspective_lh()`], [`Self::perspective_infinite_lh()`] and
39 /// [`Self::perspective_infinite_reverse_lh()`] for left-handed co-ordinate systems and
40 /// [`Self::perspective_rh()`], [`Self::perspective_infinite_rh()`] and
41 /// [`Self::perspective_infinite_reverse_rh()`] for right-handed co-ordinate systems.
42 ///
43 /// The resulting perspective project can be use to transform 3D vectors as points with
44 /// perspective correction using the [`Self::project_point3()`] convenience method.
45 #[derive(Clone, Copy)]
46 #[cfg_attr(
47 any(
48 not(any(feature = "scalar-math", target_arch = "spirv")),
49 feature = "cuda"
50 ),
51 repr(align(16))
52 )]
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 [
130 self.x_axis.x,
131 self.x_axis.y,
132 self.x_axis.z,
133 self.x_axis.w,
134 self.y_axis.x,
135 self.y_axis.y,
136 self.y_axis.z,
137 self.y_axis.w,
138 self.z_axis.x,
139 self.z_axis.y,
140 self.z_axis.z,
141 self.z_axis.w,
142 self.w_axis.x,
143 self.w_axis.y,
144 self.w_axis.z,
145 self.w_axis.w,
146 ]
147 }
148
149 /// Creates a 4x4 matrix from a `[[f32; 4]; 4]` 4D array stored in column major order.
150 /// If your data is in row major order you will need to `transpose` the returned
151 /// matrix.
152 #[inline]
153 #[must_use]
from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self154 pub const fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self {
155 Self::from_cols(
156 Vec4::from_array(m[0]),
157 Vec4::from_array(m[1]),
158 Vec4::from_array(m[2]),
159 Vec4::from_array(m[3]),
160 )
161 }
162
163 /// Creates a `[[f32; 4]; 4]` 4D array storing data in column major order.
164 /// If you require data in row major order `transpose` the matrix first.
165 #[inline]
166 #[must_use]
to_cols_array_2d(&self) -> [[f32; 4]; 4]167 pub const fn to_cols_array_2d(&self) -> [[f32; 4]; 4] {
168 [
169 self.x_axis.to_array(),
170 self.y_axis.to_array(),
171 self.z_axis.to_array(),
172 self.w_axis.to_array(),
173 ]
174 }
175
176 /// Creates a 4x4 matrix with its diagonal set to `diagonal` and all other entries set to 0.
177 #[doc(alias = "scale")]
178 #[inline]
179 #[must_use]
from_diagonal(diagonal: Vec4) -> Self180 pub const fn from_diagonal(diagonal: Vec4) -> Self {
181 Self::new(
182 diagonal.x, 0.0, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, 0.0, diagonal.z, 0.0, 0.0,
183 0.0, 0.0, diagonal.w,
184 )
185 }
186
187 #[inline]
188 #[must_use]
quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4)189 fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) {
190 glam_assert!(rotation.is_normalized());
191
192 let (x, y, z, w) = rotation.into();
193 let x2 = x + x;
194 let y2 = y + y;
195 let z2 = z + z;
196 let xx = x * x2;
197 let xy = x * y2;
198 let xz = x * z2;
199 let yy = y * y2;
200 let yz = y * z2;
201 let zz = z * z2;
202 let wx = w * x2;
203 let wy = w * y2;
204 let wz = w * z2;
205
206 let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
207 let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
208 let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
209 (x_axis, y_axis, z_axis)
210 }
211
212 /// Creates an affine transformation matrix from the given 3D `scale`, `rotation` and
213 /// `translation`.
214 ///
215 /// The resulting matrix can be used to transform 3D points and vectors. See
216 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
217 ///
218 /// # Panics
219 ///
220 /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
221 #[inline]
222 #[must_use]
from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self223 pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
224 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
225 Self::from_cols(
226 x_axis.mul(scale.x),
227 y_axis.mul(scale.y),
228 z_axis.mul(scale.z),
229 Vec4::from((translation, 1.0)),
230 )
231 }
232
233 /// Creates an affine transformation matrix from the given 3D `translation`.
234 ///
235 /// The resulting matrix can be used to transform 3D points and vectors. See
236 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
237 ///
238 /// # Panics
239 ///
240 /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
241 #[inline]
242 #[must_use]
from_rotation_translation(rotation: Quat, translation: Vec3) -> Self243 pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
244 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
245 Self::from_cols(x_axis, y_axis, z_axis, Vec4::from((translation, 1.0)))
246 }
247
248 /// Extracts `scale`, `rotation` and `translation` from `self`. The input matrix is
249 /// expected to be a 3D affine transformation matrix otherwise the output will be invalid.
250 ///
251 /// # Panics
252 ///
253 /// Will panic if the determinant of `self` is zero or if the resulting scale vector
254 /// contains any zero elements when `glam_assert` is enabled.
255 #[inline]
256 #[must_use]
to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3)257 pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
258 let det = self.determinant();
259 glam_assert!(det != 0.0);
260
261 let scale = Vec3::new(
262 self.x_axis.length() * math::signum(det),
263 self.y_axis.length(),
264 self.z_axis.length(),
265 );
266
267 glam_assert!(scale.cmpne(Vec3::ZERO).all());
268
269 let inv_scale = scale.recip();
270
271 let rotation = Quat::from_rotation_axes(
272 self.x_axis.mul(inv_scale.x).xyz(),
273 self.y_axis.mul(inv_scale.y).xyz(),
274 self.z_axis.mul(inv_scale.z).xyz(),
275 );
276
277 let translation = self.w_axis.xyz();
278
279 (scale, rotation, translation)
280 }
281
282 /// Creates an affine transformation matrix from the given `rotation` quaternion.
283 ///
284 /// The resulting matrix can be used to transform 3D points and vectors. See
285 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
286 ///
287 /// # Panics
288 ///
289 /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
290 #[inline]
291 #[must_use]
from_quat(rotation: Quat) -> Self292 pub fn from_quat(rotation: Quat) -> Self {
293 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
294 Self::from_cols(x_axis, y_axis, z_axis, Vec4::W)
295 }
296
297 /// Creates an affine transformation matrix from the given 3x3 linear transformation
298 /// matrix.
299 ///
300 /// The resulting matrix can be used to transform 3D points and vectors. See
301 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
302 #[inline]
303 #[must_use]
from_mat3(m: Mat3) -> Self304 pub fn from_mat3(m: Mat3) -> Self {
305 Self::from_cols(
306 Vec4::from((m.x_axis, 0.0)),
307 Vec4::from((m.y_axis, 0.0)),
308 Vec4::from((m.z_axis, 0.0)),
309 Vec4::W,
310 )
311 }
312
313 /// Creates an affine transformation matrix from the given 3x3 linear transformation
314 /// matrix.
315 ///
316 /// The resulting matrix can be used to transform 3D points and vectors. See
317 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
318 #[inline]
319 #[must_use]
from_mat3a(m: Mat3A) -> Self320 pub fn from_mat3a(m: Mat3A) -> Self {
321 Self::from_cols(
322 Vec4::from((m.x_axis, 0.0)),
323 Vec4::from((m.y_axis, 0.0)),
324 Vec4::from((m.z_axis, 0.0)),
325 Vec4::W,
326 )
327 }
328
329 /// Creates an affine transformation matrix from the given 3D `translation`.
330 ///
331 /// The resulting matrix can be used to transform 3D points and vectors. See
332 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
333 #[inline]
334 #[must_use]
from_translation(translation: Vec3) -> Self335 pub fn from_translation(translation: Vec3) -> Self {
336 Self::from_cols(
337 Vec4::X,
338 Vec4::Y,
339 Vec4::Z,
340 Vec4::new(translation.x, translation.y, translation.z, 1.0),
341 )
342 }
343
344 /// Creates an affine transformation matrix containing a 3D rotation around a normalized
345 /// rotation `axis` of `angle` (in radians).
346 ///
347 /// The resulting matrix can be used to transform 3D points and vectors. See
348 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
349 ///
350 /// # Panics
351 ///
352 /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
353 #[inline]
354 #[must_use]
from_axis_angle(axis: Vec3, angle: f32) -> Self355 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
356 glam_assert!(axis.is_normalized());
357
358 let (sin, cos) = math::sin_cos(angle);
359 let axis_sin = axis.mul(sin);
360 let axis_sq = axis.mul(axis);
361 let omc = 1.0 - cos;
362 let xyomc = axis.x * axis.y * omc;
363 let xzomc = axis.x * axis.z * omc;
364 let yzomc = axis.y * axis.z * omc;
365 Self::from_cols(
366 Vec4::new(
367 axis_sq.x * omc + cos,
368 xyomc + axis_sin.z,
369 xzomc - axis_sin.y,
370 0.0,
371 ),
372 Vec4::new(
373 xyomc - axis_sin.z,
374 axis_sq.y * omc + cos,
375 yzomc + axis_sin.x,
376 0.0,
377 ),
378 Vec4::new(
379 xzomc + axis_sin.y,
380 yzomc - axis_sin.x,
381 axis_sq.z * omc + cos,
382 0.0,
383 ),
384 Vec4::W,
385 )
386 }
387
388 /// Creates a affine transformation matrix containing a rotation from the given euler
389 /// rotation sequence and angles (in radians).
390 ///
391 /// The resulting matrix can be used to transform 3D points and vectors. See
392 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
393 #[inline]
394 #[must_use]
from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self395 pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
396 let quat = Quat::from_euler(order, a, b, c);
397 Self::from_quat(quat)
398 }
399
400 /// Creates an affine transformation matrix containing a 3D rotation around the x axis of
401 /// `angle` (in radians).
402 ///
403 /// The resulting matrix can be used to transform 3D points and vectors. See
404 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
405 #[inline]
406 #[must_use]
from_rotation_x(angle: f32) -> Self407 pub fn from_rotation_x(angle: f32) -> Self {
408 let (sina, cosa) = math::sin_cos(angle);
409 Self::from_cols(
410 Vec4::X,
411 Vec4::new(0.0, cosa, sina, 0.0),
412 Vec4::new(0.0, -sina, cosa, 0.0),
413 Vec4::W,
414 )
415 }
416
417 /// Creates an affine transformation matrix containing a 3D rotation around the y axis of
418 /// `angle` (in radians).
419 ///
420 /// The resulting matrix can be used to transform 3D points and vectors. See
421 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
422 #[inline]
423 #[must_use]
from_rotation_y(angle: f32) -> Self424 pub fn from_rotation_y(angle: f32) -> Self {
425 let (sina, cosa) = math::sin_cos(angle);
426 Self::from_cols(
427 Vec4::new(cosa, 0.0, -sina, 0.0),
428 Vec4::Y,
429 Vec4::new(sina, 0.0, cosa, 0.0),
430 Vec4::W,
431 )
432 }
433
434 /// Creates an affine transformation matrix containing a 3D rotation around the z axis of
435 /// `angle` (in radians).
436 ///
437 /// The resulting matrix can be used to transform 3D points and vectors. See
438 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
439 #[inline]
440 #[must_use]
from_rotation_z(angle: f32) -> Self441 pub fn from_rotation_z(angle: f32) -> Self {
442 let (sina, cosa) = math::sin_cos(angle);
443 Self::from_cols(
444 Vec4::new(cosa, sina, 0.0, 0.0),
445 Vec4::new(-sina, cosa, 0.0, 0.0),
446 Vec4::Z,
447 Vec4::W,
448 )
449 }
450
451 /// Creates an affine transformation matrix containing the given 3D non-uniform `scale`.
452 ///
453 /// The resulting matrix can be used to transform 3D points and vectors. See
454 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
455 ///
456 /// # Panics
457 ///
458 /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
459 #[inline]
460 #[must_use]
from_scale(scale: Vec3) -> Self461 pub fn from_scale(scale: Vec3) -> Self {
462 // Do not panic as long as any component is non-zero
463 glam_assert!(scale.cmpne(Vec3::ZERO).any());
464
465 Self::from_cols(
466 Vec4::new(scale.x, 0.0, 0.0, 0.0),
467 Vec4::new(0.0, scale.y, 0.0, 0.0),
468 Vec4::new(0.0, 0.0, scale.z, 0.0),
469 Vec4::W,
470 )
471 }
472
473 /// Creates a 4x4 matrix from the first 16 values in `slice`.
474 ///
475 /// # Panics
476 ///
477 /// Panics if `slice` is less than 16 elements long.
478 #[inline]
479 #[must_use]
from_cols_slice(slice: &[f32]) -> Self480 pub const fn from_cols_slice(slice: &[f32]) -> Self {
481 Self::new(
482 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
483 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
484 )
485 }
486
487 /// Writes the columns of `self` to the first 16 elements in `slice`.
488 ///
489 /// # Panics
490 ///
491 /// Panics if `slice` is less than 16 elements long.
492 #[inline]
write_cols_to_slice(self, slice: &mut [f32])493 pub fn write_cols_to_slice(self, slice: &mut [f32]) {
494 slice[0] = self.x_axis.x;
495 slice[1] = self.x_axis.y;
496 slice[2] = self.x_axis.z;
497 slice[3] = self.x_axis.w;
498 slice[4] = self.y_axis.x;
499 slice[5] = self.y_axis.y;
500 slice[6] = self.y_axis.z;
501 slice[7] = self.y_axis.w;
502 slice[8] = self.z_axis.x;
503 slice[9] = self.z_axis.y;
504 slice[10] = self.z_axis.z;
505 slice[11] = self.z_axis.w;
506 slice[12] = self.w_axis.x;
507 slice[13] = self.w_axis.y;
508 slice[14] = self.w_axis.z;
509 slice[15] = self.w_axis.w;
510 }
511
512 /// Returns the matrix column for the given `index`.
513 ///
514 /// # Panics
515 ///
516 /// Panics if `index` is greater than 3.
517 #[inline]
518 #[must_use]
col(&self, index: usize) -> Vec4519 pub fn col(&self, index: usize) -> Vec4 {
520 match index {
521 0 => self.x_axis,
522 1 => self.y_axis,
523 2 => self.z_axis,
524 3 => self.w_axis,
525 _ => panic!("index out of bounds"),
526 }
527 }
528
529 /// Returns a mutable reference to the matrix column for the given `index`.
530 ///
531 /// # Panics
532 ///
533 /// Panics if `index` is greater than 3.
534 #[inline]
col_mut(&mut self, index: usize) -> &mut Vec4535 pub fn col_mut(&mut self, index: usize) -> &mut Vec4 {
536 match index {
537 0 => &mut self.x_axis,
538 1 => &mut self.y_axis,
539 2 => &mut self.z_axis,
540 3 => &mut self.w_axis,
541 _ => panic!("index out of bounds"),
542 }
543 }
544
545 /// Returns the matrix row for the given `index`.
546 ///
547 /// # Panics
548 ///
549 /// Panics if `index` is greater than 3.
550 #[inline]
551 #[must_use]
row(&self, index: usize) -> Vec4552 pub fn row(&self, index: usize) -> Vec4 {
553 match index {
554 0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
555 1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
556 2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
557 3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
558 _ => panic!("index out of bounds"),
559 }
560 }
561
562 /// Returns `true` if, and only if, all elements are finite.
563 /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
564 #[inline]
565 #[must_use]
is_finite(&self) -> bool566 pub fn is_finite(&self) -> bool {
567 self.x_axis.is_finite()
568 && self.y_axis.is_finite()
569 && self.z_axis.is_finite()
570 && self.w_axis.is_finite()
571 }
572
573 /// Returns `true` if any elements are `NaN`.
574 #[inline]
575 #[must_use]
is_nan(&self) -> bool576 pub fn is_nan(&self) -> bool {
577 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
578 }
579
580 /// Returns the transpose of `self`.
581 #[inline]
582 #[must_use]
transpose(&self) -> Self583 pub fn transpose(&self) -> Self {
584 Self {
585 x_axis: Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
586 y_axis: Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
587 z_axis: Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
588 w_axis: Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
589 }
590 }
591
592 /// Returns the determinant of `self`.
593 #[must_use]
determinant(&self) -> f32594 pub fn determinant(&self) -> f32 {
595 let (m00, m01, m02, m03) = self.x_axis.into();
596 let (m10, m11, m12, m13) = self.y_axis.into();
597 let (m20, m21, m22, m23) = self.z_axis.into();
598 let (m30, m31, m32, m33) = self.w_axis.into();
599
600 let a2323 = m22 * m33 - m23 * m32;
601 let a1323 = m21 * m33 - m23 * m31;
602 let a1223 = m21 * m32 - m22 * m31;
603 let a0323 = m20 * m33 - m23 * m30;
604 let a0223 = m20 * m32 - m22 * m30;
605 let a0123 = m20 * m31 - m21 * m30;
606
607 m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223)
608 - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223)
609 + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123)
610 - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123)
611 }
612
613 /// Returns the inverse of `self`.
614 ///
615 /// If the matrix is not invertible the returned matrix will be invalid.
616 ///
617 /// # Panics
618 ///
619 /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
620 #[must_use]
inverse(&self) -> Self621 pub fn inverse(&self) -> Self {
622 let (m00, m01, m02, m03) = self.x_axis.into();
623 let (m10, m11, m12, m13) = self.y_axis.into();
624 let (m20, m21, m22, m23) = self.z_axis.into();
625 let (m30, m31, m32, m33) = self.w_axis.into();
626
627 let coef00 = m22 * m33 - m32 * m23;
628 let coef02 = m12 * m33 - m32 * m13;
629 let coef03 = m12 * m23 - m22 * m13;
630
631 let coef04 = m21 * m33 - m31 * m23;
632 let coef06 = m11 * m33 - m31 * m13;
633 let coef07 = m11 * m23 - m21 * m13;
634
635 let coef08 = m21 * m32 - m31 * m22;
636 let coef10 = m11 * m32 - m31 * m12;
637 let coef11 = m11 * m22 - m21 * m12;
638
639 let coef12 = m20 * m33 - m30 * m23;
640 let coef14 = m10 * m33 - m30 * m13;
641 let coef15 = m10 * m23 - m20 * m13;
642
643 let coef16 = m20 * m32 - m30 * m22;
644 let coef18 = m10 * m32 - m30 * m12;
645 let coef19 = m10 * m22 - m20 * m12;
646
647 let coef20 = m20 * m31 - m30 * m21;
648 let coef22 = m10 * m31 - m30 * m11;
649 let coef23 = m10 * m21 - m20 * m11;
650
651 let fac0 = Vec4::new(coef00, coef00, coef02, coef03);
652 let fac1 = Vec4::new(coef04, coef04, coef06, coef07);
653 let fac2 = Vec4::new(coef08, coef08, coef10, coef11);
654 let fac3 = Vec4::new(coef12, coef12, coef14, coef15);
655 let fac4 = Vec4::new(coef16, coef16, coef18, coef19);
656 let fac5 = Vec4::new(coef20, coef20, coef22, coef23);
657
658 let vec0 = Vec4::new(m10, m00, m00, m00);
659 let vec1 = Vec4::new(m11, m01, m01, m01);
660 let vec2 = Vec4::new(m12, m02, m02, m02);
661 let vec3 = Vec4::new(m13, m03, m03, m03);
662
663 let inv0 = vec1.mul(fac0).sub(vec2.mul(fac1)).add(vec3.mul(fac2));
664 let inv1 = vec0.mul(fac0).sub(vec2.mul(fac3)).add(vec3.mul(fac4));
665 let inv2 = vec0.mul(fac1).sub(vec1.mul(fac3)).add(vec3.mul(fac5));
666 let inv3 = vec0.mul(fac2).sub(vec1.mul(fac4)).add(vec2.mul(fac5));
667
668 let sign_a = Vec4::new(1.0, -1.0, 1.0, -1.0);
669 let sign_b = Vec4::new(-1.0, 1.0, -1.0, 1.0);
670
671 let inverse = Self::from_cols(
672 inv0.mul(sign_a),
673 inv1.mul(sign_b),
674 inv2.mul(sign_a),
675 inv3.mul(sign_b),
676 );
677
678 let col0 = Vec4::new(
679 inverse.x_axis.x,
680 inverse.y_axis.x,
681 inverse.z_axis.x,
682 inverse.w_axis.x,
683 );
684
685 let dot0 = self.x_axis.mul(col0);
686 let dot1 = dot0.x + dot0.y + dot0.z + dot0.w;
687
688 glam_assert!(dot1 != 0.0);
689
690 let rcp_det = dot1.recip();
691 inverse.mul(rcp_det)
692 }
693
694 /// Creates a left-handed view matrix using a camera position, an up direction, and a facing
695 /// direction.
696 ///
697 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
698 #[inline]
699 #[must_use]
look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self700 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
701 Self::look_to_rh(eye, -dir, up)
702 }
703
704 /// Creates a right-handed view matrix using a camera position, an up direction, and a facing
705 /// direction.
706 ///
707 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
708 #[inline]
709 #[must_use]
look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self710 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
711 let f = dir.normalize();
712 let s = f.cross(up).normalize();
713 let u = s.cross(f);
714
715 Self::from_cols(
716 Vec4::new(s.x, u.x, -f.x, 0.0),
717 Vec4::new(s.y, u.y, -f.y, 0.0),
718 Vec4::new(s.z, u.z, -f.z, 0.0),
719 Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
720 )
721 }
722
723 /// Creates a left-handed view matrix using a camera position, an up direction, and a focal
724 /// point.
725 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
726 ///
727 /// # Panics
728 ///
729 /// Will panic if `up` is not normalized when `glam_assert` is enabled.
730 #[inline]
731 #[must_use]
look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self732 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
733 glam_assert!(up.is_normalized());
734 Self::look_to_lh(eye, center.sub(eye), up)
735 }
736
737 /// Creates a right-handed view matrix using a camera position, an up direction, and a focal
738 /// point.
739 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
740 ///
741 /// # Panics
742 ///
743 /// Will panic if `up` is not normalized when `glam_assert` is enabled.
744 #[inline]
look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self745 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
746 glam_assert!(up.is_normalized());
747 Self::look_to_rh(eye, center.sub(eye), up)
748 }
749
750 /// Creates a right-handed perspective projection matrix with [-1,1] depth range.
751 /// This is the same as the OpenGL `gluPerspective` function.
752 /// See <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml>
753 #[inline]
754 #[must_use]
perspective_rh_gl( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32, ) -> Self755 pub fn perspective_rh_gl(
756 fov_y_radians: f32,
757 aspect_ratio: f32,
758 z_near: f32,
759 z_far: f32,
760 ) -> Self {
761 let inv_length = 1.0 / (z_near - z_far);
762 let f = 1.0 / math::tan(0.5 * fov_y_radians);
763 let a = f / aspect_ratio;
764 let b = (z_near + z_far) * inv_length;
765 let c = (2.0 * z_near * z_far) * inv_length;
766 Self::from_cols(
767 Vec4::new(a, 0.0, 0.0, 0.0),
768 Vec4::new(0.0, f, 0.0, 0.0),
769 Vec4::new(0.0, 0.0, b, -1.0),
770 Vec4::new(0.0, 0.0, c, 0.0),
771 )
772 }
773
774 /// Creates a left-handed perspective projection matrix with `[0,1]` depth range.
775 ///
776 /// # Panics
777 ///
778 /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
779 /// enabled.
780 #[inline]
781 #[must_use]
perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self782 pub fn perspective_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
783 glam_assert!(z_near > 0.0 && z_far > 0.0);
784 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
785 let h = cos_fov / sin_fov;
786 let w = h / aspect_ratio;
787 let r = z_far / (z_far - z_near);
788 Self::from_cols(
789 Vec4::new(w, 0.0, 0.0, 0.0),
790 Vec4::new(0.0, h, 0.0, 0.0),
791 Vec4::new(0.0, 0.0, r, 1.0),
792 Vec4::new(0.0, 0.0, -r * z_near, 0.0),
793 )
794 }
795
796 /// Creates a right-handed perspective projection matrix with `[0,1]` depth range.
797 ///
798 /// # Panics
799 ///
800 /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
801 /// enabled.
802 #[inline]
803 #[must_use]
perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self804 pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
805 glam_assert!(z_near > 0.0 && z_far > 0.0);
806 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
807 let h = cos_fov / sin_fov;
808 let w = h / aspect_ratio;
809 let r = z_far / (z_near - z_far);
810 Self::from_cols(
811 Vec4::new(w, 0.0, 0.0, 0.0),
812 Vec4::new(0.0, h, 0.0, 0.0),
813 Vec4::new(0.0, 0.0, r, -1.0),
814 Vec4::new(0.0, 0.0, r * z_near, 0.0),
815 )
816 }
817
818 /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range.
819 ///
820 /// # Panics
821 ///
822 /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
823 #[inline]
824 #[must_use]
perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self825 pub fn perspective_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
826 glam_assert!(z_near > 0.0);
827 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
828 let h = cos_fov / sin_fov;
829 let w = h / aspect_ratio;
830 Self::from_cols(
831 Vec4::new(w, 0.0, 0.0, 0.0),
832 Vec4::new(0.0, h, 0.0, 0.0),
833 Vec4::new(0.0, 0.0, 1.0, 1.0),
834 Vec4::new(0.0, 0.0, -z_near, 0.0),
835 )
836 }
837
838 /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range.
839 ///
840 /// # Panics
841 ///
842 /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
843 #[inline]
844 #[must_use]
perspective_infinite_reverse_lh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self845 pub fn perspective_infinite_reverse_lh(
846 fov_y_radians: f32,
847 aspect_ratio: f32,
848 z_near: f32,
849 ) -> Self {
850 glam_assert!(z_near > 0.0);
851 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
852 let h = cos_fov / sin_fov;
853 let w = h / aspect_ratio;
854 Self::from_cols(
855 Vec4::new(w, 0.0, 0.0, 0.0),
856 Vec4::new(0.0, h, 0.0, 0.0),
857 Vec4::new(0.0, 0.0, 0.0, 1.0),
858 Vec4::new(0.0, 0.0, z_near, 0.0),
859 )
860 }
861
862 /// Creates an infinite right-handed perspective projection matrix with
863 /// `[0,1]` depth range.
864 #[inline]
865 #[must_use]
perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self866 pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
867 glam_assert!(z_near > 0.0);
868 let f = 1.0 / math::tan(0.5 * fov_y_radians);
869 Self::from_cols(
870 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
871 Vec4::new(0.0, f, 0.0, 0.0),
872 Vec4::new(0.0, 0.0, -1.0, -1.0),
873 Vec4::new(0.0, 0.0, -z_near, 0.0),
874 )
875 }
876
877 /// Creates an infinite reverse right-handed perspective projection matrix
878 /// with `[0,1]` depth range.
879 #[inline]
880 #[must_use]
perspective_infinite_reverse_rh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self881 pub fn perspective_infinite_reverse_rh(
882 fov_y_radians: f32,
883 aspect_ratio: f32,
884 z_near: f32,
885 ) -> Self {
886 glam_assert!(z_near > 0.0);
887 let f = 1.0 / math::tan(0.5 * fov_y_radians);
888 Self::from_cols(
889 Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
890 Vec4::new(0.0, f, 0.0, 0.0),
891 Vec4::new(0.0, 0.0, 0.0, -1.0),
892 Vec4::new(0.0, 0.0, z_near, 0.0),
893 )
894 }
895
896 /// Creates a right-handed orthographic projection matrix with `[-1,1]` depth
897 /// range. This is the same as the OpenGL `glOrtho` function in OpenGL.
898 /// See
899 /// <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml>
900 #[inline]
901 #[must_use]
orthographic_rh_gl( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self902 pub fn orthographic_rh_gl(
903 left: f32,
904 right: f32,
905 bottom: f32,
906 top: f32,
907 near: f32,
908 far: f32,
909 ) -> Self {
910 let a = 2.0 / (right - left);
911 let b = 2.0 / (top - bottom);
912 let c = -2.0 / (far - near);
913 let tx = -(right + left) / (right - left);
914 let ty = -(top + bottom) / (top - bottom);
915 let tz = -(far + near) / (far - near);
916
917 Self::from_cols(
918 Vec4::new(a, 0.0, 0.0, 0.0),
919 Vec4::new(0.0, b, 0.0, 0.0),
920 Vec4::new(0.0, 0.0, c, 0.0),
921 Vec4::new(tx, ty, tz, 1.0),
922 )
923 }
924
925 /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range.
926 #[inline]
927 #[must_use]
orthographic_lh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self928 pub fn orthographic_lh(
929 left: f32,
930 right: f32,
931 bottom: f32,
932 top: f32,
933 near: f32,
934 far: f32,
935 ) -> Self {
936 let rcp_width = 1.0 / (right - left);
937 let rcp_height = 1.0 / (top - bottom);
938 let r = 1.0 / (far - near);
939 Self::from_cols(
940 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
941 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
942 Vec4::new(0.0, 0.0, r, 0.0),
943 Vec4::new(
944 -(left + right) * rcp_width,
945 -(top + bottom) * rcp_height,
946 -r * near,
947 1.0,
948 ),
949 )
950 }
951
952 /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range.
953 #[inline]
954 #[must_use]
orthographic_rh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self955 pub fn orthographic_rh(
956 left: f32,
957 right: f32,
958 bottom: f32,
959 top: f32,
960 near: f32,
961 far: f32,
962 ) -> Self {
963 let rcp_width = 1.0 / (right - left);
964 let rcp_height = 1.0 / (top - bottom);
965 let r = 1.0 / (near - far);
966 Self::from_cols(
967 Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
968 Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
969 Vec4::new(0.0, 0.0, r, 0.0),
970 Vec4::new(
971 -(left + right) * rcp_width,
972 -(top + bottom) * rcp_height,
973 r * near,
974 1.0,
975 ),
976 )
977 }
978
979 /// Transforms the given 3D vector as a point, applying perspective correction.
980 ///
981 /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is `1.0`.
982 /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
983 ///
984 /// This method assumes that `self` contains a projective transform.
985 #[inline]
986 #[must_use]
project_point3(&self, rhs: Vec3) -> Vec3987 pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
988 let mut res = self.x_axis.mul(rhs.x);
989 res = self.y_axis.mul(rhs.y).add(res);
990 res = self.z_axis.mul(rhs.z).add(res);
991 res = self.w_axis.add(res);
992 res = res.mul(res.wwww().recip());
993 res.xyz()
994 }
995
996 /// Transforms the given 3D vector as a point.
997 ///
998 /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
999 /// `1.0`.
1000 ///
1001 /// This method assumes that `self` contains a valid affine transform. It does not perform
1002 /// a persective divide, if `self` contains a perspective transform, or if you are unsure,
1003 /// the [`Self::project_point3()`] method should be used instead.
1004 ///
1005 /// # Panics
1006 ///
1007 /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1008 #[inline]
1009 #[must_use]
transform_point3(&self, rhs: Vec3) -> Vec31010 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1011 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1012 let mut res = self.x_axis.mul(rhs.x);
1013 res = self.y_axis.mul(rhs.y).add(res);
1014 res = self.z_axis.mul(rhs.z).add(res);
1015 res = self.w_axis.add(res);
1016 res.xyz()
1017 }
1018
1019 /// Transforms the give 3D vector as a direction.
1020 ///
1021 /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
1022 /// `0.0`.
1023 ///
1024 /// This method assumes that `self` contains a valid affine transform.
1025 ///
1026 /// # Panics
1027 ///
1028 /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1029 #[inline]
1030 #[must_use]
transform_vector3(&self, rhs: Vec3) -> Vec31031 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1032 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1033 let mut res = self.x_axis.mul(rhs.x);
1034 res = self.y_axis.mul(rhs.y).add(res);
1035 res = self.z_axis.mul(rhs.z).add(res);
1036 res.xyz()
1037 }
1038
1039 /// Transforms the given [`Vec3A`] as 3D point.
1040 ///
1041 /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`.
1042 #[inline]
1043 #[must_use]
transform_point3a(&self, rhs: Vec3A) -> Vec3A1044 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1045 self.transform_point3(rhs.into()).into()
1046 }
1047
1048 /// Transforms the give [`Vec3A`] as 3D vector.
1049 ///
1050 /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `0.0`.
1051 #[inline]
1052 #[must_use]
transform_vector3a(&self, rhs: Vec3A) -> Vec3A1053 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1054 self.transform_vector3(rhs.into()).into()
1055 }
1056
1057 /// Transforms a 4D vector.
1058 #[inline]
1059 #[must_use]
mul_vec4(&self, rhs: Vec4) -> Vec41060 pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1061 let mut res = self.x_axis.mul(rhs.x);
1062 res = res.add(self.y_axis.mul(rhs.y));
1063 res = res.add(self.z_axis.mul(rhs.z));
1064 res = res.add(self.w_axis.mul(rhs.w));
1065 res
1066 }
1067
1068 /// Multiplies two 4x4 matrices.
1069 #[inline]
1070 #[must_use]
mul_mat4(&self, rhs: &Self) -> Self1071 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1072 Self::from_cols(
1073 self.mul(rhs.x_axis),
1074 self.mul(rhs.y_axis),
1075 self.mul(rhs.z_axis),
1076 self.mul(rhs.w_axis),
1077 )
1078 }
1079
1080 /// Adds two 4x4 matrices.
1081 #[inline]
1082 #[must_use]
add_mat4(&self, rhs: &Self) -> Self1083 pub fn add_mat4(&self, rhs: &Self) -> Self {
1084 Self::from_cols(
1085 self.x_axis.add(rhs.x_axis),
1086 self.y_axis.add(rhs.y_axis),
1087 self.z_axis.add(rhs.z_axis),
1088 self.w_axis.add(rhs.w_axis),
1089 )
1090 }
1091
1092 /// Subtracts two 4x4 matrices.
1093 #[inline]
1094 #[must_use]
sub_mat4(&self, rhs: &Self) -> Self1095 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1096 Self::from_cols(
1097 self.x_axis.sub(rhs.x_axis),
1098 self.y_axis.sub(rhs.y_axis),
1099 self.z_axis.sub(rhs.z_axis),
1100 self.w_axis.sub(rhs.w_axis),
1101 )
1102 }
1103
1104 /// Multiplies a 4x4 matrix by a scalar.
1105 #[inline]
1106 #[must_use]
mul_scalar(&self, rhs: f32) -> Self1107 pub fn mul_scalar(&self, rhs: f32) -> Self {
1108 Self::from_cols(
1109 self.x_axis.mul(rhs),
1110 self.y_axis.mul(rhs),
1111 self.z_axis.mul(rhs),
1112 self.w_axis.mul(rhs),
1113 )
1114 }
1115
1116 /// Returns true if the absolute difference of all elements between `self` and `rhs`
1117 /// is less than or equal to `max_abs_diff`.
1118 ///
1119 /// This can be used to compare if two matrices contain similar elements. It works best
1120 /// when comparing with a known value. The `max_abs_diff` that should be used used
1121 /// depends on the values being compared against.
1122 ///
1123 /// For more see
1124 /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
1125 #[inline]
1126 #[must_use]
abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool1127 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1128 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1129 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1130 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1131 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1132 }
1133
1134 #[inline]
as_dmat4(&self) -> DMat41135 pub fn as_dmat4(&self) -> DMat4 {
1136 DMat4::from_cols(
1137 self.x_axis.as_dvec4(),
1138 self.y_axis.as_dvec4(),
1139 self.z_axis.as_dvec4(),
1140 self.w_axis.as_dvec4(),
1141 )
1142 }
1143 }
1144
1145 impl Default for Mat4 {
1146 #[inline]
default() -> Self1147 fn default() -> Self {
1148 Self::IDENTITY
1149 }
1150 }
1151
1152 impl Add<Mat4> for Mat4 {
1153 type Output = Self;
1154 #[inline]
add(self, rhs: Self) -> Self::Output1155 fn add(self, rhs: Self) -> Self::Output {
1156 self.add_mat4(&rhs)
1157 }
1158 }
1159
1160 impl AddAssign<Mat4> for Mat4 {
1161 #[inline]
add_assign(&mut self, rhs: Self)1162 fn add_assign(&mut self, rhs: Self) {
1163 *self = self.add_mat4(&rhs);
1164 }
1165 }
1166
1167 impl Sub<Mat4> for Mat4 {
1168 type Output = Self;
1169 #[inline]
sub(self, rhs: Self) -> Self::Output1170 fn sub(self, rhs: Self) -> Self::Output {
1171 self.sub_mat4(&rhs)
1172 }
1173 }
1174
1175 impl SubAssign<Mat4> for Mat4 {
1176 #[inline]
sub_assign(&mut self, rhs: Self)1177 fn sub_assign(&mut self, rhs: Self) {
1178 *self = self.sub_mat4(&rhs);
1179 }
1180 }
1181
1182 impl Neg for Mat4 {
1183 type Output = Self;
1184 #[inline]
neg(self) -> Self::Output1185 fn neg(self) -> Self::Output {
1186 Self::from_cols(
1187 self.x_axis.neg(),
1188 self.y_axis.neg(),
1189 self.z_axis.neg(),
1190 self.w_axis.neg(),
1191 )
1192 }
1193 }
1194
1195 impl Mul<Mat4> for Mat4 {
1196 type Output = Self;
1197 #[inline]
mul(self, rhs: Self) -> Self::Output1198 fn mul(self, rhs: Self) -> Self::Output {
1199 self.mul_mat4(&rhs)
1200 }
1201 }
1202
1203 impl MulAssign<Mat4> for Mat4 {
1204 #[inline]
mul_assign(&mut self, rhs: Self)1205 fn mul_assign(&mut self, rhs: Self) {
1206 *self = self.mul_mat4(&rhs);
1207 }
1208 }
1209
1210 impl Mul<Vec4> for Mat4 {
1211 type Output = Vec4;
1212 #[inline]
mul(self, rhs: Vec4) -> Self::Output1213 fn mul(self, rhs: Vec4) -> Self::Output {
1214 self.mul_vec4(rhs)
1215 }
1216 }
1217
1218 impl Mul<Mat4> for f32 {
1219 type Output = Mat4;
1220 #[inline]
mul(self, rhs: Mat4) -> Self::Output1221 fn mul(self, rhs: Mat4) -> Self::Output {
1222 rhs.mul_scalar(self)
1223 }
1224 }
1225
1226 impl Mul<f32> for Mat4 {
1227 type Output = Self;
1228 #[inline]
mul(self, rhs: f32) -> Self::Output1229 fn mul(self, rhs: f32) -> Self::Output {
1230 self.mul_scalar(rhs)
1231 }
1232 }
1233
1234 impl MulAssign<f32> for Mat4 {
1235 #[inline]
mul_assign(&mut self, rhs: f32)1236 fn mul_assign(&mut self, rhs: f32) {
1237 *self = self.mul_scalar(rhs);
1238 }
1239 }
1240
1241 impl Sum<Self> for Mat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,1242 fn sum<I>(iter: I) -> Self
1243 where
1244 I: Iterator<Item = Self>,
1245 {
1246 iter.fold(Self::ZERO, Self::add)
1247 }
1248 }
1249
1250 impl<'a> Sum<&'a Self> for Mat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,1251 fn sum<I>(iter: I) -> Self
1252 where
1253 I: Iterator<Item = &'a Self>,
1254 {
1255 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1256 }
1257 }
1258
1259 impl Product for Mat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,1260 fn product<I>(iter: I) -> Self
1261 where
1262 I: Iterator<Item = Self>,
1263 {
1264 iter.fold(Self::IDENTITY, Self::mul)
1265 }
1266 }
1267
1268 impl<'a> Product<&'a Self> for Mat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,1269 fn product<I>(iter: I) -> Self
1270 where
1271 I: Iterator<Item = &'a Self>,
1272 {
1273 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1274 }
1275 }
1276
1277 impl PartialEq for Mat4 {
1278 #[inline]
eq(&self, rhs: &Self) -> bool1279 fn eq(&self, rhs: &Self) -> bool {
1280 self.x_axis.eq(&rhs.x_axis)
1281 && self.y_axis.eq(&rhs.y_axis)
1282 && self.z_axis.eq(&rhs.z_axis)
1283 && self.w_axis.eq(&rhs.w_axis)
1284 }
1285 }
1286
1287 #[cfg(not(target_arch = "spirv"))]
1288 impl AsRef<[f32; 16]> for Mat4 {
1289 #[inline]
as_ref(&self) -> &[f32; 16]1290 fn as_ref(&self) -> &[f32; 16] {
1291 unsafe { &*(self as *const Self as *const [f32; 16]) }
1292 }
1293 }
1294
1295 #[cfg(not(target_arch = "spirv"))]
1296 impl AsMut<[f32; 16]> for Mat4 {
1297 #[inline]
as_mut(&mut self) -> &mut [f32; 16]1298 fn as_mut(&mut self) -> &mut [f32; 16] {
1299 unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
1300 }
1301 }
1302
1303 #[cfg(not(target_arch = "spirv"))]
1304 impl fmt::Debug for Mat4 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result1305 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1306 fmt.debug_struct(stringify!(Mat4))
1307 .field("x_axis", &self.x_axis)
1308 .field("y_axis", &self.y_axis)
1309 .field("z_axis", &self.z_axis)
1310 .field("w_axis", &self.w_axis)
1311 .finish()
1312 }
1313 }
1314
1315 #[cfg(not(target_arch = "spirv"))]
1316 impl fmt::Display for Mat4 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1317 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1318 write!(
1319 f,
1320 "[{}, {}, {}, {}]",
1321 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1322 )
1323 }
1324 }
1325