I wrote a better expression in case the boat layer reaches the edge of the composition. I suggest precomping the boat and water layer in a 2x wide comp to animate the boat across a full comp otherwise the expression won’t work past the edge of the main comp. I hope that makes sense:
Final position expression:
target = thisComp.layer("Controller").effect("Boat")("Layer");
targetWorldPos = target.toWorld(target.anchorPoint);
sample = thisComp.layer("Controller").effect("Ocean")("Layer");
for (i = 0; i < height; i++){
if (sample.sampleImage([clamp(targetWorldPos[0],0,thisComp.width), i], [0.5, 0.5], true)[3] > 0){
top = [0,i];
break;
} else {
top = [0,thisComp.height];
}
}
newWorldPos = target.fromWorld(target.toWorld(top));
[value[0],newWorldPos[1]]
To be able to rock the boat:
Final rotation expression:
target = thisComp.layer("Controller").effect("Boat")("Layer");
targetWorldPos = target.toWorld(target.anchorPoint);
sample = thisComp.layer("Controller").effect("Ocean")("Layer");
offset = -10;
for (i = 0; i < height; i++){
if (sample.sampleImage([clamp(targetWorldPos[0]+offset,0,thisComp.width), i], [0.5, 0.5], true)[3] > 0){
top = [0,i];
break;
} else {
top = [0,thisComp.height];
}
}
newWorldPos = target.fromWorld(target.toWorld(top));
offsetPos = [target.position[0]+offset,newWorldPos[1]];
for (i = 0; i < height; i++){
if (sample.sampleImage([clamp(targetWorldPos[0],0,thisComp.width), i], [0.5, 0.5], true)[3] > 0){
top = [0,i];
break;
} else {
top = [0,thisComp.height];
}
}
targetWorldPos = target.fromWorld(target.toWorld(top));
boatPos = [target.position[0],targetWorldPos[1]];
radians = Math.atan2(boatPos[1] - offsetPos[1],boatPos[0] - offsetPos[0]);
radiansToDegrees(radians);
This is going to be really slow to calculate. You should bake all of these expressions. Then after you bake the rotation put this expression on it otherwise it will be really choppy:
Final baked rotation expression:
smooth(.5,10)
Dan Fredley