ラベル After Effects の投稿を表示しています。 すべての投稿を表示
ラベル After Effects の投稿を表示しています。 すべての投稿を表示

2008/02/13

After Effectsのエクスプレッションでパーティクルを表現する-03

お久しぶりです。それではAfter Effectsのエクスプレッションでパーティクルを表現する記事の第三回目です。今回は今までの知識を応用しつつ、もうすこしパーティクルの挙動を複雑にしていきます。途中で少し数式が出てきますがそんな難しくないんで大丈夫だと思います。(クリックで動画再生)

前回より少し複雑な運動にしてみました。それではこのような表現をExpressionでつけていきます。このプロジェクトのデータはこちらからダウンロードできます。

基本的な考え方

基本的な考えは前回と同様です。ただ今回はパーティクルの動きを複雑化するために、少し数学の力を借りることにします。

今回は曲線が中央から飛び出すような表現にしたかったので、パーティクルの動きを二次元の極座標として考えて、運動を記述することにしました。画面中央を原点とすると、パーティクルの位置ベクトルxは、

math01

math02

で考えると都合がよさそうです。ですがべつにこれといって根拠があるわけではないので、そこは各々が適当にやればいいような気がします。後はこのkr,Cr,θ0,Cθの値を各インデックスごとにランダムにしてやればうまくいきそうです。

しかし様々な曲線が飛び交うようにするには、Cθの値をある程度極端にしなければなりません。ただCθを、例えば-10 < Cθ < 10として、その値を一様な乱数で決定してしまうと、Cθ ~ 0、つまり直線も曲線と同じ割合で作られてしまいます。それはできるだけ避けたかったので、今回は練習がてら「確率密度関数」を始めに定義して、その確率分布に従う乱数を生成するようにしました。

確率密度関数

今回はCθ~0の部分をなるべく作らないように、確率密度関数f(x)を

math03

として定義しました。

math04

(イメージとしてはこんな感じ)

今回はこの確率密度関数f(x)を用いて、Cθを作ることにします。

それではエクスプレッションを記述します。nullを作成。レイヤー名を"system"とし、スケールにアニメーションを打ち、パーティクルの名前を"c_01"とします。そしてパーティクルの位置とスケールのエクスプレッションに以下を記述します。

位置のエクスプレッション



var system = thisComp.layer("system");
var rate = thisComp.layer("system").effect("レート")("スライダ");
var seed = thisComp.layer("system").effect("シード")("スライダ");
var centre = thisComp.layer("system").position;
var varR = thisComp.layer("system").effect("半径のヴァリエーション")("スライダ");
var VR = thisComp.layer("system").effect("半径速度")("スライダ");
var varVR = thisComp.layer("system").effect("半径速度のヴァリエーション")("スライダ");
var kr = thisComp.layer("system").effect("半径変位量")("スライダ");
var ktheta = thisComp.layer("system").effect("角度変位量")("スライダ");

/*--------Expression記述-----------*/
var index = name.slice(2,4)-1;
seedRandom( seed+index ,true );
var otime = time - index/rate;
var t;
if(otime > 0){
t = otime;
}else{
t = 0;
}

//運動式の記述
var r = random(kr-varR, kr+varR)*Math.log( random(VR-varVR,VR+varVR)*t + 1);
var theta = random(6.283) + RZRandom(ktheta)*t;

var pos = [r*Math.cos(theta),r*Math.sin(theta)];

centre + pos;

//棄却法を用いて確率分布を作成。
function RZRandom(alpha){
var x,y;
while(1){
x = random(-alpha, alpha);
y = random(0, alpha);
if( Math.abs(x) > y ){
return x;
}
}
}

確率密度関数のところは棄却法を用いました。


スケールのエクスプレッション


var system = thisComp.layer("system");

var rate = thisComp.layer("system").effect("レート")("スライダ");
var seed = thisComp.layer("system").effect("シード")("スライダ");
var variation = thisComp.layer("system").effect("スケールのヴァリエーション")("スライダ");

/*----------Expression開始------------*/
var index = name.slice(2,4)-1;
seedRandom( seed+index,true );

random(1-variation, 1+variation)*system.scale.value_at_time( time - index/rate );


particle03SS
プロジェクトのスクリーンショット。



最後にエコーとグローを加え、タイムリマップで強調させて完成です。レンダリングは正直かなり重いですが、それでもパーティクルのレートや速度、その変化量まで柔軟に変更できるという点が便利かと。

2007/10/25

After Effectsのエクスプレッションでパーティクルを表現する-02

それではAfter Effectsのエクスプレッション(Expression)でパーティクルを表現する記事の第二回目です。前回はあまり面白くない動画となってしまったので、少し手を加えてみることにしました。(クリックで動画再生)

