Adobe After Effects ユーザーのための支援ファイルセット

QE

QE+ Blog
Quick Effects plusの開発者がお届けするAfter Effectsに関するBlogです

続)ドットモーションコントロール 1(スキャンライン風)

IMAGE PHOTO

ぶらり・つぎはぎだらけのエクスプレッション紀行/
ドットモーションコントロール 1(スキャンライン風)の続編です。
メインの緑のドットの動きが完成、ドットの軌道を埋めてゆく処理にエフェクトを断念。動きで確認すれば以下まででしたね。


実は断念する前に[CC RepeTile]エフェクト(上下左右にタイリングするエフェクト)これで埋めて行けるじゃん。という展開に一瞬なったのですが。

IMAGE PHOTO

ただこのエフェクト、結果から言うとコラップスをONにした時点でエフェクトが効かないという代物でして、OFFにして使用してしまうとドットを拡大した時に甘くなってしまう難点があって、結局のところやはりエフェクト断念に行き着いた次第です。

では、白いドットレイヤーを配置させた後、Xスケールの拡大で対応させる方法しかないのか検討したところ、CS3から搭載されたシェイプレイヤーにリピーター機能という代案が浮上。ベクターシェイプをコピーして繰り返す方法なので基本的に[CC RepeTile]エフェクトと同じ感覚です。また、ベクターシェイプなので拡大処理もクリアできます。

前者(Xスケール拡大案)はアンカーポイントをドット幅の右端や左端に寄せながら[100% , 100%]→[4200% , 100%]のような数値コントロールとなり、
後者(リピーター案)はアンカーポイントはセンターのまま、コピー数を升目に合わせて[0]→[42]のような具合です。
どちらが楽な感じします? この2択。やっぱ後者ですかね。

なので、シェイプレイヤーにリピーターという方法を選択してみます。

▼ 続 STEP 01
最初は、ひと升を20 x 20 pixelsとした正確な四角いシェイプレイヤーを作成せねばなりません。
大抵はシェイプツールを直感的にドラッグして描画するので、正確なことは逆に厄介だったりします。
ルーラー表示などをさせてもアンカーポイントをセンターにした正確な20 x 20 pixelsピッタリの正方形を描くのは以外と面倒なものです。

そこで、すでに20 x 20 pixelsになっている緑のドット、
この平面レイヤーに新規マスクパスを仮に作成 →
そのマスクパスをコピー →
適当なシェイプレイヤーを作成 →
シェイプレイヤーのパスをペーストして置き換える。

こうすれば正確な20 x 20 pixelsでアンカーポイントが中央のシェイプレイヤーが作成できます。
STEP01
緑のドットの平面レイヤーを選択して【レイヤー】メニュー→【マスク】→【新規マスク】を適用、作成されたマスクから" マスクパス "プロパティを選択してコピーします。
コピー後はマスクを削除して構いません。

レイヤーを選択していない状況でペンツールを選択して適当なシェイプを描き、シェイプレイヤーを作成します。
STEP01
シェイプレイヤーの" パス "プロパティを選択してペーストすると20 x 20 pixelsの正方形パスと置き換わります。

▼ 続 STEP 02
ここからは順を追ってエクスプレッションを記述してゆきます。
一列ごとにシェイプレイヤーを分けてゆくことになるのでレイヤー名称を分かりやすく「001」と変更して、階層も下に下げておきます。
STEP02
まずは" 位置 "の求め方からです。
白いドットが一列目を埋め始めるのは、緑のドットの[X position]のスライダー に設定されている1番目のキーフレーム時間の緑のドット位置と同じです。
なので、その時の値を参照するエクスプレッション言語メニュー▶Property▶にあるvalueAtTime(t)を使い

t=thisComp.layer("G-DOT").effect("X position")("スライダー").key(1).time;
thisComp.layer("G-DOT").transform.position.valueAtTime(t)


と記述します。
" スケール "は緑のドットのスケールと同じになるようピックウィップでドラッグ&ドロップします。

thisComp.layer("G-DOT").transform.scale

次いで" 不透明度 "です。
現状設定では0フレから緑のドットが動き出すキーフレームが設定されているので、最背面でもある白いドットの" 不透明度 "は最初から100%のままで良い訳ですが、
仮に緑のドットの動きだしのタイミングが後ろにずれて、白いドットを消しておきたいことがあるやもしれません。
さらにこのレイヤーは2列目に移る際に複製して使い回します。
この2列目では折り返す15フレームが来るまで消えていなければなりません。ということもあって、あえてエクスプレッションを使います。

