Skip to content

Commit

Permalink
Add Mul operator for Quaternion + Vector3.
Browse files Browse the repository at this point in the history
  • Loading branch information
theKidOfArcrania committed Sep 14, 2024
1 parent cdf6c5c commit 4a31626
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 2 deletions.
13 changes: 13 additions & 0 deletions godot-core/src/builtin/quaternion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,19 @@ impl Mul<Quaternion> for Quaternion {
}
}

impl Mul<Vector3> for Quaternion {
type Output = Vector3;

/// Multiplies a quaternion to a vector, which functionally rotates this
/// vector as a 3D point by this quaternion
///
/// # Panics
/// If the quaternion is not normalized
fn mul(self, rhs: Vector3) -> Self::Output {
Vector3::from_glam(self.to_glam().mul_vec3(rhs.to_glam()))
}
}

// SAFETY:
// This type is represented as `Self` in Godot, so `*mut Self` is sound.
unsafe impl GodotFfi for Quaternion {
Expand Down
4 changes: 2 additions & 2 deletions godot-core/src/builtin/vectors/vector_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,14 +419,14 @@ macro_rules! impl_vector_fns {
}

/// Converts the corresponding `glam` type to `Self`.
fn from_glam(v: $GlamVector) -> Self {
pub(crate) fn from_glam(v: $GlamVector) -> Self {
Self::new(
$( v.$comp ),*
)
}

/// Converts `self` to the corresponding `glam` type.
fn to_glam(self) -> $GlamVector {
pub(crate) fn to_glam(self) -> $GlamVector {
<$GlamVector>::new(
$( self.$comp ),*
)
Expand Down
24 changes: 24 additions & 0 deletions itest/rust/src/builtin_tests/geometry/quaternion_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,4 +178,28 @@ fn quaternion_spherical_cubic_interpolate_in_time() {
);
assert_eq!(outcome, Quaternion::default())
}

#[itest]
fn quaternion_mul1() {
use godot::builtin::real;
use std::f32::consts::PI;

let q = Quaternion::from_axis_angle(Vector3::UP, PI / 2.0 as real);
let rotated = q * Vector3::new(1.0, 4.2, 0.0);
assert_eq_approx!(rotated.x, 0.0);
assert_eq_approx!(rotated.y, 4.2);
assert_eq_approx!(rotated.z, -1.0);
}

#[itest]
fn quaternion_mul2() {
use godot::builtin::real;
use std::f32::consts::PI;

let q = Quaternion::from_axis_angle(-Vector3::UP, PI / 2.0 as real);
let rotated = q * Vector3::new(1.0, 4.2, 2.0);
assert_eq_approx!(rotated.x, -2.0);
assert_eq_approx!(rotated.y, 4.2);
assert_eq_approx!(rotated.z, 1.0);
}
// TODO more tests

0 comments on commit 4a31626

Please sign in to comment.