aeexp02

このように星が外側に流れていく表現をエクスプレッションでつけていきます。今回のプロジェクトデータはこちらからダウンロードできます。

基本的な考え方

基本的な考えは前回と変わらず、

  1. レイヤーの名前を利用してインデックスを指定し、
  2. インデックスを利用してアニメートする時間を決定
する流れとなります。ただし今回は出現位置がエミッタによって決まるのではなく、半径Rの円内部でランダムに出現させるようにするところと、パーティクルが外側に移動していくところが異なっています。

random()メソッドについて

今回重要となるのがrandom()メソッドについてです。random()メソッドは文字通り0~1のランダムな値を返すメソッドで、AEのエクスプレッションでは非常によく使われる関数です。ただ、このまま使用してしまうと1フレームごとに異なる値が帰ってきてしまいます。通常の使用用途でしたらこれでいいのですが、今回は時間で変わることのない値を返してほしいので、random()メソッドの前にseedRandom()関数を記述します。

seedRandom(offset,timeless)関数は乱数シード値を変更するメソッドです。offsetにはシードの値、timelessにはrandom()メソッドの乱数シード値に時間を使用するかを記述します。通常ではtimeless=falseとなっていますが、今回はtrueにしてrandom()メソッドを時間に依存しないようにしました。

エクスプレッション

それではエクスプレッションを記述していきます。nullを作成しスケールに0→100→0%となるようにキーフレームを打ち、パーティクルの名前を"s_01"とします。そしてパーティクルの位置とスケールのエクスプレッションに以下を記述します。

位置のエクスプレッション


var centre = [320,240]; //中心点
var radius = 209; //半径
var seed = 10; //シード
var rate = 28; //一秒間に何回パーティクルが出現するか
var vel = 1; //速度比例定数

/************Expression開始*************/
var num = name.slice(2,4)-1;
seedRandom( seed+num,true );

//初期位置に関する記述
var r = random(radius);
var theta = random(6.283);
var pos = new Array( r*Math.cos(theta),r*Math.sin(theta) );

//移動に関する記述
var t_start = num/rate; var transfer;
if(time < t_start){
transfer = new Array(0,0);
}else{
transfer = mul( pos , vel*(time - t_start) );
}

//最終位置の決定
centre + pos + transfer;

スケールのエクスプレッション


var rate = 28; //一秒間に何回パーティクルが出現するか
var num = name.slice(2,4)-1;
thisComp.layer("null").scale.value_at_time( time - num/rate );


スクリーンショットは上をクリック。


もちろん最初の変数は変更しやすくするために、nullにエクスプレッション制御のエフェクトを追加して指定させてあげたほうが使いやすいと思います。


その後にCtrl+dキーを使ってパーティクルを大量に複製させ、グロー処理を行ったりとかの味付けをして完成です。背景の星空はフラクタルノイズを使用しました。よーく見ると背景もアニメーションしているのが分かるはずです。


ただ正直この程度だったらエクスプレッションを使用せずにパーティクルエフェクトを使用したほうが現実的ですね。一応半径を変形できたり後に動きを柔軟につけられるとか利点はあるんですけど。次回はエクスプレッションならではのアニメーションをさせてみます。


補足説明


AfterEffectsはベクトル関係のメソッドが充実しています。小さな三角形をクリックして、"Vector Math"を調べると加算、減算、スカラー倍、内積、外積、単位ベクトル化など大体のベクトル演算が揃っていることがわかります。ちなみにこのメソッドを使わなくても、


  • 加算:vec1 + vec2

  • 減算:vec1 - vec2

  • スカラー倍:k*vec1


程度だったらわざわざメソッドで処理しなくてもきちんと認識してくれます。もちろん"vec1*vec2"のようなものはエラーになります。

2007/10/15

After Effectsのエクスプレッションでパーティクルを表現する-01