そして、この時間が来たら〜というような条件付の記述には、
if 構文
  if (time > t){
      数値AやメゾッドA;
  }else{
      数値BやメゾッドB;
  }
を使います。
分かりやすく解釈すれば
現在の時間がtの指定時間を過ぎたら〜数値Aやメゾッド(命令)Aをなさい!
現在の時間がtを過ぎる以外は〜数値Bやメゾッド(命令)Bでいなさい!
というような具合です。 なので、ここでは

t=thisComp.layer("G-DOT").effect("X position")("スライダー").key(2).time;
  if (time > t) {
     100;
  }else{
     0;
  }


というように記述します。

続けて、白いドットのシェイプレイヤーのコンテンツの追加から" リピーター "を追加します。
追加された" リピーター 1 "の" コピー数 "と" トランスフォーム:リピーター 1 "にある" 位置 "にエクスプレッションを記述します。
※レイヤーが元々持っているトランスフォームの" 位置 "ではありませんので、ご注意を。
STEP02
まずは " トランスフォーム:リピーター 1 "の" 位置 "です。
この位置はコピー複製する間隔です。この部分に限って言えばシェイプレイヤーが拡大した場合でもその比率を保つようなので、単純に緑のドット幅に合わせる
w=thisComp.layer("G-DOT").width;
[w,0]

だけでOKです。

そして何やら長くなってしまっている" コピー数 "です。
ここでは

s=thisComp.layer("G-DOT").transform.scale[0]/100;
w=thisComp.layer("G-DOT").width*s;
t1=thisComp.layer("G-DOT").effect("X position")("スライダー").key(1).time;
t2=thisComp.layer("G-DOT").effect("X position")("スライダー").key(3).time;
v1=thisComp.layer("G-DOT").effect("X position")("スライダー")/w;
v2=thisComp.layer("G-DOT").effect("X position")("スライダー").key(3).value/w;
  if ((time > t1) && (time < t2)){
      v1;
  }else{
     v2+1;
  }


のように記述しています。頭にある

s=thisComp.layer("G-DOT").transform.scale[0]/100;
w=thisComp.layer("G-DOT").width*s;
t1=thisComp.layer("G-DOT").effect("X position")("スライダー").key(1).time;
t2=thisComp.layer("G-DOT").effect("X position")("スライダー").key(3).time;
v1=thisComp.layer("G-DOT").effect("X position")("スライダー")/w;
v2=thisComp.layer("G-DOT").effect("X position")("スライダー").key(3).value/w;

ですが、演算式に必要な要素を代用したものです。
上から順に解いてまとめると

s=緑のドットのXスケールから100で割った値
w=スケール調整された緑のドット幅
t1=緑のドットの[X position]スライダーの1番目のキーフレーム時間
t2=緑のドットの[X position]スライダーの3番目のキーフレーム時間
v1=現在の時間の緑のドットの[X position]スライダー値、割るドット幅の値
v2=緑のドットの[X position]スライダーの3番目のキーフレーム値、割るドット幅の値

です。以降、このような複文を連発しますが、この部分は割愛します。

その下のif 構文です。
列の升目を埋めるコピー作業は緑のドットの移動に伴ってアニメートした後、右端に到達した時点で列を埋め尽くす数で留まっていなくてはなりません。
しかし緑のドットは一列目以降も動き続けますので、この時間でステイなさい。という2つの条件が必要になってくる訳です。
ひとつは、現在の時間がt1を過ぎたら〜v1にしないさい!

ふたつめは、現在の時間がt2を過ぎたら〜v2でいなさい!
が以下の部分になります。
 if ((time > t1) && (time < t2)){
      v1;
  }else{
     v2+1;
  }

ひとまず、これで一列目の升目を埋めるシェイプレイヤーができます。プレビューしてみてください。

▼ 続 STEP 03
では、2列目に移ります。
白いドットのシェイプレイヤー「001」を複製して「002」を作成します。
もし「001」を複製したレイヤー名称が「001 2」となるようなら数字の前に半角スペースを入れ「 001」にすると、以降の複製で自動的に「 002」「 003」「 004」となります。
名前なんてどうだっていいじゃん。
と思われますが、これが後に大事なポイントになります。

