1use crate::{DMat3, DMat4, DQuat, DVec3};
4use core::ops::{Deref, DerefMut, Mul, MulAssign};
5
6#[derive(Copy, Clone)]
8#[repr(C)]
9pub struct DAffine3 {
10 pub matrix3: DMat3,
11 pub translation: DVec3,
12}
13
14impl DAffine3 {
15 pub const ZERO: Self = Self {
20 matrix3: DMat3::ZERO,
21 translation: DVec3::ZERO,
22 };
23
24 pub const IDENTITY: Self = Self {
28 matrix3: DMat3::IDENTITY,
29 translation: DVec3::ZERO,
30 };
31
32 pub const NAN: Self = Self {
34 matrix3: DMat3::NAN,
35 translation: DVec3::NAN,
36 };
37
38 #[inline(always)]
40 #[must_use]
41 pub const fn from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3, w_axis: DVec3) -> Self {
42 Self {
43 matrix3: DMat3::from_cols(x_axis, y_axis, z_axis),
44 translation: w_axis,
45 }
46 }
47
48 #[inline]
50 #[must_use]
51 pub fn from_cols_array(m: &[f64; 12]) -> Self {
52 Self {
53 matrix3: DMat3::from_cols_array(&[
54 m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8],
55 ]),
56 translation: DVec3::from_array([m[9], m[10], m[11]]),
57 }
58 }
59
60 #[inline]
62 #[must_use]
63 pub fn to_cols_array(&self) -> [f64; 12] {
64 let x = &self.matrix3.x_axis;
65 let y = &self.matrix3.y_axis;
66 let z = &self.matrix3.z_axis;
67 let w = &self.translation;
68 [x.x, x.y, x.z, y.x, y.y, y.z, z.x, z.y, z.z, w.x, w.y, w.z]
69 }
70
71 #[inline]
76 #[must_use]
77 pub fn from_cols_array_2d(m: &[[f64; 3]; 4]) -> Self {
78 Self {
79 matrix3: DMat3::from_cols(m[0].into(), m[1].into(), m[2].into()),
80 translation: m[3].into(),
81 }
82 }
83
84 #[inline]
88 #[must_use]
89 pub fn to_cols_array_2d(&self) -> [[f64; 3]; 4] {
90 [
91 self.matrix3.x_axis.into(),
92 self.matrix3.y_axis.into(),
93 self.matrix3.z_axis.into(),
94 self.translation.into(),
95 ]
96 }
97
98 #[inline]
104 #[must_use]
105 pub fn from_cols_slice(slice: &[f64]) -> Self {
106 Self {
107 matrix3: DMat3::from_cols_slice(&slice[0..9]),
108 translation: DVec3::from_slice(&slice[9..12]),
109 }
110 }
111
112 #[inline]
118 pub fn write_cols_to_slice(self, slice: &mut [f64]) {
119 self.matrix3.write_cols_to_slice(&mut slice[0..9]);
120 self.translation.write_to_slice(&mut slice[9..12]);
121 }
122
123 #[inline]
126 #[must_use]
127 pub fn from_scale(scale: DVec3) -> Self {
128 Self {
129 matrix3: DMat3::from_diagonal(scale),
130 translation: DVec3::ZERO,
131 }
132 }
133 #[inline]
135 #[must_use]
136 pub fn from_quat(rotation: DQuat) -> Self {
137 Self {
138 matrix3: DMat3::from_quat(rotation),
139 translation: DVec3::ZERO,
140 }
141 }
142
143 #[inline]
146 #[must_use]
147 pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
148 Self {
149 matrix3: DMat3::from_axis_angle(axis, angle),
150 translation: DVec3::ZERO,
151 }
152 }
153
154 #[inline]
157 #[must_use]
158 pub fn from_rotation_x(angle: f64) -> Self {
159 Self {
160 matrix3: DMat3::from_rotation_x(angle),
161 translation: DVec3::ZERO,
162 }
163 }
164
165 #[inline]
168 #[must_use]
169 pub fn from_rotation_y(angle: f64) -> Self {
170 Self {
171 matrix3: DMat3::from_rotation_y(angle),
172 translation: DVec3::ZERO,
173 }
174 }
175
176 #[inline]
179 #[must_use]
180 pub fn from_rotation_z(angle: f64) -> Self {
181 Self {
182 matrix3: DMat3::from_rotation_z(angle),
183 translation: DVec3::ZERO,
184 }
185 }
186
187 #[inline]
189 #[must_use]
190 pub fn from_translation(translation: DVec3) -> Self {
191 #[allow(clippy::useless_conversion)]
192 Self {
193 matrix3: DMat3::IDENTITY,
194 translation: translation.into(),
195 }
196 }
197
198 #[inline]
201 #[must_use]
202 pub fn from_mat3(mat3: DMat3) -> Self {
203 #[allow(clippy::useless_conversion)]
204 Self {
205 matrix3: mat3.into(),
206 translation: DVec3::ZERO,
207 }
208 }
209
210 #[inline]
215 #[must_use]
216 pub fn from_mat3_translation(mat3: DMat3, translation: DVec3) -> Self {
217 #[allow(clippy::useless_conversion)]
218 Self {
219 matrix3: mat3.into(),
220 translation: translation.into(),
221 }
222 }
223
224 #[inline]
230 #[must_use]
231 pub fn from_scale_rotation_translation(
232 scale: DVec3,
233 rotation: DQuat,
234 translation: DVec3,
235 ) -> Self {
236 let rotation = DMat3::from_quat(rotation);
237 #[allow(clippy::useless_conversion)]
238 Self {
239 matrix3: DMat3::from_cols(
240 rotation.x_axis * scale.x,
241 rotation.y_axis * scale.y,
242 rotation.z_axis * scale.z,
243 ),
244 translation: translation.into(),
245 }
246 }
247
248 #[inline]
252 #[must_use]
253 pub fn from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self {
254 #[allow(clippy::useless_conversion)]
255 Self {
256 matrix3: DMat3::from_quat(rotation),
257 translation: translation.into(),
258 }
259 }
260
261 #[inline]
264 #[must_use]
265 pub fn from_mat4(m: DMat4) -> Self {
266 Self {
267 matrix3: DMat3::from_cols(
268 DVec3::from_vec4(m.x_axis),
269 DVec3::from_vec4(m.y_axis),
270 DVec3::from_vec4(m.z_axis),
271 ),
272 translation: DVec3::from_vec4(m.w_axis),
273 }
274 }
275
276 #[inline]
286 #[must_use]
287 pub fn to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3) {
288 use crate::f64::math;
289 let det = self.matrix3.determinant();
290 glam_assert!(det != 0.0);
291
292 let scale = DVec3::new(
293 self.matrix3.x_axis.length() * math::signum(det),
294 self.matrix3.y_axis.length(),
295 self.matrix3.z_axis.length(),
296 );
297
298 glam_assert!(scale.cmpne(DVec3::ZERO).all());
299
300 let inv_scale = scale.recip();
301
302 #[allow(clippy::useless_conversion)]
303 let rotation = DQuat::from_mat3(&DMat3::from_cols(
304 (self.matrix3.x_axis * inv_scale.x).into(),
305 (self.matrix3.y_axis * inv_scale.y).into(),
306 (self.matrix3.z_axis * inv_scale.z).into(),
307 ));
308
309 #[allow(clippy::useless_conversion)]
310 (scale, rotation, self.translation.into())
311 }
312
313 #[inline]
318 #[must_use]
319 pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
320 Self::look_to_rh(eye, -dir, up)
321 }
322
323 #[inline]
328 #[must_use]
329 pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
330 let f = dir.normalize();
331 let s = f.cross(up).normalize();
332 let u = s.cross(f);
333
334 Self {
335 matrix3: DMat3::from_cols(
336 DVec3::new(s.x, u.x, -f.x),
337 DVec3::new(s.y, u.y, -f.y),
338 DVec3::new(s.z, u.z, -f.z),
339 ),
340 translation: DVec3::new(-eye.dot(s), -eye.dot(u), eye.dot(f)),
341 }
342 }
343
344 #[inline]
352 #[must_use]
353 pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
354 glam_assert!(up.is_normalized());
355 Self::look_to_lh(eye, center - eye, up)
356 }
357
358 #[inline]
366 #[must_use]
367 pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
368 glam_assert!(up.is_normalized());
369 Self::look_to_rh(eye, center - eye, up)
370 }
371
372 #[inline]
374 pub fn transform_point3(&self, rhs: DVec3) -> DVec3 {
375 #[allow(clippy::useless_conversion)]
376 ((self.matrix3.x_axis * rhs.x)
377 + (self.matrix3.y_axis * rhs.y)
378 + (self.matrix3.z_axis * rhs.z)
379 + self.translation)
380 .into()
381 }
382
383 #[inline]
388 #[must_use]
389 pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 {
390 #[allow(clippy::useless_conversion)]
391 ((self.matrix3.x_axis * rhs.x)
392 + (self.matrix3.y_axis * rhs.y)
393 + (self.matrix3.z_axis * rhs.z))
394 .into()
395 }
396
397 #[inline]
402 #[must_use]
403 pub fn is_finite(&self) -> bool {
404 self.matrix3.is_finite() && self.translation.is_finite()
405 }
406
407 #[inline]
409 #[must_use]
410 pub fn is_nan(&self) -> bool {
411 self.matrix3.is_nan() || self.translation.is_nan()
412 }
413
414 #[inline]
424 #[must_use]
425 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
426 self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff)
427 && self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
428 }
429
430 #[inline]
434 #[must_use]
435 pub fn inverse(&self) -> Self {
436 let matrix3 = self.matrix3.inverse();
437 let translation = -(matrix3 * self.translation);
439
440 Self {
441 matrix3,
442 translation,
443 }
444 }
445
446 #[inline]
448 #[must_use]
449 pub fn as_affine3a(&self) -> crate::Affine3A {
450 crate::Affine3A::from_mat3_translation(self.matrix3.as_mat3(), self.translation.as_vec3())
451 }
452}
453
454impl Default for DAffine3 {
455 #[inline(always)]
456 fn default() -> Self {
457 Self::IDENTITY
458 }
459}
460
461impl Deref for DAffine3 {
462 type Target = crate::deref::Cols4<DVec3>;
463 #[inline(always)]
464 fn deref(&self) -> &Self::Target {
465 unsafe { &*(self as *const Self as *const Self::Target) }
466 }
467}
468
469impl DerefMut for DAffine3 {
470 #[inline(always)]
471 fn deref_mut(&mut self) -> &mut Self::Target {
472 unsafe { &mut *(self as *mut Self as *mut Self::Target) }
473 }
474}
475
476impl PartialEq for DAffine3 {
477 #[inline]
478 fn eq(&self, rhs: &Self) -> bool {
479 self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation)
480 }
481}
482
483impl core::fmt::Debug for DAffine3 {
484 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
485 fmt.debug_struct(stringify!(DAffine3))
486 .field("matrix3", &self.matrix3)
487 .field("translation", &self.translation)
488 .finish()
489 }
490}
491
492impl core::fmt::Display for DAffine3 {
493 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
494 if let Some(p) = f.precision() {
495 write!(
496 f,
497 "[{:.*}, {:.*}, {:.*}, {:.*}]",
498 p,
499 self.matrix3.x_axis,
500 p,
501 self.matrix3.y_axis,
502 p,
503 self.matrix3.z_axis,
504 p,
505 self.translation
506 )
507 } else {
508 write!(
509 f,
510 "[{}, {}, {}, {}]",
511 self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation
512 )
513 }
514 }
515}
516
517impl<'a> core::iter::Product<&'a Self> for DAffine3 {
518 fn product<I>(iter: I) -> Self
519 where
520 I: Iterator<Item = &'a Self>,
521 {
522 iter.fold(Self::IDENTITY, |a, &b| a * b)
523 }
524}
525
526impl Mul for DAffine3 {
527 type Output = DAffine3;
528
529 #[inline]
530 fn mul(self, rhs: DAffine3) -> Self::Output {
531 Self {
532 matrix3: self.matrix3 * rhs.matrix3,
533 translation: self.matrix3 * rhs.translation + self.translation,
534 }
535 }
536}
537
538impl MulAssign for DAffine3 {
539 #[inline]
540 fn mul_assign(&mut self, rhs: DAffine3) {
541 *self = self.mul(rhs);
542 }
543}
544
545impl From<DAffine3> for DMat4 {
546 #[inline]
547 fn from(m: DAffine3) -> DMat4 {
548 DMat4::from_cols(
549 m.matrix3.x_axis.extend(0.0),
550 m.matrix3.y_axis.extend(0.0),
551 m.matrix3.z_axis.extend(0.0),
552 m.translation.extend(1.0),
553 )
554 }
555}
556
557impl Mul<DMat4> for DAffine3 {
558 type Output = DMat4;
559
560 #[inline]
561 fn mul(self, rhs: DMat4) -> Self::Output {
562 DMat4::from(self) * rhs
563 }
564}
565
566impl Mul<DAffine3> for DMat4 {
567 type Output = DMat4;
568
569 #[inline]
570 fn mul(self, rhs: DAffine3) -> Self::Output {
571 self * DMat4::from(rhs)
572 }
573}