Creative Communities of the World Forums

The peer to peer support community for media production professionals.

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 pm

    I 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 am

    Is 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 am

    Yup, 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 am

    I see. Very informative. Thanks again Dan. What kinds of boats do you like?

  • Mike Foran

    March 22, 2013 at 5:33 pm

    So 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 pm

    I 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 pm

    Seriously. 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.

We use anonymous cookies to give you the best experience we can.
Our Privacy policy | GDPR Policy