複製した「 002」に記述されているエクスプレッションを順に書き換えてゆきます。
「 002」のレイヤーを選択してキーボードのEを2回、プッシュするとレイヤーにあるすべてのエクスプレッションを表示させるショートカットになります。
STEP03
下から順番に調整します。
以降、変更する部分と変更した後をオレンジ文字で表記します。
まずは、" 不透明度 "です。既存のエクスプレッション

t=thisComp.layer("G-DOT").effect("X position")("スライダー").key(2).time;
  if (time > t) {
     100;
  }else{
     0;
  }

を、

t=thisComp.layer("G-DOT").effect("X position")("スライダー").key(4).time;
  if (time > t) {
     100;
  }else{
     0;
  }

と、4番目のキーフレームで登場するように変更。
" スケール "は変更なしで、
次に" 位置 "です。既存のエクスプレッション

t=thisComp.layer("G-DOT").effect("X position")("スライダー").key(1).time;
thisComp.layer("G-DOT").transform.position.valueAtTime(t)

を、こちらも4番目のキーフレームを参照するよう

t=thisComp.layer("G-DOT").effect("X position")("スライダー").key(4).time;
thisComp.layer("G-DOT").transform.position.valueAtTime(t)

とします。
続いて" トランスフォーム:リピーター 1 "の" 位置 "です。
これは

w=thisComp.layer("G-DOT").width;
[-w,0]

と、逆方向のマイナス値にするだけです。
そして肝心のリピーターの" コピー数 "ですが、
こちらは、ほぼ前面見直しなので変更後の記述のみをオレンジ表記にしています。

s=thisComp.layer("G-DOT").transform.scale[0]/100;
w=thisComp.layer("G-DOT").width*s;
h=thisComp.layer("G-DOT").height*s;
t=thisComp.layer("G-DOT").effect("X position")("スライダー").key(4).time;
v1=thisComp.layer("G-DOT").effect("X position")("スライダー")/w;
v2=thisComp.layer("G-DOT").effect("X position")("スライダー").key(3).value/w;
v3=thisComp.layer("G-DOT").effect("Y position")("スライダー");
n=Number(thisLayer.name);
  if ((time > t) && (v3 < h*n)){
      v2-v1;
  }else{
     v2+1;
  }


この中に
n=Number(thisLayer.name);
という記述があります。これはレイヤー名称の数字を数値として置き換え、演算式に組み込んでいます。このNumber()は数字以外のテキストは扱えません。

このレイヤー名称の「002」を" 2 "として処理している理由ですが、if 構文の中の
(v3 < h*n)
は" Y position "スライダー値が2列目の数値になったら〜という2列目の2を定義しています。
こうしておくと、レイヤー名称の「003」は3列目、「004」は4列目というように複製の度に自動化できるからです。
お〜ナイス。
2列目はこれで完了です。プレビューしてみてください。

▼ 続 STEP 04
続いて3列目です。
その前に一体いつまで書き換えるのかという疑問ですが、
3列目の「 003」は以降の奇数列ですべて同じレイヤーで処理できます。
そして偶数列は「 004」を調整すれば、後はコピー天国が待っています。
よって、後「 003」と「 004」の2つの書き換えのみです。
3列目は奇数列なので「 001」の複製から、「 004」は偶数列なので「 002」の複製から書き換えるとよいでしょう。
以降スピードアップによりエクスプレッションだけ表記します。
STEP04
「 003」レイヤー
" リピーター 1 "の" コピー数 "
s=thisComp.layer("G-DOT").transform.scale[0]/100;
w=thisComp.layer("G-DOT").width*s;
t=thisComp.layer("G-DOT").effect("X position")("スライダー").key(4).time;
v1=thisComp.layer("G-DOT").effect("X position")("スライダー")/w;
v2=thisComp.layer("G-DOT").effect("X position")("スライダー").key(3).value/w;
n=Number(thisLayer.name);
  if ((time > t*(n-1)) && (time < t*n)){
      v1;
  }else{
     v2+1;
  }


" トランスフォーム:リピーター 1 "の" 位置 "
w=thisComp.layer("G-DOT").width;
[w,0]

