1use crate::{Affine3A, Mat3, Mat4, Quat, Vec3};
4use core::ops::{Deref, DerefMut, Mul, MulAssign};
5
6#[cfg(all(feature = "zerocopy", not(feature = "core-simd")))]
7use zerocopy_derive::*;
8
9#[derive(Copy, Clone)]
11#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
12#[cfg_attr(
13 all(feature = "zerocopy", not(feature = "core-simd")),
14 derive(FromBytes, Immutable, IntoBytes, KnownLayout)
15)]
16#[repr(C)]
17pub struct Affine3 {
18 pub matrix3: Mat3,
19 pub translation: Vec3,
20}
21
22impl Affine3 {
23 pub const ZERO: Self = Self {
28 matrix3: Mat3::ZERO,
29 translation: Vec3::ZERO,
30 };
31
32 pub const IDENTITY: Self = Self {
36 matrix3: Mat3::IDENTITY,
37 translation: Vec3::ZERO,
38 };
39
40 pub const NAN: Self = Self {
42 matrix3: Mat3::NAN,
43 translation: Vec3::NAN,
44 };
45
46 #[inline(always)]
48 #[must_use]
49 pub const fn from_cols(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3, w_axis: Vec3) -> Self {
50 Self {
51 matrix3: Mat3::from_cols(x_axis, y_axis, z_axis),
52 translation: w_axis,
53 }
54 }
55
56 #[inline]
58 #[must_use]
59 pub fn from_cols_array(m: &[f32; 12]) -> Self {
60 Self {
61 matrix3: Mat3::from_cols_array(&[m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]]),
62 translation: Vec3::from_array([m[9], m[10], m[11]]),
63 }
64 }
65
66 #[inline]
68 #[must_use]
69 pub fn to_cols_array(&self) -> [f32; 12] {
70 let x = &self.matrix3.x_axis;
71 let y = &self.matrix3.y_axis;
72 let z = &self.matrix3.z_axis;
73 let w = &self.translation;
74 [x.x, x.y, x.z, y.x, y.y, y.z, z.x, z.y, z.z, w.x, w.y, w.z]
75 }
76
77 #[inline]
82 #[must_use]
83 pub fn from_cols_array_2d(m: &[[f32; 3]; 4]) -> Self {
84 Self {
85 matrix3: Mat3::from_cols(m[0].into(), m[1].into(), m[2].into()),
86 translation: m[3].into(),
87 }
88 }
89
90 #[inline]
94 #[must_use]
95 pub fn to_cols_array_2d(&self) -> [[f32; 3]; 4] {
96 [
97 self.matrix3.x_axis.into(),
98 self.matrix3.y_axis.into(),
99 self.matrix3.z_axis.into(),
100 self.translation.into(),
101 ]
102 }
103
104 #[inline]
110 #[must_use]
111 pub fn from_cols_slice(slice: &[f32]) -> Self {
112 Self {
113 matrix3: Mat3::from_cols_slice(&slice[0..9]),
114 translation: Vec3::from_slice(&slice[9..12]),
115 }
116 }
117
118 #[inline]
124 pub fn write_cols_to_slice(&self, slice: &mut [f32]) {
125 self.matrix3.write_cols_to_slice(&mut slice[0..9]);
126 self.translation.write_to_slice(&mut slice[9..12]);
127 }
128
129 #[inline]
132 #[must_use]
133 pub fn from_scale(scale: Vec3) -> Self {
134 Self {
135 matrix3: Mat3::from_diagonal(scale),
136 translation: Vec3::ZERO,
137 }
138 }
139 #[inline]
141 #[must_use]
142 pub fn from_quat(rotation: Quat) -> Self {
143 Self {
144 matrix3: Mat3::from_quat(rotation),
145 translation: Vec3::ZERO,
146 }
147 }
148
149 #[inline]
152 #[must_use]
153 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
154 Self {
155 matrix3: Mat3::from_axis_angle(axis, angle),
156 translation: Vec3::ZERO,
157 }
158 }
159
160 #[inline]
163 #[must_use]
164 pub fn from_rotation_x(angle: f32) -> Self {
165 Self {
166 matrix3: Mat3::from_rotation_x(angle),
167 translation: Vec3::ZERO,
168 }
169 }
170
171 #[inline]
174 #[must_use]
175 pub fn from_rotation_y(angle: f32) -> Self {
176 Self {
177 matrix3: Mat3::from_rotation_y(angle),
178 translation: Vec3::ZERO,
179 }
180 }
181
182 #[inline]
185 #[must_use]
186 pub fn from_rotation_z(angle: f32) -> Self {
187 Self {
188 matrix3: Mat3::from_rotation_z(angle),
189 translation: Vec3::ZERO,
190 }
191 }
192
193 #[inline]
195 #[must_use]
196 pub fn from_translation(translation: Vec3) -> Self {
197 #[allow(clippy::useless_conversion)]
198 Self {
199 matrix3: Mat3::IDENTITY,
200 translation: translation.into(),
201 }
202 }
203
204 #[inline]
207 #[must_use]
208 pub fn from_mat3(mat3: Mat3) -> Self {
209 #[allow(clippy::useless_conversion)]
210 Self {
211 matrix3: mat3.into(),
212 translation: Vec3::ZERO,
213 }
214 }
215
216 #[inline]
221 #[must_use]
222 pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
223 #[allow(clippy::useless_conversion)]
224 Self {
225 matrix3: mat3.into(),
226 translation: translation.into(),
227 }
228 }
229
230 #[inline]
236 #[must_use]
237 pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
238 let rotation = Mat3::from_quat(rotation);
239 #[allow(clippy::useless_conversion)]
240 Self {
241 matrix3: Mat3::from_cols(
242 rotation.x_axis * scale.x,
243 rotation.y_axis * scale.y,
244 rotation.z_axis * scale.z,
245 ),
246 translation: translation.into(),
247 }
248 }
249
250 #[inline]
254 #[must_use]
255 pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
256 #[allow(clippy::useless_conversion)]
257 Self {
258 matrix3: Mat3::from_quat(rotation),
259 translation: translation.into(),
260 }
261 }
262
263 #[inline]
266 #[must_use]
267 pub fn from_mat4(m: Mat4) -> Self {
268 Self {
269 matrix3: Mat3::from_cols(
270 Vec3::from_vec4(m.x_axis),
271 Vec3::from_vec4(m.y_axis),
272 Vec3::from_vec4(m.z_axis),
273 ),
274 translation: Vec3::from_vec4(m.w_axis),
275 }
276 }
277
278 #[inline]
288 #[must_use]
289 pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
290 use crate::f32::math;
291 let det = self.matrix3.determinant();
292 glam_assert!(det != 0.0);
293
294 let scale = Vec3::new(
295 self.matrix3.x_axis.length() * math::signum(det),
296 self.matrix3.y_axis.length(),
297 self.matrix3.z_axis.length(),
298 );
299
300 glam_assert!(scale.cmpne(Vec3::ZERO).all());
301
302 let inv_scale = scale.recip();
303
304 #[allow(clippy::useless_conversion)]
305 let rotation = Quat::from_mat3(&Mat3::from_cols(
306 (self.matrix3.x_axis * inv_scale.x).into(),
307 (self.matrix3.y_axis * inv_scale.y).into(),
308 (self.matrix3.z_axis * inv_scale.z).into(),
309 ));
310
311 #[allow(clippy::useless_conversion)]
312 (scale, rotation, self.translation.into())
313 }
314
315 #[deprecated(
320 since = "0.33.1",
321 note = "use the `glam::camera::lh::view::look_to_affine3` function instead"
322 )]
323 #[inline]
324 #[must_use]
325 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
326 #[allow(deprecated)]
327 Self::look_to_rh(eye, -dir, up)
328 }
329
330 #[deprecated(
335 since = "0.33.1",
336 note = "use the `glam::camera::rh::view::look_to_affine3` function instead"
337 )]
338 #[inline]
339 #[must_use]
340 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
341 let f = dir.normalize();
342 let s = f.cross(up).normalize();
343 let u = s.cross(f);
344
345 Self {
346 matrix3: Mat3::from_cols(
347 Vec3::new(s.x, u.x, -f.x),
348 Vec3::new(s.y, u.y, -f.y),
349 Vec3::new(s.z, u.z, -f.z),
350 ),
351 translation: Vec3::new(-eye.dot(s), -eye.dot(u), eye.dot(f)),
352 }
353 }
354
355 #[deprecated(
363 since = "0.33.1",
364 note = "use the `glam::camera::lh::view::look_at_affine3` function instead"
365 )]
366 #[inline]
367 #[must_use]
368 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
369 glam_assert!(up.is_normalized());
370 #[allow(deprecated)]
371 Self::look_to_lh(eye, center - eye, up)
372 }
373
374 #[deprecated(
382 since = "0.33.1",
383 note = "use the `glam::camera::rh::view::look_at_affine3` function instead"
384 )]
385 #[inline]
386 #[must_use]
387 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
388 glam_assert!(up.is_normalized());
389 #[allow(deprecated)]
390 Self::look_to_rh(eye, center - eye, up)
391 }
392
393 #[inline]
395 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
396 #[allow(clippy::useless_conversion)]
397 ((self.matrix3.x_axis * rhs.x)
398 + (self.matrix3.y_axis * rhs.y)
399 + (self.matrix3.z_axis * rhs.z)
400 + self.translation)
401 .into()
402 }
403
404 #[inline]
409 #[must_use]
410 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
411 #[allow(clippy::useless_conversion)]
412 ((self.matrix3.x_axis * rhs.x)
413 + (self.matrix3.y_axis * rhs.y)
414 + (self.matrix3.z_axis * rhs.z))
415 .into()
416 }
417
418 #[inline]
423 #[must_use]
424 pub fn is_finite(&self) -> bool {
425 self.matrix3.is_finite() && self.translation.is_finite()
426 }
427
428 #[inline]
430 #[must_use]
431 pub fn is_nan(&self) -> bool {
432 self.matrix3.is_nan() || self.translation.is_nan()
433 }
434
435 #[inline]
445 #[must_use]
446 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
447 self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff)
448 && self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
449 }
450
451 #[inline]
455 #[must_use]
456 pub fn inverse(&self) -> Self {
457 let matrix3 = self.matrix3.inverse();
458 let translation = -(matrix3 * self.translation);
460
461 Self {
462 matrix3,
463 translation,
464 }
465 }
466
467 #[cfg(feature = "f64")]
469 #[inline]
470 #[must_use]
471 pub fn as_daffine3(&self) -> crate::DAffine3 {
472 crate::DAffine3::from_mat3_translation(self.matrix3.as_dmat3(), self.translation.as_dvec3())
473 }
474}
475
476impl Default for Affine3 {
477 #[inline(always)]
478 fn default() -> Self {
479 Self::IDENTITY
480 }
481}
482
483impl Deref for Affine3 {
484 type Target = crate::deref::Cols4<Vec3>;
485 #[inline(always)]
486 fn deref(&self) -> &Self::Target {
487 unsafe { &*(self as *const Self as *const Self::Target) }
488 }
489}
490
491impl DerefMut for Affine3 {
492 #[inline(always)]
493 fn deref_mut(&mut self) -> &mut Self::Target {
494 unsafe { &mut *(self as *mut Self as *mut Self::Target) }
495 }
496}
497
498impl PartialEq for Affine3 {
499 #[inline]
500 fn eq(&self, rhs: &Self) -> bool {
501 self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation)
502 }
503}
504
505impl core::fmt::Debug for Affine3 {
506 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
507 fmt.debug_struct(stringify!(Affine3))
508 .field("matrix3", &self.matrix3)
509 .field("translation", &self.translation)
510 .finish()
511 }
512}
513
514impl core::fmt::Display for Affine3 {
515 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
516 if let Some(p) = f.precision() {
517 write!(
518 f,
519 "[{:.*}, {:.*}, {:.*}, {:.*}]",
520 p,
521 self.matrix3.x_axis,
522 p,
523 self.matrix3.y_axis,
524 p,
525 self.matrix3.z_axis,
526 p,
527 self.translation
528 )
529 } else {
530 write!(
531 f,
532 "[{}, {}, {}, {}]",
533 self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation
534 )
535 }
536 }
537}
538
539impl<'a> core::iter::Product<&'a Self> for Affine3 {
540 fn product<I>(iter: I) -> Self
541 where
542 I: Iterator<Item = &'a Self>,
543 {
544 iter.fold(Self::IDENTITY, |a, &b| a * b)
545 }
546}
547
548impl Mul for Affine3 {
549 type Output = Self;
550
551 #[inline]
552 fn mul(self, rhs: Self) -> Self {
553 Self {
554 matrix3: self.matrix3 * rhs.matrix3,
555 translation: self.matrix3 * rhs.translation + self.translation,
556 }
557 }
558}
559
560impl Mul<&Self> for Affine3 {
561 type Output = Self;
562 #[inline]
563 fn mul(self, rhs: &Self) -> Self {
564 self.mul(*rhs)
565 }
566}
567
568impl Mul<&Affine3> for &Affine3 {
569 type Output = Affine3;
570 #[inline]
571 fn mul(self, rhs: &Affine3) -> Affine3 {
572 (*self).mul(*rhs)
573 }
574}
575
576impl Mul<Affine3> for &Affine3 {
577 type Output = Affine3;
578 #[inline]
579 fn mul(self, rhs: Affine3) -> Affine3 {
580 (*self).mul(rhs)
581 }
582}
583
584impl MulAssign for Affine3 {
585 #[inline]
586 fn mul_assign(&mut self, rhs: Self) {
587 *self = self.mul(rhs);
588 }
589}
590
591impl MulAssign<&Self> for Affine3 {
592 #[inline]
593 fn mul_assign(&mut self, rhs: &Self) {
594 self.mul_assign(*rhs);
595 }
596}
597
598impl Mul<Mat4> for Affine3 {
599 type Output = Mat4;
600
601 #[inline]
602 fn mul(self, rhs: Mat4) -> Self::Output {
603 Mat4::from(self) * rhs
604 }
605}
606
607impl Mul<&Mat4> for Affine3 {
608 type Output = Mat4;
609 #[inline]
610 fn mul(self, rhs: &Mat4) -> Mat4 {
611 self.mul(*rhs)
612 }
613}
614
615impl Mul<&Mat4> for &Affine3 {
616 type Output = Mat4;
617 #[inline]
618 fn mul(self, rhs: &Mat4) -> Mat4 {
619 (*self).mul(*rhs)
620 }
621}
622
623impl Mul<Mat4> for &Affine3 {
624 type Output = Mat4;
625 #[inline]
626 fn mul(self, rhs: Mat4) -> Mat4 {
627 (*self).mul(rhs)
628 }
629}
630
631impl Mul<Affine3> for Mat4 {
632 type Output = Self;
633
634 #[inline]
635 fn mul(self, rhs: Affine3) -> Self {
636 self * Self::from(rhs)
637 }
638}
639
640impl Mul<&Affine3> for Mat4 {
641 type Output = Self;
642 #[inline]
643 fn mul(self, rhs: &Affine3) -> Self {
644 self.mul(*rhs)
645 }
646}
647
648impl Mul<&Affine3> for &Mat4 {
649 type Output = Mat4;
650 #[inline]
651 fn mul(self, rhs: &Affine3) -> Mat4 {
652 (*self).mul(*rhs)
653 }
654}
655
656impl Mul<Affine3> for &Mat4 {
657 type Output = Mat4;
658 #[inline]
659 fn mul(self, rhs: Affine3) -> Mat4 {
660 (*self).mul(rhs)
661 }
662}
663
664impl MulAssign<Affine3> for Mat4 {
665 #[inline]
666 fn mul_assign(&mut self, rhs: Affine3) {
667 *self = self.mul(rhs);
668 }
669}
670
671impl MulAssign<&Affine3> for Mat4 {
672 #[inline]
673 fn mul_assign(&mut self, rhs: &Affine3) {
674 self.mul_assign(*rhs);
675 }
676}
677
678impl From<Affine3> for Mat4 {
679 #[inline]
680 fn from(m: Affine3) -> Self {
681 Self::from_cols(
682 m.matrix3.x_axis.extend(0.0),
683 m.matrix3.y_axis.extend(0.0),
684 m.matrix3.z_axis.extend(0.0),
685 m.translation.extend(1.0),
686 )
687 }
688}
689
690impl From<Affine3A> for Affine3 {
691 #[inline]
692 fn from(a: Affine3A) -> Self {
693 Self::from_cols(
694 a.matrix3.x_axis.into(),
695 a.matrix3.y_axis.into(),
696 a.matrix3.z_axis.into(),
697 a.translation.into(),
698 )
699 }
700}