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]
|
#[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)
|
self.core.sample_with(t, <T as Animatable>::interpolate)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sample_clamped(&self, t: f32) -> T {
|
fn sample_unchecked(&self, t: f32) -> T {
|
||||||
// Sampling by keyframes is automatically clamped to the keyframe bounds.
|
self.sample_clamped(t)
|
||||||
self.sample_unchecked(t)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,10 +23,15 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sample_unchecked(&self, t: f32) -> T {
|
fn sample_clamped(&self, t: f32) -> T {
|
||||||
self.core
|
self.core
|
||||||
.sample_with(t, |x, y, t| if t >= 1.0 { y.clone() } else { x.clone() })
|
.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> {
|
impl<T> SteppedKeyframeCurve<T> {
|
||||||
@ -57,7 +62,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sample_unchecked(&self, t: f32) -> V {
|
fn sample_clamped(&self, t: f32) -> V {
|
||||||
match self.core.sample_interp_timed(t) {
|
match self.core.sample_interp_timed(t) {
|
||||||
// In all the cases where only one frame matters, defer to the position within it.
|
// In all the cases where only one frame matters, defer to the position within it.
|
||||||
InterpolationDatum::Exact((_, v))
|
InterpolationDatum::Exact((_, v))
|
||||||
@ -69,6 +74,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sample_unchecked(&self, t: f32) -> V {
|
||||||
|
self.sample_clamped(t)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> CubicKeyframeCurve<T> {
|
impl<T> CubicKeyframeCurve<T> {
|
||||||
@ -112,7 +122,7 @@ impl Curve<Quat> for CubicRotationCurve {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sample_unchecked(&self, t: f32) -> Quat {
|
fn sample_clamped(&self, t: f32) -> Quat {
|
||||||
let vec = match self.core.sample_interp_timed(t) {
|
let vec = match self.core.sample_interp_timed(t) {
|
||||||
// In all the cases where only one frame matters, defer to the position within it.
|
// In all the cases where only one frame matters, defer to the position within it.
|
||||||
InterpolationDatum::Exact((_, v))
|
InterpolationDatum::Exact((_, v))
|
||||||
@ -125,6 +135,11 @@ impl Curve<Quat> for CubicRotationCurve {
|
|||||||
};
|
};
|
||||||
Quat::from_vec4(vec.normalize())
|
Quat::from_vec4(vec.normalize())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sample_unchecked(&self, t: f32) -> Quat {
|
||||||
|
self.sample_clamped(t)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CubicRotationCurve {
|
impl CubicRotationCurve {
|
||||||
@ -170,7 +185,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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) {
|
match self.core.sample_interp(t) {
|
||||||
InterpolationDatum::Exact(v)
|
InterpolationDatum::Exact(v)
|
||||||
| InterpolationDatum::LeftTail(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> {
|
impl<T> WideLinearKeyframeCurve<T> {
|
||||||
@ -219,7 +239,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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) {
|
match self.core.sample_interp(t) {
|
||||||
InterpolationDatum::Exact(v)
|
InterpolationDatum::Exact(v)
|
||||||
| InterpolationDatum::LeftTail(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> {
|
impl<T> WideSteppedKeyframeCurve<T> {
|
||||||
@ -269,7 +294,7 @@ where
|
|||||||
self.core.domain()
|
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) {
|
match self.core.sample_interp_timed(t) {
|
||||||
InterpolationDatum::Exact((_, v))
|
InterpolationDatum::Exact((_, v))
|
||||||
| InterpolationDatum::LeftTail((_, 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.
|
/// An error indicating that a multisampling keyframe curve could not be constructed.
|
||||||
|
@ -54,13 +54,21 @@ impl<T> Curve<T> for ColorCurve<T>
|
|||||||
where
|
where
|
||||||
T: Mix + Clone,
|
T: Mix + Clone,
|
||||||
{
|
{
|
||||||
|
#[inline]
|
||||||
fn domain(&self) -> Interval {
|
fn domain(&self) -> Interval {
|
||||||
self.core.domain()
|
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)
|
self.core.sample_with(t, T::mix)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sample_unchecked(&self, t: f32) -> T {
|
||||||
|
self.sample_clamped(t)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -94,9 +94,15 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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)
|
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> {
|
impl<T, I> SampleCurve<T, I> {
|
||||||
@ -143,10 +149,16 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sample_unchecked(&self, t: f32) -> T {
|
fn sample_clamped(&self, t: f32) -> T {
|
||||||
|
// `EvenCore::sample_with` is implicitly clamped.
|
||||||
self.core
|
self.core
|
||||||
.sample_with(t, <T as StableInterpolate>::interpolate_stable)
|
.sample_with(t, <T as StableInterpolate>::interpolate_stable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sample_unchecked(&self, t: f32) -> T {
|
||||||
|
self.sample_clamped(t)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> SampleAutoCurve<T> {
|
impl<T> SampleAutoCurve<T> {
|
||||||
@ -242,9 +254,15 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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)
|
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> {
|
impl<T, I> UnevenSampleCurve<T, I> {
|
||||||
@ -301,10 +319,16 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sample_unchecked(&self, t: f32) -> T {
|
fn sample_clamped(&self, t: f32) -> T {
|
||||||
|
// `UnevenCore::sample_with` is implicitly clamped.
|
||||||
self.core
|
self.core
|
||||||
.sample_with(t, <T as StableInterpolate>::interpolate_stable)
|
.sample_with(t, <T as StableInterpolate>::interpolate_stable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sample_unchecked(&self, t: f32) -> T {
|
||||||
|
self.sample_clamped(t)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> UnevenSampleAutoCurve<T> {
|
impl<T> UnevenSampleAutoCurve<T> {
|
||||||
|
Loading…
Reference in New Issue
Block a user