1 // Generated from affine.rs.tera template. Edit the template, not the generated file. 2 3 use crate::{Mat3, Mat3A, Mat4, Quat, Vec3, Vec3A}; 4 use core::ops::{Deref, DerefMut, Mul, MulAssign}; 5 6 /// A 3D affine transform, which can represent translation, rotation, scaling and shear. 7 /// 8 /// This type is 16 byte aligned. 9 #[derive(Copy, Clone)] 10 #[repr(C)] 11 pub struct Affine3A { 12 pub matrix3: Mat3A, 13 pub translation: Vec3A, 14 } 15 16 impl Affine3A { 17 /// The degenerate zero transform. 18 /// 19 /// This transforms any finite vector and point to zero. 20 /// The zero transform is non-invertible. 21 pub const ZERO: Self = Self { 22 matrix3: Mat3A::ZERO, 23 translation: Vec3A::ZERO, 24 }; 25 26 /// The identity transform. 27 /// 28 /// Multiplying a vector with this returns the same vector. 29 pub const IDENTITY: Self = Self { 30 matrix3: Mat3A::IDENTITY, 31 translation: Vec3A::ZERO, 32 }; 33 34 /// All NAN:s. 35 pub const NAN: Self = Self { 36 matrix3: Mat3A::NAN, 37 translation: Vec3A::NAN, 38 }; 39 40 /// Creates an affine transform from three column vectors. 41 #[inline(always)] 42 #[must_use] from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A, w_axis: Vec3A) -> Self43 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 /// Creates an affine transform from a `[f32; 12]` array stored in column major order. 51 #[inline] 52 #[must_use] from_cols_array(m: &[f32; 12]) -> Self53 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 /// Creates a `[f32; 12]` array storing data in column major order. 61 #[inline] 62 #[must_use] to_cols_array(&self) -> [f32; 12]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 /// Creates an affine transform from a `[[f32; 3]; 4]` 72 /// 3D array stored in column major order. 73 /// If your data is in row major order you will need to `transpose` the returned 74 /// matrix. 75 #[inline] 76 #[must_use] from_cols_array_2d(m: &[[f32; 3]; 4]) -> Self77 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 /// Creates a `[[f32; 3]; 4]` 3D array storing data in 85 /// column major order. 86 /// If you require data in row major order `transpose` the matrix first. 87 #[inline] 88 #[must_use] to_cols_array_2d(&self) -> [[f32; 3]; 4]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 /// Creates an affine transform from the first 12 values in `slice`. 99 /// 100 /// # Panics 101 /// 102 /// Panics if `slice` is less than 12 elements long. 103 #[inline] 104 #[must_use] from_cols_slice(slice: &[f32]) -> Self105 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 /// Writes the columns of `self` to the first 12 elements in `slice`. 113 /// 114 /// # Panics 115 /// 116 /// Panics if `slice` is less than 12 elements long. 117 #[inline] write_cols_to_slice(self, slice: &mut [f32])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 /// Creates an affine transform that changes scale. 124 /// Note that if any scale is zero the transform will be non-invertible. 125 #[inline] 126 #[must_use] from_scale(scale: Vec3) -> Self127 pub fn from_scale(scale: Vec3) -> Self { 128 Self { 129 matrix3: Mat3A::from_diagonal(scale), 130 translation: Vec3A::ZERO, 131 } 132 } 133 /// Creates an affine transform from the given `rotation` quaternion. 134 #[inline] 135 #[must_use] from_quat(rotation: Quat) -> Self136 pub fn from_quat(rotation: Quat) -> Self { 137 Self { 138 matrix3: Mat3A::from_quat(rotation), 139 translation: Vec3A::ZERO, 140 } 141 } 142 143 /// Creates an affine transform containing a 3D rotation around a normalized 144 /// rotation `axis` of `angle` (in radians). 145 #[inline] 146 #[must_use] from_axis_angle(axis: Vec3, angle: f32) -> Self147 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 /// Creates an affine transform containing a 3D rotation around the x axis of 155 /// `angle` (in radians). 156 #[inline] 157 #[must_use] from_rotation_x(angle: f32) -> Self158 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 /// Creates an affine transform containing a 3D rotation around the y axis of 166 /// `angle` (in radians). 167 #[inline] 168 #[must_use] from_rotation_y(angle: f32) -> Self169 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 /// Creates an affine transform containing a 3D rotation around the z axis of 177 /// `angle` (in radians). 178 #[inline] 179 #[must_use] from_rotation_z(angle: f32) -> Self180 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 /// Creates an affine transformation from the given 3D `translation`. 188 #[inline] 189 #[must_use] from_translation(translation: Vec3) -> Self190 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 /// Creates an affine transform from a 3x3 matrix (expressing scale, shear and 199 /// rotation) 200 #[inline] 201 #[must_use] from_mat3(mat3: Mat3) -> Self202 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 /// Creates an affine transform from a 3x3 matrix (expressing scale, shear and rotation) 211 /// and a translation vector. 212 /// 213 /// Equivalent to `Affine3A::from_translation(translation) * Affine3A::from_mat3(mat3)` 214 #[inline] 215 #[must_use] from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self216 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 /// Creates an affine transform from the given 3D `scale`, `rotation` and 225 /// `translation`. 226 /// 227 /// Equivalent to `Affine3A::from_translation(translation) * 228 /// Affine3A::from_quat(rotation) * Affine3A::from_scale(scale)` 229 #[inline] 230 #[must_use] from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self231 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 /// Creates an affine transform from the given 3D `rotation` and `translation`. 245 /// 246 /// Equivalent to `Affine3A::from_translation(translation) * Affine3A::from_quat(rotation)` 247 #[inline] 248 #[must_use] from_rotation_translation(rotation: Quat, translation: Vec3) -> Self249 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 /// The given `Mat4` must be an affine transform, 258 /// i.e. contain no perspective transform. 259 #[inline] 260 #[must_use] from_mat4(m: Mat4) -> Self261 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 /// Extracts `scale`, `rotation` and `translation` from `self`. 273 /// 274 /// The transform is expected to be non-degenerate and without shearing, or the output 275 /// will be invalid. 276 /// 277 /// # Panics 278 /// 279 /// Will panic if the determinant `self.matrix3` is zero or if the resulting scale 280 /// vector contains any zero elements when `glam_assert` is enabled. 281 #[inline] 282 #[must_use] to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3)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 /// Creates a left-handed view transform using a camera position, an up direction, and a facing 310 /// direction. 311 /// 312 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. 313 #[inline] 314 #[must_use] look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self315 pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { 316 Self::look_to_rh(eye, -dir, up) 317 } 318 319 /// Creates a right-handed view transform using a camera position, an up direction, and a facing 320 /// direction. 321 /// 322 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. 323 #[inline] 324 #[must_use] look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self325 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 /// Creates a left-handed view transform using a camera position, an up direction, and a focal 341 /// point. 342 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. 343 /// 344 /// # Panics 345 /// 346 /// Will panic if `up` is not normalized when `glam_assert` is enabled. 347 #[inline] 348 #[must_use] look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self349 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 /// Creates a right-handed view transform using a camera position, an up direction, and a focal 355 /// point. 356 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. 357 /// 358 /// # Panics 359 /// 360 /// Will panic if `up` is not normalized when `glam_assert` is enabled. 361 #[inline] 362 #[must_use] look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self363 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 /// Transforms the given 3D points, applying shear, scale, rotation and translation. 369 #[inline] transform_point3(&self, rhs: Vec3) -> Vec3370 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 /// Transforms the given 3D vector, applying shear, scale and rotation (but NOT 380 /// translation). 381 /// 382 /// To also apply translation, use [`Self::transform_point3()`] instead. 383 #[inline] 384 #[must_use] transform_vector3(&self, rhs: Vec3) -> Vec3385 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 /// Transforms the given [`Vec3A`], applying shear, scale, rotation and translation. 394 #[inline] 395 #[must_use] transform_point3a(&self, rhs: Vec3A) -> Vec3A396 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A { 397 self.matrix3 * rhs + self.translation 398 } 399 400 /// Transforms the given [`Vec3A`], applying shear, scale and rotation (but NOT 401 /// translation). 402 /// 403 /// To also apply translation, use [`Self::transform_point3a()`] instead. 404 #[inline] 405 #[must_use] transform_vector3a(&self, rhs: Vec3A) -> Vec3A406 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A { 407 self.matrix3 * rhs 408 } 409 410 /// Returns `true` if, and only if, all elements are finite. 411 /// 412 /// If any element is either `NaN`, positive or negative infinity, this will return 413 /// `false`. 414 #[inline] 415 #[must_use] is_finite(&self) -> bool416 pub fn is_finite(&self) -> bool { 417 self.matrix3.is_finite() && self.translation.is_finite() 418 } 419 420 /// Returns `true` if any elements are `NaN`. 421 #[inline] 422 #[must_use] is_nan(&self) -> bool423 pub fn is_nan(&self) -> bool { 424 self.matrix3.is_nan() || self.translation.is_nan() 425 } 426 427 /// Returns true if the absolute difference of all elements between `self` and `rhs` 428 /// is less than or equal to `max_abs_diff`. 429 /// 430 /// This can be used to compare if two 3x4 matrices contain similar elements. It works 431 /// best when comparing with a known value. The `max_abs_diff` that should be used used 432 /// depends on the values being compared against. 433 /// 434 /// For more see 435 /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/). 436 #[inline] 437 #[must_use] abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool438 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 /// Return the inverse of this transform. 444 /// 445 /// Note that if the transform is not invertible the result will be invalid. 446 #[inline] 447 #[must_use] inverse(&self) -> Self448 pub fn inverse(&self) -> Self { 449 let matrix3 = self.matrix3.inverse(); 450 // transform negative translation by the matrix inverse: 451 let translation = -(matrix3 * self.translation); 452 453 Self { 454 matrix3, 455 translation, 456 } 457 } 458 } 459 460 impl Default for Affine3A { 461 #[inline(always)] default() -> Self462 fn default() -> Self { 463 Self::IDENTITY 464 } 465 } 466 467 impl Deref for Affine3A { 468 type Target = crate::deref::Cols4<Vec3A>; 469 #[inline(always)] deref(&self) -> &Self::Target470 fn deref(&self) -> &Self::Target { 471 unsafe { &*(self as *const Self as *const Self::Target) } 472 } 473 } 474 475 impl DerefMut for Affine3A { 476 #[inline(always)] deref_mut(&mut self) -> &mut Self::Target477 fn deref_mut(&mut self) -> &mut Self::Target { 478 unsafe { &mut *(self as *mut Self as *mut Self::Target) } 479 } 480 } 481 482 impl PartialEq for Affine3A { 483 #[inline] eq(&self, rhs: &Self) -> bool484 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"))] 490 impl core::fmt::Debug for Affine3A { fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result491 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"))] 500 impl core::fmt::Display for Affine3A { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result501 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 510 impl<'a> core::iter::Product<&'a Self> for Affine3A { product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,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 519 impl Mul for Affine3A { 520 type Output = Affine3A; 521 522 #[inline] mul(self, rhs: Affine3A) -> Self::Output523 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 531 impl MulAssign for Affine3A { 532 #[inline] mul_assign(&mut self, rhs: Affine3A)533 fn mul_assign(&mut self, rhs: Affine3A) { 534 *self = self.mul(rhs); 535 } 536 } 537 538 impl From<Affine3A> for Mat4 { 539 #[inline] from(m: Affine3A) -> Mat4540 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 550 impl Mul<Mat4> for Affine3A { 551 type Output = Mat4; 552 553 #[inline] mul(self, rhs: Mat4) -> Self::Output554 fn mul(self, rhs: Mat4) -> Self::Output { 555 Mat4::from(self) * rhs 556 } 557 } 558 559 impl Mul<Affine3A> for Mat4 { 560 type Output = Mat4; 561 562 #[inline] mul(self, rhs: Affine3A) -> Self::Output563 fn mul(self, rhs: Affine3A) -> Self::Output { 564 self * Mat4::from(rhs) 565 } 566 } 567