reverse-engineering linear() and ease()?

Moderators: Disciple, zlovatt

Post Reply
User avatar
pablohotsauce
Posts: 10
Joined: April 13th, 2019, 2:19 pm

October 10th, 2019, 1:51 pm

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.
User avatar
pablohotsauce
Posts: 10
Joined: April 13th, 2019, 2:19 pm

October 21st, 2019, 12:34 am

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.

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;
}
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.)

Image

Image
Post Reply