Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions Creating an ocean of text layers, all reacting to a displacement map

  • Creating an ocean of text layers, all reacting to a displacement map

    Posted by Chris Mellor on April 26, 2012 at 9:05 pm

    here is the history of my issue. I decided to move the discussion here because my problem is now strictly involving expressions.
    I am trying to create a sea of text layers, where each word rises and falls like a wave. After Particular and Form failed me (refer to the link to other thread) I now must make the 500+ duplicates of my layers and have them linked through expressions. I created the bed of Words no problem. They sit above a Displacement Map (pre-comp’d Fractal Noise) and are vertically displaced according to the luminance value using the sampleImage() and rgbToHsl() expressions. Now the tricky part is getting the Rotation to work.
    Here is what I want to happen:

    And here is what I get:

    From here, I have been trying to map the rotation of my layers from the Displacement Map. Here is the code I have so far:
    // sampling
    target = thisComp.layer("Turbulence Layer");
    samplePoint = [position[0],position[1]];
    sampleRadius = [1,1];
    rgb = target.sampleImage(samplePoint, sampleRadius, true, time);
    lum = rgbToHsl(rgb)[2];
    rgbOld = target.sampleImage(samplePoint, sampleRadius, true, time-thisComp.frameDuration);
    lumOld = rgbToHsl(rgbOld)[2];

    delta = (lum-lumOld)*100 // change in luminence

    if (delta > 0) {
    ease(delta, 0, 4, 0, -30)
    }
    else {
    ease(delta, 0, -4, 0, 30)}

    This makes sense to me; if the change in luminance is positive (meaning the Word layer is rising on a wave) then the rotation should ease from 0 to -30. If it is negative, then it should rotate accordingly in the opposite direction.
    But the rotation is extremely jittery. It kind of looks right, but it tweaks out all over the place.

    Any help would be super appreciated!!!

    -Chris

    Dan Ebberts replied 14 years, 3 months ago 2 Members · 5 Replies
  • 5 Replies
  • Dan Ebberts

    April 26, 2012 at 9:51 pm

    I don’t think the amount of luminance change from one frame to the next is going to have the right relationship to the angle. It seems like you could use the expression you used to find the top of the wave, but do it some distance to the left and right of the text’s position. Then with p1 and p2, you could derive the angle. Something like this (just shooting from the hip here):

    delta = p2 – p1;
    radiansToDegrees(Math.atan2(delta[1],delta[0]))

    Dan

  • Chris Mellor

    April 27, 2012 at 4:03 pm

    Thanks so much Dan! Although I am not quite sure how arctangent2 works… it works! Unfortunately these expressions are now causing AE to act really buggy. Sometimes the program crashes, but more often, I get a “Timeout while waiting for engine” error. Sounds to me like there is some kind of infinite loop problem, but I can’t imagine where.
    If someone could look over my code and give me some feedback, that would be great. Maybe there are some redundancies or simple syntax errors I am overlooking.
    Here is the code for the Position value of my word layer, remember this is one layer meant to be duplicated 500+ times:
    leader = thisComp.layer("Attractor"); // null layer

    // spacial offset from null
    seedRandom(index, true);
    offsetX = random(0,20)*thisComp.layer("Spacial Slider").effect("X")("Slider")*thisComp.layer("Spacial Slider").effect("XYZ")("Slider");
    offsetY = random(-20,20)*thisComp.layer("Spacial Slider").effect("Y")("Slider")*thisComp.layer("Spacial Slider").effect("XYZ")("Slider");
    x = leader.position[0] + offsetX*time; // the *time makes it so it is always moving, so the atan2() in the rotation expression is never dividing by 0
    y = leader.position[1] + offsetY;

    // z bump
    zMin = thisComp.layer("Wave Height Sliders").effect("zMin")("Slider");
    zMax = thisComp.layer("Wave Height Sliders").effect("zMax")("Slider");
    target = thisComp.layer("Turbulence Layer");
    samplePoint = [Math.abs(x),Math.abs(y)];
    sampleRadius = [5,5];
    rgb = target.sampleImage(samplePoint, sampleRadius);
    lum = rgbToHsl(rgb)[2];
    offsetZ = ease(lum, 0, 1, zMin, zMax)*thisComp.layer("Spacial Slider").effect("Z")("Slider");
    z = leader.position[2] + offsetZ;

    [x, y, z]

    and the zRotation expression looks like this:
    p1 = position;
    p2 = position.valueAtTime(time-thisComp.frameDuration*5);
    delta = p1-p2;

    radiansToDegrees(Math.atan2(delta[2],delta[0]))

    Does this all make sense? Is there a smarter way I could write this so AE doesn’t get confused reading it??

    -Chris

  • Dan Ebberts

    April 27, 2012 at 5:04 pm

    I wasn’t suggesting that you sample the position at the previous frame, but rather, sample the luminance a small distance to the left and right of the layer’s position (at the current frame) so you can then use Math.atan2() to calculate the slope of the wave for that layer.

    Let me ask you this–does your visible wave just consist of the text layers? If so, I think I might have a much simpler solution for you.

    Dan

  • Chris Mellor

    April 27, 2012 at 6:29 pm

    Yes, I’m simply trying to simulate a large body of water using words. I got very close with Trapcode Form by creating a plane of sprites (my words) and applying the displacement map to it to simulate the subtle waves. But Form won’t allow the words to rotate as they move along the waves so I am using these expressions instead.

    I would love to know if there is a simpler solution because all of these expressions are severely affecting AE… I am getting the timeout error almost every time I RAM preview now.

    -Chris

  • Dan Ebberts

    April 27, 2012 at 7:39 pm

    OK–play around with these. You’ll probably want to tie the variables to sliders (it’s important that they match in the two expressions).


    // *** position ***

    maxX = 300;
    maxZ = 100;
    maxY = 100;
    tMult = .25;
    xMult = .25;
    zMult = .25;

    seedRandom(index,true);
    x = random(-maxX,maxX);
    z = random(-maxZ,maxZ);
    y = maxY*noise([x*xMult,z*zMult,time*tMult]);

    value + [x,y,z]

    // *** z rotation ***

    maxX = 300;
    maxZ = 100;
    maxY = 100;
    tMult = .25;
    xMult = .25;
    zMult = .25;

    deltaX = 10;
    rMult = .15;

    seedRandom(index,true);
    x = random(-maxX,maxX);
    z = random(-maxZ,maxZ);
    y1 = maxY*noise([(x-deltaX)*xMult,z*zMult,time*tMult]);
    y2 = maxY*noise([(x+deltaX)*xMult,z*zMult,time*tMult]);

    rMult*radiansToDegrees(Math.atan2(y2-y1,2*deltaX))

    Dan

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