" 位置 "
t=thisComp.layer("G-DOT").effect("X position")("スライダー").key(4).time;
n=Number(thisLayer.name);
thisComp.layer("G-DOT").transform.position.valueAtTime(t*(n-1))


" スケール "
thisComp.layer("G-DOT").transform.scale

" 不透明度 "
t=thisComp.layer("G-DOT").effect("X position")("スライダー").key(4).time;
n=Number(thisLayer.name);
 if (time > t*(n-1)){
    100;
  }else{
    0;
  }


STEP03
「 004」レイヤー
" リピーター 1 "の" コピー数 "
s=thisComp.layer("G-DOT").transform.scale[0]/100;
w=thisComp.layer("G-DOT").width*s;
h=thisComp.layer("G-DOT").height*s;
t=thisComp.layer("G-DOT").effect("X position")("スライダー").key(4).time;
v1=thisComp.layer("G-DOT").effect("X position")("スライダー")/w;
v2=thisComp.layer("G-DOT").effect("X position")("スライダー").key(3).value/w;
v3=thisComp.layer("G-DOT").effect("Y position")("スライダー");
n=Number(thisLayer.name);
  if ((time > t) && (v3 < h*n)){
      v2-v1;
  }else{
     v2+1;
  }


" トランスフォーム:リピーター 1 "の" 位置 "
w=thisComp.layer("G-DOT").width;
[-w,0]


" 位置 "
t=thisComp.layer("G-DOT").effect("X position")("スライダー").key(4).time;
n=Number(thisLayer.name);
thisComp.layer("G-DOT").transform.position.valueAtTime(t*(n-1))


" スケール "
thisComp.layer("G-DOT").transform.scale

" 不透明度 "
t=thisComp.layer("G-DOT").effect("X position")("スライダー").key(4).time;
n=Number(thisLayer.name);
  if (time > t*(n-1)) {
     100;
  }else{
     0;
  }

▼ 続 STEP 05
さて、レイヤー「 003」と「 004」のエクスプレッションが完了したので、後はコピー天国です。
レイヤー「 003」と「 004」選択して升目が埋まるまで複製し続けます。
ここでは「 009」ですべて埋まります。
升目が埋まりきったら、レイヤーを順に並び替え、ほぼできあがりのようなものです。
プレビューしてみてください。
STEP05

▼ 続 STEP 06
最後に白いドットが升目を埋めてゆくレイヤーのみを多目的にマスク処理できるように整えます。こちらの調整もいちを書きますが、ここからは各ユーザーで自由に整えて下さい。読み飛ばしても構いません。

ここでは、スキャンライン風ドットモーションを作成したコンポジションが仮に「コンポ 1」ならプロジェクトパネルで「コンポ 1」を複製して「コンポ 2」を作成します。

複製した「コンポ 2」のタイムラインではグリッドレイヤー「Grid layer」を一番上に配置した後、[グリッド]エフェクト内の不透明度を100%に設定、緑のドット「G-DOT」レイヤーを不可視にします。「Grid layer」の描画モードを" シルエットアルファ "に設定するとグリッドラインの部分を透明に抜けるように設定できます。
STEP06
そして「コンポ 1」では「 001」から「 009」までの白いドットのシェイプレイヤーをすべて削除します。
STEP06
「コンポ 2」のタイムラインを分離してフロー状態にするか、タイムラインを2段にするなどして「コンポ 1」と「コンポ 2」を同時に表示できるよう並び替えます。
「コンポ 1」の緑のドットレイヤーに適用している[X position][Y position][scale]の3つの[スライダー]エフェクトをすべて削除して、" 位置 "と" スケール "のエクスプレッションを「コンポ 2」の緑のドットレイヤーの同じプロパティにピックウィップでドラッグ&ドロップします。
(※[スライダー]エフェクトを削除した時にエラーが出ますが、無視してください。)

これで「コンポ 1」にある緑のドットレイヤーは「コンポ 2」の緑のドットレイヤーとシンクロします。
STEP06
あとは「コンポ 1」のタイムラインにプロジェクトパネルから「コンポ 2」レイヤーを配置すれば、長かった着地点の完成です。ただドットモーションのタイミングは「コンポ 2」でコントロールすることになってしまいますが、まぁ、いいしょ。
STEP06


日時: 2011年02月28日 14:20