Skip to content

Commit 553bf87

Browse files
bors[bot]HexorgBromeon
authored
Merge #898
898: Adding Transform3D operations - fixes issues/290 r=Bromeon a=Hexorg I wanted to get more people's eyes on this. Everything but the linear interpolation unit test works. The problem with linear interpolation is that godot seems to do it differently..? I opened up godot source and I swear I've implemented it the same, yet the engine gives me a different interpolation result for the same inputs. Co-authored-by: Hexorg <[email protected]> Co-authored-by: Jan Haller <[email protected]>
2 parents fa7c178 + 79e1850 commit 553bf87

File tree

2 files changed

+326
-10
lines changed

2 files changed

+326
-10
lines changed

gdnative-core/src/core_types/geom/basis.rs

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::core_types::{IsEqualApprox, Quat, Vector3};
2-
use core::ops::Mul;
2+
use crate::globalscope::lerp;
33
use glam::Mat3;
4+
use std::ops::Mul;
45

56
/// A 3x3 matrix, typically used as an orthogonal basis for [`Transform`][crate::core_types::Transform].
67
///
@@ -241,12 +242,46 @@ impl Basis {
241242
///
242243
/// If the determinant of `self` is zero.
243244
#[inline]
244-
pub fn inverted(&self) -> Self {
245+
pub fn inverse(&self) -> Self {
245246
let mut copy = *self;
246247
copy.invert();
247248
copy
248249
}
249250

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+
250285
/// Transposes the matrix.
251286
#[inline]
252287
fn transpose(&mut self) {
@@ -309,6 +344,20 @@ impl Basis {
309344
m.is_equal_approx(&Self::IDENTITY)
310345
}
311346

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+
312361
/// Returns an orthonormalized version of the matrix: 3 orthogonal basis vectors of unit length.
313362
#[inline]
314363
pub fn orthonormalized(&self) -> Self {
@@ -369,6 +418,18 @@ impl Basis {
369418
copy
370419
}
371420

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+
372433
/// Multiplies the matrix from left with the scaling matrix: M -> S·M
373434
///
374435
/// See the comment for [Basis::rotated](#method.rotated) for further explanation.
@@ -789,6 +850,6 @@ mod tests {
789850
Vector3::new(-0.165055, 0.94041, -0.297299),
790851
Vector3::new(0.98324, 0.180557, 0.025257),
791852
);
792-
assert!(expected.is_equal_approx(&b.inverted()));
853+
assert!(expected.is_equal_approx(&b.inverse()));
793854
}
794855
}

0 commit comments

Comments
 (0)