custom eases through expressions

Moderators: Disciple, zlovatt

Post Reply
yuppster
Posts: 16
Joined: March 3rd, 2006, 4:01 pm

Is there anyway to replicate custom eases through expressions?

For example, you can do this to animate opacity from 0 to 100 from 1 to 5 seconds.
easeOut(time,1,5,0,100);

But what if I wanted to put specific values for speed/influence?

Anyone?
Mylenium
Posts: 139
Joined: July 20th, 2005, 12:07 am

yuppster wrote:Is there anyway to replicate custom eases through expressions?

For example, you can do this to animate opacity from 0 to 100 from 1 to 5 seconds.
easeOut(time,1,5,0,100);

But what if I wanted to put specific values for speed/influence?

Anyone?
Nope, ease is always hardwired. You could write a custom function though that evaluates for each keyframe...

Mylenium
[Pour Mylène, ange sur terre]
yuppster
Posts: 16
Joined: March 3rd, 2006, 4:01 pm

Thanks for the response Mylenium. Can you elaborate on what you mean about a function that evaluates for each keyframe?
User avatar
Atomic
Posts: 157
Joined: April 30th, 2007, 5:55 am
Location: United States, Ohio

What you need to do it add an expression that evaluates every frame.

I'm not sure how to set speed and influence, but here is the an example of the source.text property being updated every frame.

Code: Select all

thisFrame=timeToFrames(t=time+thisComp.displayStartTime,fps=1.0/thisComp.frameDuration,isDuration=false);
if (thisFrame==0){text.sourceText = 'Shaky';}
if (thisFrame==1){text.sourceText = 'Wake';}
if (thisFrame==2){text.sourceText = 'A Tire';}
if (thisFrame==3){text.sourceText = 'Tube';}
if (thisFrame==4){text.sourceText = 'Passing';}
if (thisFrame==5){text.sourceText = 'Through';}
if (thisFrame==6){text.sourceText = 'Your';}
if (thisFrame==7){text.sourceText = 'New ';}
if (thisFrame==8){text.sourceText = 'Blue';}
if (thisFrame==9){text.sourceText = 'Cube';}
This technique does produce "ugly" expression code but it does work.
Simply add what code you need in the if statement of a given frame.
You could also use greater than or less than to allow a single if statement to encompass a range of frames.

Code: Select all

if (thisFrame<30){text.sourceText = 'Shaky';}
if (thisFrame <60){text.sourceText = 'Cube';}
//etc...
This would update the text every second.

This was taken from a script posted here:
http://www.aenhancers.com/viewtopic.php?t=751
yuppster
Posts: 16
Joined: March 3rd, 2006, 4:01 pm

Thanks Atomic, now I understand. So something like this works for me, albeit being "ugly" like you said and a bit of work. Just created the animation how I wanted and copied the values for each frame over. (Oh, and I noticed that Motion Blur breaks this expression, not sure why.)

Code: Select all

thisFrame=timeToFrames(t=time+thisComp.displayStartTime,fps=1.0/thisComp.frameDuration,isDuration=false); 
if (thisFrame==0){position = [113,270];} 
if (thisFrame==1){position = [214.2085,270];} 
if (thisFrame==2){position = [370.4263,270];} 
if (thisFrame==3){position = [460.2031,270];} 
if (thisFrame==4){position = [516.8243,270];} 
if (thisFrame==5){position = [556.21142,270];} 
if (thisFrame==6){position = [584.89936,270];} 
if (thisFrame==7){position = [606.19488,270];} 
if (thisFrame==8){position = [622.02218,270];} 
if (thisFrame==9){position = [633.60311,270];} 
if (thisFrame==10){position = [641.76502,270];} 
if (thisFrame==11){position = [647.10807,270];} 
if (thisFrame==12){position = [650.0744,270];} 
if (thisFrame==13){position = [651,270];} 
if (thisFrame>13) {position = [651,270];}
So that works for my situation, but out of interest still wondering if it's somehow possible to build an expression that can take speed/influence values. I know that the ease, easeIn, easeOut are hardwired and it can't be accomplished that way, but is it technically impossible for the code to figure them out - even if the math is complicated?
Mylenium
Posts: 139
Joined: July 20th, 2005, 12:07 am

yuppster wrote:So that works for my situation, but out of interest still wondering if it's somehow possible to build an expression that can take speed/influence values. I know that the ease, easeIn, easeOut are hardwired and it can't be accomplished that way, but is it technically impossible for the code to figure them out - even if the math is complicated?
It's possible, you just have to limit yourself to some rules like only working with linear temporal interpolation. Based on that you can easily cobble up some code. I also think you're not exactly looking to re-create a full interpolation algorithm, as I understand it you are just looking to adjust the steepness and rounding falloff of a given curve. Some rough ideas on how I would approach it:

- decide on which side of a keyframe you are by comparing time*0.5 with the next keyframe
- implement a rule for which fraction of this time slice is supposed to hold the actual ease routine time*0.5*x
- divide the segment into managable chunks (not necessarily frames) time*0.5*x/y to keep it halfway fast
- calculate the values based on valueAtTime(time*0.5*x/y)*z*formula where z is the actual index of the time slice and formula refers to your custom routine. The entire thing needs to be contained in a loop to get a result for every slice.
- if necerssary, use additional functions like .smooth() to make the result more pleasant

In mathematically correct terms you would have to use integration methods (+=, -=) as each new intermediate value should be based on the previously agrregated one, but I wouldn't use it if you can avoid it. It's a major performance hit.

Mylenium
[Pour Mylène, ange sur terre]
nab
Posts: 203
Joined: November 29th, 2005, 3:00 am
Location: Royan
Contact:

Is there anyway to replicate custom eases through expressions?
Yes, there is.
As suggested above, you can write your own interpolation function that would calculate the intermediate values from the current key and the next one.
First you would have to retrieve the keys...

Here is an example that interpolates keys using cosine function (position expression):

Code: Select all

prop = thisComp.layer("LayerName").position;
t = time;

if (prop.numKeys)
{
	k1 = getPrevKey(prop, t);
	k2 = getNextKey(prop, t);
	t = linear(t, k1.time, k2.time, 0, 1);

	cosineInterpolate(k1.value, k2.value, t);
}
else
	value;
Functions are defined here (they have to be included in the expression).
)orgen
Posts: 34
Joined: August 28th, 2006, 4:12 am

that's great!...

I dont fully understand the code behind this, but is there any way to adopt these easing equations into one after effects compatible format?

http://www.robertpenner.com/easing/

Would it be possible for an equation like this to follow the motion path between the keyframes?
Colin Braley
Posts: 13
Joined: July 14th, 2005, 7:33 pm
Location: VA
Contact:

Yes, all of these could definitely be coded into an AE expression...there are actually a ton of types of interpolation methods out there...spline based interpolation, polynomial based, lerp, cosine, etc. Maybe sometime in the next two weeks I'll get some time to code a few of these, I can see a few instances in which these would be useful. I don't know what type of time/motivation I will have, so who knows...
If you need a specific one coded, I bet you could find some example code (not written for AE) and I bet there are a bunch of people on here who are willing/able to translate it into something for use in an AE expression.
yuppster
Posts: 16
Joined: March 3rd, 2006, 4:01 pm

Hey, thanks guys for all your responses.

Basically I'm trying to replicate keyframed animations exactly - completely in expressions. (So for Nab's code, I wouldn't need the getPrevKey and getNextKey functions. It'd be fed with my own time and value...values).

Ideally, there'd be a function that I could feed speed/influence values into (taken from the values in the "keyframe velocity" box of my original keyframes). I guess that'd be 8 values (incoming and outgoing speed and influence). Don't know if something like that is possible.
lunelson
Posts: 18
Joined: March 26th, 2006, 1:58 am

This is very interesting. I've been looking for something like this because I find the default easing to accelerate and decelerate too slowly on long moves.

Could the cosine based script above be modified for easeIn and easeOut versions?

I downloaded the actionscript from Robert Penner's site and I think the math he is implementing is very similar...just the AE method posted here has fewer variables:

Code: Select all

class com.robertpenner.easing.Sine {
	static function easeIn (t:Number, b:Number, c:Number, d:Number):Number {
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	}
	static function easeOut (t:Number, b:Number, c:Number, d:Number):Number {
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	}
	static function easeInOut (t:Number, b:Number, c:Number, d:Number):Number {
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	}
}
This is probably a quick hack for the code wizards here...anyone?
User avatar
lloydalvarez
Enhancement master
Posts: 460
Joined: June 17th, 2004, 9:27 am
Location: New York City, NY
Contact:

Check out this script by Ian Haigh.

http://ianhaigh.com/easeandwizz/

-Lloyd
)orgen
Posts: 34
Joined: August 28th, 2006, 4:12 am

perfect...thanks Ian Haigh ;)
Post Reply