Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

move layer constantly in a certain direction depending on 3d-Rotation?

Explorer ,
Apr 07, 2020 Apr 07, 2020

Hi,

 

I am trying to work my head around an expression, but am not able to write it.

 

I have multiple layers being assigned a random position as initial value.

I also apply a 3d-effekt for rotation on it, which I will keyframe manually.

 

I would like to have each layer move constantly to the right starting at its initial position, if the rotation of the 3d-effect = 0; and change direction (move to the left) if the 3d-effekt rotation changes to 180°.

I thought of using a "Transform"-Effect wherein to write an expression, so to not mess with the random-expression for the original Position. But that's my way of thinking to not make it too complicated.

 

Eather way, in theory I guess I need to:

get the position at the given time

then add a value if the Effect=0 or subtract if the Effect=180.

Haven't been able to write it though.

 

Any help appreciated as always 🙂

TOPICS
Expressions
7.6K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Apr 10, 2020 Apr 10, 2020

I think I completely misunderstood what you are trying to do. This is where screenshots showing us what you are doing to at least one of the layers would help a lot. 

 

I think you have some kind of animation on the position property of a 3D layer and you want to control how fast that layer moves and in what direction by the rotation property of the layer. Let's say the movement you want to control is along the X-axis and the rotation you want to use is the Y-axis. 

 

If that is the case then a

...
Translate
LEGEND ,
Apr 07, 2020 Apr 07, 2020

Could be as trivial as if()else{}, though the hold-up likely is on what your 180 deg determination is based. Moving relative to a camera and maintaining a consistent behavior might be trickier than jsut in a 2D comp. To be honest, though, since you plan on keyframing the rotation, what would be the issue with also animating the motion? This could even be as trivial as animating at once and then applying two different animation presets - one for the left side movement, one for the right side.

 

Mylenium

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 07, 2020 Apr 07, 2020

It's a bit hard to explain, but I'll try 🙂

 

It's a couple of hundreds of layers all starting at a different time. I create them by just duplicating. They all of a random position in 3d-space. As said, they should be moving in the same speed in one direction.

I will manually select groups of layers at a given point in my timeline and copy-paste the rotation-effect (with the rotation from 0 to +180 already applied), making that group of layers turn at the same time. At a later point the next group etc..

Having the movement already embedded, when copy-pasting, would make things a lot easier due to the amount of layers.

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Apr 07, 2020 Apr 07, 2020

Why not just separate the dimensionss for position and then just add the time expression tothe X position value?

 

E.g.

 

time*a

 

with a being whatever number you decide? 1 pixel per second is the default.so use math to get the speed you're after.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 07, 2020 Apr 07, 2020

that would work for just moving in one direction. But how to make it go the other direction from where it ended up after a certain amount of time (in my case when the rotation is applied)?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 07, 2020 Apr 07, 2020

just tried again.

with a if / when adding the time to the x-position or subtracting for the other condition makes the layer jump back to the original position and then move into the other direction.

 

I guess what I am looking for (and not knowing how to), how to read out the present position and then adding or subtraction a value... no?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
Apr 07, 2020 Apr 07, 2020

I'm not sure if a if-statement without else is accepted by the JavaScript expression engine, but this should do it:

 

// current position of layer
myPos = thisLayer.transform.position;

// rotation effect, drop it in here
rot_fx = ;

//speed of left/right movement
speed = 2;

// check direction and invert speed if necassary
if (rotation_effect < 180){
	speed = -speed;
}

// time increases with each frame, speed is +2 or -2 so mySpeed is + or - as well
mySpeed = time*speed;

// add + or - value of mySpeed to x position
myX = myPos[0] + mySpeed

// return position array

[myX, myPos[1]];


 

*Martin

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 09, 2020 Apr 09, 2020

Thank you Martin,

 

unfortunatelly not working. When the direction changes (rot-fx applies), the object first jumps the double-distance into the other direction and move from there.

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 07, 2020 Apr 07, 2020

Try this:

 

 

 

angle = thisComp.layer("Null 1 Control").effect("Angle Control")("Angle") - 90;
ofSt = thisComp.layer("Null 1 Control").effect("Slider Control")("Slider");
strt = time - inPoint;
t = strt - ofSt;
freq = easeIn(t, 0, .5, 10, 0);
amp = easeIn(t, 0, .5, 100, 0);
RndmPos = wiggle(freq, amp);
if (strt < ofSt)
	moV = RndmPos	
else moV = value
xMove = t * angle;

[moV[0] + xMove, moV[1]]

 

