glam-rs
glam-rs copied to clipboard
`slerp` for vectors (feature request)
I'm in a situation where I would like to slerp
two Vec3
s, something like the following pseudocode:
fn slerp(from: Vec3, to: Vec3, alpha: f32):
angle = angle_between(from, to) * alpha
return from.rotate_by(amount: angle, plane: plane_between(from, to))
I think this can be implemented in terms of quaternions, but it is not directly obvious to me and I'm not sure if it is the most performant way either.
Does this fit in the scope of the library?
You can create a Quat rotation between two vectors with https://docs.rs/glam/latest/glam/f32/struct.Quat.html#method.from_rotation_arc.
For slerp you need a start and end orientation to slerp between though, you can probably get that via:
let q0 = Quat::from_rotation_arc(FORWARD_DIR, from);
let q1 = Quat::from_rotation_arc(FORWARD_DIR, to);
let qa = q0.slerp(q1, alpha);
Where FORWARD_DIR
is the bind pose of your object (i.e. what direction it faces with no rotation applied).
Whether that achieves what you want I am not sure. I would need to see some wider code context of how you are using this to determine if it makes sense to add a helper.
The Bevy 2D rotation example might help, it's in 2D but they're using quaternions for all rotations so the same thing should work in 3D - https://github.com/bevyengine/bevy/blob/main/examples/2d/rotation.rs.
I was iterating on a dual contouring implementation, and I was interpolating normals between two points, so it really was just taking two unit Vec3
and interpolating them across the unit sphere. I was doing a simple hack of lerp
-ing them and then re-normalizing the result (nlerp
), but I was getting odd results, so I wanted to quickly experiment by interpolating the normals "correctly".
I could kind of guess how to implement this in terms of quaternions, although it wasn't an instantly obvious solution as I'm not really familiar with quaternions. I did something along these lines:
Quat::IDENTITY.slerp(Quat::from_rotation_vec(from, to), alpha).mul_vec3(from)
I don't have the exact code I used because it turned out that normal interpolation was not the cause of my issues, and I quickly scrapped the code. I just thought that a proper Vec3
slerp would be a nice quality-of-life addition to this library and it would have saved me some time. Also, at least according to this stackoverflow answer, a proper Vec3::slerp
function can be more efficient than a quaternion-based implementation.
Of course, it's up to you whether it's worth it to include this functionality. As a precedent, Unity provides a Vec3.slerp
function.