ADOBE AFTER EFFECTS: Forum Expressions Tutorials Creative Cloud

Smoothing camera movements following a null

COW Forums : Adobe After Effects Expressions

<< PREVIOUS   •   FAQ   •   VIEW ALL   •   PRINT   •   NEXT >>
Nicolas Guionnet
Smoothing camera movements following a null
on Mar 14, 2019 at 12:11:32 pm

Hi,

I have a bunch of 2D objets on a layer. I want to follow them with a camera. So I create a NULL that will be at the center of the group of objects.
The point of interest of my camera is set to the NULL position.
Unfortunately, due to the type of calculation involved to position the NULL, its movements are not quite smooth.

Do you know a way to filtrate, I mean to smooth its movements and affect the result to an intermediary NULL2 that would be my new point of interest ?

In a more traditional programming environment, I would have applied a basic filtering algorithm ... but to do this in AE, I would need to keep variables from one frame to the next ...

Is there a way to do this in AE ? (I am sure there is ... ☺ )

Wo Wo ! Wait ! As I am writing these lines ... I remember the .valueAtTime(t) function.
It would let me access the former position of NUUL2 and any position of NULL to compute the new NULL2 position ...
Although I don't know if I can access NULL2.transform.position.valueAtTime( t-1 ) in the expression calculating NULL.transform.position at time t ...

Any idea, advice ?
Thanks !


Return to posts index

Oleg Pirogov
Re: Smoothing camera movements following a null
on Mar 14, 2019 at 12:42:20 pm

How about converting NULL 1 animation to keyframes, copying it to NULL 2 and smoothing the movement through spatial interpolation?

BTW,
>if I can access NULL2.transform.position.valueAtTime( t-1 ) in the expression calculating NULL.transform.position at time t
yes, sure.


Return to posts index

Nicolas Guionnet
Re: Smoothing camera movements following a null
on Mar 15, 2019 at 1:00:33 am

Thanks for your help Oleg !

Converting animation to keyframes, copying it and smoothing the movement through spatial interpolation ... is a possible solution but I have to do it every time the animation of NULL1 is changed ... and it depends on the behavior of a lot of objects that may change often according to my needs.
So I need it to be automatic.

I think I will go for the second option. I will write the filtering expression soon and publish it here (I might not be the only beginner who needs this ...)

Thanks !


Return to posts index


Nicolas Guionnet
Re: Smoothing camera movements following a null
on Mar 15, 2019 at 1:55:22 pm

A DEBUG INSANITY ...
... well, I have been trying to solve this for a few hours. What I see is beyond my (poor) understanding of AE.
I wrote my expression using this simple filtering algorithm :
newPositionB = previousPositionB + 0.2*(positionA - previousPositionB)
This way B follows A (more) smoothly.

The result I get is almost satisfying, visually. But I checked the value : there is a little error.
So I pasted my expression in a text layer to debug ... and this is crazy :
The values calculated in the debug text are right ... but they are not applied to B's position.

Debug text gives me for instance newPosition[0] = 977 but B is at 968 ...

Moreover, in B's expression, I tested all the intermediary variables (lastPosition, targetPosition ) by affecting them to the first coordinate ... and it is consistent with the debug text. ONLY, newPosition ... which is calculated from the others remains erroneous ...

So I really don't understand ...

Does any body have an idea ? ... to save my soul before it blows out.
Thanks !

// expression for B's position
targetPosition = thisComp.layer("NULL--All-In-A-Frame").transform.position.value;
smoothCoeff = thisComp.layer("Curseurs---->").effect("smoothCoeff")("Slider").value/100 ;
newPosition = [0,0,0] ;
if (time>0) {
lastPosition = thisComp.layer("NULL-filtered").position.valueAtTime(time-thisComp.frameDuration);
// filter core :
newPosition[0] = lastPosition[0] + smoothCoeff*(targetPosition[0] - lastPosition[0]) ;
newPosition[1] = lastPosition[1] + smoothCoeff*(targetPosition[1] - lastPosition[1]) ;
newPosition[2] = lastPosition[2] + smoothCoeff*(targetPosition[2] - lastPosition[2]) ;
}
else {newPosition = targetPosition.slice() ;}
[newPosition[0],newPosition[1] ,newPosition[2] ]

