Eliminate redundant clamping from sample-interpolated curves (#15620)
# Objective Currently, sample-interpolated curves (such as those used by the glTF loader for animations) do unnecessary extra work when `sample_clamped` is called, since their implementations of `sample_unchecked` are already clamped. Eliminating this redundant sampling is a small, easy performance win which doesn't compromise on the animation system's internal usage of `sample_clamped`, which guarantees that it never samples curves out-of-bounds. ## Solution For sample-interpolated curves, define `sample_clamped` in the way `sample_unchecked` is currently defined, and then redirect `sample_unchecked` to `sample_clamped`. This is arguably a more idiomatic way of using the `cores` as well, which is nice. ## Testing Ran `many_foxes` to make sure I didn't break anything.
This commit is contained in:
parent
46180a75f8
commit
528ca4f95e
@ -1021,14 +1021,14 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_unchecked(&self, t: f32) -> T {
|
||||
fn sample_clamped(&self, t: f32) -> T {
|
||||
// `UnevenCore::sample_with` is implicitly clamped.
|
||||
self.core.sample_with(t, <T as Animatable>::interpolate)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_clamped(&self, t: f32) -> T {
|
||||
// Sampling by keyframes is automatically clamped to the keyframe bounds.
|
||||
self.sample_unchecked(t)
|
||||
fn sample_unchecked(&self, t: f32) -> T {
|
||||
self.sample_clamped(t)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,10 +23,15 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_unchecked(&self, t: f32) -> T {
|
||||
fn sample_clamped(&self, t: f32) -> T {
|
||||
self.core
|
||||
.sample_with(t, |x, y, t| if t >= 1.0 { y.clone() } else { x.clone() })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_unchecked(&self, t: f32) -> T {
|
||||
self.sample_clamped(t)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> SteppedKeyframeCurve<T> {
|
||||
@ -57,7 +62,7 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_unchecked(&self, t: f32) -> V {
|
||||
fn sample_clamped(&self, t: f32) -> V {
|
||||
match self.core.sample_interp_timed(t) {
|
||||
// In all the cases where only one frame matters, defer to the position within it.
|
||||
InterpolationDatum::Exact((_, v))
|
||||
@ -69,6 +74,11 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_unchecked(&self, t: f32) -> V {
|
||||
self.sample_clamped(t)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> CubicKeyframeCurve<T> {
|
||||
@ -112,7 +122,7 @@ impl Curve<Quat> for CubicRotationCurve {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_unchecked(&self, t: f32) -> Quat {
|
||||
fn sample_clamped(&self, t: f32) -> Quat {
|
||||
let vec = match self.core.sample_interp_timed(t) {
|
||||
// In all the cases where only one frame matters, defer to the position within it.
|
||||
InterpolationDatum::Exact((_, v))
|
||||
@ -125,6 +135,11 @@ impl Curve<Quat> for CubicRotationCurve {
|
||||
};
|
||||
Quat::from_vec4(vec.normalize())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_unchecked(&self, t: f32) -> Quat {
|
||||
self.sample_clamped(t)
|
||||
}
|
||||
}
|
||||
|
||||
impl CubicRotationCurve {
|
||||
@ -170,7 +185,7 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_iter_unchecked(&self, t: f32) -> impl Iterator<Item = T> {
|
||||
fn sample_iter_clamped(&self, t: f32) -> impl Iterator<Item = T> {
|
||||
match self.core.sample_interp(t) {
|
||||
InterpolationDatum::Exact(v)
|
||||
| InterpolationDatum::LeftTail(v)
|
||||
@ -182,6 +197,11 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_iter_unchecked(&self, t: f32) -> impl Iterator<Item = T> {
|
||||
self.sample_iter_clamped(t)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> WideLinearKeyframeCurve<T> {
|
||||
@ -219,7 +239,7 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_iter_unchecked(&self, t: f32) -> impl Iterator<Item = T> {
|
||||
fn sample_iter_clamped(&self, t: f32) -> impl Iterator<Item = T> {
|
||||
match self.core.sample_interp(t) {
|
||||
InterpolationDatum::Exact(v)
|
||||
| InterpolationDatum::LeftTail(v)
|
||||
@ -234,6 +254,11 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_iter_unchecked(&self, t: f32) -> impl Iterator<Item = T> {
|
||||
self.sample_iter_clamped(t)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> WideSteppedKeyframeCurve<T> {
|
||||
@ -269,7 +294,7 @@ where
|
||||
self.core.domain()
|
||||
}
|
||||
|
||||
fn sample_iter_unchecked(&self, t: f32) -> impl Iterator<Item = T> {
|
||||
fn sample_iter_clamped(&self, t: f32) -> impl Iterator<Item = T> {
|
||||
match self.core.sample_interp_timed(t) {
|
||||
InterpolationDatum::Exact((_, v))
|
||||
| InterpolationDatum::LeftTail((_, v))
|
||||
@ -285,6 +310,11 @@ where
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_iter_unchecked(&self, t: f32) -> impl Iterator<Item = T> {
|
||||
self.sample_iter_clamped(t)
|
||||
}
|
||||
}
|
||||
|
||||
/// An error indicating that a multisampling keyframe curve could not be constructed.
|
||||
|
@ -54,13 +54,21 @@ impl<T> Curve<T> for ColorCurve<T>
|
||||
where
|
||||
T: Mix + Clone,
|
||||
{
|
||||
#[inline]
|
||||
fn domain(&self) -> Interval {
|
||||
self.core.domain()
|
||||
}
|
||||
|
||||
fn sample_unchecked(&self, t: f32) -> T {
|
||||
#[inline]
|
||||
fn sample_clamped(&self, t: f32) -> T {
|
||||
// `EvenCore::sample_with` clamps the input implicitly.
|
||||
self.core.sample_with(t, T::mix)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_unchecked(&self, t: f32) -> T {
|
||||
self.sample_clamped(t)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -94,9 +94,15 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_unchecked(&self, t: f32) -> T {
|
||||
fn sample_clamped(&self, t: f32) -> T {
|
||||
// `EvenCore::sample_with` is implicitly clamped.
|
||||
self.core.sample_with(t, &self.interpolation)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_unchecked(&self, t: f32) -> T {
|
||||
self.sample_clamped(t)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, I> SampleCurve<T, I> {
|
||||
@ -143,10 +149,16 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_unchecked(&self, t: f32) -> T {
|
||||
fn sample_clamped(&self, t: f32) -> T {
|
||||
// `EvenCore::sample_with` is implicitly clamped.
|
||||
self.core
|
||||
.sample_with(t, <T as StableInterpolate>::interpolate_stable)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_unchecked(&self, t: f32) -> T {
|
||||
self.sample_clamped(t)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> SampleAutoCurve<T> {
|
||||
@ -242,9 +254,15 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_unchecked(&self, t: f32) -> T {
|
||||
fn sample_clamped(&self, t: f32) -> T {
|
||||
// `UnevenCore::sample_with` is implicitly clamped.
|
||||
self.core.sample_with(t, &self.interpolation)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_unchecked(&self, t: f32) -> T {
|
||||
self.sample_clamped(t)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, I> UnevenSampleCurve<T, I> {
|
||||
@ -301,10 +319,16 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_unchecked(&self, t: f32) -> T {
|
||||
fn sample_clamped(&self, t: f32) -> T {
|
||||
// `UnevenCore::sample_with` is implicitly clamped.
|
||||
self.core
|
||||
.sample_with(t, <T as StableInterpolate>::interpolate_stable)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sample_unchecked(&self, t: f32) -> T {
|
||||
self.sample_clamped(t)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> UnevenSampleAutoCurve<T> {
|
||||
|
Loading…
Reference in New Issue
Block a user