Closed iwikal closed 1 week ago
One possible way to support slerp without having to touch a lot of the splines internals would be to make use of this resampling, and to introduce another public trait:
pub trait Slerp<T> {
fn slerp(other: Self, t: T) -> Self;
}
Quaternions would implement this trait.
We also add a wrapper struct around the quats that forwards Interpolate::lerp
to Slerp::slerp
.
struct SlerpWrapper<V>(V);
impl<T, V> Interpolate<T> for SlerpWrapper<V>
where V: Slerp<T>
{
fn lerp(a: Self, b: Self, t: T) -> Self {
a.0.slerp(b.0, t)
}
}
Then we can add another constructor for Spline
that resamples using this wrapper, then unwraps it again:
pub fn resample_quats<T, V>(keys: Vec<Key<T, V>>, interval: T, interpolation: Interpolation<T, V>) -> Self
where V: Slerp<T>
{
let mut spline = Self::from_iter(keys.into_iter().map(
|Key { t, interpolation, value }| Key { t, interpolation, value: SlerpWrapper(value) }
);
spline.resample(interval, interpolation);
Self::from_iter(spline.0.into_iter().map(
|Key { t, interpolation, value: SlerpWrapper(value) }| Key { t, interpolation, value }
)
}
I would also be completely fine with not having that interpolation
argument. Linear interpolation is probably the most common thing you want after resampling, since it's the cheapest.
Hm, I think slerp
should be an implementation detail of Interpolate
, right? Maybe the bounds need to be adapted, indeed. I’ll have a deeper look at your issue this night — I’m also following what people are doing in bevy
. Thanks for opening! <3
I guess there's nothing in the core of splines itself that specifies nlerp to be the default impl for Quat, but that's how it works in the provided impl for cgmath::Quat, and how I did it in my impl-glam PR for consistency. A thought: maybe it should be the opposite to what I just proposed here. Maybe the default behavior should be the accurate, albeit slow implementation, and if people want the faster, less general-purpose solution, they opt into that?
An unintended but perhaps useful side effect of the resampling feature is that it can be used for other kinds of splines too. I don't know the performance characteristics of the algorithms splines
supports, but if there's an expensive one, it can also be approximated by resampling it to shorter linear segments.
I’m moving the project to sourcehut. Feel free to reopen there if you want to — issues / mailing list. Thank you.
Normalized lerps are nice and all, but what if my keyframes are far enough apart that the non-constant velocity becomes noticable? I would like for there to be a convenient way to get something more slerpy-looking. Besides somehow adding support for using real slerps in quaternion splines, I had an idea of a method on
Spline
that would make it easier to still get the performance benefits of nlerps:I'm sure a regular interval is not the most optimal resampling strategy, but it's the easiest to implement. A more sophisticated strategy would try to minimize the number of control points while staying within some allowable error margin.