1use crate::{DMat3, DMat4, DQuat, DVec3};
4use core::ops::{Deref, DerefMut, Mul, MulAssign};
5
6#[derive(Copy, Clone)]
8#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
9#[repr(C)]
10pub struct DAffine3 {
11 pub matrix3: DMat3,
12 pub translation: DVec3,
13}
14
15impl DAffine3 {
16 pub const ZERO: Self = Self {
21 matrix3: DMat3::ZERO,
22 translation: DVec3::ZERO,
23 };
24
25 pub const IDENTITY: Self = Self {
29 matrix3: DMat3::IDENTITY,
30 translation: DVec3::ZERO,
31 };
32
33 pub const NAN: Self = Self {
35 matrix3: DMat3::NAN,
36 translation: DVec3::NAN,
37 };
38
39 #[inline(always)]
41 #[must_use]
42 pub const fn from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3, w_axis: DVec3) -> Self {
43 Self {
44 matrix3: DMat3::from_cols(x_axis, y_axis, z_axis),
45 translation: w_axis,
46 }
47 }
48
49 #[inline]
51 #[must_use]
52 pub fn from_cols_array(m: &[f64; 12]) -> Self {
53 Self {
54 matrix3: DMat3::from_cols_array(&[
55 m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8],
56 ]),
57 translation: DVec3::from_array([m[9], m[10], m[11]]),
58 }
59 }
60
61 #[inline]
63 #[must_use]
64 pub fn to_cols_array(&self) -> [f64; 12] {
65 let x = &self.matrix3.x_axis;
66 let y = &self.matrix3.y_axis;
67 let z = &self.matrix3.z_axis;
68 let w = &self.translation;
69 [x.x, x.y, x.z, y.x, y.y, y.z, z.x, z.y, z.z, w.x, w.y, w.z]
70 }
71
72 #[inline]
77 #[must_use]
78 pub fn from_cols_array_2d(m: &[[f64; 3]; 4]) -> Self {
79 Self {
80 matrix3: DMat3::from_cols(m[0].into(), m[1].into(), m[2].into()),
81 translation: m[3].into(),
82 }
83 }
84
85 #[inline]
89 #[must_use]
90 pub fn to_cols_array_2d(&self) -> [[f64; 3]; 4] {
91 [
92 self.matrix3.x_axis.into(),
93 self.matrix3.y_axis.into(),
94 self.matrix3.z_axis.into(),
95 self.translation.into(),
96 ]
97 }
98
99 #[inline]
105 #[must_use]
106 pub fn from_cols_slice(slice: &[f64]) -> Self {
107 Self {
108 matrix3: DMat3::from_cols_slice(&slice[0..9]),
109 translation: DVec3::from_slice(&slice[9..12]),
110 }
111 }
112
113 #[inline]
119 pub fn write_cols_to_slice(self, slice: &mut [f64]) {
120 self.matrix3.write_cols_to_slice(&mut slice[0..9]);
121 self.translation.write_to_slice(&mut slice[9..12]);
122 }
123
124 #[inline]
127 #[must_use]
128 pub fn from_scale(scale: DVec3) -> Self {
129 Self {
130 matrix3: DMat3::from_diagonal(scale),
131 translation: DVec3::ZERO,
132 }
133 }
134 #[inline]
136 #[must_use]
137 pub fn from_quat(rotation: DQuat) -> Self {
138 Self {
139 matrix3: DMat3::from_quat(rotation),
140 translation: DVec3::ZERO,
141 }
142 }
143
144 #[inline]
147 #[must_use]
148 pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
149 Self {
150 matrix3: DMat3::from_axis_angle(axis, angle),
151 translation: DVec3::ZERO,
152 }
153 }
154
155 #[inline]
158 #[must_use]
159 pub fn from_rotation_x(angle: f64) -> Self {
160 Self {
161 matrix3: DMat3::from_rotation_x(angle),
162 translation: DVec3::ZERO,
163 }
164 }
165
166 #[inline]
169 #[must_use]
170 pub fn from_rotation_y(angle: f64) -> Self {
171 Self {
172 matrix3: DMat3::from_rotation_y(angle),
173 translation: DVec3::ZERO,
174 }
175 }
176
177 #[inline]
180 #[must_use]
181 pub fn from_rotation_z(angle: f64) -> Self {
182 Self {
183 matrix3: DMat3::from_rotation_z(angle),
184 translation: DVec3::ZERO,
185 }
186 }
187
188 #[inline]
190 #[must_use]
191 pub fn from_translation(translation: DVec3) -> Self {
192 #[allow(clippy::useless_conversion)]
193 Self {
194 matrix3: DMat3::IDENTITY,
195 translation: translation.into(),
196 }
197 }
198
199 #[inline]
202 #[must_use]
203 pub fn from_mat3(mat3: DMat3) -> Self {
204 #[allow(clippy::useless_conversion)]
205 Self {
206 matrix3: mat3.into(),
207 translation: DVec3::ZERO,
208 }
209 }
210
211 #[inline]
216 #[must_use]
217 pub fn from_mat3_translation(mat3: DMat3, translation: DVec3) -> Self {
218 #[allow(clippy::useless_conversion)]
219 Self {
220 matrix3: mat3.into(),
221 translation: translation.into(),
222 }
223 }
224
225 #[inline]
231 #[must_use]
232 pub fn from_scale_rotation_translation(
233 scale: DVec3,
234 rotation: DQuat,
235 translation: DVec3,
236 ) -> Self {
237 let rotation = DMat3::from_quat(rotation);
238 #[allow(clippy::useless_conversion)]
239 Self {
240 matrix3: DMat3::from_cols(
241 rotation.x_axis * scale.x,
242 rotation.y_axis * scale.y,
243 rotation.z_axis * scale.z,
244 ),
245 translation: translation.into(),
246 }
247 }
248
249 #[inline]
253 #[must_use]
254 pub fn from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self {
255 #[allow(clippy::useless_conversion)]
256 Self {
257 matrix3: DMat3::from_quat(rotation),
258 translation: translation.into(),
259 }
260 }
261
262 #[inline]
265 #[must_use]
266 pub fn from_mat4(m: DMat4) -> Self {
267 Self {
268 matrix3: DMat3::from_cols(
269 DVec3::from_vec4(m.x_axis),
270 DVec3::from_vec4(m.y_axis),
271 DVec3::from_vec4(m.z_axis),
272 ),
273 translation: DVec3::from_vec4(m.w_axis),
274 }
275 }
276
277 #[inline]
287 #[must_use]
288 pub fn to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3) {
289 use crate::f64::math;
290 let det = self.matrix3.determinant();
291 glam_assert!(det != 0.0);
292
293 let scale = DVec3::new(
294 self.matrix3.x_axis.length() * math::signum(det),
295 self.matrix3.y_axis.length(),
296 self.matrix3.z_axis.length(),
297 );
298
299 glam_assert!(scale.cmpne(DVec3::ZERO).all());
300
301 let inv_scale = scale.recip();
302
303 #[allow(clippy::useless_conversion)]
304 let rotation = DQuat::from_mat3(&DMat3::from_cols(
305 (self.matrix3.x_axis * inv_scale.x).into(),
306 (self.matrix3.y_axis * inv_scale.y).into(),
307 (self.matrix3.z_axis * inv_scale.z).into(),
308 ));
309
310 #[allow(clippy::useless_conversion)]
311 (scale, rotation, self.translation.into())
312 }
313
314 #[inline]
319 #[must_use]
320 pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
321 Self::look_to_rh(eye, -dir, up)
322 }
323
324 #[inline]
329 #[must_use]
330 pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
331 let f = dir.normalize();
332 let s = f.cross(up).normalize();
333 let u = s.cross(f);
334
335 Self {
336 matrix3: DMat3::from_cols(
337 DVec3::new(s.x, u.x, -f.x),
338 DVec3::new(s.y, u.y, -f.y),
339 DVec3::new(s.z, u.z, -f.z),
340 ),
341 translation: DVec3::new(-eye.dot(s), -eye.dot(u), eye.dot(f)),
342 }
343 }
344
345 #[inline]
353 #[must_use]
354 pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
355 glam_assert!(up.is_normalized());
356 Self::look_to_lh(eye, center - eye, up)
357 }
358
359 #[inline]
367 #[must_use]
368 pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
369 glam_assert!(up.is_normalized());
370 Self::look_to_rh(eye, center - eye, up)
371 }
372
373 #[inline]
375 pub fn transform_point3(&self, rhs: DVec3) -> DVec3 {
376 #[allow(clippy::useless_conversion)]
377 ((self.matrix3.x_axis * rhs.x)
378 + (self.matrix3.y_axis * rhs.y)
379 + (self.matrix3.z_axis * rhs.z)
380 + self.translation)
381 .into()
382 }
383
384 #[inline]
389 #[must_use]
390 pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 {
391 #[allow(clippy::useless_conversion)]
392 ((self.matrix3.x_axis * rhs.x)
393 + (self.matrix3.y_axis * rhs.y)
394 + (self.matrix3.z_axis * rhs.z))
395 .into()
396 }
397
398 #[inline]
403 #[must_use]
404 pub fn is_finite(&self) -> bool {
405 self.matrix3.is_finite() && self.translation.is_finite()
406 }
407
408 #[inline]
410 #[must_use]
411 pub fn is_nan(&self) -> bool {
412 self.matrix3.is_nan() || self.translation.is_nan()
413 }
414
415 #[inline]
425 #[must_use]
426 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
427 self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff)
428 && self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
429 }
430
431 #[inline]
435 #[must_use]
436 pub fn inverse(&self) -> Self {
437 let matrix3 = self.matrix3.inverse();
438 let translation = -(matrix3 * self.translation);
440
441 Self {
442 matrix3,
443 translation,
444 }
445 }
446
447 #[inline]
449 #[must_use]
450 pub fn as_affine3a(&self) -> crate::Affine3A {
451 crate::Affine3A::from_mat3_translation(self.matrix3.as_mat3(), self.translation.as_vec3())
452 }
453}
454
455impl Default for DAffine3 {
456 #[inline(always)]
457 fn default() -> Self {
458 Self::IDENTITY
459 }
460}
461
462impl Deref for DAffine3 {
463 type Target = crate::deref::Cols4<DVec3>;
464 #[inline(always)]
465 fn deref(&self) -> &Self::Target {
466 unsafe { &*(self as *const Self as *const Self::Target) }
467 }
468}
469
470impl DerefMut for DAffine3 {
471 #[inline(always)]
472 fn deref_mut(&mut self) -> &mut Self::Target {
473 unsafe { &mut *(self as *mut Self as *mut Self::Target) }
474 }
475}
476
477impl PartialEq for DAffine3 {
478 #[inline]
479 fn eq(&self, rhs: &Self) -> bool {
480 self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation)
481 }
482}
483
484impl core::fmt::Debug for DAffine3 {
485 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
486 fmt.debug_struct(stringify!(DAffine3))
487 .field("matrix3", &self.matrix3)
488 .field("translation", &self.translation)
489 .finish()
490 }
491}
492
493impl core::fmt::Display for DAffine3 {
494 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
495 if let Some(p) = f.precision() {
496 write!(
497 f,
498 "[{:.*}, {:.*}, {:.*}, {:.*}]",
499 p,
500 self.matrix3.x_axis,
501 p,
502 self.matrix3.y_axis,
503 p,
504 self.matrix3.z_axis,
505 p,
506 self.translation
507 )
508 } else {
509 write!(
510 f,
511 "[{}, {}, {}, {}]",
512 self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation
513 )
514 }
515 }
516}
517
518impl<'a> core::iter::Product<&'a Self> for DAffine3 {
519 fn product<I>(iter: I) -> Self
520 where
521 I: Iterator<Item = &'a Self>,
522 {
523 iter.fold(Self::IDENTITY, |a, &b| a * b)
524 }
525}
526
527impl Mul for DAffine3 {
528 type Output = Self;
529
530 #[inline]
531 fn mul(self, rhs: Self) -> Self {
532 Self {
533 matrix3: self.matrix3 * rhs.matrix3,
534 translation: self.matrix3 * rhs.translation + self.translation,
535 }
536 }
537}
538
539impl Mul<&Self> for DAffine3 {
540 type Output = Self;
541 #[inline]
542 fn mul(self, rhs: &Self) -> Self {
543 self.mul(*rhs)
544 }
545}
546
547impl Mul<&DAffine3> for &DAffine3 {
548 type Output = DAffine3;
549 #[inline]
550 fn mul(self, rhs: &DAffine3) -> DAffine3 {
551 (*self).mul(*rhs)
552 }
553}
554
555impl Mul<DAffine3> for &DAffine3 {
556 type Output = DAffine3;
557 #[inline]
558 fn mul(self, rhs: DAffine3) -> DAffine3 {
559 (*self).mul(rhs)
560 }
561}
562
563impl MulAssign for DAffine3 {
564 #[inline]
565 fn mul_assign(&mut self, rhs: Self) {
566 *self = self.mul(rhs);
567 }
568}
569
570impl MulAssign<&Self> for DAffine3 {
571 #[inline]
572 fn mul_assign(&mut self, rhs: &Self) {
573 self.mul_assign(*rhs);
574 }
575}
576
577impl Mul<DMat4> for DAffine3 {
578 type Output = DMat4;
579
580 #[inline]
581 fn mul(self, rhs: DMat4) -> Self::Output {
582 DMat4::from(self) * rhs
583 }
584}
585
586impl Mul<&DMat4> for DAffine3 {
587 type Output = DMat4;
588 #[inline]
589 fn mul(self, rhs: &DMat4) -> DMat4 {
590 self.mul(*rhs)
591 }
592}
593
594impl Mul<&DMat4> for &DAffine3 {
595 type Output = DMat4;
596 #[inline]
597 fn mul(self, rhs: &DMat4) -> DMat4 {
598 (*self).mul(*rhs)
599 }
600}
601
602impl Mul<DMat4> for &DAffine3 {
603 type Output = DMat4;
604 #[inline]
605 fn mul(self, rhs: DMat4) -> DMat4 {
606 (*self).mul(rhs)
607 }
608}
609
610impl Mul<DAffine3> for DMat4 {
611 type Output = Self;
612
613 #[inline]
614 fn mul(self, rhs: DAffine3) -> Self {
615 self * Self::from(rhs)
616 }
617}
618
619impl Mul<&DAffine3> for DMat4 {
620 type Output = Self;
621 #[inline]
622 fn mul(self, rhs: &DAffine3) -> Self {
623 self.mul(*rhs)
624 }
625}
626
627impl Mul<&DAffine3> for &DMat4 {
628 type Output = DMat4;
629 #[inline]
630 fn mul(self, rhs: &DAffine3) -> DMat4 {
631 (*self).mul(*rhs)
632 }
633}
634
635impl Mul<DAffine3> for &DMat4 {
636 type Output = DMat4;
637 #[inline]
638 fn mul(self, rhs: DAffine3) -> DMat4 {
639 (*self).mul(rhs)
640 }
641}
642
643impl MulAssign<DAffine3> for DMat4 {
644 #[inline]
645 fn mul_assign(&mut self, rhs: DAffine3) {
646 *self = self.mul(rhs);
647 }
648}
649
650impl MulAssign<&DAffine3> for DMat4 {
651 #[inline]
652 fn mul_assign(&mut self, rhs: &DAffine3) {
653 self.mul_assign(*rhs);
654 }
655}
656
657impl From<DAffine3> for DMat4 {
658 #[inline]
659 fn from(m: DAffine3) -> Self {
660 Self::from_cols(
661 m.matrix3.x_axis.extend(0.0),
662 m.matrix3.y_axis.extend(0.0),
663 m.matrix3.z_axis.extend(0.0),
664 m.translation.extend(1.0),
665 )
666 }
667}