最近はニコニコ動画とかYoutubeの登場によって、After Effectsを利用して映像を製作する人が増えているような気がします。しかしAfter Effectsを解説している日本のサイトは数えられるほど少なく、またその中でエクスプレッションの説明をしているサイトなんていうともうほとんどありません(なんか前もおんなじこと書いたような気がする) というわけでこれからAfter Effectsのエクスプレッション(Expression)の情報を載せていきたいと思います。よくある入門的な記事じゃなく、即戦力になる実用的な使い方を紹介していくつもりです。興味のある人は検索からたどりつくでしょう。たぶん :(

エクスプレッションを使用して似非パーティクルシステムを作る。

After Effectsには一応標準でパーティクルプレイグラウンドという、パーティクルを発生させるエフェクトがあったりするんですけど正直使い勝手はあまりよくありません。そこで今回はエクスプレッションを利用してエミットからパーティクルを放出させるエフェクトを作ってみることにします。

参考にしたサイト

水玉映像・・・基本的な考え方はこのサイトを参考にさせていただきました。ホント勉強になります。感謝。

エクスプレッションを使うメリット
  1. パーティクルの一つ一つに複雑な動きや統一的な動きをつけられる(これが一番大きいです。微調整もしやすいですし、数十個のフッテージを一括して調整できます)
  2. 処理が基本的に軽い。(せいぜい数十個のレイヤーしか扱いませんし)
  3. 手作業でやらなければいけないアニメート作業がエクスプレッションを使用することである程度軽減される
デメリット
  1. いちいちエクスプレッションを書かないといけない
  2. 数百個とか莫大な数のフッテージは処理できない
  3. 数式やプログラムに拒絶反応を示す人は苦手かも
ってなかんじです。パーティクルとまではいかないけど数十個のフッテージの動きを統一させたいなんて場合には使えると思います。

螺旋を描く星群を作る


今回作る動画は次のような感じです。(クリックで動画再生)

モーショングラフィックス的には面白くない動画ですけど、始めはこんなんからやっていきます。
今回使用したプロジェクトデータはこちらからダウンロードできます。

エミッタの動きを作る


それではまずパーティクルの発生源であるエミッタの動きをエクスプレッションでつけていきます。
「レイヤー→新規→ヌルオブジェクト」を選択してヌルオブジェクトを作ります。レイヤー名を"null"にして位置のストップウォッチをAlt + クリック。螺旋の動きをエクスプレッションにて記述していきます。
螺旋の動きを表すベクトルP(t)は

P(t) = ( r(t)cosωt , r(t)sinωt ) , r(t) = R - kt (R,k,ωは定数)

で表現できるので、エクスプレッションは

 
//初期化宣言
var R = 230; //最大半径
var k = -80; //減衰量
var omega = 10; //角速度(rad/s)
var alpha = -1; //開始角度(rad)

//Expression開始。
var r = R + k*time;

if( r < 0){
r = 0;
}

var pos = new Array( r*Math.cos( omega*time + alpha ),
r*Math.sin( omega*time + alpha ));

position + pos;

となります。これで螺旋の動きをつけることができました。

パーティクルを作る


それではパーティクルの製作に取り掛かりたいと思います。制作方法は大まかに


  1. フッテージ(パーティクル)がどの場所で現れるのかエクスプレッションで記述。レイヤー名を"なんたら01"みたいな感じにすることで、複製させたときに01,02,03...と各フッテージにインデックスがつけられるようにする。

  2. エクスプレッションでレイヤー名から自分のインデックスだけを切り出して、適切な場所に配置。

  3. スケールや回転などのアニメーションさせたいプロパティは"null"にアニメーションを記述し、エクスプレッションで参照させることによって一括管理する。



となっています。文章で説明するよりもスクリーンショットを見てもらったほうが早いです。(クリックで拡大)



このエクスプレッションで重要なメソッドとプロパティは以下のようになります。

  • name.slice(val1,val2)
    nameプロパティは自身のレイヤー名を表すプロパティで、slice(val1,val2)メソッドはval1を開始位置、val2を終了位置として文字列を抜き出すメソッドです。この場合は"s_50"という文字列から50が抜き出されることとなります。

  • value_at_time(time)
    特定のプロパティの、任意の時間での値を返します。たとえばposition.value_at_time(1)でしたら1秒の時点での位置情報を返しますし、scale.value_at_time(2)でしたら2秒の時点でのスケールの値を返します。
    ただし注意しなければいけないのが、「value_at_timeメソッドは、エクスプレッションで記述された値を返さない」 ということです。value_at_timeメソッドが返す値はあくまでキーフレームの値であり、エクスプレッションは無視されます。

それではオブジェクトの位置を決定し、スケールをアニメートさせるために、位置とスケールのエクスプレッションを記述します。
パーティクルの表現に重要となるのはインデックスの値です。"s_○○"の○○の値によって、自身が出現するべき時間と位置を決定させます。

位置のエクスプレッション
 
var num = name.slice(2,4)-1;
thisComp.layer("null").position.value_at_time( num *
thisComp.layer("null").effect("比例定数")("スライダ"));

スケールのエクスプレッション
 
var num = name.slice(2,4)-1;
scale = thisComp.layer("null").scale.value_at_time(time -
num*thisComp.layer("null").effect("比例定数")("スライダ"));

とりあえず今回のプロジェクトデータを参照すれば、ある程度分かるかと思います。
今回はとりあえず軽めにいきました。次から少し応用に入っていきます。