A while ago, I tried reverse-engineering AE's native linear() function, basically trying to recreate it from scratch. I was trying to do some auto-proximity animations in Blender, on a big array of 3D objects. I couldn't figure out the exact math + logic though, so my version didn't work exactly like I wanted it to.
Does anyone think they can reverse-engineer linear()? Or does anyone know of some JS libraries that include a replica? I'm sure it's only a few lines. Is there a generic term for what this function does? (Proportion calculation or sth?)
I'm guessing ease() is just extra stuff on top of linear(), involving an exponential transfer function.
reverse-engineering linear() and ease()?
- pablohotsauce
- Posts: 10
- Joined: April 13th, 2019, 2:19 pm
Figured it out a while ago. According to StackOverflow, this type of function is a variation on what's called linear interpolation. My reverse-engineered version of AE's variation is below, in basic JavaScript. To apply eases, find some easing equation online and modify the var refProportion using that equation, so that it's not a straight line from 0 -> 1, but rather an exponential curve of whatever kind.
When converted to Python and applied to objects in Blender, it enables stuff like the below. (And yeah, you can do this kinda stuff w/ add-ons, but I wanted to see how far I could get w/ code.)


Code: Select all
function fauxLinear(ref, refStart, refEnd, outStart, outEnd) {
// constrain ref to range of refStart-refEnd
if (refEnd < refStart) { [refEnd, refStart] = [refStart, refEnd]; }
ref = (ref < refStart) ? refStart :
(ref > refEnd) ? refEnd : ref;
// calculate input range and ref proportion
const refRange = Math.abs(refEnd - refStart) || .001; // avoid dbz
const refProportion = (ref - refStart) / refRange;
// calculations for final output
let outRange = [], finalVal = [];
if ( !Array.isArray(outStart) ) { outStart = [outStart], outEnd = [outEnd]; }
for (let i in outStart) {
outRange[i] = outEnd[i] - outStart[i];
finalVal[i] = (outRange[i] * refProportion + outStart[i]);
}
return ( outStart.length == 1 ) ? finalVal[0] : finalVal;
}

