1use crate::{Mat3, Mat3A, Mat4, Quat, Vec3, Vec3A};
4use core::ops::{Deref, DerefMut, Mul, MulAssign};
5
6#[derive(Copy, Clone)]
10#[repr(C)]
11pub struct Affine3A {
12 pub matrix3: Mat3A,
13 pub translation: Vec3A,
14}
15
16impl Affine3A {
17 pub const ZERO: Self = Self {
22 matrix3: Mat3A::ZERO,
23 translation: Vec3A::ZERO,
24 };
25
26 pub const IDENTITY: Self = Self {
30 matrix3: Mat3A::IDENTITY,
31 translation: Vec3A::ZERO,
32 };
33
34 pub const NAN: Self = Self {
36 matrix3: Mat3A::NAN,
37 translation: Vec3A::NAN,
38 };
39
40 #[inline(always)]
42 #[must_use]
43 pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A, w_axis: Vec3A) -> Self {
44 Self {
45 matrix3: Mat3A::from_cols(x_axis, y_axis, z_axis),
46 translation: w_axis,
47 }
48 }
49
50 #[inline]
52 #[must_use]
53 pub fn from_cols_array(m: &[f32; 12]) -> Self {
54 Self {
55 matrix3: Mat3A::from_cols_array(&[
56 m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8],
57 ]),
58 translation: Vec3A::from_array([m[9], m[10], m[11]]),
59 }
60 }
61
62 #[inline]
64 #[must_use]
65 pub fn to_cols_array(&self) -> [f32; 12] {
66 let x = &self.matrix3.x_axis;
67 let y = &self.matrix3.y_axis;
68 let z = &self.matrix3.z_axis;
69 let w = &self.translation;
70 [x.x, x.y, x.z, y.x, y.y, y.z, z.x, z.y, z.z, w.x, w.y, w.z]
71 }
72
73 #[inline]
78 #[must_use]
79 pub fn from_cols_array_2d(m: &[[f32; 3]; 4]) -> Self {
80 Self {
81 matrix3: Mat3A::from_cols(m[0].into(), m[1].into(), m[2].into()),
82 translation: m[3].into(),
83 }
84 }
85
86 #[inline]
90 #[must_use]
91 pub fn to_cols_array_2d(&self) -> [[f32; 3]; 4] {
92 [
93 self.matrix3.x_axis.into(),
94 self.matrix3.y_axis.into(),
95 self.matrix3.z_axis.into(),
96 self.translation.into(),
97 ]
98 }
99
100 #[inline]
106 #[must_use]
107 pub fn from_cols_slice(slice: &[f32]) -> Self {
108 Self {
109 matrix3: Mat3A::from_cols_slice(&slice[0..9]),
110 translation: Vec3A::from_slice(&slice[9..12]),
111 }
112 }
113
114 #[inline]
120 pub fn write_cols_to_slice(self, slice: &mut [f32]) {
121 self.matrix3.write_cols_to_slice(&mut slice[0..9]);
122 self.translation.write_to_slice(&mut slice[9..12]);
123 }
124
125 #[inline]
128 #[must_use]
129 pub fn from_scale(scale: Vec3) -> Self {
130 Self {
131 matrix3: Mat3A::from_diagonal(scale),
132 translation: Vec3A::ZERO,
133 }
134 }
135 #[inline]
137 #[must_use]
138 pub fn from_quat(rotation: Quat) -> Self {
139 Self {
140 matrix3: Mat3A::from_quat(rotation),
141 translation: Vec3A::ZERO,
142 }
143 }
144
145 #[inline]
148 #[must_use]
149 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
150 Self {
151 matrix3: Mat3A::from_axis_angle(axis, angle),
152 translation: Vec3A::ZERO,
153 }
154 }
155
156 #[inline]
159 #[must_use]
160 pub fn from_rotation_x(angle: f32) -> Self {
161 Self {
162 matrix3: Mat3A::from_rotation_x(angle),
163 translation: Vec3A::ZERO,
164 }
165 }
166
167 #[inline]
170 #[must_use]
171 pub fn from_rotation_y(angle: f32) -> Self {
172 Self {
173 matrix3: Mat3A::from_rotation_y(angle),
174 translation: Vec3A::ZERO,
175 }
176 }
177
178 #[inline]
181 #[must_use]
182 pub fn from_rotation_z(angle: f32) -> Self {
183 Self {
184 matrix3: Mat3A::from_rotation_z(angle),
185 translation: Vec3A::ZERO,
186 }
187 }
188
189 #[inline]
191 #[must_use]
192 pub fn from_translation(translation: Vec3) -> Self {
193 #[allow(clippy::useless_conversion)]
194 Self {
195 matrix3: Mat3A::IDENTITY,
196 translation: translation.into(),
197 }
198 }
199
200 #[inline]
203 #[must_use]
204 pub fn from_mat3(mat3: Mat3) -> Self {
205 #[allow(clippy::useless_conversion)]
206 Self {
207 matrix3: mat3.into(),
208 translation: Vec3A::ZERO,
209 }
210 }
211
212 #[inline]
217 #[must_use]
218 pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
219 #[allow(clippy::useless_conversion)]
220 Self {
221 matrix3: mat3.into(),
222 translation: translation.into(),
223 }
224 }
225
226 #[inline]
232 #[must_use]
233 pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
234 let rotation = Mat3A::from_quat(rotation);
235 #[allow(clippy::useless_conversion)]
236 Self {
237 matrix3: Mat3A::from_cols(
238 rotation.x_axis * scale.x,
239 rotation.y_axis * scale.y,
240 rotation.z_axis * scale.z,
241 ),
242 translation: translation.into(),
243 }
244 }
245
246 #[inline]
250 #[must_use]
251 pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
252 #[allow(clippy::useless_conversion)]
253 Self {
254 matrix3: Mat3A::from_quat(rotation),
255 translation: translation.into(),
256 }
257 }
258
259 #[inline]
262 #[must_use]
263 pub fn from_mat4(m: Mat4) -> Self {
264 Self {
265 matrix3: Mat3A::from_cols(
266 Vec3A::from_vec4(m.x_axis),
267 Vec3A::from_vec4(m.y_axis),
268 Vec3A::from_vec4(m.z_axis),
269 ),
270 translation: Vec3A::from_vec4(m.w_axis),
271 }
272 }
273
274 #[inline]
284 #[must_use]
285 pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
286 use crate::f32::math;
287 let det = self.matrix3.determinant();
288 glam_assert!(det != 0.0);
289
290 let scale = Vec3::new(
291 self.matrix3.x_axis.length() * math::signum(det),
292 self.matrix3.y_axis.length(),
293 self.matrix3.z_axis.length(),
294 );
295
296 glam_assert!(scale.cmpne(Vec3::ZERO).all());
297
298 let inv_scale = scale.recip();
299
300 #[allow(clippy::useless_conversion)]
301 let rotation = Quat::from_mat3(&Mat3::from_cols(
302 (self.matrix3.x_axis * inv_scale.x).into(),
303 (self.matrix3.y_axis * inv_scale.y).into(),
304 (self.matrix3.z_axis * inv_scale.z).into(),
305 ));
306
307 #[allow(clippy::useless_conversion)]
308 (scale, rotation, self.translation.into())
309 }
310
311 #[inline]
316 #[must_use]
317 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
318 Self::look_to_rh(eye, -dir, up)
319 }
320
321 #[inline]
326 #[must_use]
327 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
328 let f = dir.normalize();
329 let s = f.cross(up).normalize();
330 let u = s.cross(f);
331
332 Self {
333 matrix3: Mat3A::from_cols(
334 Vec3A::new(s.x, u.x, -f.x),
335 Vec3A::new(s.y, u.y, -f.y),
336 Vec3A::new(s.z, u.z, -f.z),
337 ),
338 translation: Vec3A::new(-eye.dot(s), -eye.dot(u), eye.dot(f)),
339 }
340 }
341
342 #[inline]
350 #[must_use]
351 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
352 glam_assert!(up.is_normalized());
353 Self::look_to_lh(eye, center - eye, up)
354 }
355
356 #[inline]
364 #[must_use]
365 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
366 glam_assert!(up.is_normalized());
367 Self::look_to_rh(eye, center - eye, up)
368 }
369
370 #[inline]
372 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
373 #[allow(clippy::useless_conversion)]
374 ((self.matrix3.x_axis * rhs.x)
375 + (self.matrix3.y_axis * rhs.y)
376 + (self.matrix3.z_axis * rhs.z)
377 + self.translation)
378 .into()
379 }
380
381 #[inline]
386 #[must_use]
387 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
388 #[allow(clippy::useless_conversion)]
389 ((self.matrix3.x_axis * rhs.x)
390 + (self.matrix3.y_axis * rhs.y)
391 + (self.matrix3.z_axis * rhs.z))
392 .into()
393 }
394
395 #[inline]
397 #[must_use]
398 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
399 self.matrix3 * rhs + self.translation
400 }
401
402 #[inline]
407 #[must_use]
408 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
409 self.matrix3 * rhs
410 }
411
412 #[inline]
417 #[must_use]
418 pub fn is_finite(&self) -> bool {
419 self.matrix3.is_finite() && self.translation.is_finite()
420 }
421
422 #[inline]
424 #[must_use]
425 pub fn is_nan(&self) -> bool {
426 self.matrix3.is_nan() || self.translation.is_nan()
427 }
428
429 #[inline]
439 #[must_use]
440 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
441 self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff)
442 && self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
443 }
444
445 #[inline]
449 #[must_use]
450 pub fn inverse(&self) -> Self {
451 let matrix3 = self.matrix3.inverse();
452 let translation = -(matrix3 * self.translation);
454
455 Self {
456 matrix3,
457 translation,
458 }
459 }
460}
461
462impl Default for Affine3A {
463 #[inline(always)]
464 fn default() -> Self {
465 Self::IDENTITY
466 }
467}
468
469impl Deref for Affine3A {
470 type Target = crate::deref::Cols4<Vec3A>;
471 #[inline(always)]
472 fn deref(&self) -> &Self::Target {
473 unsafe { &*(self as *const Self as *const Self::Target) }
474 }
475}
476
477impl DerefMut for Affine3A {
478 #[inline(always)]
479 fn deref_mut(&mut self) -> &mut Self::Target {
480 unsafe { &mut *(self as *mut Self as *mut Self::Target) }
481 }
482}
483
484impl PartialEq for Affine3A {
485 #[inline]
486 fn eq(&self, rhs: &Self) -> bool {
487 self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation)
488 }
489}
490
491impl core::fmt::Debug for Affine3A {
492 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
493 fmt.debug_struct(stringify!(Affine3A))
494 .field("matrix3", &self.matrix3)
495 .field("translation", &self.translation)
496 .finish()
497 }
498}
499
500impl core::fmt::Display for Affine3A {
501 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
502 if let Some(p) = f.precision() {
503 write!(
504 f,
505 "[{:.*}, {:.*}, {:.*}, {:.*}]",
506 p,
507 self.matrix3.x_axis,
508 p,
509 self.matrix3.y_axis,
510 p,
511 self.matrix3.z_axis,
512 p,
513 self.translation
514 )
515 } else {
516 write!(
517 f,
518 "[{}, {}, {}, {}]",
519 self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation
520 )
521 }
522 }
523}
524
525impl<'a> core::iter::Product<&'a Self> for Affine3A {
526 fn product<I>(iter: I) -> Self
527 where
528 I: Iterator<Item = &'a Self>,
529 {
530 iter.fold(Self::IDENTITY, |a, &b| a * b)
531 }
532}
533
534impl Mul for Affine3A {
535 type Output = Affine3A;
536
537 #[inline]
538 fn mul(self, rhs: Affine3A) -> Self::Output {
539 Self {
540 matrix3: self.matrix3 * rhs.matrix3,
541 translation: self.matrix3 * rhs.translation + self.translation,
542 }
543 }
544}
545
546impl MulAssign for Affine3A {
547 #[inline]
548 fn mul_assign(&mut self, rhs: Affine3A) {
549 *self = self.mul(rhs);
550 }
551}
552
553impl From<Affine3A> for Mat4 {
554 #[inline]
555 fn from(m: Affine3A) -> Mat4 {
556 Mat4::from_cols(
557 m.matrix3.x_axis.extend(0.0),
558 m.matrix3.y_axis.extend(0.0),
559 m.matrix3.z_axis.extend(0.0),
560 m.translation.extend(1.0),
561 )
562 }
563}
564
565impl Mul<Mat4> for Affine3A {
566 type Output = Mat4;
567
568 #[inline]
569 fn mul(self, rhs: Mat4) -> Self::Output {
570 Mat4::from(self) * rhs
571 }
572}
573
574impl Mul<Affine3A> for Mat4 {
575 type Output = Mat4;
576
577 #[inline]
578 fn mul(self, rhs: Affine3A) -> Self::Output {
579 self * Mat4::from(rhs)
580 }
581}