--------------------------------------------------------------------------------------
// Expression for debug text
targetPosition = thisComp.layer("NULL--All-In-A-Frame").transform.position.value;
smoothCoeff = thisComp.layer("Curseurs---->").effect("smoothCoeff")("Slider").value/100 ;
newPosition = [0,0,0] ;

if (time>0) {
lastPosition = thisComp.layer("NULL-filtered").position.valueAtTime(time-thisComp.frameDuration);
// filter core :
newPosition[0] = lastPosition[0] + smoothCoeff*(targetPosition[0] - lastPosition[0]) ;
newPosition[1] = lastPosition[1] + smoothCoeff*(targetPosition[1] - lastPosition[1]) ;
newPosition[2] = lastPosition[2] + smoothCoeff*(targetPosition[2] - lastPosition[2]) ;
}
else {newPosition = targetPosition.slice() ;}


"last Position = " + lastPosition + "\n targetPosition = " + targetPosition + "\n newPosition = " + newPosition


Return to posts index

Nicolas Guionnet
Re: Smoothing camera movements following a null
on Mar 15, 2019 at 4:36:19 pm

It seems that it is not possible to use the previous position of an Object to calculate its new position.
The following expression does not work ... The NULL should move. (it is in the NULL.position)

I guess this sort of recursive code is not allowed ...
Any idea ?

newPosition = [] ;
if (time>0) {
lastPosition = thisComp.layer("NULL").position.valueAtTime(time-thisComp.frameDuration);
// filter core :
newPosition[0] = lastPosition[0] + 10 ;
newPosition[1] = lastPosition[1] ;
newPosition[2] = lastPosition[2] ;
}
else {newPosition = [960,540,0] ;}

[newPosition[0],newPosition[1],newPosition[2] ]






Return to posts index

Kalleheikki Kannisto
Re: Smoothing camera movements following a null
on Mar 16, 2019 at 1:55:25 pm
Last Edited By Kalleheikki Kannisto on Mar 16, 2019 at 1:57:31 pm

My assumption is that you would have to write a piece of code that calculated the nulls position for a given range of frames, in the same fashion as you are doing for one frame, i.e calculating the outcome at each frame with a loop, and average them out.

Simplified, if your code for a given null was (A+B+C)/3

Your averaged value would be ((A1+B1+C1)/3 + (A2+B2+C2)/3 + (A3+B3+C3)/3)/3

Where A1 is a value 1 frame back, A2 a value at current frame and A3 the value at the next frame.

With a loop, you can make the range as large as you want.

The point being, you would do the full position calculation using valueAtTime() to retrieve the values of A, B and C at a given time for each of the frames in the loop and then averaged them out. Rather than retrieving the result of the NULL position calculation through valueAtTime().

Would seem less error-prone.

Kalleheikki Kannisto
Senior Graphic Designer


Return to posts index


Nicolas Guionnet
Re: Smoothing camera movements following a null
on Mar 16, 2019 at 6:12:37 pm

Hi Kalleheikki ! ... and thanks !

Yes that's a good solution, I think. In fact I posted on another forum the question about the legitimacy of my former recursive approach. The answer was "no way" ...
I took a great deal of time to think of a workaround ... and I came to the same idea as you ! Local Average smooths out a function.
As I read your lines I understand that we could even circumvent a flaw of the recursive method : It's late ! The first order filter never reaches the position of its target ... it's late.

(If I am not wrong --- again ...) With the average method, we could select the values of the target position in a neighborhood ot t ... not necessarily the values before. We could apply a set of Gaussian curve coefficient around t ... (And yes, with the recursive method you can't access the future.)
The video is a loop so the algorithm could also see time as a loop so tMax + 1 = 0

I am so excited to try this ! I used to do math for the sake of math ... but doing math for visual results is really fun ... ☺

Thanks !


Return to posts index

<< PREVIOUS   •   VIEW ALL   •   PRINT   •   NEXT >>
© 2019 CreativeCOW.net All Rights Reserved
[TOP]