Code to resample an animation curve (reducing keyframes)

I currently have some raw data e.g. daily temperature over a year. The data forms a smooth curve and I’d like to use an animation curve instead to reduce the size.

When I import an fbx animation it optimizes raw data into curves. I’d like to use a similar process.
6906401--808886--Resampling.PNG

6906401--808898--Comp2.PNG

I could hack around it by creating a new blender animation, then import my data as bone animations e.g. temperature data => x bone position. Then export it as an fbx, let Unity optimize the animation data and extract the curve. It just feels like there should be a simpler solution.

Questions:

  • Is there a way to access the process Unity uses to optimize/compress curves? It’ fine if it’s only supported in the editor.
  • Is there an example of an algorithm I could use to optimize it myself?

As far as I know this is a soft science. You can see the allowable error bands settings above in Unity, and there must be some heuristic followed in order to choose where to optimize, where to give detailed keyframes.

This is a branch of signal processing similar to how MP3 compression optimizes away the stuff your ear cannot really hear first, leaving the main part of the signal intact. Simplest is obviously just remove every other sample, but that’s a low-pass filter… then you move onto more complicated stuff where you do an FFT on the signal and decide what is important, where the information is.

Keep in mind that 365 floating point numbers is almost nothing in a modern computer, so be sure your optimization is even needed!

1 Like

Thanks for the information. I’ve never seen FFT before, it’s cool how curves can be broken down into harmonics. I’ll have to read more about it but it sounds really useful, I sometimes have noisy data and it looks like it should help clean it up.

My original thought was that an animation curve would use less space. After checking over the docs it looks like each keyframe uses more data than I was expecting. I thought it might be four floats (time, value, in tangent, out tangent). Turns out a keyframe is 28 bytes: float inTangent, float inWeight, float outTangent, float outWeight, float time, float value, enum weightedMode. So to use the same amount of space as the raw data I would need one animation curve keyframe for every 7 raw keyframes.

I was thinking of finding the high points (red), low points (blue) and change in curve (green) as shown in the diagram below.
6908792--809420--fft.png

Animation curve: 50 keyframes or 1,400 bytes of data.
Raw data: 100 keyframes or 400 bytes of data
FFT: 20 harmonics or 80 bytes of data

The other issue with the animation curve is that it’s slower than the raw data e.g. search keys to find a keyframe at time, need to search per curve.

Conclusion:

  • Raw data isn’t as bad as I thought it was. If the data is too dense then I might add a low-pass filter like you suggested. I think I’ll stick with the raw data.
  • If I did want to save space FFT would be a better option but it is a bit more expensive to calculate.
  • I’ll probably only use animation curves when I want to visually edit the data.
2 Likes

Hello, sorry for reviving this thread, is there no way to run the unity Animation Compression on runtime? we got really good results when using it on the editor, but we need to somehow use it on runtime to process some external animations.