Ease out a Quaternion?

Hello, I have some code to ease out variables over time, for example:

``````source += (target - source) * deltaSpeed;
``````

This will slowly move a source towards the target, by adding small amount of the required distance each frame (difference between target/source x speed)

The question is how do I replicate this with a quaternion?
I’ve tried this, multiplying target by the inverse of source to replicate subtraction, using slerp to replicate multiplying it by speed, and then multiplying the entire thing to replicate adding it back to source.

``````source = source * Quaternion.Slerp(Quaternion.identity, target * Quaternion.Inverse(source), deltaSpeed);
``````

However that makes it go in wild directions. Any ideas how to do this properly? Thanks!
(P.s. how do I make my newlines/spaces show up here?

I think you misunderstand what Slerp does…
**
Slerp stands for Spherical Interpolation, which is just the spherical version of Lerp, which stands for linear interpolation. Lerp is pretty simple; given arguments a, b, and c choose a point between a and b where this point is the same distance between a and b that c is between 0 and 1. So Lerp(2, 12, 0.5) = 7. You can use Lerp for a kind of “Easing in” to a number by feeding back the result:

``````float value = 0;

void Update(){
value = Lerp(value, 10, speed * Time.deltaTime);
}
``````

This code will make value approach 10 quickly at first, then slower as it gets closer to 10. That means that you could replace your top code snippet with `source = Lerp(source, target, speed*Time.deltaTime);` and have the same effect.
**
So, with Slerp, we can do the exact same thing for quaternions. Nothing fancy required.

``````source = Quaternion.Slerp(source, target, speed * Time.deltaTime);
``````

Which will ease you into the target rotation from the source rotation.

How do you define the rate of your motion / rotation in such case? Let’s say:
“In every second, I want the object to pass some portion P of its remaining distance”.
Then, if your framerate was simply 1, then your deltaTime would be 1. Then all you’d need to do would be to multiply the remaining distance by portion P (which is a value between 0 and 1). This, using the unity’s Slerp, would be written as follows:

transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, P);

Slerp is a bit more complicated by itself, so let’s rewrite the whole problem to linear motion and Lerps:

``````transform.position = Vector3.Lerp(transform.position, targetPosition, P);
``````

Which could be rewritten as:

``````Vector3 remaining = targetPosition - transform.position;
transform.position += remaining * P;
``````

The key thing to note here is this: We are multiplying the remaining distance by some unitless value that ranges from 0 to 1.
The only problem remains, that the FPS is practically never exactly one (that would be a really bad game, really) and we need to recalculate the new portion, adequate to the actual delta time. Now, the popular mistake is that we simply multiply the portion by deltaTime. That’s going to slow the progress down as the FPS increases. That statement itself is true, but let’s see if that works.
Let’s change FPS to 2. That makes our deltaTime equal 0.5. We now multiply our remaining distance by some value twice as often. We need to make sure, that after two multiplications (in 2 FPS instead of 1 FPS) we end up with the same value. Let’s say we want to pass 90% of the remaining distance in a second. That’s multiplying by 0.9 every second. That’s NOT multiplying by 0.9 * 0.5 (our deltaTime) twice. That would equal approximately 0.2, which is very far from the original value. We instead want to make sure that two multiplications over two frames give us a total multiplier of 0.9. And that multiplier, of course, equals the square root of 0.9.
Now, we need to expand this solution to any FPS. Our root won’t be square, but the FPS.
And we end up with something like this:

``````float t = 1-Mathf.Pow(1-beta, deltaTime);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, t);
``````

where beta is how much of the distance is passed every second. Change 1-beta to beta, to describe how much of the distance is passed every second.
Notice that I’ve switched back to using quaternions and slerp. It’s because we are calculating the proportion in relation to the time, and we don’t really care what it is used for.

Edit: I feel like I skipped some steps in my thoughts and math. Just ask if anything is unclear