1 // Generated from mat.rs.tera template. Edit the template, not the generated file.
2
3 use crate::{f64::math, swizzles::*, DMat3, DQuat, DVec3, DVec4, EulerRot, Mat4};
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]
dmat4(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> DMat412 pub const fn dmat4(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> DMat4 {
13 DMat4::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 [`DAffine3`](crate::DAffine3) 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(feature = "cuda", repr(align(16)))]
47 #[repr(C)]
48 pub struct DMat4 {
49 pub x_axis: DVec4,
50 pub y_axis: DVec4,
51 pub z_axis: DVec4,
52 pub w_axis: DVec4,
53 }
54
55 impl DMat4 {
56 /// A 4x4 matrix with all elements set to `0.0`.
57 pub const ZERO: Self = Self::from_cols(DVec4::ZERO, DVec4::ZERO, DVec4::ZERO, DVec4::ZERO);
58
59 /// A 4x4 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
60 pub const IDENTITY: Self = Self::from_cols(DVec4::X, DVec4::Y, DVec4::Z, DVec4::W);
61
62 /// All NAN:s.
63 pub const NAN: Self = Self::from_cols(DVec4::NAN, DVec4::NAN, DVec4::NAN, DVec4::NAN);
64
65 #[allow(clippy::too_many_arguments)]
66 #[inline(always)]
67 #[must_use]
new( m00: f64, m01: f64, m02: f64, m03: f64, m10: f64, m11: f64, m12: f64, m13: f64, m20: f64, m21: f64, m22: f64, m23: f64, m30: f64, m31: f64, m32: f64, m33: f64, ) -> Self68 const fn new(
69 m00: f64,
70 m01: f64,
71 m02: f64,
72 m03: f64,
73 m10: f64,
74 m11: f64,
75 m12: f64,
76 m13: f64,
77 m20: f64,
78 m21: f64,
79 m22: f64,
80 m23: f64,
81 m30: f64,
82 m31: f64,
83 m32: f64,
84 m33: f64,
85 ) -> Self {
86 Self {
87 x_axis: DVec4::new(m00, m01, m02, m03),
88 y_axis: DVec4::new(m10, m11, m12, m13),
89 z_axis: DVec4::new(m20, m21, m22, m23),
90 w_axis: DVec4::new(m30, m31, m32, m33),
91 }
92 }
93
94 /// Creates a 4x4 matrix from four column vectors.
95 #[inline(always)]
96 #[must_use]
from_cols(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> Self97 pub const fn from_cols(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> Self {
98 Self {
99 x_axis,
100 y_axis,
101 z_axis,
102 w_axis,
103 }
104 }
105
106 /// Creates a 4x4 matrix from a `[f64; 16]` array stored in column major order.
107 /// If your data is stored in row major you will need to `transpose` the returned
108 /// matrix.
109 #[inline]
110 #[must_use]
from_cols_array(m: &[f64; 16]) -> Self111 pub const fn from_cols_array(m: &[f64; 16]) -> Self {
112 Self::new(
113 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],
114 m[14], m[15],
115 )
116 }
117
118 /// Creates a `[f64; 16]` array storing data in column major order.
119 /// If you require data in row major order `transpose` the matrix first.
120 #[inline]
121 #[must_use]
to_cols_array(&self) -> [f64; 16]122 pub const fn to_cols_array(&self) -> [f64; 16] {
123 [
124 self.x_axis.x,
125 self.x_axis.y,
126 self.x_axis.z,
127 self.x_axis.w,
128 self.y_axis.x,
129 self.y_axis.y,
130 self.y_axis.z,
131 self.y_axis.w,
132 self.z_axis.x,
133 self.z_axis.y,
134 self.z_axis.z,
135 self.z_axis.w,
136 self.w_axis.x,
137 self.w_axis.y,
138 self.w_axis.z,
139 self.w_axis.w,
140 ]
141 }
142
143 /// Creates a 4x4 matrix from a `[[f64; 4]; 4]` 4D array stored in column major order.
144 /// If your data is in row major order you will need to `transpose` the returned
145 /// matrix.
146 #[inline]
147 #[must_use]
from_cols_array_2d(m: &[[f64; 4]; 4]) -> Self148 pub const fn from_cols_array_2d(m: &[[f64; 4]; 4]) -> Self {
149 Self::from_cols(
150 DVec4::from_array(m[0]),
151 DVec4::from_array(m[1]),
152 DVec4::from_array(m[2]),
153 DVec4::from_array(m[3]),
154 )
155 }
156
157 /// Creates a `[[f64; 4]; 4]` 4D array storing data in column major order.
158 /// If you require data in row major order `transpose` the matrix first.
159 #[inline]
160 #[must_use]
to_cols_array_2d(&self) -> [[f64; 4]; 4]161 pub const fn to_cols_array_2d(&self) -> [[f64; 4]; 4] {
162 [
163 self.x_axis.to_array(),
164 self.y_axis.to_array(),
165 self.z_axis.to_array(),
166 self.w_axis.to_array(),
167 ]
168 }
169
170 /// Creates a 4x4 matrix with its diagonal set to `diagonal` and all other entries set to 0.
171 #[doc(alias = "scale")]
172 #[inline]
173 #[must_use]
from_diagonal(diagonal: DVec4) -> Self174 pub const fn from_diagonal(diagonal: DVec4) -> Self {
175 Self::new(
176 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,
177 0.0, 0.0, diagonal.w,
178 )
179 }
180
181 #[inline]
182 #[must_use]
quat_to_axes(rotation: DQuat) -> (DVec4, DVec4, DVec4)183 fn quat_to_axes(rotation: DQuat) -> (DVec4, DVec4, DVec4) {
184 glam_assert!(rotation.is_normalized());
185
186 let (x, y, z, w) = rotation.into();
187 let x2 = x + x;
188 let y2 = y + y;
189 let z2 = z + z;
190 let xx = x * x2;
191 let xy = x * y2;
192 let xz = x * z2;
193 let yy = y * y2;
194 let yz = y * z2;
195 let zz = z * z2;
196 let wx = w * x2;
197 let wy = w * y2;
198 let wz = w * z2;
199
200 let x_axis = DVec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
201 let y_axis = DVec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
202 let z_axis = DVec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
203 (x_axis, y_axis, z_axis)
204 }
205
206 /// Creates an affine transformation matrix from the given 3D `scale`, `rotation` and
207 /// `translation`.
208 ///
209 /// The resulting matrix can be used to transform 3D points and vectors. See
210 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
211 ///
212 /// # Panics
213 ///
214 /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
215 #[inline]
216 #[must_use]
from_scale_rotation_translation( scale: DVec3, rotation: DQuat, translation: DVec3, ) -> Self217 pub fn from_scale_rotation_translation(
218 scale: DVec3,
219 rotation: DQuat,
220 translation: DVec3,
221 ) -> Self {
222 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
223 Self::from_cols(
224 x_axis.mul(scale.x),
225 y_axis.mul(scale.y),
226 z_axis.mul(scale.z),
227 DVec4::from((translation, 1.0)),
228 )
229 }
230
231 /// Creates an affine transformation matrix from the given 3D `translation`.
232 ///
233 /// The resulting matrix can be used to transform 3D points and vectors. See
234 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
235 ///
236 /// # Panics
237 ///
238 /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
239 #[inline]
240 #[must_use]
from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self241 pub fn from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self {
242 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
243 Self::from_cols(x_axis, y_axis, z_axis, DVec4::from((translation, 1.0)))
244 }
245
246 /// Extracts `scale`, `rotation` and `translation` from `self`. The input matrix is
247 /// expected to be a 3D affine transformation matrix otherwise the output will be invalid.
248 ///
249 /// # Panics
250 ///
251 /// Will panic if the determinant of `self` is zero or if the resulting scale vector
252 /// contains any zero elements when `glam_assert` is enabled.
253 #[inline]
254 #[must_use]
to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3)255 pub fn to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3) {
256 let det = self.determinant();
257 glam_assert!(det != 0.0);
258
259 let scale = DVec3::new(
260 self.x_axis.length() * math::signum(det),
261 self.y_axis.length(),
262 self.z_axis.length(),
263 );
264
265 glam_assert!(scale.cmpne(DVec3::ZERO).all());
266
267 let inv_scale = scale.recip();
268
269 let rotation = DQuat::from_rotation_axes(
270 self.x_axis.mul(inv_scale.x).xyz(),
271 self.y_axis.mul(inv_scale.y).xyz(),
272 self.z_axis.mul(inv_scale.z).xyz(),
273 );
274
275 let translation = self.w_axis.xyz();
276
277 (scale, rotation, translation)
278 }
279
280 /// Creates an affine transformation matrix from the given `rotation` quaternion.
281 ///
282 /// The resulting matrix can be used to transform 3D points and vectors. See
283 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
284 ///
285 /// # Panics
286 ///
287 /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
288 #[inline]
289 #[must_use]
from_quat(rotation: DQuat) -> Self290 pub fn from_quat(rotation: DQuat) -> Self {
291 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
292 Self::from_cols(x_axis, y_axis, z_axis, DVec4::W)
293 }
294
295 /// Creates an affine transformation matrix from the given 3x3 linear transformation
296 /// matrix.
297 ///
298 /// The resulting matrix can be used to transform 3D points and vectors. See
299 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
300 #[inline]
301 #[must_use]
from_mat3(m: DMat3) -> Self302 pub fn from_mat3(m: DMat3) -> Self {
303 Self::from_cols(
304 DVec4::from((m.x_axis, 0.0)),
305 DVec4::from((m.y_axis, 0.0)),
306 DVec4::from((m.z_axis, 0.0)),
307 DVec4::W,
308 )
309 }
310
311 /// Creates an affine transformation matrix from the given 3D `translation`.
312 ///
313 /// The resulting matrix can be used to transform 3D points and vectors. See
314 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
315 #[inline]
316 #[must_use]
from_translation(translation: DVec3) -> Self317 pub fn from_translation(translation: DVec3) -> Self {
318 Self::from_cols(
319 DVec4::X,
320 DVec4::Y,
321 DVec4::Z,
322 DVec4::new(translation.x, translation.y, translation.z, 1.0),
323 )
324 }
325
326 /// Creates an affine transformation matrix containing a 3D rotation around a normalized
327 /// rotation `axis` of `angle` (in radians).
328 ///
329 /// The resulting matrix can be used to transform 3D points and vectors. See
330 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
331 ///
332 /// # Panics
333 ///
334 /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
335 #[inline]
336 #[must_use]
from_axis_angle(axis: DVec3, angle: f64) -> Self337 pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
338 glam_assert!(axis.is_normalized());
339
340 let (sin, cos) = math::sin_cos(angle);
341 let axis_sin = axis.mul(sin);
342 let axis_sq = axis.mul(axis);
343 let omc = 1.0 - cos;
344 let xyomc = axis.x * axis.y * omc;
345 let xzomc = axis.x * axis.z * omc;
346 let yzomc = axis.y * axis.z * omc;
347 Self::from_cols(
348 DVec4::new(
349 axis_sq.x * omc + cos,
350 xyomc + axis_sin.z,
351 xzomc - axis_sin.y,
352 0.0,
353 ),
354 DVec4::new(
355 xyomc - axis_sin.z,
356 axis_sq.y * omc + cos,
357 yzomc + axis_sin.x,
358 0.0,
359 ),
360 DVec4::new(
361 xzomc + axis_sin.y,
362 yzomc - axis_sin.x,
363 axis_sq.z * omc + cos,
364 0.0,
365 ),
366 DVec4::W,
367 )
368 }
369
370 /// Creates a affine transformation matrix containing a rotation from the given euler
371 /// rotation sequence and angles (in radians).
372 ///
373 /// The resulting matrix can be used to transform 3D points and vectors. See
374 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
375 #[inline]
376 #[must_use]
from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self377 pub fn from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self {
378 let quat = DQuat::from_euler(order, a, b, c);
379 Self::from_quat(quat)
380 }
381
382 /// Creates an affine transformation matrix containing a 3D rotation around the x axis of
383 /// `angle` (in radians).
384 ///
385 /// The resulting matrix can be used to transform 3D points and vectors. See
386 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
387 #[inline]
388 #[must_use]
from_rotation_x(angle: f64) -> Self389 pub fn from_rotation_x(angle: f64) -> Self {
390 let (sina, cosa) = math::sin_cos(angle);
391 Self::from_cols(
392 DVec4::X,
393 DVec4::new(0.0, cosa, sina, 0.0),
394 DVec4::new(0.0, -sina, cosa, 0.0),
395 DVec4::W,
396 )
397 }
398
399 /// Creates an affine transformation matrix containing a 3D rotation around the y axis of
400 /// `angle` (in radians).
401 ///
402 /// The resulting matrix can be used to transform 3D points and vectors. See
403 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
404 #[inline]
405 #[must_use]
from_rotation_y(angle: f64) -> Self406 pub fn from_rotation_y(angle: f64) -> Self {
407 let (sina, cosa) = math::sin_cos(angle);
408 Self::from_cols(
409 DVec4::new(cosa, 0.0, -sina, 0.0),
410 DVec4::Y,
411 DVec4::new(sina, 0.0, cosa, 0.0),
412 DVec4::W,
413 )
414 }
415
416 /// Creates an affine transformation matrix containing a 3D rotation around the z axis of
417 /// `angle` (in radians).
418 ///
419 /// The resulting matrix can be used to transform 3D points and vectors. See
420 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
421 #[inline]
422 #[must_use]
from_rotation_z(angle: f64) -> Self423 pub fn from_rotation_z(angle: f64) -> Self {
424 let (sina, cosa) = math::sin_cos(angle);
425 Self::from_cols(
426 DVec4::new(cosa, sina, 0.0, 0.0),
427 DVec4::new(-sina, cosa, 0.0, 0.0),
428 DVec4::Z,
429 DVec4::W,
430 )
431 }
432
433 /// Creates an affine transformation matrix containing the given 3D non-uniform `scale`.
434 ///
435 /// The resulting matrix can be used to transform 3D points and vectors. See
436 /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
437 ///
438 /// # Panics
439 ///
440 /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
441 #[inline]
442 #[must_use]
from_scale(scale: DVec3) -> Self443 pub fn from_scale(scale: DVec3) -> Self {
444 // Do not panic as long as any component is non-zero
445 glam_assert!(scale.cmpne(DVec3::ZERO).any());
446
447 Self::from_cols(
448 DVec4::new(scale.x, 0.0, 0.0, 0.0),
449 DVec4::new(0.0, scale.y, 0.0, 0.0),
450 DVec4::new(0.0, 0.0, scale.z, 0.0),
451 DVec4::W,
452 )
453 }
454
455 /// Creates a 4x4 matrix from the first 16 values in `slice`.
456 ///
457 /// # Panics
458 ///
459 /// Panics if `slice` is less than 16 elements long.
460 #[inline]
461 #[must_use]
from_cols_slice(slice: &[f64]) -> Self462 pub const fn from_cols_slice(slice: &[f64]) -> Self {
463 Self::new(
464 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
465 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
466 )
467 }
468
469 /// Writes the columns of `self` to the first 16 elements in `slice`.
470 ///
471 /// # Panics
472 ///
473 /// Panics if `slice` is less than 16 elements long.
474 #[inline]
write_cols_to_slice(self, slice: &mut [f64])475 pub fn write_cols_to_slice(self, slice: &mut [f64]) {
476 slice[0] = self.x_axis.x;
477 slice[1] = self.x_axis.y;
478 slice[2] = self.x_axis.z;
479 slice[3] = self.x_axis.w;
480 slice[4] = self.y_axis.x;
481 slice[5] = self.y_axis.y;
482 slice[6] = self.y_axis.z;
483 slice[7] = self.y_axis.w;
484 slice[8] = self.z_axis.x;
485 slice[9] = self.z_axis.y;
486 slice[10] = self.z_axis.z;
487 slice[11] = self.z_axis.w;
488 slice[12] = self.w_axis.x;
489 slice[13] = self.w_axis.y;
490 slice[14] = self.w_axis.z;
491 slice[15] = self.w_axis.w;
492 }
493
494 /// Returns the matrix column for the given `index`.
495 ///
496 /// # Panics
497 ///
498 /// Panics if `index` is greater than 3.
499 #[inline]
500 #[must_use]
col(&self, index: usize) -> DVec4501 pub fn col(&self, index: usize) -> DVec4 {
502 match index {
503 0 => self.x_axis,
504 1 => self.y_axis,
505 2 => self.z_axis,
506 3 => self.w_axis,
507 _ => panic!("index out of bounds"),
508 }
509 }
510
511 /// Returns a mutable reference to the matrix column for the given `index`.
512 ///
513 /// # Panics
514 ///
515 /// Panics if `index` is greater than 3.
516 #[inline]
col_mut(&mut self, index: usize) -> &mut DVec4517 pub fn col_mut(&mut self, index: usize) -> &mut DVec4 {
518 match index {
519 0 => &mut self.x_axis,
520 1 => &mut self.y_axis,
521 2 => &mut self.z_axis,
522 3 => &mut self.w_axis,
523 _ => panic!("index out of bounds"),
524 }
525 }
526
527 /// Returns the matrix row for the given `index`.
528 ///
529 /// # Panics
530 ///
531 /// Panics if `index` is greater than 3.
532 #[inline]
533 #[must_use]
row(&self, index: usize) -> DVec4534 pub fn row(&self, index: usize) -> DVec4 {
535 match index {
536 0 => DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
537 1 => DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
538 2 => DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
539 3 => DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
540 _ => panic!("index out of bounds"),
541 }
542 }
543
544 /// Returns `true` if, and only if, all elements are finite.
545 /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
546 #[inline]
547 #[must_use]
is_finite(&self) -> bool548 pub fn is_finite(&self) -> bool {
549 self.x_axis.is_finite()
550 && self.y_axis.is_finite()
551 && self.z_axis.is_finite()
552 && self.w_axis.is_finite()
553 }
554
555 /// Returns `true` if any elements are `NaN`.
556 #[inline]
557 #[must_use]
is_nan(&self) -> bool558 pub fn is_nan(&self) -> bool {
559 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
560 }
561
562 /// Returns the transpose of `self`.
563 #[inline]
564 #[must_use]
transpose(&self) -> Self565 pub fn transpose(&self) -> Self {
566 Self {
567 x_axis: DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
568 y_axis: DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
569 z_axis: DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
570 w_axis: DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
571 }
572 }
573
574 /// Returns the determinant of `self`.
575 #[must_use]
determinant(&self) -> f64576 pub fn determinant(&self) -> f64 {
577 let (m00, m01, m02, m03) = self.x_axis.into();
578 let (m10, m11, m12, m13) = self.y_axis.into();
579 let (m20, m21, m22, m23) = self.z_axis.into();
580 let (m30, m31, m32, m33) = self.w_axis.into();
581
582 let a2323 = m22 * m33 - m23 * m32;
583 let a1323 = m21 * m33 - m23 * m31;
584 let a1223 = m21 * m32 - m22 * m31;
585 let a0323 = m20 * m33 - m23 * m30;
586 let a0223 = m20 * m32 - m22 * m30;
587 let a0123 = m20 * m31 - m21 * m30;
588
589 m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223)
590 - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223)
591 + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123)
592 - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123)
593 }
594
595 /// Returns the inverse of `self`.
596 ///
597 /// If the matrix is not invertible the returned matrix will be invalid.
598 ///
599 /// # Panics
600 ///
601 /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
602 #[must_use]
inverse(&self) -> Self603 pub fn inverse(&self) -> Self {
604 let (m00, m01, m02, m03) = self.x_axis.into();
605 let (m10, m11, m12, m13) = self.y_axis.into();
606 let (m20, m21, m22, m23) = self.z_axis.into();
607 let (m30, m31, m32, m33) = self.w_axis.into();
608
609 let coef00 = m22 * m33 - m32 * m23;
610 let coef02 = m12 * m33 - m32 * m13;
611 let coef03 = m12 * m23 - m22 * m13;
612
613 let coef04 = m21 * m33 - m31 * m23;
614 let coef06 = m11 * m33 - m31 * m13;
615 let coef07 = m11 * m23 - m21 * m13;
616
617 let coef08 = m21 * m32 - m31 * m22;
618 let coef10 = m11 * m32 - m31 * m12;
619 let coef11 = m11 * m22 - m21 * m12;
620
621 let coef12 = m20 * m33 - m30 * m23;
622 let coef14 = m10 * m33 - m30 * m13;
623 let coef15 = m10 * m23 - m20 * m13;
624
625 let coef16 = m20 * m32 - m30 * m22;
626 let coef18 = m10 * m32 - m30 * m12;
627 let coef19 = m10 * m22 - m20 * m12;
628
629 let coef20 = m20 * m31 - m30 * m21;
630 let coef22 = m10 * m31 - m30 * m11;
631 let coef23 = m10 * m21 - m20 * m11;
632
633 let fac0 = DVec4::new(coef00, coef00, coef02, coef03);
634 let fac1 = DVec4::new(coef04, coef04, coef06, coef07);
635 let fac2 = DVec4::new(coef08, coef08, coef10, coef11);
636 let fac3 = DVec4::new(coef12, coef12, coef14, coef15);
637 let fac4 = DVec4::new(coef16, coef16, coef18, coef19);
638 let fac5 = DVec4::new(coef20, coef20, coef22, coef23);
639
640 let vec0 = DVec4::new(m10, m00, m00, m00);
641 let vec1 = DVec4::new(m11, m01, m01, m01);
642 let vec2 = DVec4::new(m12, m02, m02, m02);
643 let vec3 = DVec4::new(m13, m03, m03, m03);
644
645 let inv0 = vec1.mul(fac0).sub(vec2.mul(fac1)).add(vec3.mul(fac2));
646 let inv1 = vec0.mul(fac0).sub(vec2.mul(fac3)).add(vec3.mul(fac4));
647 let inv2 = vec0.mul(fac1).sub(vec1.mul(fac3)).add(vec3.mul(fac5));
648 let inv3 = vec0.mul(fac2).sub(vec1.mul(fac4)).add(vec2.mul(fac5));
649
650 let sign_a = DVec4::new(1.0, -1.0, 1.0, -1.0);
651 let sign_b = DVec4::new(-1.0, 1.0, -1.0, 1.0);
652
653 let inverse = Self::from_cols(
654 inv0.mul(sign_a),
655 inv1.mul(sign_b),
656 inv2.mul(sign_a),
657 inv3.mul(sign_b),
658 );
659
660 let col0 = DVec4::new(
661 inverse.x_axis.x,
662 inverse.y_axis.x,
663 inverse.z_axis.x,
664 inverse.w_axis.x,
665 );
666
667 let dot0 = self.x_axis.mul(col0);
668 let dot1 = dot0.x + dot0.y + dot0.z + dot0.w;
669
670 glam_assert!(dot1 != 0.0);
671
672 let rcp_det = dot1.recip();
673 inverse.mul(rcp_det)
674 }
675
676 /// Creates a left-handed view matrix using a camera position, an up direction, and a facing
677 /// direction.
678 ///
679 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
680 #[inline]
681 #[must_use]
look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self682 pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
683 Self::look_to_rh(eye, -dir, up)
684 }
685
686 /// Creates a right-handed view matrix using a camera position, an up direction, and a facing
687 /// direction.
688 ///
689 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
690 #[inline]
691 #[must_use]
look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self692 pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
693 let f = dir.normalize();
694 let s = f.cross(up).normalize();
695 let u = s.cross(f);
696
697 Self::from_cols(
698 DVec4::new(s.x, u.x, -f.x, 0.0),
699 DVec4::new(s.y, u.y, -f.y, 0.0),
700 DVec4::new(s.z, u.z, -f.z, 0.0),
701 DVec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
702 )
703 }
704
705 /// Creates a left-handed view matrix using a camera position, an up direction, and a focal
706 /// point.
707 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
708 ///
709 /// # Panics
710 ///
711 /// Will panic if `up` is not normalized when `glam_assert` is enabled.
712 #[inline]
713 #[must_use]
look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self714 pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
715 glam_assert!(up.is_normalized());
716 Self::look_to_lh(eye, center.sub(eye), up)
717 }
718
719 /// Creates a right-handed view matrix using a camera position, an up direction, and a focal
720 /// point.
721 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
722 ///
723 /// # Panics
724 ///
725 /// Will panic if `up` is not normalized when `glam_assert` is enabled.
726 #[inline]
look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self727 pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
728 glam_assert!(up.is_normalized());
729 Self::look_to_rh(eye, center.sub(eye), up)
730 }
731
732 /// Creates a right-handed perspective projection matrix with [-1,1] depth range.
733 /// This is the same as the OpenGL `gluPerspective` function.
734 /// See <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml>
735 #[inline]
736 #[must_use]
perspective_rh_gl( fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64, ) -> Self737 pub fn perspective_rh_gl(
738 fov_y_radians: f64,
739 aspect_ratio: f64,
740 z_near: f64,
741 z_far: f64,
742 ) -> Self {
743 let inv_length = 1.0 / (z_near - z_far);
744 let f = 1.0 / math::tan(0.5 * fov_y_radians);
745 let a = f / aspect_ratio;
746 let b = (z_near + z_far) * inv_length;
747 let c = (2.0 * z_near * z_far) * inv_length;
748 Self::from_cols(
749 DVec4::new(a, 0.0, 0.0, 0.0),
750 DVec4::new(0.0, f, 0.0, 0.0),
751 DVec4::new(0.0, 0.0, b, -1.0),
752 DVec4::new(0.0, 0.0, c, 0.0),
753 )
754 }
755
756 /// Creates a left-handed perspective projection matrix with `[0,1]` depth range.
757 ///
758 /// # Panics
759 ///
760 /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
761 /// enabled.
762 #[inline]
763 #[must_use]
perspective_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self764 pub fn perspective_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
765 glam_assert!(z_near > 0.0 && z_far > 0.0);
766 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
767 let h = cos_fov / sin_fov;
768 let w = h / aspect_ratio;
769 let r = z_far / (z_far - z_near);
770 Self::from_cols(
771 DVec4::new(w, 0.0, 0.0, 0.0),
772 DVec4::new(0.0, h, 0.0, 0.0),
773 DVec4::new(0.0, 0.0, r, 1.0),
774 DVec4::new(0.0, 0.0, -r * z_near, 0.0),
775 )
776 }
777
778 /// Creates a right-handed perspective projection matrix with `[0,1]` depth range.
779 ///
780 /// # Panics
781 ///
782 /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
783 /// enabled.
784 #[inline]
785 #[must_use]
perspective_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self786 pub fn perspective_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
787 glam_assert!(z_near > 0.0 && z_far > 0.0);
788 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
789 let h = cos_fov / sin_fov;
790 let w = h / aspect_ratio;
791 let r = z_far / (z_near - z_far);
792 Self::from_cols(
793 DVec4::new(w, 0.0, 0.0, 0.0),
794 DVec4::new(0.0, h, 0.0, 0.0),
795 DVec4::new(0.0, 0.0, r, -1.0),
796 DVec4::new(0.0, 0.0, r * z_near, 0.0),
797 )
798 }
799
800 /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range.
801 ///
802 /// # Panics
803 ///
804 /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
805 #[inline]
806 #[must_use]
perspective_infinite_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self807 pub fn perspective_infinite_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
808 glam_assert!(z_near > 0.0);
809 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
810 let h = cos_fov / sin_fov;
811 let w = h / aspect_ratio;
812 Self::from_cols(
813 DVec4::new(w, 0.0, 0.0, 0.0),
814 DVec4::new(0.0, h, 0.0, 0.0),
815 DVec4::new(0.0, 0.0, 1.0, 1.0),
816 DVec4::new(0.0, 0.0, -z_near, 0.0),
817 )
818 }
819
820 /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range.
821 ///
822 /// # Panics
823 ///
824 /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
825 #[inline]
826 #[must_use]
perspective_infinite_reverse_lh( fov_y_radians: f64, aspect_ratio: f64, z_near: f64, ) -> Self827 pub fn perspective_infinite_reverse_lh(
828 fov_y_radians: f64,
829 aspect_ratio: f64,
830 z_near: f64,
831 ) -> Self {
832 glam_assert!(z_near > 0.0);
833 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
834 let h = cos_fov / sin_fov;
835 let w = h / aspect_ratio;
836 Self::from_cols(
837 DVec4::new(w, 0.0, 0.0, 0.0),
838 DVec4::new(0.0, h, 0.0, 0.0),
839 DVec4::new(0.0, 0.0, 0.0, 1.0),
840 DVec4::new(0.0, 0.0, z_near, 0.0),
841 )
842 }
843
844 /// Creates an infinite right-handed perspective projection matrix with
845 /// `[0,1]` depth range.
846 #[inline]
847 #[must_use]
perspective_infinite_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self848 pub fn perspective_infinite_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
849 glam_assert!(z_near > 0.0);
850 let f = 1.0 / math::tan(0.5 * fov_y_radians);
851 Self::from_cols(
852 DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
853 DVec4::new(0.0, f, 0.0, 0.0),
854 DVec4::new(0.0, 0.0, -1.0, -1.0),
855 DVec4::new(0.0, 0.0, -z_near, 0.0),
856 )
857 }
858
859 /// Creates an infinite reverse right-handed perspective projection matrix
860 /// with `[0,1]` depth range.
861 #[inline]
862 #[must_use]
perspective_infinite_reverse_rh( fov_y_radians: f64, aspect_ratio: f64, z_near: f64, ) -> Self863 pub fn perspective_infinite_reverse_rh(
864 fov_y_radians: f64,
865 aspect_ratio: f64,
866 z_near: f64,
867 ) -> Self {
868 glam_assert!(z_near > 0.0);
869 let f = 1.0 / math::tan(0.5 * fov_y_radians);
870 Self::from_cols(
871 DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
872 DVec4::new(0.0, f, 0.0, 0.0),
873 DVec4::new(0.0, 0.0, 0.0, -1.0),
874 DVec4::new(0.0, 0.0, z_near, 0.0),
875 )
876 }
877
878 /// Creates a right-handed orthographic projection matrix with `[-1,1]` depth
879 /// range. This is the same as the OpenGL `glOrtho` function in OpenGL.
880 /// See
881 /// <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml>
882 #[inline]
883 #[must_use]
orthographic_rh_gl( left: f64, right: f64, bottom: f64, top: f64, near: f64, far: f64, ) -> Self884 pub fn orthographic_rh_gl(
885 left: f64,
886 right: f64,
887 bottom: f64,
888 top: f64,
889 near: f64,
890 far: f64,
891 ) -> Self {
892 let a = 2.0 / (right - left);
893 let b = 2.0 / (top - bottom);
894 let c = -2.0 / (far - near);
895 let tx = -(right + left) / (right - left);
896 let ty = -(top + bottom) / (top - bottom);
897 let tz = -(far + near) / (far - near);
898
899 Self::from_cols(
900 DVec4::new(a, 0.0, 0.0, 0.0),
901 DVec4::new(0.0, b, 0.0, 0.0),
902 DVec4::new(0.0, 0.0, c, 0.0),
903 DVec4::new(tx, ty, tz, 1.0),
904 )
905 }
906
907 /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range.
908 #[inline]
909 #[must_use]
orthographic_lh( left: f64, right: f64, bottom: f64, top: f64, near: f64, far: f64, ) -> Self910 pub fn orthographic_lh(
911 left: f64,
912 right: f64,
913 bottom: f64,
914 top: f64,
915 near: f64,
916 far: f64,
917 ) -> Self {
918 let rcp_width = 1.0 / (right - left);
919 let rcp_height = 1.0 / (top - bottom);
920 let r = 1.0 / (far - near);
921 Self::from_cols(
922 DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
923 DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
924 DVec4::new(0.0, 0.0, r, 0.0),
925 DVec4::new(
926 -(left + right) * rcp_width,
927 -(top + bottom) * rcp_height,
928 -r * near,
929 1.0,
930 ),
931 )
932 }
933
934 /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range.
935 #[inline]
936 #[must_use]
orthographic_rh( left: f64, right: f64, bottom: f64, top: f64, near: f64, far: f64, ) -> Self937 pub fn orthographic_rh(
938 left: f64,
939 right: f64,
940 bottom: f64,
941 top: f64,
942 near: f64,
943 far: f64,
944 ) -> Self {
945 let rcp_width = 1.0 / (right - left);
946 let rcp_height = 1.0 / (top - bottom);
947 let r = 1.0 / (near - far);
948 Self::from_cols(
949 DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
950 DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
951 DVec4::new(0.0, 0.0, r, 0.0),
952 DVec4::new(
953 -(left + right) * rcp_width,
954 -(top + bottom) * rcp_height,
955 r * near,
956 1.0,
957 ),
958 )
959 }
960
961 /// Transforms the given 3D vector as a point, applying perspective correction.
962 ///
963 /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is `1.0`.
964 /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
965 ///
966 /// This method assumes that `self` contains a projective transform.
967 #[inline]
968 #[must_use]
project_point3(&self, rhs: DVec3) -> DVec3969 pub fn project_point3(&self, rhs: DVec3) -> DVec3 {
970 let mut res = self.x_axis.mul(rhs.x);
971 res = self.y_axis.mul(rhs.y).add(res);
972 res = self.z_axis.mul(rhs.z).add(res);
973 res = self.w_axis.add(res);
974 res = res.mul(res.wwww().recip());
975 res.xyz()
976 }
977
978 /// Transforms the given 3D vector as a point.
979 ///
980 /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
981 /// `1.0`.
982 ///
983 /// This method assumes that `self` contains a valid affine transform. It does not perform
984 /// a persective divide, if `self` contains a perspective transform, or if you are unsure,
985 /// the [`Self::project_point3()`] method should be used instead.
986 ///
987 /// # Panics
988 ///
989 /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
990 #[inline]
991 #[must_use]
transform_point3(&self, rhs: DVec3) -> DVec3992 pub fn transform_point3(&self, rhs: DVec3) -> DVec3 {
993 glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
994 let mut res = self.x_axis.mul(rhs.x);
995 res = self.y_axis.mul(rhs.y).add(res);
996 res = self.z_axis.mul(rhs.z).add(res);
997 res = self.w_axis.add(res);
998 res.xyz()
999 }
1000
1001 /// Transforms the give 3D vector as a direction.
1002 ///
1003 /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
1004 /// `0.0`.
1005 ///
1006 /// This method assumes that `self` contains a valid affine transform.
1007 ///
1008 /// # Panics
1009 ///
1010 /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1011 #[inline]
1012 #[must_use]
transform_vector3(&self, rhs: DVec3) -> DVec31013 pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 {
1014 glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
1015 let mut res = self.x_axis.mul(rhs.x);
1016 res = self.y_axis.mul(rhs.y).add(res);
1017 res = self.z_axis.mul(rhs.z).add(res);
1018 res.xyz()
1019 }
1020
1021 /// Transforms a 4D vector.
1022 #[inline]
1023 #[must_use]
mul_vec4(&self, rhs: DVec4) -> DVec41024 pub fn mul_vec4(&self, rhs: DVec4) -> DVec4 {
1025 let mut res = self.x_axis.mul(rhs.x);
1026 res = res.add(self.y_axis.mul(rhs.y));
1027 res = res.add(self.z_axis.mul(rhs.z));
1028 res = res.add(self.w_axis.mul(rhs.w));
1029 res
1030 }
1031
1032 /// Multiplies two 4x4 matrices.
1033 #[inline]
1034 #[must_use]
mul_mat4(&self, rhs: &Self) -> Self1035 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1036 Self::from_cols(
1037 self.mul(rhs.x_axis),
1038 self.mul(rhs.y_axis),
1039 self.mul(rhs.z_axis),
1040 self.mul(rhs.w_axis),
1041 )
1042 }
1043
1044 /// Adds two 4x4 matrices.
1045 #[inline]
1046 #[must_use]
add_mat4(&self, rhs: &Self) -> Self1047 pub fn add_mat4(&self, rhs: &Self) -> Self {
1048 Self::from_cols(
1049 self.x_axis.add(rhs.x_axis),
1050 self.y_axis.add(rhs.y_axis),
1051 self.z_axis.add(rhs.z_axis),
1052 self.w_axis.add(rhs.w_axis),
1053 )
1054 }
1055
1056 /// Subtracts two 4x4 matrices.
1057 #[inline]
1058 #[must_use]
sub_mat4(&self, rhs: &Self) -> Self1059 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1060 Self::from_cols(
1061 self.x_axis.sub(rhs.x_axis),
1062 self.y_axis.sub(rhs.y_axis),
1063 self.z_axis.sub(rhs.z_axis),
1064 self.w_axis.sub(rhs.w_axis),
1065 )
1066 }
1067
1068 /// Multiplies a 4x4 matrix by a scalar.
1069 #[inline]
1070 #[must_use]
mul_scalar(&self, rhs: f64) -> Self1071 pub fn mul_scalar(&self, rhs: f64) -> Self {
1072 Self::from_cols(
1073 self.x_axis.mul(rhs),
1074 self.y_axis.mul(rhs),
1075 self.z_axis.mul(rhs),
1076 self.w_axis.mul(rhs),
1077 )
1078 }
1079
1080 /// Returns true if the absolute difference of all elements between `self` and `rhs`
1081 /// is less than or equal to `max_abs_diff`.
1082 ///
1083 /// This can be used to compare if two matrices contain similar elements. It works best
1084 /// when comparing with a known value. The `max_abs_diff` that should be used used
1085 /// depends on the values being compared against.
1086 ///
1087 /// For more see
1088 /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
1089 #[inline]
1090 #[must_use]
abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool1091 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
1092 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1093 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1094 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1095 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1096 }
1097
1098 #[inline]
as_mat4(&self) -> Mat41099 pub fn as_mat4(&self) -> Mat4 {
1100 Mat4::from_cols(
1101 self.x_axis.as_vec4(),
1102 self.y_axis.as_vec4(),
1103 self.z_axis.as_vec4(),
1104 self.w_axis.as_vec4(),
1105 )
1106 }
1107 }
1108
1109 impl Default for DMat4 {
1110 #[inline]
default() -> Self1111 fn default() -> Self {
1112 Self::IDENTITY
1113 }
1114 }
1115
1116 impl Add<DMat4> for DMat4 {
1117 type Output = Self;
1118 #[inline]
add(self, rhs: Self) -> Self::Output1119 fn add(self, rhs: Self) -> Self::Output {
1120 self.add_mat4(&rhs)
1121 }
1122 }
1123
1124 impl AddAssign<DMat4> for DMat4 {
1125 #[inline]
add_assign(&mut self, rhs: Self)1126 fn add_assign(&mut self, rhs: Self) {
1127 *self = self.add_mat4(&rhs);
1128 }
1129 }
1130
1131 impl Sub<DMat4> for DMat4 {
1132 type Output = Self;
1133 #[inline]
sub(self, rhs: Self) -> Self::Output1134 fn sub(self, rhs: Self) -> Self::Output {
1135 self.sub_mat4(&rhs)
1136 }
1137 }
1138
1139 impl SubAssign<DMat4> for DMat4 {
1140 #[inline]
sub_assign(&mut self, rhs: Self)1141 fn sub_assign(&mut self, rhs: Self) {
1142 *self = self.sub_mat4(&rhs);
1143 }
1144 }
1145
1146 impl Neg for DMat4 {
1147 type Output = Self;
1148 #[inline]
neg(self) -> Self::Output1149 fn neg(self) -> Self::Output {
1150 Self::from_cols(
1151 self.x_axis.neg(),
1152 self.y_axis.neg(),
1153 self.z_axis.neg(),
1154 self.w_axis.neg(),
1155 )
1156 }
1157 }
1158
1159 impl Mul<DMat4> for DMat4 {
1160 type Output = Self;
1161 #[inline]
mul(self, rhs: Self) -> Self::Output1162 fn mul(self, rhs: Self) -> Self::Output {
1163 self.mul_mat4(&rhs)
1164 }
1165 }
1166
1167 impl MulAssign<DMat4> for DMat4 {
1168 #[inline]
mul_assign(&mut self, rhs: Self)1169 fn mul_assign(&mut self, rhs: Self) {
1170 *self = self.mul_mat4(&rhs);
1171 }
1172 }
1173
1174 impl Mul<DVec4> for DMat4 {
1175 type Output = DVec4;
1176 #[inline]
mul(self, rhs: DVec4) -> Self::Output1177 fn mul(self, rhs: DVec4) -> Self::Output {
1178 self.mul_vec4(rhs)
1179 }
1180 }
1181
1182 impl Mul<DMat4> for f64 {
1183 type Output = DMat4;
1184 #[inline]
mul(self, rhs: DMat4) -> Self::Output1185 fn mul(self, rhs: DMat4) -> Self::Output {
1186 rhs.mul_scalar(self)
1187 }
1188 }
1189
1190 impl Mul<f64> for DMat4 {
1191 type Output = Self;
1192 #[inline]
mul(self, rhs: f64) -> Self::Output1193 fn mul(self, rhs: f64) -> Self::Output {
1194 self.mul_scalar(rhs)
1195 }
1196 }
1197
1198 impl MulAssign<f64> for DMat4 {
1199 #[inline]
mul_assign(&mut self, rhs: f64)1200 fn mul_assign(&mut self, rhs: f64) {
1201 *self = self.mul_scalar(rhs);
1202 }
1203 }
1204
1205 impl Sum<Self> for DMat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,1206 fn sum<I>(iter: I) -> Self
1207 where
1208 I: Iterator<Item = Self>,
1209 {
1210 iter.fold(Self::ZERO, Self::add)
1211 }
1212 }
1213
1214 impl<'a> Sum<&'a Self> for DMat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,1215 fn sum<I>(iter: I) -> Self
1216 where
1217 I: Iterator<Item = &'a Self>,
1218 {
1219 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1220 }
1221 }
1222
1223 impl Product for DMat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,1224 fn product<I>(iter: I) -> Self
1225 where
1226 I: Iterator<Item = Self>,
1227 {
1228 iter.fold(Self::IDENTITY, Self::mul)
1229 }
1230 }
1231
1232 impl<'a> Product<&'a Self> for DMat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,1233 fn product<I>(iter: I) -> Self
1234 where
1235 I: Iterator<Item = &'a Self>,
1236 {
1237 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1238 }
1239 }
1240
1241 impl PartialEq for DMat4 {
1242 #[inline]
eq(&self, rhs: &Self) -> bool1243 fn eq(&self, rhs: &Self) -> bool {
1244 self.x_axis.eq(&rhs.x_axis)
1245 && self.y_axis.eq(&rhs.y_axis)
1246 && self.z_axis.eq(&rhs.z_axis)
1247 && self.w_axis.eq(&rhs.w_axis)
1248 }
1249 }
1250
1251 #[cfg(not(target_arch = "spirv"))]
1252 impl AsRef<[f64; 16]> for DMat4 {
1253 #[inline]
as_ref(&self) -> &[f64; 16]1254 fn as_ref(&self) -> &[f64; 16] {
1255 unsafe { &*(self as *const Self as *const [f64; 16]) }
1256 }
1257 }
1258
1259 #[cfg(not(target_arch = "spirv"))]
1260 impl AsMut<[f64; 16]> for DMat4 {
1261 #[inline]
as_mut(&mut self) -> &mut [f64; 16]1262 fn as_mut(&mut self) -> &mut [f64; 16] {
1263 unsafe { &mut *(self as *mut Self as *mut [f64; 16]) }
1264 }
1265 }
1266
1267 #[cfg(not(target_arch = "spirv"))]
1268 impl fmt::Debug for DMat4 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result1269 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1270 fmt.debug_struct(stringify!(DMat4))
1271 .field("x_axis", &self.x_axis)
1272 .field("y_axis", &self.y_axis)
1273 .field("z_axis", &self.z_axis)
1274 .field("w_axis", &self.w_axis)
1275 .finish()
1276 }
1277 }
1278
1279 #[cfg(not(target_arch = "spirv"))]
1280 impl fmt::Display for DMat4 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1281 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1282 write!(
1283 f,
1284 "[{}, {}, {}, {}]",
1285 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1286 )
1287 }
1288 }
1289