Friday, February 27, 2015

Interpolating between Positions and Radii

Having completed the technology to fill in the space between spheres, the next step is to build the systems to let the spheres move and change size!

If you think back to the original project idea, you'll remember we intend to implement an interface through which to make shapes comprised of spheres, where the user can set keyframes for sounds, colors, sizes, and positions!

So, to begin the process Amier used the Blueprint interface to make a "man".

It was simple to do - in the Event Blueprint section of the previously mentioned Caplet Collection collection, OnEventBeginPlay (called when the game starts) is triggered, and I call our "add caplet" function several times with parameters that describe the man.

To allow movement, I began by making an array of vectors (which are used by UE4 to represent any 3 dimensional float) that will represent the positions of the object, and to scale the Caplet I made an array of floats.
Then, inside the Caplet object I added two functions and modified an existing one (scale):

Interp

This is called by the Caplet Collection in tick for each Caplet. It takes in the delta time since the last tick, and keeps track of a floating point variable called 'time'. Time is incremented by delta time, and if it is greater than 1 the current indices in the position and scale arrays are incremented, and time set to 0. The indices are also kept within their bounds here as well.
Finally, Move and Scale are called.

Interp's Implementation


Move
This is called by Interp. It is relatively simple, but made ugly by the blueprint's constraints with regards to branching statements. The algorithm checks if the current position index is greater than the Positions Array's length - 1.
If so, simply set the current position to the current index (since the index starts at 0, and is guaranteed to have a value of at most array length-1). If not, that means interpolation must occur between the current index and the next index.

So, how to lerp between two points mathematically? Just for fun I wanted to derive it myself, without "cheating" and looking at notes/books/internet.
At first, I came up with this:
float Lerp(float a, float b, float t)
{ return (b-a)*t + a; }

While it took about 5 seconds to come up with and implement, unfortunately this was not safe for floating points, which I realized after my precision flew out the window. I quickly switched to one a bit more safe:
float Lerp(float a, float b, float t)
{ return (1-t)*a + t*b; }

To apply this to vectors, you need to perform it per each component between the two vectors.
So, I achieved the interpolated position between two vectors and some time t in [0,1] and the code looks like this.

At this point, you need to consider the edge case where the index is at the last position - there needs to be support to allow smooth interpolation from the end of the array to the beginning. I placed another branch to check if the current index is the final one and if so, lerp to the initial member of the array.

I want the user to be able to add more positions relative the the caplet collection object, and the blueprint functions to set position are limited to adding offsets (not good for interpolating cause they compound, unless you subtract the difference from the new interpolated value and the previous one and offset by that much, which gets complex). So using functions that set the actor's location in world space, I interpolate all the positions using the relative space, and offset by the position of the root Caplet Collection's world position, achieving a correct final result.

The final method.



Scale
Scale used to be a function called when the Caplet was created to force its set radius to match the rendered one, and as such had relative offsets/scales which would compound if called each frame. So, I reworked it and using the same algorithms I applied in Move, I achieved an interpolating radius.

Scale's Implementation


Click here for a quick video of it in action!


No comments:

Post a Comment