I was given an interesting Twitter challenge this evening, and thought that I’d post the solution here on my blog. John Dickinson of MotionWorks asked how to get one layer moving precisely in opposition to another layer in 2D or 3D space around a given point, and without using null objects of any kind. Here are my solutions:
2D
a=thisComp.width/2;
b=thisComp.height/2;
refl=[a,b];
par=thisComp.layer(“Parent Layer”).transform.position;
dist=sub(refl,par);
add(refl,dist);
3D
a=thisComp.width/2;
b=thisComp.height/2;
c=0;
refl=[a,b,c];
par=thisComp.layer(“Parent Layer”).transform.position;
dist=sub(refl,par);
add(refl,dist);
***Place these expressions in the position value of the layer that you wish to mirror the “parent” layer.
***You can substitute any position values that you want in the “refl”, including another layer or null.
***Read on if you want to see how the math works!
***UPDATE: If you copy/paste this into After Effects, make sure that you delete any extra characters that come out of the code (like “?” between each line). Also, my copy of AE doesn’t like the quotation marks around “Parent Layer”, so you’ll want to replace them as well.
How the Math Works
The trick for me was seeing the relationship between a given point of reflection (in this case, the center of the composition in comp and world space) and the location of the “parent” layer. If I could find the distance between each of the parent layer’s dimensions and the reflection point, then I could add that distance to the reflection point and call that resulting value the position value of the child. In other words, as the distance increased between the parent and the reflection point, the distance would increase IN THE OPPOSITE DIRECTION for the child layer. This worked in both 2 and 3-dimensions.
Since position information for layers are arrays, I could use the vector math expressions to make my work a little easier and clean up the code. (My initial solution that I sent was much longer and less elegant! Fortunately, I had a chance to clean up my work a little bit!) The add() and sub() methods both require two arguments, each arrays of either 2 or 3-dimensions, otherwise known as vectors. So, I took the reflection point first, established all of it’s values, and gave it a variable named “refl”. Next, I needed to have the position value of the parent layer entered into the expression, and since it needed to be variable AND manipulable by the vector math methods, we set it up in the variable “par”. Finally, the distance between the parent layer and the reflection point (stored in the expression using a variable named “dist”) was established using the sub() method, and added back to the reflection point using the add() method, yielding the final result.
Phew!!
What the add() and sub() Methods Do
Vector math methods take two vectors and perform mathematical operations upon their values in the order the user defines, and does so for each dimension of the arrays within the method. Put more simply, the add() method looks at the first dimension of each array and adds them all together, does so for the second dimension, and so on. It expresses it’s final answer as a new array. The sub() method works in the same way, but it subtracts the array dimensions. In other words, the add() method looks like this:
a=thisComp.layer(“Example”).transform.position[0];
b=thisComp.layer(“Example”).transform.position[1];
c=thisComp.layer(“Example”).transform.position[2];
d=thisComp.layer(“Example 2″).transform.position[0];
e=thisComp.layer(“Example 2″).transform.position[1];
f=thisComp.layer(“Example 2″).transform.position[2];
x=(a+d);
y=(b+e);
z=(c+f);
[x,y,z]
Now I don’t know about you, but I like this a LOT better…
vec1=thisComp.layer(“Example”).transform.position;
vec2=thisComp.layer(“Example 2″).transform.position;
add(vec1,vec2)
Instead of having to write a bunch of variables describing each dimension of each layer, we can just call up all of the values at once and let After Effects do the work! (Disclaimer: the draft that I sent to John was the first one above. With all of the variables. How embarassing…!) The sub() method works similarly to the add() method, except that it subtracts values rather than adds them. (Shocking, I know…)
Conclusion
Thanks, John, for a great challenge! It made me think a little bit at this late hour (1AM EST as I write this post), but also gave me a chance to demonstrate some great expression methods!