LookAtMe! A 2D lookAt() function in AE Expressions

The lookAt() function in After Effects’ expression language doesn’t work for 2D.

If you’re trying to use it to align the layer to look at a given point, without having to remember all the trigonometry you learned in school, it turns out you should have spent less time smoking behind the shelter sheds, because this is what it does:

When used in 2D, if the looked-at point is below the looking-from point the direction reverses.

There’s a fix for this though, and it can be used to build a better Auto-Orient than the one Adobe gave you.

function lookAtMe(fromPt, toPt){
  d = toPt - fromPt

  //prevent divide-by-zero errors
  if (d[0] == 0){
    A = (d[1]>0)? 90: -90;
  } else {
    //using my trigonometric super powers for good instead of evil
    A = radiansToDegrees(Math.atan(d[1]/d[0]))
  }
  //shorthand for if the X difference is negative, add 180°
  return 90 + ((d[0]>0)?A: 180+A);
}

This function can be used as a 2D lookAt, returning a single rotation value, which produces this result:
lookAtMe

This can be used to replace the rather feeble Auto-orient function in AE, using the expression below.

For 2D layers apply this expression applied to the rotation channel:

//the function from before
function lookAtMe(fromPt, toPt){
  d = toPt - fromPt
  if (d[0] == 0){
    theAngle = (d[1]>0)? 90: -90;
  } else {
    theAngle = radiansToDegrees(Math.atan(d[1]/d[0]))
  }
  return 90 + ((d[0]>0)?theAngle : 180+theAngle );
}

//lookBack and lookForward can be set to smooth out
//sharp changes of direction.
//for more accuracy set them lower,
//for smoother turns set them higher.
//if you have hold keyframes in your motion path
//you might get better results using a value of 0

lookBack = 5; //how far back to use as the look-from point
lookForward = 5;//how far ahead to use as the look-to point

fd = thisComp.frameDuration; //for convenience;
lookAheadTime = time + lookForward * fd; 

//the looked-from frame
p0= transform.position.valueAtTime(time - lookBack * fd); 
//the looked-at frame
p1=transform.position.valueAtTime(lookAheadTime); 

//check to see if there is any movement
//if not scan ahead until there is movement,
//up until the end of the layer+1 frame
while (p1 == p0 && lookAheadTime <= outPoint + fd){
  p1=transform.position.valueAtTime(lookAheadTime);
  lookAheadTime += fd;
}
lookAtMe(p0, p1);

Looking ahead until there is movement prevents it getting confused when the layer is starting the movement, as happens on the first keyframe. This expression will line the layer up, before it moves, ready to go as soon as it starts moving.

This has two settings that can be adjusted to suit the motion. The lookBack and lookForward variables can be set depending on your motion, and the smoothness you want to achieve. By setting them to higher values the object will turn smoothly at sharp corners.

If you set lookForward higher than lookBack it looks like the layer is skidding. This could be useful.

2 comments

  1. How to I specify which layer is the look from and which layer is the look to? Thanks.

    Reply

Leave a Reply

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