Smooth Transitions

Blitz3D Forums/Blitz3D Programming/Smooth Transitions

Axel Wheeler(Posted 2011) [#1]
So I've been working on code to perform smooth transitions. Of any kind. You basically feed it start and end values, and a time (in millisecs). Then when you want the current value, you just ask. It will give you a linear or cosine-based interpolated value (or any mixture of these... see below) between the start and end values you gave it, based on the current time.

It is highly beta, so use care. For now it's pretty much a request for suggestions. Also if something like this is already in the code archives let me know and I'll gnash my teeth accordingly.

There is also some weird but fun example code at the end. Enjoy.

Here are the commands:

t.Transition=CreateTransition(startValue#,endValue#,mSecs#,cosine#=1.0)


Store the result in an identifier so you can refer to it later.

mSecs are 1000ths of a second. Cosine amount means 0=linear, 1.0=cosine, 1.5= a 50/50 mixture of the two. See the attached example code to see the difference.

GetTransitionValue#(t.Transition)


Use the identifier you got from CreateTransition. It knows what time it is; no need to specify.

It will return -9999 if the transition object has been purged, to minimize errors. You should trap this if there is any chance of calling a purged transition.

Expired transitions still exist (until they are purged) and will return the ending value.

PurgeTransitions(age=0)


Run this each game loop; it clears out all the old transitions. They do NOT delete themselves when the time expires; that would cause errors, which would be bad. So run this with an age of perhaps 5000 ms, just to be sure you are no longer referring to it.

CheckTransition(t.Transition)


If you want to see how much time is left (as in -324 ms) this is how you do it. The result is negative when there is time left, positive when it is overtime.

First the functions, then some example code:



Now the example code:



Last edited 2011

Last edited 2011

Last edited 2011

Last edited 2011


Kryzon(Posted 2011) [#2]
Hello Axel. This looks really interesting, thanks for sharing.

If you wouldn't mind, could you describe how are you using the Cosine function to retrieve the interpolated value, located in the GetTransitionValue function? most specifically the cosineProportion calculation.
Thanks again.


Axel Wheeler(Posted 2011) [#3]
Certainly.

Local cosineProportion#=(1-Cos(straightProportion*180))*.5


We need to take a value from (0.0, 1.0) and stretch it, so the middle value is the same and the end values are the same, but all the remaining values are stretched toward the ends. The Cos() function does this, but it requires values (0, 180) to do it. Also it produces values from (1.0, -1.0). So there are three steps basically:

1. Convert (0.0, 1.0) to (0.0, 180.0)

2. Run Cos() on it

3. Convert the results, which are (1.0, -1.0), back to (0.0, 1.0)

Step 1 is accomplished by the straightProportion*180.0 part.

Step 2 is just Cos() of that result.

Step 3 is a kludgy way of flipping the result of step two (1.0, -1.0) around and compressing it in half to produce (0.0, 1.0). The "1.0-" part flips it to (0.0, 2.0) (which is not intuitive for me at least) and the "*.5" part brings it back to (0.0, 1.0) (which is much more intuitive!).

The result is a nice smooth curve.

The next line just creates the weighted average of the two (linear and cosine) based on the "cosine" argument. That is poorly named I suppose, especially since it is also (0.0, 1.0); I should have called it "cosineWeight" or something.

Does this help?

Here's a page that describes this and other interpolation methods. There's a better one out there but I can't find it right now...

http://local.wasp.uwa.edu.au/~pbourke/miscellaneous/interpolation/

Thanks for the feedback Kryzon!


Kryzon(Posted 2011) [#4]
Perfect logic, thanks a lot.

EDIT: Do you think this could be used for 3D paths? that article states that "By a cute trick the cosine interpolation reverts to linear if applied independently to each coordinate". But I can't imagine why that might be.

Last edited 2011


Axel Wheeler(Posted 2011) [#5]
I'm not sure what they're talking about there, although if you were to take the mirror image a cosine curve (from 0-1) and apply another cosine curve on that, you would presumably go back to a straight line. But it doesn't sound like that's quite what they're describing.

Are you planning to trace a smooth curve in 3d space through a series of set points? I would guess the hermite solution would be the best. I've implemented Catmull-Rom (hermite) interpolation for smoothing terrains but not for paths in 3d.

All my cosine function above does is move from point to point in a straight line, accelerating and decelerating.


Kryzon(Posted 2011) [#6]
I was thinking applying this from point to point in a path (defined by a lot of these points), once for each axis and then combining the results as the final entity positioning.


Axel Wheeler(Posted 2011) [#7]
I think that since cosine interpolation is a kind of fake smoothness it would look weird for that purpose. Imagine points going 0,0 - 1,1 - 2,2 etc. with a slope of 1.0. In this case linear interpolation is actually better and produces a straight line through the points. Cosine interpolation weirdly creates a smoothed staircase effect. So it has its limitations. For what you are describing I would think having the path curve to the horizontal at each of the referenct points would be unacceptable.

I thought I had posted my Catmull-Rom code at some point but I guess not. I'm creating a new thread with it. It may be adaptable to what you are doing but I never tried it. Good luck!