Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

slerp for vectors (feature request) #377

Open
kovaxis opened this issue Feb 22, 2023 · 2 comments
Open

slerp for vectors (feature request) #377

kovaxis opened this issue Feb 22, 2023 · 2 comments
Labels
enhancement New feature or request

Comments

@kovaxis
Copy link

kovaxis commented Feb 22, 2023

I'm in a situation where I would like to slerp two Vec3s, 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?

@bitshifter
Copy link
Owner

bitshifter commented Feb 22, 2023

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.

@kovaxis
Copy link
Author

kovaxis commented Mar 1, 2023

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants