Max Planck

Stib’s constant: a Planck Limit for After Effects.

I’ve built my own version of built-in After Effects expressions functions. Here’s why.

Max PlanckThe loopOut, loopIn, loopOutDuration and loopInDuration methods in After Effects are very useful tools that even non-scripters should learn to use, like the better-known wiggle method. By simply selecting one from a drop-down you can easily add repetition and continuation to keyframed properties. If you don’t know about them, go have a look at Adobe’s reference.

For scripters, one problem with them is that they can’t be combined with other temporal methods such as valueAtTime. So you can have a property with the loopOut method or with valueAtTime, but there’s no way to get the valueAtTime of a property that has been looped, or to loop a property that uses valueAtTime in its expression.

So if you want to muck around with time, and you want to add looping to your property you have to build your own version of the looping functions.

So here’s the challenge I was facing. I wanted to add an offset, and a multiplier to the value of a property so that I could duplicate the layer and have the property change at a different speed, and starting at a different time, all controlled by scripts. And I wanted the property to continue after the last keyframe, as if I had used loopOut(continue). So here’s what I did:

LoopOut(continue), when applied to a property will continue to change the property at the velocity it has at the last keyframe. So if it is applied to a position property and the property is moving on the x axis 1 pixel per frame and -5 pixels per frame on the y axis, at n frames after the last keyframe the value will have changed by [n * 1, n * -5]. The absolute value will be k + [n * 1, n * -5] where k is the value at the last keyframe.

That should be easy enough to implement right? Just find the velocityAtTime at the time of the last keyframe and use that to offset the value. Unfortunately there’s a hitch. If you measure the velocityAtTime of the property right at the last keyframe’s time it will always be zero. Obviously AE decides that the motion stops at the time of the last keyframe. So we need to measure the velocity just a tiny bit before the keyframe. How tiny? Well, what we want to do is find the smallest possible increment which AE will accept, a sort of Planck Time for After Effects if you will. Behold:

σ = 0.000019531250000095 s

I call it stib’s constant, or σ. Basically this is the smallest time increment that After Effects will consider as being before a keyframe. I found it by trial and error – I worked backwards and got to 0.0000195312500000949999999999 which doesn’t work, and 0.0000195312500000950000000000 which did, so that seems to be the limit.

At 10-20s you’re halfway to the actual Planck Time, so if you’re using After Effects to do something which relies on zeptosecond accuracy (yes, that’s a real word), you’re on your own.

For for most purposes 0.00002 seconds, will do. But you could just copy and paste the number above if you want to be super accurate, ish.

So here’s how I implement loopOut(continue):

lastkeyTime=key(numKeys).time;
valueAtTime(time) +  (time - lastkeyTime) * velocityAtTime(lastkeyTime - 0.00002);

I’m not sure if it depends on the frame rate of the comp. I can’t be arsed trying it on anything except 25fps, again, if you find anything let me know.

Here it is used in an expression that will offset the action a random amount–up to half the duration of the comp, and scale the speed somewhere between three quarters and one and a half times as fast as the keyframed action. It works for properties with any number of dimensions.

seedRandom(index, timeless=true);
lastkeyTime=key(numKeys).time;
timeOffset = (time-random(thisComp.duration-lastkeyTime*2)) * random (0.75, 1.5);

if (timeOffset > lastkeyTime){
   valueAtTime(timeOffset) +  (timeOffset - lastkeyTime)* velocityAtTime(lastkeyTime - 0.00002);
} else {
   valueAtTime(timeOffset)
}

Leave a Reply

Your email address will not be published. Required fields are marked *