(now that I look at the ease method for the wiggle I see set that up incorrectly. don't have time to fix it now but the expression should still work)

I don't know how you are generating your random movement but you should be able to just replace the wiggle method with that.  I based the start time for the end of the random motion on a slider control. Set the slider to 1 and the random motion will stop at 1-second and the movement in X will begin with the speed based on the value of the Angle Control with no movement at 90º.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 09, 2020 Apr 09, 2020

There is a little misunderstanding. I am not applying a random movement (wiggle), but a random initial starting position.

 

Imagine a groud of people. (no one can be at the same place at the same time, that's why the random position).

All walk with the same speed into one direction (to the left). If a person turns around, it walks into the other direction (to the right). The tricky part is, each person appears on the scene at a different time in my timeline, and each person will turn around at a different time.

All attempts so far make the person jump to the left he double distance it has moved to the right before.

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Mentor ,
Apr 09, 2020 Apr 09, 2020

Meh! I see the issue.

 

This is the classic case where you need to use a previous calculated value for the current frame. This is not possible with expressions. Instead, you need to recalculate the value for each frame.

This ends in a for-loop, starting at 0 and counting up to your current frame, doing the math over and over again. The longer your comp is, the longer this for-loop will execute.

 

The for-loop will work for sure, but maybe you find a better approach. Why not creating the animation with keyframes (walks left for x seconds, turn around and walks right) in a long comp. The keyframes are placed in the middle of the timeline, so you have enough animation going on to boh sides. Then you use the comp, place it randomly with your expression and cut of start and ending point. With time remap, you can also use expressions for this.

 

*Martin

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 10, 2020 Apr 10, 2020

Hi Martin,

 

thanks again. I have never used a for-loop. Is that complicated?

I consider the other idea, but it will bring new problems 🙂

Anyway, I keep on thinking, just have to postpone the problem a bit.

A question though: is it possible to get the time of a keyframe?

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 10, 2020 Apr 10, 2020

nevermind, just found how to get the time of a keyframe. Maybe it will help

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Apr 10, 2020 Apr 10, 2020

I think I completely misunderstood what you are trying to do. This is where screenshots showing us what you are doing to at least one of the layers would help a lot. 

 

I think you have some kind of animation on the position property of a 3D layer and you want to control how fast that layer moves and in what direction by the rotation property of the layer. Let's say the movement you want to control is along the X-axis and the rotation you want to use is the Y-axis. 

 

If that is the case then a variation of Dan Ebberts Expression Speed and Frequency Control methods should do the trick. Just a simple linear method applied to the position would only change the speed based on angles. You will need the complex math in Dan's solutions to change the direction.

 

Once again, a screenshot showing us the modified properties of at least one layer would be a big help in figuring out what you are trying to do. 

 

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 10, 2020 Apr 10, 2020

Dear Rick,

 

you are totally right, a screenshot would have helped. But I think you understood my goal. 🙂

I will definitly look into Dan Ebberts approach!

By now I found a solution, which is working, but not satisfying, because it leaves no flexibility of changes.

(I attach a screenshot). In that situation my "people" turn twice on the y-axis, and move along the x-axis. The movement is controlled by two null objects as masters, one moving two the left one pixel per frame, the other one to the right one pixel per frame. The slaves  move following the "left-null" at their beginning. When they turn (keyframe 1+2) they follow the "right-null" and then again the left (after keyframe 3+4). I calculate the distance which has added up between the null's acording to the time of the keyframes 1 and 3 and add/subtract it to the position. But that only works if the speed of the nulls stay one pixel per frame.

Well, a bit complicated, specific and hard-coded, but at least a result.

Anyway, I'll keep looking. Do you mean the section "Linear Keyframe Integrator" is what I need?

 

best, r

 

and the code:

 

 

 

seedRandom(index, true);
xOrigin = random (-1500, 1500); //random initial Position
t = (time -inPoint)*30; //time of Layer in Frames
tS = time-inPoint; //time of Layer in Seconds
prop = transform.yRotation;
n = prop.numKeys;
tKey1 = (prop.key(1).time-inPoint)*30; //time of 1.Keyframe of rotation
tKey3 = (prop.key(3).time-inPoint)*30; //time of 3.Keyframe of rotation
left = thisComp.layer("left").transform.xPosition.valueAtTime(tS); //Position of null left
right = thisComp.layer("right").transform.xPosition.valueAtTime(tS); //Position of null right
if (t > tKey1 && t < tKey3)
xNew = xOrigin+right-(2*tKey1)
else if (t >= tKey3)
xNew = xOrigin+left+(2*(tKey3-tKey1))
else
xNew = xOrigin+left

 

 

 

 

Bildschirmfoto 2020-04-10 um 23.38.39.png

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 10, 2020 Apr 10, 2020

Dear Rick,

 

you are totally right of course, a screenshot would have helped. But I think you understood my goal. 🙂

I will definitly look into Dan Ebberts approach!

By now I found a solution, which is working, but not satisfying, because it leaves no flexibility of changes.

(I attach a screenshot). In that situation my "people" turn twice on the y-axis, and move along the x-axis. The movement is controlled by two null objects as masters, one moving two the left one pixel per frame, the other one to the right one pixel per frame. The slaves  move following the "left-null" at their beginning. When they turn (keyframe 1+2) they follow the "right-null" and then again the left (after keyframe 3+4). I calculate the distance which has added up between the null's acording to the time of the keyframes 1 and 3 and add/subtract it to the position. But that only works if the speed of the nulls stay one pixel per frame.

Well, a bit complicated, specific and hard-coded, but at least a result.

Anyway, I'll keep looking. Do you mean the section "Linear Keyframe Integrator" is what I need?

 

best, r

 

and the code:

 

seedRandom(index, true);
xOrigin = random (-1500, 1500); //random initial Position
t = (time -inPoint)*30; //time of Layer in Frames
tS = time-inPoint; //time of Layers in Seconds
prop = transform.yRotation; 
n = prop.numKeys;
tKey1 = (prop.key(1).time-inPoint)*30;  //time of 1.Keyframes of rotation
tKey3 = (prop.key(3).time-inPoint)*30;  //time of 3.Keyframes of rotation
left = thisComp.layer("left").transform.xPosition.valueAtTime(tS); //Position of null left
right = thisComp.layer("right").transform.xPosition.valueAtTime(tS);  //Position of null right
if (t > tKey1 && t < tKey3)
	xNew = xOrigin+right-(2*tKey1)
else if (t >= tKey3)
	xNew = xOrigin+left+(2*(tKey3-tKey1))
else 
	xNew = xOrigin+left

 

Bildschirmfoto 2020-04-10 um 23.43.46.png

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 11, 2020 Apr 11, 2020

Dear Rick,

 

with a fresh eye this morning I looked at Dan Ebberts Expression Speed and Frequency Control

You were right, it is EXACTLY what I needed.

Thank you so much!

 

Bildschirmfoto 2020-04-11 um 09.11.44.png

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Oct 23, 2023 Oct 23, 2023
LATEST

TRY THIS 
---------------------------------------------------------------------------------------------


var rotationDuration = 60; // The duration of each rotation in frames
var maxRotationAngle = 180; // The maximum angle to rotate (in degrees)
var pauseDuration = 30; // The duration to pause in frames (1 second at 30fps)

var currentTime = time - inPoint; // Calculate the time relative to the layer's in-point

var cycleNumber = Math.floor(currentTime / (rotationDuration + pauseDuration));
var seed = Math.floor(time / (rotationDuration + pauseDuration)); // Create a seed for random rotation
seedRandom(seed, true);

var rotationAngle = random(0, maxRotationAngle);
var normalizedTime = currentTime % (rotationDuration + pauseDuration);
var rotation;

if (normalizedTime < rotationDuration) {
    // Animate the rotation during the rotation duration
    var progress = normalizedTime / rotationDuration;
    rotation = progress * rotationAngle;
} else {
    // Pause the rotation
    rotation = rotationAngle; // Hold the final rotation
}

rotation;

-------------------------------------------------------------------------------------------------------------------------------------
both sides rotation

var rotationDuration = 1; // The duration of each rotation in frames
var maxRotationAngle = 180; // The maximum angle to rotate (in degrees)
var pauseDuration = .01; // The duration to pause in frames (0.5 seconds at 30fps)

var currentTime = time - inPoint; // Calculate the time relative to the layer's in-point

var cycleNumber = Math.floor(currentTime / (rotationDuration + pauseDuration));
var seed = Math.floor(time / (rotationDuration + pauseDuration)); // Create a seed for random rotation
seedRandom(seed, true);

var rotationAngle;

if (cycleNumber % 2 === 0) {
    // Rotate during the first half of the cycle
    var normalizedTime = currentTime % (rotationDuration + pauseDuration);
    if (normalizedTime < rotationDuration) {
        var progress = normalizedTime / rotationDuration;
        rotationAngle = progress * maxRotationAngle;
    } else {
        rotationAngle = maxRotationAngle; // Hold the final rotation
    }
} else {
    // Rotate the other way during the second half of the cycle
    var normalizedTime = currentTime % (rotationDuration + pauseDuration);
    if (normalizedTime < rotationDuration) {
        var progress = normalizedTime / rotationDuration;
        rotationAngle = -progress * maxRotationAngle;
    } else {
        rotationAngle = -maxRotationAngle; // Hold the final rotation
    }
}

rotationAngle;

 

--

Regards Karthik 09847661702
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines