|
1 | 1 | use crate::core_types::{IsEqualApprox, Quat, Vector3};
|
2 |
| -use core::ops::Mul; |
| 2 | +use crate::globalscope::lerp; |
3 | 3 | use glam::Mat3;
|
| 4 | +use std::ops::Mul; |
4 | 5 |
|
5 | 6 | /// A 3x3 matrix, typically used as an orthogonal basis for [`Transform`][crate::core_types::Transform].
|
6 | 7 | ///
|
@@ -241,12 +242,46 @@ impl Basis {
|
241 | 242 | ///
|
242 | 243 | /// If the determinant of `self` is zero.
|
243 | 244 | #[inline]
|
244 |
| - pub fn inverted(&self) -> Self { |
| 245 | + pub fn inverse(&self) -> Self { |
245 | 246 | let mut copy = *self;
|
246 | 247 | copy.invert();
|
247 | 248 | copy
|
248 | 249 | }
|
249 | 250 |
|
| 251 | + #[inline] |
| 252 | + #[deprecated = "Use `inverse` instead."] |
| 253 | + pub fn inverted(&self) -> Self { |
| 254 | + self.inverse() |
| 255 | + } |
| 256 | + |
| 257 | + /// Returns linear interpolation on a sphere between two basis by weight amount (on the range of 0.0 to 1.0). |
| 258 | + #[inline] |
| 259 | + pub fn slerp(&self, other: &Basis, weight: f32) -> Self { |
| 260 | + let from = self.to_quat(); |
| 261 | + let to = other.to_quat(); |
| 262 | + let mut result = Basis::from_quat(from.slerp(to, weight)); |
| 263 | + |
| 264 | + for i in 0..3 { |
| 265 | + result.elements[i] *= lerp( |
| 266 | + self.elements[i].length()..=other.elements[i].length(), |
| 267 | + weight, |
| 268 | + ); |
| 269 | + } |
| 270 | + |
| 271 | + result |
| 272 | + } |
| 273 | + |
| 274 | + /// Returns linear interpolation between two basis by weight amount (on the range of 0.0 to 1.0). |
| 275 | + #[inline] |
| 276 | + pub fn lerp(&self, other: &Basis, weight: f32) -> Self { |
| 277 | + // this is how godot is doing it at https://github.com/godotengine/godot/blob/master/core/math/basis.cpp#L964 |
| 278 | + // but Godot engine output for me differs than godot-rust |
| 279 | + let a = self.elements[0].linear_interpolate(other.elements[0], weight); |
| 280 | + let b = self.elements[1].linear_interpolate(other.elements[1], weight); |
| 281 | + let c = self.elements[2].linear_interpolate(other.elements[2], weight); |
| 282 | + Basis::from_rows(a, b, c) |
| 283 | + } |
| 284 | + |
250 | 285 | /// Transposes the matrix.
|
251 | 286 | #[inline]
|
252 | 287 | fn transpose(&mut self) {
|
@@ -309,6 +344,20 @@ impl Basis {
|
309 | 344 | m.is_equal_approx(&Self::IDENTITY)
|
310 | 345 | }
|
311 | 346 |
|
| 347 | + #[inline] |
| 348 | + fn orthogonalize(&mut self) { |
| 349 | + let scale = self.scale(); |
| 350 | + self.orthonormalize(); |
| 351 | + self.scale_local(scale); |
| 352 | + } |
| 353 | + |
| 354 | + #[inline] |
| 355 | + pub fn orthogonalized(&self) -> Self { |
| 356 | + let mut copy = *self; |
| 357 | + copy.orthogonalize(); |
| 358 | + copy |
| 359 | + } |
| 360 | + |
312 | 361 | /// Returns an orthonormalized version of the matrix: 3 orthogonal basis vectors of unit length.
|
313 | 362 | #[inline]
|
314 | 363 | pub fn orthonormalized(&self) -> Self {
|
@@ -369,6 +418,18 @@ impl Basis {
|
369 | 418 | copy
|
370 | 419 | }
|
371 | 420 |
|
| 421 | + /// In-place basis scaling in object-local coordinate system |
| 422 | + #[inline] |
| 423 | + fn scale_local(&mut self, scale: Vector3) { |
| 424 | + *self = self.scaled_local(scale); |
| 425 | + } |
| 426 | + |
| 427 | + /// Returns basis scaled in object-local coordinate system |
| 428 | + #[inline] |
| 429 | + fn scaled_local(&self, scale: Vector3) -> Self { |
| 430 | + (*self) * Basis::from_diagonal(scale) |
| 431 | + } |
| 432 | + |
372 | 433 | /// Multiplies the matrix from left with the scaling matrix: M -> S·M
|
373 | 434 | ///
|
374 | 435 | /// See the comment for [Basis::rotated](#method.rotated) for further explanation.
|
@@ -789,6 +850,6 @@ mod tests {
|
789 | 850 | Vector3::new(-0.165055, 0.94041, -0.297299),
|
790 | 851 | Vector3::new(0.98324, 0.180557, 0.025257),
|
791 | 852 | );
|
792 |
| - assert!(expected.is_equal_approx(&b.inverted())); |
| 853 | + assert!(expected.is_equal_approx(&b.inverse())); |
793 | 854 | }
|
794 | 855 | }
|
0 commit comments