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