1 // Generated from mat.rs.tera template. Edit the template, not the generated file.
2
3 use crate::{
4 euler::{FromEuler, ToEuler},
5 f64::math,
6 swizzles::*,
7 DMat2, DMat4, DQuat, DVec2, DVec3, EulerRot, Mat3,
8 };
9 use core::fmt;
10 use core::iter::{Product, Sum};
11 use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
12
13 /// Creates a 3x3 matrix from three column vectors.
14 #[inline(always)]
15 #[must_use]
dmat3(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> DMat316 pub const fn dmat3(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> DMat3 {
17 DMat3::from_cols(x_axis, y_axis, z_axis)
18 }
19
20 /// A 3x3 column major matrix.
21 ///
22 /// This 3x3 matrix type features convenience methods for creating and using linear and
23 /// affine transformations. If you are primarily dealing with 2D affine transformations the
24 /// [`DAffine2`](crate::DAffine2) type is much faster and more space efficient than
25 /// using a 3x3 matrix.
26 ///
27 /// Linear transformations including 3D rotation and scale can be created using methods
28 /// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`],
29 /// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or
30 /// [`Self::from_rotation_z()`].
31 ///
32 /// The resulting matrices can be use to transform 3D vectors using regular vector
33 /// multiplication.
34 ///
35 /// Affine transformations including 2D translation, rotation and scale can be created
36 /// using methods such as [`Self::from_translation()`], [`Self::from_angle()`],
37 /// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`].
38 ///
39 /// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods
40 /// are provided for performing affine transforms on 2D vectors and points. These multiply
41 /// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for
42 /// vectors respectively. These methods assume that `Self` contains a valid affine
43 /// transform.
44 #[derive(Clone, Copy)]
45 #[repr(C)]
46 pub struct DMat3 {
47 pub x_axis: DVec3,
48 pub y_axis: DVec3,
49 pub z_axis: DVec3,
50 }
51
52 impl DMat3 {
53 /// A 3x3 matrix with all elements set to `0.0`.
54 pub const ZERO: Self = Self::from_cols(DVec3::ZERO, DVec3::ZERO, DVec3::ZERO);
55
56 /// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
57 pub const IDENTITY: Self = Self::from_cols(DVec3::X, DVec3::Y, DVec3::Z);
58
59 /// All NAN:s.
60 pub const NAN: Self = Self::from_cols(DVec3::NAN, DVec3::NAN, DVec3::NAN);
61
62 #[allow(clippy::too_many_arguments)]
63 #[inline(always)]
64 #[must_use]
new( m00: f64, m01: f64, m02: f64, m10: f64, m11: f64, m12: f64, m20: f64, m21: f64, m22: f64, ) -> Self65 const fn new(
66 m00: f64,
67 m01: f64,
68 m02: f64,
69 m10: f64,
70 m11: f64,
71 m12: f64,
72 m20: f64,
73 m21: f64,
74 m22: f64,
75 ) -> Self {
76 Self {
77 x_axis: DVec3::new(m00, m01, m02),
78 y_axis: DVec3::new(m10, m11, m12),
79 z_axis: DVec3::new(m20, m21, m22),
80 }
81 }
82
83 /// Creates a 3x3 matrix from three column vectors.
84 #[inline(always)]
85 #[must_use]
from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> Self86 pub const fn from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> Self {
87 Self {
88 x_axis,
89 y_axis,
90 z_axis,
91 }
92 }
93
94 /// Creates a 3x3 matrix from a `[f64; 9]` array stored in column major order.
95 /// If your data is stored in row major you will need to `transpose` the returned
96 /// matrix.
97 #[inline]
98 #[must_use]
from_cols_array(m: &[f64; 9]) -> Self99 pub const fn from_cols_array(m: &[f64; 9]) -> Self {
100 Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
101 }
102
103 /// Creates a `[f64; 9]` array storing data in column major order.
104 /// If you require data in row major order `transpose` the matrix first.
105 #[inline]
106 #[must_use]
to_cols_array(&self) -> [f64; 9]107 pub const fn to_cols_array(&self) -> [f64; 9] {
108 [
109 self.x_axis.x,
110 self.x_axis.y,
111 self.x_axis.z,
112 self.y_axis.x,
113 self.y_axis.y,
114 self.y_axis.z,
115 self.z_axis.x,
116 self.z_axis.y,
117 self.z_axis.z,
118 ]
119 }
120
121 /// Creates a 3x3 matrix from a `[[f64; 3]; 3]` 3D array stored in column major order.
122 /// If your data is in row major order you will need to `transpose` the returned
123 /// matrix.
124 #[inline]
125 #[must_use]
from_cols_array_2d(m: &[[f64; 3]; 3]) -> Self126 pub const fn from_cols_array_2d(m: &[[f64; 3]; 3]) -> Self {
127 Self::from_cols(
128 DVec3::from_array(m[0]),
129 DVec3::from_array(m[1]),
130 DVec3::from_array(m[2]),
131 )
132 }
133
134 /// Creates a `[[f64; 3]; 3]` 3D array storing data in column major order.
135 /// If you require data in row major order `transpose` the matrix first.
136 #[inline]
137 #[must_use]
to_cols_array_2d(&self) -> [[f64; 3]; 3]138 pub const fn to_cols_array_2d(&self) -> [[f64; 3]; 3] {
139 [
140 self.x_axis.to_array(),
141 self.y_axis.to_array(),
142 self.z_axis.to_array(),
143 ]
144 }
145
146 /// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
147 #[doc(alias = "scale")]
148 #[inline]
149 #[must_use]
from_diagonal(diagonal: DVec3) -> Self150 pub const fn from_diagonal(diagonal: DVec3) -> Self {
151 Self::new(
152 diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
153 )
154 }
155
156 /// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
157 #[inline]
158 #[must_use]
from_mat4(m: DMat4) -> Self159 pub fn from_mat4(m: DMat4) -> Self {
160 Self::from_cols(
161 DVec3::from_vec4(m.x_axis),
162 DVec3::from_vec4(m.y_axis),
163 DVec3::from_vec4(m.z_axis),
164 )
165 }
166
167 /// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column
168 /// and `j`th row.
169 ///
170 /// # Panics
171 ///
172 /// Panics if `i` or `j` is greater than 3.
173 #[inline]
174 #[must_use]
from_mat4_minor(m: DMat4, i: usize, j: usize) -> Self175 pub fn from_mat4_minor(m: DMat4, i: usize, j: usize) -> Self {
176 match (i, j) {
177 (0, 0) => Self::from_cols(m.y_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()),
178 (0, 1) => Self::from_cols(m.y_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()),
179 (0, 2) => Self::from_cols(m.y_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()),
180 (0, 3) => Self::from_cols(m.y_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()),
181 (1, 0) => Self::from_cols(m.x_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()),
182 (1, 1) => Self::from_cols(m.x_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()),
183 (1, 2) => Self::from_cols(m.x_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()),
184 (1, 3) => Self::from_cols(m.x_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()),
185 (2, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.w_axis.yzw()),
186 (2, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.w_axis.xzw()),
187 (2, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.w_axis.xyw()),
188 (2, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.w_axis.xyz()),
189 (3, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.z_axis.yzw()),
190 (3, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.z_axis.xzw()),
191 (3, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.z_axis.xyw()),
192 (3, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.z_axis.xyz()),
193 _ => panic!("index out of bounds"),
194 }
195 }
196
197 /// Creates a 3D rotation matrix from the given quaternion.
198 ///
199 /// # Panics
200 ///
201 /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
202 #[inline]
203 #[must_use]
from_quat(rotation: DQuat) -> Self204 pub fn from_quat(rotation: DQuat) -> Self {
205 glam_assert!(rotation.is_normalized());
206
207 let x2 = rotation.x + rotation.x;
208 let y2 = rotation.y + rotation.y;
209 let z2 = rotation.z + rotation.z;
210 let xx = rotation.x * x2;
211 let xy = rotation.x * y2;
212 let xz = rotation.x * z2;
213 let yy = rotation.y * y2;
214 let yz = rotation.y * z2;
215 let zz = rotation.z * z2;
216 let wx = rotation.w * x2;
217 let wy = rotation.w * y2;
218 let wz = rotation.w * z2;
219
220 Self::from_cols(
221 DVec3::new(1.0 - (yy + zz), xy + wz, xz - wy),
222 DVec3::new(xy - wz, 1.0 - (xx + zz), yz + wx),
223 DVec3::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
224 )
225 }
226
227 /// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in
228 /// radians).
229 ///
230 /// # Panics
231 ///
232 /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
233 #[inline]
234 #[must_use]
from_axis_angle(axis: DVec3, angle: f64) -> Self235 pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
236 glam_assert!(axis.is_normalized());
237
238 let (sin, cos) = math::sin_cos(angle);
239 let (xsin, ysin, zsin) = axis.mul(sin).into();
240 let (x, y, z) = axis.into();
241 let (x2, y2, z2) = axis.mul(axis).into();
242 let omc = 1.0 - cos;
243 let xyomc = x * y * omc;
244 let xzomc = x * z * omc;
245 let yzomc = y * z * omc;
246 Self::from_cols(
247 DVec3::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
248 DVec3::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
249 DVec3::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
250 )
251 }
252
253 /// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
254 /// radians).
255 #[inline]
256 #[must_use]
from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self257 pub fn from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self {
258 Self::from_euler_angles(order, a, b, c)
259 }
260
261 /// Extract Euler angles with the given Euler rotation order.
262 ///
263 /// Note if the input matrix contains scales, shears, or other non-rotation transformations then
264 /// the resulting Euler angles will be ill-defined.
265 ///
266 /// # Panics
267 ///
268 /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
269 #[inline]
270 #[must_use]
to_euler(&self, order: EulerRot) -> (f64, f64, f64)271 pub fn to_euler(&self, order: EulerRot) -> (f64, f64, f64) {
272 glam_assert!(
273 self.x_axis.is_normalized()
274 && self.y_axis.is_normalized()
275 && self.z_axis.is_normalized()
276 );
277 self.to_euler_angles(order)
278 }
279
280 /// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
281 #[inline]
282 #[must_use]
from_rotation_x(angle: f64) -> Self283 pub fn from_rotation_x(angle: f64) -> Self {
284 let (sina, cosa) = math::sin_cos(angle);
285 Self::from_cols(
286 DVec3::X,
287 DVec3::new(0.0, cosa, sina),
288 DVec3::new(0.0, -sina, cosa),
289 )
290 }
291
292 /// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
293 #[inline]
294 #[must_use]
from_rotation_y(angle: f64) -> Self295 pub fn from_rotation_y(angle: f64) -> Self {
296 let (sina, cosa) = math::sin_cos(angle);
297 Self::from_cols(
298 DVec3::new(cosa, 0.0, -sina),
299 DVec3::Y,
300 DVec3::new(sina, 0.0, cosa),
301 )
302 }
303
304 /// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
305 #[inline]
306 #[must_use]
from_rotation_z(angle: f64) -> Self307 pub fn from_rotation_z(angle: f64) -> Self {
308 let (sina, cosa) = math::sin_cos(angle);
309 Self::from_cols(
310 DVec3::new(cosa, sina, 0.0),
311 DVec3::new(-sina, cosa, 0.0),
312 DVec3::Z,
313 )
314 }
315
316 /// Creates an affine transformation matrix from the given 2D `translation`.
317 ///
318 /// The resulting matrix can be used to transform 2D points and vectors. See
319 /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
320 #[inline]
321 #[must_use]
from_translation(translation: DVec2) -> Self322 pub fn from_translation(translation: DVec2) -> Self {
323 Self::from_cols(
324 DVec3::X,
325 DVec3::Y,
326 DVec3::new(translation.x, translation.y, 1.0),
327 )
328 }
329
330 /// Creates an affine transformation matrix from the given 2D rotation `angle` (in
331 /// radians).
332 ///
333 /// The resulting matrix can be used to transform 2D points and vectors. See
334 /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
335 #[inline]
336 #[must_use]
from_angle(angle: f64) -> Self337 pub fn from_angle(angle: f64) -> Self {
338 let (sin, cos) = math::sin_cos(angle);
339 Self::from_cols(
340 DVec3::new(cos, sin, 0.0),
341 DVec3::new(-sin, cos, 0.0),
342 DVec3::Z,
343 )
344 }
345
346 /// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in
347 /// radians) and `translation`.
348 ///
349 /// The resulting matrix can be used to transform 2D points and vectors. See
350 /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
351 #[inline]
352 #[must_use]
from_scale_angle_translation(scale: DVec2, angle: f64, translation: DVec2) -> Self353 pub fn from_scale_angle_translation(scale: DVec2, angle: f64, translation: DVec2) -> Self {
354 let (sin, cos) = math::sin_cos(angle);
355 Self::from_cols(
356 DVec3::new(cos * scale.x, sin * scale.x, 0.0),
357 DVec3::new(-sin * scale.y, cos * scale.y, 0.0),
358 DVec3::new(translation.x, translation.y, 1.0),
359 )
360 }
361
362 /// Creates an affine transformation matrix from the given non-uniform 2D `scale`.
363 ///
364 /// The resulting matrix can be used to transform 2D points and vectors. See
365 /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
366 ///
367 /// # Panics
368 ///
369 /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
370 #[inline]
371 #[must_use]
from_scale(scale: DVec2) -> Self372 pub fn from_scale(scale: DVec2) -> Self {
373 // Do not panic as long as any component is non-zero
374 glam_assert!(scale.cmpne(DVec2::ZERO).any());
375
376 Self::from_cols(
377 DVec3::new(scale.x, 0.0, 0.0),
378 DVec3::new(0.0, scale.y, 0.0),
379 DVec3::Z,
380 )
381 }
382
383 /// Creates an affine transformation matrix from the given 2x2 matrix.
384 ///
385 /// The resulting matrix can be used to transform 2D points and vectors. See
386 /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
387 #[inline]
from_mat2(m: DMat2) -> Self388 pub fn from_mat2(m: DMat2) -> Self {
389 Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), DVec3::Z)
390 }
391
392 /// Creates a 3x3 matrix from the first 9 values in `slice`.
393 ///
394 /// # Panics
395 ///
396 /// Panics if `slice` is less than 9 elements long.
397 #[inline]
398 #[must_use]
from_cols_slice(slice: &[f64]) -> Self399 pub const fn from_cols_slice(slice: &[f64]) -> Self {
400 Self::new(
401 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
402 slice[8],
403 )
404 }
405
406 /// Writes the columns of `self` to the first 9 elements in `slice`.
407 ///
408 /// # Panics
409 ///
410 /// Panics if `slice` is less than 9 elements long.
411 #[inline]
write_cols_to_slice(self, slice: &mut [f64])412 pub fn write_cols_to_slice(self, slice: &mut [f64]) {
413 slice[0] = self.x_axis.x;
414 slice[1] = self.x_axis.y;
415 slice[2] = self.x_axis.z;
416 slice[3] = self.y_axis.x;
417 slice[4] = self.y_axis.y;
418 slice[5] = self.y_axis.z;
419 slice[6] = self.z_axis.x;
420 slice[7] = self.z_axis.y;
421 slice[8] = self.z_axis.z;
422 }
423
424 /// Returns the matrix column for the given `index`.
425 ///
426 /// # Panics
427 ///
428 /// Panics if `index` is greater than 2.
429 #[inline]
430 #[must_use]
col(&self, index: usize) -> DVec3431 pub fn col(&self, index: usize) -> DVec3 {
432 match index {
433 0 => self.x_axis,
434 1 => self.y_axis,
435 2 => self.z_axis,
436 _ => panic!("index out of bounds"),
437 }
438 }
439
440 /// Returns a mutable reference to the matrix column for the given `index`.
441 ///
442 /// # Panics
443 ///
444 /// Panics if `index` is greater than 2.
445 #[inline]
col_mut(&mut self, index: usize) -> &mut DVec3446 pub fn col_mut(&mut self, index: usize) -> &mut DVec3 {
447 match index {
448 0 => &mut self.x_axis,
449 1 => &mut self.y_axis,
450 2 => &mut self.z_axis,
451 _ => panic!("index out of bounds"),
452 }
453 }
454
455 /// Returns the matrix row for the given `index`.
456 ///
457 /// # Panics
458 ///
459 /// Panics if `index` is greater than 2.
460 #[inline]
461 #[must_use]
row(&self, index: usize) -> DVec3462 pub fn row(&self, index: usize) -> DVec3 {
463 match index {
464 0 => DVec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
465 1 => DVec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
466 2 => DVec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
467 _ => panic!("index out of bounds"),
468 }
469 }
470
471 /// Returns `true` if, and only if, all elements are finite.
472 /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
473 #[inline]
474 #[must_use]
is_finite(&self) -> bool475 pub fn is_finite(&self) -> bool {
476 self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
477 }
478
479 /// Returns `true` if any elements are `NaN`.
480 #[inline]
481 #[must_use]
is_nan(&self) -> bool482 pub fn is_nan(&self) -> bool {
483 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
484 }
485
486 /// Returns the transpose of `self`.
487 #[inline]
488 #[must_use]
transpose(&self) -> Self489 pub fn transpose(&self) -> Self {
490 Self {
491 x_axis: DVec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
492 y_axis: DVec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
493 z_axis: DVec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
494 }
495 }
496
497 /// Returns the determinant of `self`.
498 #[inline]
499 #[must_use]
determinant(&self) -> f64500 pub fn determinant(&self) -> f64 {
501 self.z_axis.dot(self.x_axis.cross(self.y_axis))
502 }
503
504 /// Returns the inverse of `self`.
505 ///
506 /// If the matrix is not invertible the returned matrix will be invalid.
507 ///
508 /// # Panics
509 ///
510 /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
511 #[inline]
512 #[must_use]
inverse(&self) -> Self513 pub fn inverse(&self) -> Self {
514 let tmp0 = self.y_axis.cross(self.z_axis);
515 let tmp1 = self.z_axis.cross(self.x_axis);
516 let tmp2 = self.x_axis.cross(self.y_axis);
517 let det = self.z_axis.dot(tmp2);
518 glam_assert!(det != 0.0);
519 let inv_det = DVec3::splat(det.recip());
520 Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose()
521 }
522
523 /// Transforms the given 2D vector as a point.
524 ///
525 /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`.
526 ///
527 /// This method assumes that `self` contains a valid affine transform.
528 ///
529 /// # Panics
530 ///
531 /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
532 #[inline]
533 #[must_use]
transform_point2(&self, rhs: DVec2) -> DVec2534 pub fn transform_point2(&self, rhs: DVec2) -> DVec2 {
535 glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
536 DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
537 }
538
539 /// Rotates the given 2D vector.
540 ///
541 /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`.
542 ///
543 /// This method assumes that `self` contains a valid affine transform.
544 ///
545 /// # Panics
546 ///
547 /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
548 #[inline]
549 #[must_use]
transform_vector2(&self, rhs: DVec2) -> DVec2550 pub fn transform_vector2(&self, rhs: DVec2) -> DVec2 {
551 glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
552 DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
553 }
554
555 /// Creates a left-handed view matrix using a facing direction and an up direction.
556 ///
557 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
558 ///
559 /// # Panics
560 ///
561 /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled.
562 #[inline]
563 #[must_use]
look_to_lh(dir: DVec3, up: DVec3) -> Self564 pub fn look_to_lh(dir: DVec3, up: DVec3) -> Self {
565 Self::look_to_rh(-dir, up)
566 }
567
568 /// Creates a right-handed view matrix using a facing direction and an up direction.
569 ///
570 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
571 ///
572 /// # Panics
573 ///
574 /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled.
575 #[inline]
576 #[must_use]
look_to_rh(dir: DVec3, up: DVec3) -> Self577 pub fn look_to_rh(dir: DVec3, up: DVec3) -> Self {
578 glam_assert!(dir.is_normalized());
579 glam_assert!(up.is_normalized());
580 let f = dir;
581 let s = f.cross(up).normalize();
582 let u = s.cross(f);
583
584 Self::from_cols(
585 DVec3::new(s.x, u.x, -f.x),
586 DVec3::new(s.y, u.y, -f.y),
587 DVec3::new(s.z, u.z, -f.z),
588 )
589 }
590
591 /// Creates a left-handed view matrix using a camera position, a focal point and an up
592 /// direction.
593 ///
594 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
595 ///
596 /// # Panics
597 ///
598 /// Will panic if `up` is not normalized when `glam_assert` is enabled.
599 #[inline]
600 #[must_use]
look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self601 pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
602 Self::look_to_lh(center.sub(eye).normalize(), up)
603 }
604
605 /// Creates a right-handed view matrix using a camera position, a focal point and an up
606 /// direction.
607 ///
608 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
609 ///
610 /// # Panics
611 ///
612 /// Will panic if `up` is not normalized when `glam_assert` is enabled.
613 #[inline]
look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self614 pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
615 Self::look_to_rh(center.sub(eye).normalize(), up)
616 }
617
618 /// Transforms a 3D vector.
619 #[inline]
620 #[must_use]
mul_vec3(&self, rhs: DVec3) -> DVec3621 pub fn mul_vec3(&self, rhs: DVec3) -> DVec3 {
622 let mut res = self.x_axis.mul(rhs.x);
623 res = res.add(self.y_axis.mul(rhs.y));
624 res = res.add(self.z_axis.mul(rhs.z));
625 res
626 }
627
628 /// Multiplies two 3x3 matrices.
629 #[inline]
630 #[must_use]
mul_mat3(&self, rhs: &Self) -> Self631 pub fn mul_mat3(&self, rhs: &Self) -> Self {
632 Self::from_cols(
633 self.mul(rhs.x_axis),
634 self.mul(rhs.y_axis),
635 self.mul(rhs.z_axis),
636 )
637 }
638
639 /// Adds two 3x3 matrices.
640 #[inline]
641 #[must_use]
add_mat3(&self, rhs: &Self) -> Self642 pub fn add_mat3(&self, rhs: &Self) -> Self {
643 Self::from_cols(
644 self.x_axis.add(rhs.x_axis),
645 self.y_axis.add(rhs.y_axis),
646 self.z_axis.add(rhs.z_axis),
647 )
648 }
649
650 /// Subtracts two 3x3 matrices.
651 #[inline]
652 #[must_use]
sub_mat3(&self, rhs: &Self) -> Self653 pub fn sub_mat3(&self, rhs: &Self) -> Self {
654 Self::from_cols(
655 self.x_axis.sub(rhs.x_axis),
656 self.y_axis.sub(rhs.y_axis),
657 self.z_axis.sub(rhs.z_axis),
658 )
659 }
660
661 /// Multiplies a 3x3 matrix by a scalar.
662 #[inline]
663 #[must_use]
mul_scalar(&self, rhs: f64) -> Self664 pub fn mul_scalar(&self, rhs: f64) -> Self {
665 Self::from_cols(
666 self.x_axis.mul(rhs),
667 self.y_axis.mul(rhs),
668 self.z_axis.mul(rhs),
669 )
670 }
671
672 /// Divides a 3x3 matrix by a scalar.
673 #[inline]
674 #[must_use]
div_scalar(&self, rhs: f64) -> Self675 pub fn div_scalar(&self, rhs: f64) -> Self {
676 let rhs = DVec3::splat(rhs);
677 Self::from_cols(
678 self.x_axis.div(rhs),
679 self.y_axis.div(rhs),
680 self.z_axis.div(rhs),
681 )
682 }
683
684 /// Returns true if the absolute difference of all elements between `self` and `rhs`
685 /// is less than or equal to `max_abs_diff`.
686 ///
687 /// This can be used to compare if two matrices contain similar elements. It works best
688 /// when comparing with a known value. The `max_abs_diff` that should be used used
689 /// depends on the values being compared against.
690 ///
691 /// For more see
692 /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
693 #[inline]
694 #[must_use]
abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool695 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
696 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
697 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
698 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
699 }
700
701 /// Takes the absolute value of each element in `self`
702 #[inline]
703 #[must_use]
abs(&self) -> Self704 pub fn abs(&self) -> Self {
705 Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
706 }
707
708 #[inline]
as_mat3(&self) -> Mat3709 pub fn as_mat3(&self) -> Mat3 {
710 Mat3::from_cols(
711 self.x_axis.as_vec3(),
712 self.y_axis.as_vec3(),
713 self.z_axis.as_vec3(),
714 )
715 }
716 }
717
718 impl Default for DMat3 {
719 #[inline]
default() -> Self720 fn default() -> Self {
721 Self::IDENTITY
722 }
723 }
724
725 impl Add<DMat3> for DMat3 {
726 type Output = Self;
727 #[inline]
add(self, rhs: Self) -> Self::Output728 fn add(self, rhs: Self) -> Self::Output {
729 self.add_mat3(&rhs)
730 }
731 }
732
733 impl AddAssign<DMat3> for DMat3 {
734 #[inline]
add_assign(&mut self, rhs: Self)735 fn add_assign(&mut self, rhs: Self) {
736 *self = self.add_mat3(&rhs);
737 }
738 }
739
740 impl Sub<DMat3> for DMat3 {
741 type Output = Self;
742 #[inline]
sub(self, rhs: Self) -> Self::Output743 fn sub(self, rhs: Self) -> Self::Output {
744 self.sub_mat3(&rhs)
745 }
746 }
747
748 impl SubAssign<DMat3> for DMat3 {
749 #[inline]
sub_assign(&mut self, rhs: Self)750 fn sub_assign(&mut self, rhs: Self) {
751 *self = self.sub_mat3(&rhs);
752 }
753 }
754
755 impl Neg for DMat3 {
756 type Output = Self;
757 #[inline]
neg(self) -> Self::Output758 fn neg(self) -> Self::Output {
759 Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
760 }
761 }
762
763 impl Mul<DMat3> for DMat3 {
764 type Output = Self;
765 #[inline]
mul(self, rhs: Self) -> Self::Output766 fn mul(self, rhs: Self) -> Self::Output {
767 self.mul_mat3(&rhs)
768 }
769 }
770
771 impl MulAssign<DMat3> for DMat3 {
772 #[inline]
mul_assign(&mut self, rhs: Self)773 fn mul_assign(&mut self, rhs: Self) {
774 *self = self.mul_mat3(&rhs);
775 }
776 }
777
778 impl Mul<DVec3> for DMat3 {
779 type Output = DVec3;
780 #[inline]
mul(self, rhs: DVec3) -> Self::Output781 fn mul(self, rhs: DVec3) -> Self::Output {
782 self.mul_vec3(rhs)
783 }
784 }
785
786 impl Mul<DMat3> for f64 {
787 type Output = DMat3;
788 #[inline]
mul(self, rhs: DMat3) -> Self::Output789 fn mul(self, rhs: DMat3) -> Self::Output {
790 rhs.mul_scalar(self)
791 }
792 }
793
794 impl Mul<f64> for DMat3 {
795 type Output = Self;
796 #[inline]
mul(self, rhs: f64) -> Self::Output797 fn mul(self, rhs: f64) -> Self::Output {
798 self.mul_scalar(rhs)
799 }
800 }
801
802 impl MulAssign<f64> for DMat3 {
803 #[inline]
mul_assign(&mut self, rhs: f64)804 fn mul_assign(&mut self, rhs: f64) {
805 *self = self.mul_scalar(rhs);
806 }
807 }
808
809 impl Div<DMat3> for f64 {
810 type Output = DMat3;
811 #[inline]
div(self, rhs: DMat3) -> Self::Output812 fn div(self, rhs: DMat3) -> Self::Output {
813 rhs.div_scalar(self)
814 }
815 }
816
817 impl Div<f64> for DMat3 {
818 type Output = Self;
819 #[inline]
div(self, rhs: f64) -> Self::Output820 fn div(self, rhs: f64) -> Self::Output {
821 self.div_scalar(rhs)
822 }
823 }
824
825 impl DivAssign<f64> for DMat3 {
826 #[inline]
div_assign(&mut self, rhs: f64)827 fn div_assign(&mut self, rhs: f64) {
828 *self = self.div_scalar(rhs);
829 }
830 }
831
832 impl Sum<Self> for DMat3 {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,833 fn sum<I>(iter: I) -> Self
834 where
835 I: Iterator<Item = Self>,
836 {
837 iter.fold(Self::ZERO, Self::add)
838 }
839 }
840
841 impl<'a> Sum<&'a Self> for DMat3 {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,842 fn sum<I>(iter: I) -> Self
843 where
844 I: Iterator<Item = &'a Self>,
845 {
846 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
847 }
848 }
849
850 impl Product for DMat3 {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,851 fn product<I>(iter: I) -> Self
852 where
853 I: Iterator<Item = Self>,
854 {
855 iter.fold(Self::IDENTITY, Self::mul)
856 }
857 }
858
859 impl<'a> Product<&'a Self> for DMat3 {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,860 fn product<I>(iter: I) -> Self
861 where
862 I: Iterator<Item = &'a Self>,
863 {
864 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
865 }
866 }
867
868 impl PartialEq for DMat3 {
869 #[inline]
eq(&self, rhs: &Self) -> bool870 fn eq(&self, rhs: &Self) -> bool {
871 self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
872 }
873 }
874
875 #[cfg(not(target_arch = "spirv"))]
876 impl AsRef<[f64; 9]> for DMat3 {
877 #[inline]
as_ref(&self) -> &[f64; 9]878 fn as_ref(&self) -> &[f64; 9] {
879 unsafe { &*(self as *const Self as *const [f64; 9]) }
880 }
881 }
882
883 #[cfg(not(target_arch = "spirv"))]
884 impl AsMut<[f64; 9]> for DMat3 {
885 #[inline]
as_mut(&mut self) -> &mut [f64; 9]886 fn as_mut(&mut self) -> &mut [f64; 9] {
887 unsafe { &mut *(self as *mut Self as *mut [f64; 9]) }
888 }
889 }
890
891 impl fmt::Debug for DMat3 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result892 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
893 fmt.debug_struct(stringify!(DMat3))
894 .field("x_axis", &self.x_axis)
895 .field("y_axis", &self.y_axis)
896 .field("z_axis", &self.z_axis)
897 .finish()
898 }
899 }
900
901 impl fmt::Display for DMat3 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result902 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
903 if let Some(p) = f.precision() {
904 write!(
905 f,
906 "[{:.*}, {:.*}, {:.*}]",
907 p, self.x_axis, p, self.y_axis, p, self.z_axis
908 )
909 } else {
910 write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
911 }
912 }
913 }
914