1 // Generated from affine.rs.tera template. Edit the template, not the generated file. 2 3 use crate::{DMat3, DMat4, DQuat, DVec3}; 4 use core::ops::{Deref, DerefMut, Mul, MulAssign}; 5 6 /// A 3D affine transform, which can represent translation, rotation, scaling and shear. 7 #[derive(Copy, Clone)] 8 #[repr(C)] 9 pub struct DAffine3 { 10 pub matrix3: DMat3, 11 pub translation: DVec3, 12 } 13 14 impl DAffine3 { 15 /// The degenerate zero transform. 16 /// 17 /// This transforms any finite vector and point to zero. 18 /// The zero transform is non-invertible. 19 pub const ZERO: Self = Self { 20 matrix3: DMat3::ZERO, 21 translation: DVec3::ZERO, 22 }; 23 24 /// The identity transform. 25 /// 26 /// Multiplying a vector with this returns the same vector. 27 pub const IDENTITY: Self = Self { 28 matrix3: DMat3::IDENTITY, 29 translation: DVec3::ZERO, 30 }; 31 32 /// All NAN:s. 33 pub const NAN: Self = Self { 34 matrix3: DMat3::NAN, 35 translation: DVec3::NAN, 36 }; 37 38 /// Creates an affine transform from three column vectors. 39 #[inline(always)] 40 #[must_use] from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3, w_axis: DVec3) -> Self41 pub const fn from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3, w_axis: DVec3) -> Self { 42 Self { 43 matrix3: DMat3::from_cols(x_axis, y_axis, z_axis), 44 translation: w_axis, 45 } 46 } 47 48 /// Creates an affine transform from a `[f64; 12]` array stored in column major order. 49 #[inline] 50 #[must_use] from_cols_array(m: &[f64; 12]) -> Self51 pub fn from_cols_array(m: &[f64; 12]) -> Self { 52 Self { 53 matrix3: DMat3::from_cols_array(&[ 54 m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], 55 ]), 56 translation: DVec3::from_array([m[9], m[10], m[11]]), 57 } 58 } 59 60 /// Creates a `[f64; 12]` array storing data in column major order. 61 #[inline] 62 #[must_use] to_cols_array(&self) -> [f64; 12]63 pub fn to_cols_array(&self) -> [f64; 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 `[[f64; 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: &[[f64; 3]; 4]) -> Self77 pub fn from_cols_array_2d(m: &[[f64; 3]; 4]) -> Self { 78 Self { 79 matrix3: DMat3::from_cols(m[0].into(), m[1].into(), m[2].into()), 80 translation: m[3].into(), 81 } 82 } 83 84 /// Creates a `[[f64; 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) -> [[f64; 3]; 4]89 pub fn to_cols_array_2d(&self) -> [[f64; 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: &[f64]) -> Self105 pub fn from_cols_slice(slice: &[f64]) -> Self { 106 Self { 107 matrix3: DMat3::from_cols_slice(&slice[0..9]), 108 translation: DVec3::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 [f64])118 pub fn write_cols_to_slice(self, slice: &mut [f64]) { 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: DVec3) -> Self127 pub fn from_scale(scale: DVec3) -> Self { 128 Self { 129 matrix3: DMat3::from_diagonal(scale), 130 translation: DVec3::ZERO, 131 } 132 } 133 /// Creates an affine transform from the given `rotation` quaternion. 134 #[inline] 135 #[must_use] from_quat(rotation: DQuat) -> Self136 pub fn from_quat(rotation: DQuat) -> Self { 137 Self { 138 matrix3: DMat3::from_quat(rotation), 139 translation: DVec3::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: DVec3, angle: f64) -> Self147 pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self { 148 Self { 149 matrix3: DMat3::from_axis_angle(axis, angle), 150 translation: DVec3::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: f64) -> Self158 pub fn from_rotation_x(angle: f64) -> Self { 159 Self { 160 matrix3: DMat3::from_rotation_x(angle), 161 translation: DVec3::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: f64) -> Self169 pub fn from_rotation_y(angle: f64) -> Self { 170 Self { 171 matrix3: DMat3::from_rotation_y(angle), 172 translation: DVec3::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: f64) -> Self180 pub fn from_rotation_z(angle: f64) -> Self { 181 Self { 182 matrix3: DMat3::from_rotation_z(angle), 183 translation: DVec3::ZERO, 184 } 185 } 186 187 /// Creates an affine transformation from the given 3D `translation`. 188 #[inline] 189 #[must_use] from_translation(translation: DVec3) -> Self190 pub fn from_translation(translation: DVec3) -> Self { 191 #[allow(clippy::useless_conversion)] 192 Self { 193 matrix3: DMat3::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: DMat3) -> Self202 pub fn from_mat3(mat3: DMat3) -> Self { 203 #[allow(clippy::useless_conversion)] 204 Self { 205 matrix3: mat3.into(), 206 translation: DVec3::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 `DAffine3::from_translation(translation) * DAffine3::from_mat3(mat3)` 214 #[inline] 215 #[must_use] from_mat3_translation(mat3: DMat3, translation: DVec3) -> Self216 pub fn from_mat3_translation(mat3: DMat3, translation: DVec3) -> 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 `DAffine3::from_translation(translation) * 228 /// DAffine3::from_quat(rotation) * DAffine3::from_scale(scale)` 229 #[inline] 230 #[must_use] from_scale_rotation_translation( scale: DVec3, rotation: DQuat, translation: DVec3, ) -> Self231 pub fn from_scale_rotation_translation( 232 scale: DVec3, 233 rotation: DQuat, 234 translation: DVec3, 235 ) -> Self { 236 let rotation = DMat3::from_quat(rotation); 237 #[allow(clippy::useless_conversion)] 238 Self { 239 matrix3: DMat3::from_cols( 240 rotation.x_axis * scale.x, 241 rotation.y_axis * scale.y, 242 rotation.z_axis * scale.z, 243 ), 244 translation: translation.into(), 245 } 246 } 247 248 /// Creates an affine transform from the given 3D `rotation` and `translation`. 249 /// 250 /// Equivalent to `DAffine3::from_translation(translation) * DAffine3::from_quat(rotation)` 251 #[inline] 252 #[must_use] from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self253 pub fn from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self { 254 #[allow(clippy::useless_conversion)] 255 Self { 256 matrix3: DMat3::from_quat(rotation), 257 translation: translation.into(), 258 } 259 } 260 261 /// The given `DMat4` must be an affine transform, 262 /// i.e. contain no perspective transform. 263 #[inline] 264 #[must_use] from_mat4(m: DMat4) -> Self265 pub fn from_mat4(m: DMat4) -> Self { 266 Self { 267 matrix3: DMat3::from_cols( 268 DVec3::from_vec4(m.x_axis), 269 DVec3::from_vec4(m.y_axis), 270 DVec3::from_vec4(m.z_axis), 271 ), 272 translation: DVec3::from_vec4(m.w_axis), 273 } 274 } 275 276 /// Extracts `scale`, `rotation` and `translation` from `self`. 277 /// 278 /// The transform is expected to be non-degenerate and without shearing, or the output 279 /// will be invalid. 280 /// 281 /// # Panics 282 /// 283 /// Will panic if the determinant `self.matrix3` is zero or if the resulting scale 284 /// vector contains any zero elements when `glam_assert` is enabled. 285 #[inline] 286 #[must_use] to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3)287 pub fn to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3) { 288 use crate::f64::math; 289 let det = self.matrix3.determinant(); 290 glam_assert!(det != 0.0); 291 292 let scale = DVec3::new( 293 self.matrix3.x_axis.length() * math::signum(det), 294 self.matrix3.y_axis.length(), 295 self.matrix3.z_axis.length(), 296 ); 297 298 glam_assert!(scale.cmpne(DVec3::ZERO).all()); 299 300 let inv_scale = scale.recip(); 301 302 #[allow(clippy::useless_conversion)] 303 let rotation = DQuat::from_mat3(&DMat3::from_cols( 304 (self.matrix3.x_axis * inv_scale.x).into(), 305 (self.matrix3.y_axis * inv_scale.y).into(), 306 (self.matrix3.z_axis * inv_scale.z).into(), 307 )); 308 309 #[allow(clippy::useless_conversion)] 310 (scale, rotation, self.translation.into()) 311 } 312 313 /// Creates a left-handed view transform using a camera position, an up direction, and a facing 314 /// direction. 315 /// 316 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. 317 #[inline] 318 #[must_use] look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self319 pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self { 320 Self::look_to_rh(eye, -dir, up) 321 } 322 323 /// Creates a right-handed view transform using a camera position, an up direction, and a facing 324 /// direction. 325 /// 326 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. 327 #[inline] 328 #[must_use] look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self329 pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self { 330 let f = dir.normalize(); 331 let s = f.cross(up).normalize(); 332 let u = s.cross(f); 333 334 Self { 335 matrix3: DMat3::from_cols( 336 DVec3::new(s.x, u.x, -f.x), 337 DVec3::new(s.y, u.y, -f.y), 338 DVec3::new(s.z, u.z, -f.z), 339 ), 340 translation: DVec3::new(-eye.dot(s), -eye.dot(u), eye.dot(f)), 341 } 342 } 343 344 /// Creates a left-handed view transform using a camera position, an up direction, and a focal 345 /// point. 346 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. 347 /// 348 /// # Panics 349 /// 350 /// Will panic if `up` is not normalized when `glam_assert` is enabled. 351 #[inline] 352 #[must_use] look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self353 pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self { 354 glam_assert!(up.is_normalized()); 355 Self::look_to_lh(eye, center - eye, up) 356 } 357 358 /// Creates a right-handed view transform using a camera position, an up direction, and a focal 359 /// point. 360 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. 361 /// 362 /// # Panics 363 /// 364 /// Will panic if `up` is not normalized when `glam_assert` is enabled. 365 #[inline] 366 #[must_use] look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self367 pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self { 368 glam_assert!(up.is_normalized()); 369 Self::look_to_rh(eye, center - eye, up) 370 } 371 372 /// Transforms the given 3D points, applying shear, scale, rotation and translation. 373 #[inline] transform_point3(&self, rhs: DVec3) -> DVec3374 pub fn transform_point3(&self, rhs: DVec3) -> DVec3 { 375 #[allow(clippy::useless_conversion)] 376 ((self.matrix3.x_axis * rhs.x) 377 + (self.matrix3.y_axis * rhs.y) 378 + (self.matrix3.z_axis * rhs.z) 379 + self.translation) 380 .into() 381 } 382 383 /// Transforms the given 3D vector, applying shear, scale and rotation (but NOT 384 /// translation). 385 /// 386 /// To also apply translation, use [`Self::transform_point3()`] instead. 387 #[inline] 388 #[must_use] transform_vector3(&self, rhs: DVec3) -> DVec3389 pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 { 390 #[allow(clippy::useless_conversion)] 391 ((self.matrix3.x_axis * rhs.x) 392 + (self.matrix3.y_axis * rhs.y) 393 + (self.matrix3.z_axis * rhs.z)) 394 .into() 395 } 396 397 /// Returns `true` if, and only if, all elements are finite. 398 /// 399 /// If any element is either `NaN`, positive or negative infinity, this will return 400 /// `false`. 401 #[inline] 402 #[must_use] is_finite(&self) -> bool403 pub fn is_finite(&self) -> bool { 404 self.matrix3.is_finite() && self.translation.is_finite() 405 } 406 407 /// Returns `true` if any elements are `NaN`. 408 #[inline] 409 #[must_use] is_nan(&self) -> bool410 pub fn is_nan(&self) -> bool { 411 self.matrix3.is_nan() || self.translation.is_nan() 412 } 413 414 /// Returns true if the absolute difference of all elements between `self` and `rhs` 415 /// is less than or equal to `max_abs_diff`. 416 /// 417 /// This can be used to compare if two 3x4 matrices contain similar elements. It works 418 /// best when comparing with a known value. The `max_abs_diff` that should be used used 419 /// depends on the values being compared against. 420 /// 421 /// For more see 422 /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/). 423 #[inline] 424 #[must_use] abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool425 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool { 426 self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff) 427 && self.translation.abs_diff_eq(rhs.translation, max_abs_diff) 428 } 429 430 /// Return the inverse of this transform. 431 /// 432 /// Note that if the transform is not invertible the result will be invalid. 433 #[inline] 434 #[must_use] inverse(&self) -> Self435 pub fn inverse(&self) -> Self { 436 let matrix3 = self.matrix3.inverse(); 437 // transform negative translation by the matrix inverse: 438 let translation = -(matrix3 * self.translation); 439 440 Self { 441 matrix3, 442 translation, 443 } 444 } 445 } 446 447 impl Default for DAffine3 { 448 #[inline(always)] default() -> Self449 fn default() -> Self { 450 Self::IDENTITY 451 } 452 } 453 454 impl Deref for DAffine3 { 455 type Target = crate::deref::Cols4<DVec3>; 456 #[inline(always)] deref(&self) -> &Self::Target457 fn deref(&self) -> &Self::Target { 458 unsafe { &*(self as *const Self as *const Self::Target) } 459 } 460 } 461 462 impl DerefMut for DAffine3 { 463 #[inline(always)] deref_mut(&mut self) -> &mut Self::Target464 fn deref_mut(&mut self) -> &mut Self::Target { 465 unsafe { &mut *(self as *mut Self as *mut Self::Target) } 466 } 467 } 468 469 impl PartialEq for DAffine3 { 470 #[inline] eq(&self, rhs: &Self) -> bool471 fn eq(&self, rhs: &Self) -> bool { 472 self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation) 473 } 474 } 475 476 impl core::fmt::Debug for DAffine3 { fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result477 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 478 fmt.debug_struct(stringify!(DAffine3)) 479 .field("matrix3", &self.matrix3) 480 .field("translation", &self.translation) 481 .finish() 482 } 483 } 484 485 impl core::fmt::Display for DAffine3 { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result486 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 487 if let Some(p) = f.precision() { 488 write!( 489 f, 490 "[{:.*}, {:.*}, {:.*}, {:.*}]", 491 p, 492 self.matrix3.x_axis, 493 p, 494 self.matrix3.y_axis, 495 p, 496 self.matrix3.z_axis, 497 p, 498 self.translation 499 ) 500 } else { 501 write!( 502 f, 503 "[{}, {}, {}, {}]", 504 self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation 505 ) 506 } 507 } 508 } 509 510 impl<'a> core::iter::Product<&'a Self> for DAffine3 { 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 DAffine3 { 520 type Output = DAffine3; 521 522 #[inline] mul(self, rhs: DAffine3) -> Self::Output523 fn mul(self, rhs: DAffine3) -> 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 DAffine3 { 532 #[inline] mul_assign(&mut self, rhs: DAffine3)533 fn mul_assign(&mut self, rhs: DAffine3) { 534 *self = self.mul(rhs); 535 } 536 } 537 538 impl From<DAffine3> for DMat4 { 539 #[inline] from(m: DAffine3) -> DMat4540 fn from(m: DAffine3) -> DMat4 { 541 DMat4::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<DMat4> for DAffine3 { 551 type Output = DMat4; 552 553 #[inline] mul(self, rhs: DMat4) -> Self::Output554 fn mul(self, rhs: DMat4) -> Self::Output { 555 DMat4::from(self) * rhs 556 } 557 } 558 559 impl Mul<DAffine3> for DMat4 { 560 type Output = DMat4; 561 562 #[inline] mul(self, rhs: DAffine3) -> Self::Output563 fn mul(self, rhs: DAffine3) -> Self::Output { 564 self * DMat4::from(rhs) 565 } 566 } 567