Skip to content

Commit

Permalink
Merge pull request #981 from fpdotmonkey/quaternion-compatibility
Browse files Browse the repository at this point in the history
Provide feature parity for `Quaternion` with Godot
  • Loading branch information
Bromeon authored Dec 22, 2024
2 parents fe5a6b2 + 3e1fbad commit 24db37d
Showing 1 changed file with 39 additions and 4 deletions.
43 changes: 39 additions & 4 deletions godot-core/src/builtin/quaternion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ pub struct Quaternion {
}

impl Quaternion {
/// The identity quaternion, representing no rotation. This has the same rotation as [`Basis::IDENTITY`].
///
/// If a [`Vector3`] is rotated (multiplied) by this quaternion, it does not change.
pub const IDENTITY: Self = Self {
x: 0.0,
y: 0.0,
z: 0.0,
w: 1.0,
};

pub fn new(x: real, y: real, z: real, w: real) -> Self {
Self { x, y, z, w }
}
Expand All @@ -54,9 +64,28 @@ impl Quaternion {
Self::new(x, y, z, w)
}

// TODO: Constructors.
// pub fn from_vector_vector(arc_to: Vector3, arc_from: Vector3) -> Self {}
// pub fn from_basis(basis: Basis) -> Self {}
/// Constructs a Quaternion representing the shortest arc between `arc_from` and `arc_to`.
///
/// These can be imagined as two points intersecting a unit sphere's surface, with a radius of 1.0.
///
// This is an undocumented assumption of Godot's as well.
/// The inputs must be unit vectors.
///
/// For near-singular cases (`arc_from`≈`arc_to` or `arc_from`≈-`arc_to`) the current implementation is only accurate to about
/// 0.001, or better if `double-precision` is enabled.
///
/// *Godot equivalent: `Quaternion(arc_from: Vector3, arc_to: Vector3)`*
pub fn from_rotation_arc(arc_from: Vector3, arc_to: Vector3) -> Self {
debug_assert!(
arc_from.is_normalized(),
"input 1 (`arc_from`) in `Quaternion::from_rotation_arc` must be a unit vector"
);
debug_assert!(
arc_to.is_normalized(),
"input 2 (`arc_to`) in `Quaternion::from_rotation_arc` must be a unit vector"
);
<Self as GlamConv>::Glam::from_rotation_arc(arc_from.to_glam(), arc_to.to_glam()).to_front()
}

pub fn angle_to(self, to: Self) -> real {
self.glam2(&to, RQuat::angle_between)
Expand All @@ -66,7 +95,7 @@ impl Quaternion {
self.glam2(&with, RQuat::dot)
}

pub fn to_exp(self) -> Self {
pub fn exp(self) -> Self {
let mut v = Vector3::new(self.x, self.y, self.z);
let theta = v.length();
v = v.normalized();
Expand All @@ -78,6 +107,11 @@ impl Quaternion {
}
}

#[deprecated = "Moved to `Quaternion::exp()`"]
pub fn to_exp(self) -> Self {
self.exp()
}

pub fn from_euler(euler: Vector3) -> Self {
let half_a1 = euler.y * 0.5;
let half_a2 = euler.x * 0.5;
Expand Down Expand Up @@ -113,6 +147,7 @@ impl Quaternion {
}
}

#[doc(alias = "get_euler")]
pub fn to_euler(self, order: EulerOrder) -> Vector3 {
Basis::from_quat(self).to_euler(order)
}
Expand Down

0 comments on commit 24db37d

Please sign in to comment.