-
Notifications
You must be signed in to change notification settings - Fork 182
Description
I ran into a problem where I wanted to decompose a rotation into a part which rotates around a specified axis and perpendicular to it. This can be done using the swing-twist decomposition of quaternions.
I now implemented an alternative solution to my problem, but I think this library would still profit from this feature.
I implemented a crude function to do this for me based on this stackoverflow question.
/// Decompose the rotation on to 2 parts.
///
/// 1. Twist - rotation around the "direction" vector
/// 2. Swing - rotation around axis that is perpendicular to "direction" vector
///
/// The rotation can be composed back by
/// `rotation = swing * twist`.
/// Order matters!
///
/// has singularity in case of swing_rotation close to 180 degrees rotation.
/// if the input quaternion is of non-unit length, the outputs are non-unit as well
/// otherwise, outputs are both unit
fn swing_twist_decomposition(rotation: Quat, axis: Dir3) -> Option<(Quat, Quat)> {
let rotation_axis = rotation.xyz();
let projection = rotation_axis.project_onto(*axis);
let twist = {
let maybe_flipped_twist = Quat::from_vec4(projection.extend(rotation.w));
if rotation_axis.dot(projection) < 0.0 {
-maybe_flipped_twist
} else {
maybe_flipped_twist
}
};
if twist.length_squared() != 0.0 {
let swing = rotation * twist.conjugate();
Some((twist.normalize(), swing))
} else {
None
}
}
The above code is fully written by me, but the mechanism was adapted from a StackOverflow answer.
I have no clues about licensing here. If I am legally allowed, I'd like to give up any rights to the code.
There seem to be many resources on this topic online.
I have neither thoroughly tested nor benchmarked the above snipped and I assume it requires more polish. If desired, I could try putting together a PR for a full implementation?