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_slice(&m[0..9]), 54 translation: DVec3::from_slice(&m[9..12]), 55 } 56 } 57 58 /// Creates a `[f64; 12]` array storing data in column major order. 59 #[inline] 60 #[must_use] to_cols_array(&self) -> [f64; 12]61 pub fn to_cols_array(&self) -> [f64; 12] { 62 let x = &self.matrix3.x_axis; 63 let y = &self.matrix3.y_axis; 64 let z = &self.matrix3.z_axis; 65 let w = &self.translation; 66 [x.x, x.y, x.z, y.x, y.y, y.z, z.x, z.y, z.z, w.x, w.y, w.z] 67 } 68 69 /// Creates an affine transform from a `[[f64; 3]; 4]` 70 /// 3D array stored in column major order. 71 /// If your data is in row major order you will need to `transpose` the returned 72 /// matrix. 73 #[inline] 74 #[must_use] from_cols_array_2d(m: &[[f64; 3]; 4]) -> Self75 pub fn from_cols_array_2d(m: &[[f64; 3]; 4]) -> Self { 76 Self { 77 matrix3: DMat3::from_cols(m[0].into(), m[1].into(), m[2].into()), 78 translation: m[3].into(), 79 } 80 } 81 82 /// Creates a `[[f64; 3]; 4]` 3D array storing data in 83 /// column major order. 84 /// If you require data in row major order `transpose` the matrix first. 85 #[inline] 86 #[must_use] to_cols_array_2d(&self) -> [[f64; 3]; 4]87 pub fn to_cols_array_2d(&self) -> [[f64; 3]; 4] { 88 [ 89 self.matrix3.x_axis.into(), 90 self.matrix3.y_axis.into(), 91 self.matrix3.z_axis.into(), 92 self.translation.into(), 93 ] 94 } 95 96 /// Creates an affine transform from the first 12 values in `slice`. 97 /// 98 /// # Panics 99 /// 100 /// Panics if `slice` is less than 12 elements long. 101 #[inline] 102 #[must_use] from_cols_slice(slice: &[f64]) -> Self103 pub fn from_cols_slice(slice: &[f64]) -> Self { 104 Self { 105 matrix3: DMat3::from_cols_slice(&slice[0..9]), 106 translation: DVec3::from_slice(&slice[9..12]), 107 } 108 } 109 110 /// Writes the columns of `self` to the first 12 elements in `slice`. 111 /// 112 /// # Panics 113 /// 114 /// Panics if `slice` is less than 12 elements long. 115 #[inline] write_cols_to_slice(self, slice: &mut [f64])116 pub fn write_cols_to_slice(self, slice: &mut [f64]) { 117 self.matrix3.write_cols_to_slice(&mut slice[0..9]); 118 self.translation.write_to_slice(&mut slice[9..12]); 119 } 120 121 /// Creates an affine transform that changes scale. 122 /// Note that if any scale is zero the transform will be non-invertible. 123 #[inline] 124 #[must_use] from_scale(scale: DVec3) -> Self125 pub fn from_scale(scale: DVec3) -> Self { 126 Self { 127 matrix3: DMat3::from_diagonal(scale), 128 translation: DVec3::ZERO, 129 } 130 } 131 /// Creates an affine transform from the given `rotation` quaternion. 132 #[inline] 133 #[must_use] from_quat(rotation: DQuat) -> Self134 pub fn from_quat(rotation: DQuat) -> Self { 135 Self { 136 matrix3: DMat3::from_quat(rotation), 137 translation: DVec3::ZERO, 138 } 139 } 140 141 /// Creates an affine transform containing a 3D rotation around a normalized 142 /// rotation `axis` of `angle` (in radians). 143 #[inline] 144 #[must_use] from_axis_angle(axis: DVec3, angle: f64) -> Self145 pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self { 146 Self { 147 matrix3: DMat3::from_axis_angle(axis, angle), 148 translation: DVec3::ZERO, 149 } 150 } 151 152 /// Creates an affine transform containing a 3D rotation around the x axis of 153 /// `angle` (in radians). 154 #[inline] 155 #[must_use] from_rotation_x(angle: f64) -> Self156 pub fn from_rotation_x(angle: f64) -> Self { 157 Self { 158 matrix3: DMat3::from_rotation_x(angle), 159 translation: DVec3::ZERO, 160 } 161 } 162 163 /// Creates an affine transform containing a 3D rotation around the y axis of 164 /// `angle` (in radians). 165 #[inline] 166 #[must_use] from_rotation_y(angle: f64) -> Self167 pub fn from_rotation_y(angle: f64) -> Self { 168 Self { 169 matrix3: DMat3::from_rotation_y(angle), 170 translation: DVec3::ZERO, 171 } 172 } 173 174 /// Creates an affine transform containing a 3D rotation around the z axis of 175 /// `angle` (in radians). 176 #[inline] 177 #[must_use] from_rotation_z(angle: f64) -> Self178 pub fn from_rotation_z(angle: f64) -> Self { 179 Self { 180 matrix3: DMat3::from_rotation_z(angle), 181 translation: DVec3::ZERO, 182 } 183 } 184 185 /// Creates an affine transformation from the given 3D `translation`. 186 #[inline] 187 #[must_use] from_translation(translation: DVec3) -> Self188 pub fn from_translation(translation: DVec3) -> Self { 189 #[allow(clippy::useless_conversion)] 190 Self { 191 matrix3: DMat3::IDENTITY, 192 translation: translation.into(), 193 } 194 } 195 196 /// Creates an affine transform from a 3x3 matrix (expressing scale, shear and 197 /// rotation) 198 #[inline] 199 #[must_use] from_mat3(mat3: DMat3) -> Self200 pub fn from_mat3(mat3: DMat3) -> Self { 201 #[allow(clippy::useless_conversion)] 202 Self { 203 matrix3: mat3.into(), 204 translation: DVec3::ZERO, 205 } 206 } 207 208 /// Creates an affine transform from a 3x3 matrix (expressing scale, shear and rotation) 209 /// and a translation vector. 210 /// 211 /// Equivalent to `DAffine3::from_translation(translation) * DAffine3::from_mat3(mat3)` 212 #[inline] 213 #[must_use] from_mat3_translation(mat3: DMat3, translation: DVec3) -> Self214 pub fn from_mat3_translation(mat3: DMat3, translation: DVec3) -> Self { 215 #[allow(clippy::useless_conversion)] 216 Self { 217 matrix3: mat3.into(), 218 translation: translation.into(), 219 } 220 } 221 222 /// Creates an affine transform from the given 3D `scale`, `rotation` and 223 /// `translation`. 224 /// 225 /// Equivalent to `DAffine3::from_translation(translation) * 226 /// DAffine3::from_quat(rotation) * DAffine3::from_scale(scale)` 227 #[inline] 228 #[must_use] from_scale_rotation_translation( scale: DVec3, rotation: DQuat, translation: DVec3, ) -> Self229 pub fn from_scale_rotation_translation( 230 scale: DVec3, 231 rotation: DQuat, 232 translation: DVec3, 233 ) -> Self { 234 let rotation = DMat3::from_quat(rotation); 235 #[allow(clippy::useless_conversion)] 236 Self { 237 matrix3: DMat3::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 /// Creates an affine transform from the given 3D `rotation` and `translation`. 247 /// 248 /// Equivalent to `DAffine3::from_translation(translation) * DAffine3::from_quat(rotation)` 249 #[inline] 250 #[must_use] from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self251 pub fn from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self { 252 #[allow(clippy::useless_conversion)] 253 Self { 254 matrix3: DMat3::from_quat(rotation), 255 translation: translation.into(), 256 } 257 } 258 259 /// The given `DMat4` must be an affine transform, 260 /// i.e. contain no perspective transform. 261 #[inline] 262 #[must_use] from_mat4(m: DMat4) -> Self263 pub fn from_mat4(m: DMat4) -> Self { 264 Self { 265 matrix3: DMat3::from_cols( 266 DVec3::from_vec4(m.x_axis), 267 DVec3::from_vec4(m.y_axis), 268 DVec3::from_vec4(m.z_axis), 269 ), 270 translation: DVec3::from_vec4(m.w_axis), 271 } 272 } 273 274 /// Extracts `scale`, `rotation` and `translation` from `self`. 275 /// 276 /// The transform is expected to be non-degenerate and without shearing, or the output 277 /// will be invalid. 278 /// 279 /// # Panics 280 /// 281 /// Will panic if the determinant `self.matrix3` is zero or if the resulting scale 282 /// vector contains any zero elements when `glam_assert` is enabled. 283 #[inline] 284 #[must_use] to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3)285 pub fn to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3) { 286 use crate::f64::math; 287 let det = self.matrix3.determinant(); 288 glam_assert!(det != 0.0); 289 290 let scale = DVec3::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(DVec3::ZERO).all()); 297 298 let inv_scale = scale.recip(); 299 300 #[allow(clippy::useless_conversion)] 301 let rotation = DQuat::from_mat3(&DMat3::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 /// Creates a left-handed view transform using a camera position, an up direction, and a facing 312 /// direction. 313 /// 314 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. 315 #[inline] 316 #[must_use] look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self317 pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self { 318 Self::look_to_rh(eye, -dir, up) 319 } 320 321 /// Creates a right-handed view transform using a camera position, an up direction, and a facing 322 /// direction. 323 /// 324 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. 325 #[inline] 326 #[must_use] look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self327 pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self { 328 let f = dir.normalize(); 329 let s = f.cross(up).normalize(); 330 let u = s.cross(f); 331 332 Self { 333 matrix3: DMat3::from_cols( 334 DVec3::new(s.x, u.x, -f.x), 335 DVec3::new(s.y, u.y, -f.y), 336 DVec3::new(s.z, u.z, -f.z), 337 ), 338 translation: DVec3::new(-eye.dot(s), -eye.dot(u), eye.dot(f)), 339 } 340 } 341 342 /// Creates a left-handed view transform using a camera position, an up direction, and a focal 343 /// point. 344 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. 345 /// 346 /// # Panics 347 /// 348 /// Will panic if `up` is not normalized when `glam_assert` is enabled. 349 #[inline] 350 #[must_use] look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self351 pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self { 352 glam_assert!(up.is_normalized()); 353 Self::look_to_lh(eye, center - eye, up) 354 } 355 356 /// Creates a right-handed view transform using a camera position, an up direction, and a focal 357 /// point. 358 /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. 359 /// 360 /// # Panics 361 /// 362 /// Will panic if `up` is not normalized when `glam_assert` is enabled. 363 #[inline] 364 #[must_use] look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self365 pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self { 366 glam_assert!(up.is_normalized()); 367 Self::look_to_rh(eye, center - eye, up) 368 } 369 370 /// Transforms the given 3D points, applying shear, scale, rotation and translation. 371 #[inline] transform_point3(&self, rhs: DVec3) -> DVec3372 pub fn transform_point3(&self, rhs: DVec3) -> DVec3 { 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 /// Transforms the given 3D vector, applying shear, scale and rotation (but NOT 382 /// translation). 383 /// 384 /// To also apply translation, use [`Self::transform_point3()`] instead. 385 #[inline] 386 #[must_use] transform_vector3(&self, rhs: DVec3) -> DVec3387 pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 { 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 /// Returns `true` if, and only if, all elements are finite. 396 /// 397 /// If any element is either `NaN`, positive or negative infinity, this will return 398 /// `false`. 399 #[inline] 400 #[must_use] is_finite(&self) -> bool401 pub fn is_finite(&self) -> bool { 402 self.matrix3.is_finite() && self.translation.is_finite() 403 } 404 405 /// Returns `true` if any elements are `NaN`. 406 #[inline] 407 #[must_use] is_nan(&self) -> bool408 pub fn is_nan(&self) -> bool { 409 self.matrix3.is_nan() || self.translation.is_nan() 410 } 411 412 /// Returns true if the absolute difference of all elements between `self` and `rhs` 413 /// is less than or equal to `max_abs_diff`. 414 /// 415 /// This can be used to compare if two 3x4 matrices contain similar elements. It works 416 /// best when comparing with a known value. The `max_abs_diff` that should be used used 417 /// depends on the values being compared against. 418 /// 419 /// For more see 420 /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/). 421 #[inline] 422 #[must_use] abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool423 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool { 424 self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff) 425 && self.translation.abs_diff_eq(rhs.translation, max_abs_diff) 426 } 427 428 /// Return the inverse of this transform. 429 /// 430 /// Note that if the transform is not invertible the result will be invalid. 431 #[inline] 432 #[must_use] inverse(&self) -> Self433 pub fn inverse(&self) -> Self { 434 let matrix3 = self.matrix3.inverse(); 435 // transform negative translation by the matrix inverse: 436 let translation = -(matrix3 * self.translation); 437 438 Self { 439 matrix3, 440 translation, 441 } 442 } 443 } 444 445 impl Default for DAffine3 { 446 #[inline(always)] default() -> Self447 fn default() -> Self { 448 Self::IDENTITY 449 } 450 } 451 452 impl Deref for DAffine3 { 453 type Target = crate::deref::Cols4<DVec3>; 454 #[inline(always)] deref(&self) -> &Self::Target455 fn deref(&self) -> &Self::Target { 456 unsafe { &*(self as *const Self as *const Self::Target) } 457 } 458 } 459 460 impl DerefMut for DAffine3 { 461 #[inline(always)] deref_mut(&mut self) -> &mut Self::Target462 fn deref_mut(&mut self) -> &mut Self::Target { 463 unsafe { &mut *(self as *mut Self as *mut Self::Target) } 464 } 465 } 466 467 impl PartialEq for DAffine3 { 468 #[inline] eq(&self, rhs: &Self) -> bool469 fn eq(&self, rhs: &Self) -> bool { 470 self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation) 471 } 472 } 473 474 #[cfg(not(target_arch = "spirv"))] 475 impl core::fmt::Debug for DAffine3 { fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result476 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 477 fmt.debug_struct(stringify!(DAffine3)) 478 .field("matrix3", &self.matrix3) 479 .field("translation", &self.translation) 480 .finish() 481 } 482 } 483 484 #[cfg(not(target_arch = "spirv"))] 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 write!( 488 f, 489 "[{}, {}, {}, {}]", 490 self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation 491 ) 492 } 493 } 494 495 impl<'a> core::iter::Product<&'a Self> for DAffine3 { product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,496 fn product<I>(iter: I) -> Self 497 where 498 I: Iterator<Item = &'a Self>, 499 { 500 iter.fold(Self::IDENTITY, |a, &b| a * b) 501 } 502 } 503 504 impl Mul for DAffine3 { 505 type Output = DAffine3; 506 507 #[inline] mul(self, rhs: DAffine3) -> Self::Output508 fn mul(self, rhs: DAffine3) -> Self::Output { 509 Self { 510 matrix3: self.matrix3 * rhs.matrix3, 511 translation: self.matrix3 * rhs.translation + self.translation, 512 } 513 } 514 } 515 516 impl MulAssign for DAffine3 { 517 #[inline] mul_assign(&mut self, rhs: DAffine3)518 fn mul_assign(&mut self, rhs: DAffine3) { 519 *self = self.mul(rhs); 520 } 521 } 522 523 impl From<DAffine3> for DMat4 { 524 #[inline] from(m: DAffine3) -> DMat4525 fn from(m: DAffine3) -> DMat4 { 526 DMat4::from_cols( 527 m.matrix3.x_axis.extend(0.0), 528 m.matrix3.y_axis.extend(0.0), 529 m.matrix3.z_axis.extend(0.0), 530 m.translation.extend(1.0), 531 ) 532 } 533 } 534 535 impl Mul<DMat4> for DAffine3 { 536 type Output = DMat4; 537 538 #[inline] mul(self, rhs: DMat4) -> Self::Output539 fn mul(self, rhs: DMat4) -> Self::Output { 540 DMat4::from(self) * rhs 541 } 542 } 543 544 impl Mul<DAffine3> for DMat4 { 545 type Output = DMat4; 546 547 #[inline] mul(self, rhs: DAffine3) -> Self::Output548 fn mul(self, rhs: DAffine3) -> Self::Output { 549 self * DMat4::from(rhs) 550 } 551 } 552