Saturday, November 10, 2018

c++ - Smoothly extend eased animation to new target value


I am implementing animated double property from scratch, currently with SmoothStep easing, however when new target value is set, there is visible "jump" in animation speed (probably due to applied easing). I would like setTarget to smoothly extend currently ongoing animation.
I have tried to calculate originalValue_ and remaining_ based on current t (offsetting those correctly, I think, will solve the problem), but haven't managed to find the correct formula.
How do I smoothly extend ongoing smoothstep animation to new target value?


void setTargetValue(double value, double duration = 1.0)
{
originalValue_ = currentValue();
targetValue_ = value;

remaining_ = duration;
duration_ = duration;
t = 0.0;
}

double currentValue() const {
return SmoothStep(originalValue_, targetValue_, t); //x*x*(3 - 2*x)
}

void update(double deltaT) {

remaining_ = fmax(0.0, remaining_ - deltaT);
t = clamp(0.0, 1.0, 1.0 - remaining_ / duration_)
}

Answer



I was missing one important information - SmoothStep is a cubic spline interpolation with endpoints derivative being zero. There is well-known solution to cubic interpolation.
Luckily for case of animation there is no need to solve the linear equation system. Because the Di+1 is 0 by definition, all that is needed is first derivative Di at current t which is trivial for fixed order polynomial. Substituting to the equations we get new coeficients:


double derivative(double t) const {
return coeff[0] + t * (2 * coeff[1] + 3 * t * coeff[2]); //b+2cx+3dx*x
}


//in setTargetValue compute new coefficients
double coeff[3];//a = 0 by definition
//note: in real implementation interval length compensation is also needed
coeff[0] = derivative(t);//b
coeff[1] = 3 - 2 * coeff[0];//c
coeff[2] = -2 + coeff[0];//d

and evaluate the SmoothStep t mapping as follows


double SmoothStepT(double t) const {
return t * (coeff[0] + t * (coeff[1] + t * coeff[2])); //bx+cx*x+dx*x*x

}

double currentValue() const {
return Lerp(originalValue_, targetValue_, SmoothStepT(t));
}

desmos graph demonstrating smoothness with two extensions: animation extension note: coefficient a and x - t is added to "move" the extended animation to place where the previous one left to demonstrate smoothness.
note2: I am not a mathematician, if you see an error in my math, please correct me


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...