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 a971385
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 2 deletions.
12 changes: 12 additions & 0 deletions godot-core/src/builtin/quaternion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,18 @@ impl Mul<Quaternion> for Quaternion {
}
}

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

/// Applies the quaternion's rotation to the 3D point represented by the vector.
///
/// # 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
36 changes: 36 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,40 @@ 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);
}

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

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

0 comments on commit a971385

Please sign in to comment.