Activity › Forums › Adobe After Effects Expressions › Rotating Wheel in 3D space
-
Rotating Wheel in 3D space
Posted by Mike Foran on March 19, 2013 at 8:44 pmI have used Carl Larsen’s script for rotating wheels based on X axis movement, and it works great. I am currently attempting to animate a wheel in 3D space and unfortunately it just doesn’t work.
What I would like to be able to do is have my wheel automatically rotate when I move it along a motion path on the X and Z axes (don’t need to get into Y). In this case I have auto-orient to path turned on.
I’m not smart enough with the maths to figure this out. Has anyone cracked this nut already? It would be very much appreciated.
Mike Foran replied 13 years, 1 month ago 2 Members · 7 Replies -
7 Replies
-
Dan Ebberts
March 20, 2013 at 12:59 amIs it a curved path in the x/z plane? If so, that can be a tricky calculation. You need to calculate the total distance traveled up to the current frame. You can approximate it by calculating how far it moves from one frame to the next and adding those distances together for all previous frames. You could increase the accuracy by using sub-frame sampling, but it could get pretty slow if your comp is long. Here’s one version:
dist = 0;
f = timeToFrames(time);
f0 = timeToFrames(inPoint);
for (i = f; i > f0; i--){
p1 = position.valueAtTime(framesToTime(i));
p0 = position.valueAtTime(framesToTime(i-1));
dist += length(p0,p1);
}360*(dist/(Math.PI*width))
Dan
-
Mike Foran
March 20, 2013 at 3:48 amYup, that’s it. I knew straight position wouldn’t work in this case so I was trying to figure out out to determine the distance between the previous frame and the current and rotate accordingly, but I couldn’t get the math and context right. It appears that you are determining rotation from the starting point, or are you getting it just from the previous frame?
And just out of curiosity, how would one work out sub-frame sampling?
I really appreciate you taking the time to sort that out. We really ought to take up a collection here and buy you a boat or something.
-
Dan Ebberts
March 20, 2013 at 10:32 pm>And just out of curiosity, how would one work out sub-frame sampling?
This example samples twice per frame:
dist = 0;
f = timeToFrames(time);
f0 = timeToFrames(inPoint);
for (i = f; i > f0; i--){
p2 = position.valueAtTime(framesToTime(i));
p1 = position.valueAtTime(framesToTime(i-.5))
p0 = position.valueAtTime(framesToTime(i-1));
dist += length(p0,p1) + length(p1,p2);
}
360*(dist/(Math.PI*width))
Dan
-
Mike Foran
March 21, 2013 at 3:46 amI see. Very informative. Thanks again Dan. What kinds of boats do you like?
-
Mike Foran
March 22, 2013 at 5:33 pmSo I am trying to modify this script so that, when it reaches a marker on the timeline, it reverses rotation. But since it is calculating rotation based upon total length traveled I am geting errors when I try to set rotation for the opposite direction. I am not sure setting markers is the right way to do it, but I need a way to reverse the rotation. The way I have it now it resets the rotation to 0 when it hits a marker, but I would like it to not change rotation at all until it starts moving again. I would love any suggestions as to the best way to handle this.
Here is a link to the test project: https://www.dropbox.com/s/s5dfegqbvghddbd/Comp%2010.aep
// -------- Experimental Rotation Script --------- //;n = 0;
dist = 0;
w=width;// Determine if there are any markers on the timeline and if so if they are odd or even
if (thisLayer.marker.numKeys > 0){
n = thisLayer.marker.nearestKey(time).index;
if (thisLayer.marker.key(n).time > time){
n--;
}
if (n > 0){
f = timeToFrames(time);
f0 = timeToFrames(thisLayer.marker.key(n).time);
for (i = f; i > f0; i--){
p2 = position.valueAtTime(framesToTime(i));
p1 = position.valueAtTime(framesToTime(i-.5))
p0 = position.valueAtTime(framesToTime(i-1));
dist += length(p0,p1) + length(p1,p2);
}
if (n%2){
// ODD: rotate clockwise
-360*(dist/(Math.PI*w))
}else{
// EVEN: rotate counterclockwise
360*(dist/(Math.PI*w))
}
}else{
// NONE: rotate clockwise
f = timeToFrames(time);
f0 = timeToFrames(inPoint);
for (i = f; i > f0; i--){
p2 = position.valueAtTime(framesToTime(i));
p1 = position.valueAtTime(framesToTime(i-.5))
p0 = position.valueAtTime(framesToTime(i-1));
dist += length(p0,p1) + length(p1,p2);
}
360*(dist/(Math.PI*w))
}}
-
Dan Ebberts
March 22, 2013 at 6:16 pmI think this is closer to what you’re looking for:
dist = 0;
w = width;
f = timeToFrames(time);
f0 = timeToFrames(inPoint);
d = thisComp.frameDuration;
for (i = f0; i <= f; i++){
n = 0;
t = framesToTime(i);
if (thisLayer.marker.numKeys > 0){
n = thisLayer.marker.nearestKey(t).index;
if (thisLayer.marker.key(n).time > t) n--;
}
odd = n%2;
p2 = position.valueAtTime(t);
p1 = position.valueAtTime(t-d/2)
p0 = position.valueAtTime(t-d);
if (odd)
dist -= length(p0,p1) + length(p1,p2)
else
dist += length(p0,p1) + length(p1,p2);
}
360*(dist/(Math.PI*w))
Depending on what your ultimate plan is though, you could probably accomplish the same thing by have the expression figure out whether, for example, the layer is moving left or right. It gets a little trickier in 3D though.
Dan
-
Mike Foran
March 22, 2013 at 7:19 pmSeriously. What kinds of boats do you like Dan? Sailboats? Motorboats? How about a nice big yacht? I’m taking up a collection. That worked perfectly and I’ve been trying to write that for 2 days.
Reply to this Discussion! Login or Sign Up