【エクスプレッション】CC Particle Worldをヌルでコントロールするあの式は何をやっているのか?

CC Particle World をヌルでコントロールする有名な式は以下の通りです。

CC Particle World/Producerの各項目へ以下のエクスプレッションを適用(ヌルは3D化しておく)。

//Position Xへ適用。
x=thisComp.layer("ヌル 1").transform.position[0]-thisComp.width/2;
x/thisComp.width;

//Position Yへ適用。
y=thisComp.layer("ヌル 1").transform.position[1]-thisComp.height/2;
y/thisComp.width;

//Position Zへ適用。
z=thisComp.layer("ヌル 1").transform.position[2];
z/thisComp.width;

*Zについては、カメラが無い場合は『*0.87』すると書いてありましたが、必要ありません(当時とはAEのカメラ仕様が変わったのかもです)。
*この式の初出はおそらくこの方が書いたブログ記事のようなんですが、現在は閉鎖されているようです。

筆者もparticularが買えなかったときや、今でもparticularが使えない環境等ではこのエクスプレッションには大変お世話になっております。このエクスプレッションを知った当初よりもエクスプレッションへの知識が上がったので、改めて、「これは何をやっているのか」を検証してみます。

*以下、CC Particle WorldをCCPWと表記。

解説

まず、「なぜヌルの値をそのまま持ってくると位置が合わないのはなぜか?」ですが、ヌルのポジションに入っている座標(AEのワールド座標)と CCPW が採用してる座標が違うからです。これをそろえてやれば、位置が合うということですね。

具体的に違うのは2つ、『原点』と『1目盛り』ですね。

結論からまとめますと、以下となります。

  • ヌルの原点は左上だが、CCPWの原点は画面中央なので、ヌルが画面中央にあるときに[0,0,0]となるような式を作る。
  • 目盛りについて、ヌルは1動くと1ピクセル動くが、CCPWは画面右端~左端までの長さを1とするので、ヌルが画面の幅分動いたら答えが1となるような式を作る(フルHDの場合はヌルが1920動いたら答えが1となる式、ということです)。

それぞれ、見ていきましょう。

■原点を揃える。

まず原点ですが、 AEのワールド座標 は原点が[0,0,0]つまり画面左上ですが、CCPWの原点はコンポの中心です。フルHD
の場合はワールド座標が[960,540,0]の場所がCCPWにとっての[0,0,0]となる、ということですね。

この両者の違いを確かめるには、CCPWのXYZ値が[0,0,0](デフォルト状態)で、画面中央からパーティクルが出現すること、しかしヌルの位置は中央にあると[0,0,0]ではなく [960,540,0]であることを比較すればよいだけですね。

まずはこれを揃える必要があり、それがエクスプレッション内のそれぞれの1行目です。
x=thisComp.layer(“ヌル 1”).transform.position[0]-thisComp.width/2;
y=thisComp.layer(“ヌル 1”).transform.position[1]-thisComp.height/2;
z=thisComp.layer(“ヌル 1”).transform.position[2];

Zについては変換しなくてもどちらもゼロで、合っているのでそのままですね。
X,Yについては同じ形なので、Xについてだけ見てみましょう。
日本語にすれば『ヌル位置ーコンポ幅の半分』です。時間によって変わるヌル位置からつねにコンポ幅の半分を引くことで、実質『コンポ幅の半分位置(コンポ中心)をゼロとしたヌル位置』が得られるというわけです。
Yについても同様にすれば、ヌルがコンポの中心にくると[0,0,0]になりますね。これで「ヌル位置の原点をCCPWの原点に揃えた」ことになります。

■1目盛りを揃える。

まとめにも書いた通り、ヌルとCCPWは1を入力すると移動する目盛りが違います。この両者の目盛りの違いを変換する必要がありますね。

まずはXについてです。ヌルは画面右端にやると1920(コンポ幅)となり、左端にやると0ですね。ただし、上記でCCPWと原点を揃えてあるので、 コンポ中央で0、右端で960(コンポ幅/2)、左端で-960ですね。
それに対して、CCPWのXは画面右端にやると0.5となり、左端にやると-0.5となります(この0.5、-0.5という値は実際にCCPWのX値を動かしてみるとわかります)。
ということは『画面右端+さらにコンポの半分距離』まで行ったら、CCPWは1、 ヌル(原点揃え済み)は1920(コンポ幅)ですね。

両者の対応する値が出たので、昔懐かしい比率の式が使えますね。変換後の値を?とすると、
?:1 = 現在のヌル値(原点揃え済み):コンポ幅
です。なので、
?×コンポ幅 =1×現在のヌル値(原点揃え済み)
?×コンポ幅 =現在のヌル値(原点揃え済み)
?=現在のヌル値(原点揃え済み)/ コンポ幅
となります。
再びXについてのエクスプレッション式を見てみると、
x=thisComp.layer(“ヌル 1”).transform.position[0]-thisComp.width/2;
x/thisComp.width;
1行目でxに『現在のヌル値(原点揃え済み)』を入れているので、
2行目は『現在のヌル値(原点揃え済み)/ コンポ幅 』となっています。?を算出しているのがわかりますね!

■Y、Zについての罠

このようにしてYとZも…と言いたいところなんですが、ここにちょっとした罠があります。
感覚としては「Xの式にはwidthを使ったからYはheight、Zには焦点距離あたりを使えばいいのかな?」と思うのですが、実際にはそうではないです。もう一度、各式の2行目を見てみましょう。
x/thisComp.width;
y/thisComp.width;
z/thisComp.width;

すべてにコンポ幅が使われていますね…。これはなんなのでしょう?
CCPWのXは画面右端で0.5、 左端で-0.5でしたね。 その感覚で「Yは画面上端が0.5、下端が-0.5かな」と思いますが、そうではないんです。実際にCCPWの値を動かしてみるとわかりますが、YもZも、『コンポ”幅”の半分の距離』まで進むと0.5、逆だと-0.5となります。XYZどれも距離の単位は「コンポ”幅”が1」なんですね。なので、XYZそれぞれの計算全てにコンポ幅を使います。

これはCCPWの仕様です。想像するに、CCPWの制作者が「めんどうだから全部幅基準でいいっしょ」となったのか「XYZで同じ数値を入れてるのに違う距離移動しちゃうのはデザイナーがわかりづらいだろうな」となったかですかね…筆者の勝手な想像です。

以上です!

*追記
openGLの透視変換を調べていたところ、「カメラ位置をXY原点として、オブジェクト位置を-0.5~0.5の間に圧縮する変換
」といったような記述がありました。どうもCCPWの座標はこのopenGLの方式に沿っているのでは?とふと思った次第です。まったく独自の仕様ではないとすると「このような座標の実装もまあ致し方ないのか」と腑に落ちやすいですね!

よかったらシェアしてね!
  • URLをコピーしました!