Copy link to clipboard
Copied
Hey guys,
So, I'm trying to assign the X value a null object had at the previous frame so I can continue to subtract a number from it cumulatively. I'm trying to assign it to a variable (prevframe). I'm not sure where I'm going wrong, but the line I'm trying to do it on is written as follows:
prevframe = transform.xPosition.valueAtTime(time-(1/24))
So in my mind, this should be taking a look at the value of X on the null, then looking back in time to figure out what it's value was on the previous frame (my frame rate is 24, so I'm dividing 1 second in to 24 pieces and telling it to subtract that much from the current time), and assigning whatever that returns to the variable. But it's just returning a static value, even though I'm subtracting from it. I feel like it's not the correct syntax, but I really have no idea.
I want to continue to subtract a value which is based on the velocity of another object from this, which I have worked out, I just can't figure out how to reference what this nulls X position was in the previous frame so it always returns the same value until all motion has stopped. The formula the variable is being run through looks like:
finalposition = prevframe - camvelocity
Which is then assigned to the final X position of the null object.
So, I'm not sure where I'm going wrong. I hope I've provided enough information to help someone wrap their head around this and hopefully help me solve it.
Thanks in advance,
-Seth
Copy link to clipboard
Copied
I'm fairly confused by your question, but I have a few comments.
First instead of using 1/24 in your prefFrame calculation I would use thisComp.frameDuration.
an expression that would display the x position of a null in the previous frame would look like this.
nl = thisComp.layer("Null 1"); // your null
prevframe = nl.position.valueAtTime(time - thisComp.frameDuration);
x = prevframe[0]; // extract x value
[x, value[1]]
I have no idea what you're trying to do with the camvelocity or how you came up with that number. The expression listed above will allow you to animate the layers Y position and track the x position of the null one frame behind the current frame. If the null moves 10 pixels per frame the position of the layer will be 10 pixels behind the null until the motion stops.
Copy link to clipboard
Copied
Sorry it was confusing. Let me try to clarify. My null object has a starting point, which is an X value of 2020. For each frame the camera is moving, I want to subtract the cameras velocity from 2020, but I want it to be cumulative. So say the camera is moving linearly at 20 px per frame. On the first frame this starts, the value it will return is 2000. Then on the next frame I'd like it to subtract 20 from the new X value of 2000, but it continues to look at 2020 as the value to be subtracted from. So there isn't any accumulation of this X position getting lower and lower, it just gets to 2000 and stops.
When I plugged in your code I was getting the same result. I'm not sure if it's just not meant to work the way I was thinking I'd like it to, but…
What I'm trying to accomplish is kinda weird though. I'm trying to get this null, which is a parent to some glares nested in a composition, to take both camera movement and actual composition movement in to account as it drives the position of the glare objects. I wanted to see if the composition was moving faster in the main timeline, or the camera, and then add or subtract the faster velocity to the position of the null object, and have it do that continuously rather than to the null objects starting value and nothing else. so 2020 - 20 - 20 - 20 - 20 ect., with a 20 (or whatever the velocity works out to be) for each frame things remain in motion.
I want it to remain based on expressions just because I'm going to have a lot of these panels with glares, and hand keyframing each of them isn't something I'll have time to do, so I just want it to be based off of those two movements.
I think I'm going to take a different approach though. I think I'm trying to do too much with this expression that can be done in different ways. Instead of having one null I'm going to have two, and I'll have an expression within my glare objects to decide which ones coordinates to use as a parent still based on velocity.
Copy link to clipboard
Copied
I'm not sure I know what you mean by camera's velocity.
If the camera is moving 20 pixels per frame then you want to subtract 20 pixels from the the x position of he camera, then in the next frame you want to subtract 40 pixels, then then next 60 pixels.
If you define your camera as cam = thisComp.layer(Camera 1); then you take the initial position of the camera as ocp = cam.position.valueAtTime(0) you'll get the position value at the first frame of the composition. ocp = Original Camera Position. Then you subtract the current camera position as ccp = cam.position to get the total pixels the camera has moved in x. It sounds like that's what you want. All you have to do is extract the x value ([0]).
Now you can take that value and apply it to the position value of your null like this:
cam = thisComp.layer("Camera 1");
ocp = cam.position.valueAtTime(0);
ccp = cam.position;
nx = ocp - ccp;
[value[0] + nx[0], value[1], value[2]];
I'm assuming that the null is 3D. If not eliminate the last item in the array. By using value[0] + nx in the array you'll be able to adjust the starting position of the null in any axis. You can even add keyframes if you'd like.
I'm not sure you're going to get the results you are looking for. It seems like you're trying to simulate some kind of lens flair. Changing the + to a - in the final line will reverse the tracking of the null.
Copy link to clipboard
Copied
I think you've been bitten by the fact that expressions have no memory of what they've calculated on previous frames. If the camera has a constant velocity you can probably get away with something as simple as this:
v = thisComp.layer("Camera 1").transform.position.velocityAtTime(0);
value - (time - inPoint)*v[0];
If the camera has variable velocity, you need to loop through each previous frame and add up offsets created by the velocity at each frame, more like this:
f = timeToFrames(inPoint);
accum = 0;
c = thisComp.layer("Camera 1").transform.position;
for (f = timeToFrames(inPoint); f <= timeToFrames(); f++){
accum += c.velocityAtTime(framesToTime(f))[0]*thisComp.frameDuration;
}
value - accum
It gets more complicated it you need it to be anything other than horizontal motion.
Hope this helps.
Dan
Copy link to clipboard
Copied
Dan,
I tried your second expression in a test comp with the camera moving between 2 keyframes at a constant velocity. The results were nearly identical to my expression. Your first expression, the simple one also produced identical results but the layer kept moving after the camera stopped. I thought the first expression should have v where time is. That doesn't work.
v = thisComp.layer("Camera 1").transform.position.velocityAtTime(0);
value - (v - inPoint)*v[0]; // doesn't work
I can't see how to make the horizontal movement stop when the camera stops. I also discovered that under some conditions with only two keyframes the simple expression produces completely different movement.
Thanks for giving me some more to think about.
Copy link to clipboard
Copied
>The results were identical to my expression.
That sounds right. I may have over-thought this. I was thinking that to account for variable velocity, you'd have to integrate it over time, but if you integrate speed you get distance traveled. Duh. So your way is simpler and should work even if the velocity is variable.
Dan
Copy link to clipboard
Copied
I actually kind of like what's happening with the simple expression. I'm not sure how to describe the motion, but it does some really interesting things when there's a bunch of camera movement.