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_slice(&m[0..9]),
56 translation: Vec3A::from_slice(&m[9..12]),
57 }
58 }
59
60 #[inline]
62 #[must_use]
63 pub fn to_cols_array(&self) -> [f32; 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: &[[f32; 3]; 4]) -> Self {
78 Self {
79 matrix3: Mat3A::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) -> [[f32; 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: &[f32]) -> Self {
106 Self {
107 matrix3: Mat3A::from_cols_slice(&slice[0..9]),
108 translation: Vec3A::from_slice(&slice[9..12]),
109 }
110 }
111
112 #[inline]
118 pub fn write_cols_to_slice(self, slice: &mut [f32]) {
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: Vec3) -> Self {
128 Self {
129 matrix3: Mat3A::from_diagonal(scale),
130 translation: Vec3A::ZERO,
131 }
132 }
133 #[inline]
135 #[must_use]
136 pub fn from_quat(rotation: Quat) -> Self {
137 Self {
138 matrix3: Mat3A::from_quat(rotation),
139 translation: Vec3A::ZERO,
140 }
141 }
142
143 #[inline]
146 #[must_use]
147 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
148 Self {
149 matrix3: Mat3A::from_axis_angle(axis, angle),
150 translation: Vec3A::ZERO,
151 }
152 }
153
154 #[inline]
157 #[must_use]
158 pub fn from_rotation_x(angle: f32) -> Self {
159 Self {
160 matrix3: Mat3A::from_rotation_x(angle),
161 translation: Vec3A::ZERO,
162 }
163 }
164
165 #[inline]
168 #[must_use]
169 pub fn from_rotation_y(angle: f32) -> Self {
170 Self {
171 matrix3: Mat3A::from_rotation_y(angle),
172 translation: Vec3A::ZERO,
173 }
174 }
175
176 #[inline]
179 #[must_use]
180 pub fn from_rotation_z(angle: f32) -> Self {
181 Self {
182 matrix3: Mat3A::from_rotation_z(angle),
183 translation: Vec3A::ZERO,
184 }
185 }
186
187 #[inline]
189 #[must_use]
190 pub fn from_translation(translation: Vec3) -> Self {
191 #[allow(clippy::useless_conversion)]
192 Self {
193 matrix3: Mat3A::IDENTITY,
194 translation: translation.into(),
195 }
196 }
197
198 #[inline]
201 #[must_use]
202 pub fn from_mat3(mat3: Mat3) -> Self {
203 #[allow(clippy::useless_conversion)]
204 Self {
205 matrix3: mat3.into(),
206 translation: Vec3A::ZERO,
207 }
208 }
209
210 #[inline]
215 #[must_use]
216 pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> 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(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
232 let rotation = Mat3A::from_quat(rotation);
233 #[allow(clippy::useless_conversion)]
234 Self {
235 matrix3: Mat3A::from_cols(
236 rotation.x_axis * scale.x,
237 rotation.y_axis * scale.y,
238 rotation.z_axis * scale.z,
239 ),
240 translation: translation.into(),
241 }
242 }
243
244 #[inline]
248 #[must_use]
249 pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
250 #[allow(clippy::useless_conversion)]
251 Self {
252 matrix3: Mat3A::from_quat(rotation),
253 translation: translation.into(),
254 }
255 }
256
257 #[inline]
260 #[must_use]
261 pub fn from_mat4(m: Mat4) -> Self {
262 Self {
263 matrix3: Mat3A::from_cols(
264 Vec3A::from_vec4(m.x_axis),
265 Vec3A::from_vec4(m.y_axis),
266 Vec3A::from_vec4(m.z_axis),
267 ),
268 translation: Vec3A::from_vec4(m.w_axis),
269 }
270 }
271
272 #[inline]
282 #[must_use]
283 pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
284 use crate::f32::math;
285 let det = self.matrix3.determinant();
286 glam_assert!(det != 0.0);
287
288 let scale = Vec3::new(
289 self.matrix3.x_axis.length() * math::signum(det),
290 self.matrix3.y_axis.length(),
291 self.matrix3.z_axis.length(),
292 );
293
294 glam_assert!(scale.cmpne(Vec3::ZERO).all());
295
296 let inv_scale = scale.recip();
297
298 #[allow(clippy::useless_conversion)]
299 let rotation = Quat::from_mat3(&Mat3::from_cols(
300 (self.matrix3.x_axis * inv_scale.x).into(),
301 (self.matrix3.y_axis * inv_scale.y).into(),
302 (self.matrix3.z_axis * inv_scale.z).into(),
303 ));
304
305 #[allow(clippy::useless_conversion)]
306 (scale, rotation, self.translation.into())
307 }
308
309 #[inline]
314 #[must_use]
315 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
316 Self::look_to_rh(eye, -dir, up)
317 }
318
319 #[inline]
324 #[must_use]
325 pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self {
326 let f = dir.normalize();
327 let s = f.cross(up).normalize();
328 let u = s.cross(f);
329
330 Self {
331 matrix3: Mat3A::from_cols(
332 Vec3A::new(s.x, u.x, -f.x),
333 Vec3A::new(s.y, u.y, -f.y),
334 Vec3A::new(s.z, u.z, -f.z),
335 ),
336 translation: Vec3A::new(-eye.dot(s), -eye.dot(u), eye.dot(f)),
337 }
338 }
339
340 #[inline]
348 #[must_use]
349 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
350 glam_assert!(up.is_normalized());
351 Self::look_to_lh(eye, center - eye, up)
352 }
353
354 #[inline]
362 #[must_use]
363 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
364 glam_assert!(up.is_normalized());
365 Self::look_to_rh(eye, center - eye, up)
366 }
367
368 #[inline]
370 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
371 #[allow(clippy::useless_conversion)]
372 ((self.matrix3.x_axis * rhs.x)
373 + (self.matrix3.y_axis * rhs.y)
374 + (self.matrix3.z_axis * rhs.z)
375 + self.translation)
376 .into()
377 }
378
379 #[inline]
384 #[must_use]
385 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
386 #[allow(clippy::useless_conversion)]
387 ((self.matrix3.x_axis * rhs.x)
388 + (self.matrix3.y_axis * rhs.y)
389 + (self.matrix3.z_axis * rhs.z))
390 .into()
391 }
392
393 #[inline]
395 #[must_use]
396 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
397 self.matrix3 * rhs + self.translation
398 }
399
400 #[inline]
405 #[must_use]
406 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
407 self.matrix3 * rhs
408 }
409
410 #[inline]
415 #[must_use]
416 pub fn is_finite(&self) -> bool {
417 self.matrix3.is_finite() && self.translation.is_finite()
418 }
419
420 #[inline]
422 #[must_use]
423 pub fn is_nan(&self) -> bool {
424 self.matrix3.is_nan() || self.translation.is_nan()
425 }
426
427 #[inline]
437 #[must_use]
438 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
439 self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff)
440 && self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
441 }
442
443 #[inline]
447 #[must_use]
448 pub fn inverse(&self) -> Self {
449 let matrix3 = self.matrix3.inverse();
450 let translation = -(matrix3 * self.translation);
452
453 Self {
454 matrix3,
455 translation,
456 }
457 }
458}
459
460impl Default for Affine3A {
461 #[inline(always)]
462 fn default() -> Self {
463 Self::IDENTITY
464 }
465}
466
467impl Deref for Affine3A {
468 type Target = crate::deref::Cols4<Vec3A>;
469 #[inline(always)]
470 fn deref(&self) -> &Self::Target {
471 unsafe { &*(self as *const Self as *const Self::Target) }
472 }
473}
474
475impl DerefMut for Affine3A {
476 #[inline(always)]
477 fn deref_mut(&mut self) -> &mut Self::Target {
478 unsafe { &mut *(self as *mut Self as *mut Self::Target) }
479 }
480}
481
482impl PartialEq for Affine3A {
483 #[inline]
484 fn eq(&self, rhs: &Self) -> bool {
485 self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation)
486 }
487}
488
489#[cfg(not(target_arch = "spirv"))]
490impl core::fmt::Debug for Affine3A {
491 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
492 fmt.debug_struct(stringify!(Affine3A))
493 .field("matrix3", &self.matrix3)
494 .field("translation", &self.translation)
495 .finish()
496 }
497}
498
499#[cfg(not(target_arch = "spirv"))]
500impl core::fmt::Display for Affine3A {
501 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
502 write!(
503 f,
504 "[{}, {}, {}, {}]",
505 self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation
506 )
507 }
508}
509
510impl<'a> core::iter::Product<&'a Self> for Affine3A {
511 fn product<I>(iter: I) -> Self
512 where
513 I: Iterator<Item = &'a Self>,
514 {
515 iter.fold(Self::IDENTITY, |a, &b| a * b)
516 }
517}
518
519impl Mul for Affine3A {
520 type Output = Affine3A;
521
522 #[inline]
523 fn mul(self, rhs: Affine3A) -> Self::Output {
524 Self {
525 matrix3: self.matrix3 * rhs.matrix3,
526 translation: self.matrix3 * rhs.translation + self.translation,
527 }
528 }
529}
530
531impl MulAssign for Affine3A {
532 #[inline]
533 fn mul_assign(&mut self, rhs: Affine3A) {
534 *self = self.mul(rhs);
535 }
536}
537
538impl From<Affine3A> for Mat4 {
539 #[inline]
540 fn from(m: Affine3A) -> Mat4 {
541 Mat4::from_cols(
542 m.matrix3.x_axis.extend(0.0),
543 m.matrix3.y_axis.extend(0.0),
544 m.matrix3.z_axis.extend(0.0),
545 m.translation.extend(1.0),
546 )
547 }
548}
549
550impl Mul<Mat4> for Affine3A {
551 type Output = Mat4;
552
553 #[inline]
554 fn mul(self, rhs: Mat4) -> Self::Output {
555 Mat4::from(self) * rhs
556 }
557}
558
559impl Mul<Affine3A> for Mat4 {
560 type Output = Mat4;
561
562 #[inline]
563 fn mul(self, rhs: Affine3A) -> Self::Output {
564 self * Mat4::from(rhs)
565 }
566}