日本でハリウッドVFXを制作! 「経産省アイディアボックス」 結果:  
●まとめエントリはこちら ●FAQ ●お問い合わせは左のメールフォームから

2010年1月7日木曜日

メモ:radiusPP = linstep(0,lifespanPP, age);

radiusPP = linstep(0,lifespanPP, age);
各パーティクル発生後の寿命に応じて、そのパーティクル半径を変化させるエクスプレッション。
煙や泡の表現に用いられる。

●パーティクル発生後の、存在時間(年齢)によって、そのパーティクルの半径を変化させる
●サイズの変化率はlifespanPPとageの組み合わせできまる。
「age」の変化率は一定。よってサイズの変化率は「lifespanPP」に依存する。
●「linstep」によってパーティクル半径は、0~1の間におさまる。
●よって「寿命(lifespaPP)の最大値」=「パーティクル半径最大値」と考えて良い。
●「パーティクル・サイズ」を変更する物であり、動きには影響しない
●消滅する場所は、距離ではなく時間(寿命)に依存する。
●そのため消滅エリアを変更したい場合はlifespaPP(寿命)で間接的にコントロールする。
●パースペクティブやカメラ位置の変化で、パーティクルの拡散ぐあいに違いが見られる。


----------------------------------------
radiusPP:単位「cm」:working Unitに依存しない。各パーティクル個別の半径。
パーティクル単位で半径のサイズを設定します。
メタボール サーフェス、クラウド、および球体レンダー タイプに有効です。
WorkingUnitが「cm」のシーンで「radiusPP=1」の場合、直径は2グリッド分=2cmとなる。
WorkingUnitが「mm」のシーンではこれが直径が20グリッド分=2cmとなる。

----------------------------------------
linstep:
第 1 引数と第 2 引数の間の距離における、第 3 引数の割合をパーセンテージで表す。
ゼロから 1 までの浮動小数点数値が返されます。
オンラインヘルプでは上記のように、「パーセンテージで表す」となっているが、実際には小数点数であり「%」ではない。
linstep(1,3,2)の戻り値は0.5である、これは50%を意味しており、0.5%ではない。


----------------------------------------
lifespanPP:単位「」、各パーティクル個別の寿命。
パーティクルが消滅するときをパーティクル単位で秒数で設定します。float値の配列
lifespanPP = 1 :生まれてから1秒間(24フレーム)経過後に消滅。
24fpsの時、開始フレームが「0」であれば、25フレーム目で消滅

通常開始フレームは「1」なので、
開始フレームが「1」のシーンの場合、フレーム番号2でパーティクルが発生し、「2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25
の計24フレームで存在し、25フレーム目の、フレーム「26」で消滅する。
(エミッターのRateが適切で、パーティクルのスタート・フレームが1である場合)

----------------------------------------
age:単位「」。変化率は一定。
オブジェクトに含まれる各パーティクルが最初のフレーム以降存在する秒数を格納します。
これは読み取り専用アトリビュートです。

24fpsで、二つのパーティクルの「age」がフレーム毎にどう変化するか、記録してみた。
(lifespanPPは「1」に設定、またparticle Render Typeを「Numeric」にしてattributeNameを「age」に設定して表示)

1秒間が24フレームなので1フレームの秒数は、
1÷24=0.0416666.....
四捨五入すると、「約0.042秒」ということになる。

しかし、これを逆算すると0.042×24=1.008と0.008秒余る。
実際の「age」の値を見ると2フレームおきに「0.041」の増分値になっておりそれが調整されている。
これが表示されているものよりも小さな位での計算によるトータルな繰り上がりがそうなっているのか、それとも意図的に調整されているのかはわからない。

さて、これは1秒間に8回、「0.041」があるとうことになる。
(パーティクル2では発生時間が遅いため、7回までしか見えない)
3フレームごとに表れているので、24÷3=8となり、計算はあう。
また、この差は通常の「0.042秒」と較べて「0.001秒」と小さなものなので、「age」の変化は一定と結論づけて問題ないだろう。


またフレーム2で二つのパーティクルは同時に生まれているのかと思ったがそうではない。
すでに「age」が異なっており、Maya内部では、もっと細かな単位時間で計算されていることがわかる。

(*****はパーティクルが存在しないことを示す。( )内の数値は、フレーム毎の増分値。)
<パーティクル1>
1:*****
2:0.005
3:0.047(0.042)
4:0.089(0.042)
5:0.130(0.041)
6:0.172(0.042)
7:0.214(0.042)
8:0.255(0.041)
9:0.297(0.042)
10:0.339(0.042)
11:0.380(0.041)
12:0.422(0.042)
13:0.464(0.042)
14:0.505(0.041)
15:0.547(0.042)
16:0.589(0.042)
17:0.630(0.041)
18:0.672(0.042)
19:0.714(0.042)
20:0.755(0.041)
21:0.797(0.042)
22:0.839(0.042)
23:0.880(0.041)
24:0.922(0.042)
25:0.964(0.042)
26:*****

<パーティクル2>
1:*****
2:0.023
3:0.065(0.042)
4:0.106(0.041)
5:0.148(0.042)
6:0.190(0.042)
7:0.231(0.041)
8:0.273(0.042)
9:0.315(0.042)
10:0.356(0.041)
11:0.398(0.042)
12:0.440(0.042)
13:0.481(0.041)
14:0.523(0.042)
15:0.565(0.042)
16:0.606(0.041)
17:0.648(0.042)
18:0.690(0.042)
19:0.731(0.041)
20:0.773(0.042)
21:0.815(0.042)
22:0.856(0.041)
23:0.898(0.042)
24:0.940(0.042)
25:0.981(0.041)
26:*****


----------------------------------------
「lifespanPP=1」として、上記の「パーティクル1」の「age」値を使い、
冒頭のエクスプレッション「linstep(0,lifespanPP,age)」の戻り値がどう変化するかを見てみる。

1:*****
2:linstep(0,1, 0.005) =0.005
3:linstep(0,1, 0.047) =0.047
4:linstep(0,1, 0.089) =0.089
5:linstep(0,1, 0.130) =0.13
6:linstep(0,1, 0.172) =0.172
7:linstep(0,1, 0.214) =0.214
8:linstep(0,1, 0.255) =0.255
9:linstep(0,1, 0.297) =0.297
10:linstep(0,1, 0.339) =0.339
11:linstep(0,1, 0.380) =0.38
12:linstep(0,1, 0.422) =0.422
13:linstep(0,1, 0.464) =0.0.464
14:linstep(0,1, 0.505) =0.505
15:linstep(0,1, 0.547) =0.547
16:linstep(0,1, 0.589) =0.589
17:linstep(0,1, 0.630) =0.630
18:linstep(0,1, 0.672) =0.672
19:linstep(0,1, 0.714) =0.714
20:linstep(0,1, 0.755) =0.755
21:linstep(0,1, 0.797) =0.797
22:linstep(0,1, 0.839) =0.839
23:linstep(0,1, 0.880) =0.880
24:linstep(0,1, 0.922) =0.922
25:linstep(0,1, 0.964) =0.964

パーティクルの年齢(age)が25フレーム目で「0.964秒」。
26フレーム目を計算すると「1.006」秒となり、寿命(lifespanPP)の設定「1秒」を超えるため、26フレーム目では消滅する。

また冒頭のエクスプレッションでは、この値をradiusPPに当てているため、寿命に達した地点=radiusPP(半径)が「1」に達する地点ということになる。
「lifespanPP」(寿命)が大きいくなると、同一フレームでのlinstepの値=radiusPPのサイズは小さくなる。要するに変化率が下がる。

また、この半径の最大値はlinstepによって「1」に制限されているが、このlinestepの値に対してさらにエクスプレションを追加することでその制限を超えることは可能。
(例):radiusPP = linstep(0,lifespanPP, age)*2; (linstepの値を二倍にしている)


----------------------------------------
同じフレームにおいて、同時に発生したパーティクルでも、lifespanPP(寿命)が大きい場合、「radiusPP(半径)」の値は小さくなる。

上記の2フレーム目(パーティクル発生フレーム)で、lifespanPP(寿命)の違いによるradiusPPの変化は以下のようになる。
lifespanPP=1: linstep(0,1, 0.005) =0.005
lifespanPP=2: linstep(0,2, 0.005) =0.0025
lifespanPP=3: linstep(0,3, 0.005) =0.00166667
lifespanPP=4: linstep(0,4, 0.005) =0.00125
lifespanPP=5: linstep(0,5, 0.005) =0.001
lifespanPP=6: linstep(0,6, 0.005) =0.000833333
lifespanPP=7: linstep(0,7, 0.005) =0.000714286
lifespanPP=8: linstep(0,8, 0.005) =0.000625
lifespanPP=9: linstep(0,9, 0.005) =0.000555556
lifespanPP=10: linstep(0,10, 0.005) =0.0005


これは、「rand」関数を使って各パーティクルの寿命(lifespanPP)を決める場合に、どのぐらいの範囲の値を設定すれば良いかの指標となる。
lifespanPPが「10秒」のものは「1秒」のものに比較して、同じフレームでもサイズが「10分の1」。
そこまでの差を求めないのなら「rand」に設定する値の差を小さくすると良い。

lifespanPPは各パーティクルが発生後に、シーン内に存在できる時間をしめしているが、
「age」の変化率は一定であるため、パーティクル・サイズの変化率は「lifespanPP」に依存する。
●寿命が短いパーティクル==> 大きくなるのが早く。
●寿命が遅いパーティクル==> 大きくなるのが遅い。

「寿命到達=サイズが極大=「1」」であるので、一番大きなサイズに達したパーティクルは消滅する。
(サイダーの泡のような感じで、一瞬で消えていく)


----------------------------------------
検証用テストシーン
1)エミッター
rate 10, DirectionY 1,Speed 3(任意),Spread(任意)
2)パーティクルにradiusPPを追加
3)Createエクスプレッション(lifespanPPにランダムを使う場合)
radiusPP =0;
lifespanPP= rand(2,4);
4)Runtime Beforeエクスプレッション
radiusPP = linstep(0,lifespanPP,age);

エミッタの「Spread値」はいろいろ変えてみて、違いをみてみると良い。
寿命を一定にしたい場合は、「lifespaPP = 3(任意);」


<検証結果>
ライフスパン(固定):
発生源から一定の距離で、極大に達して、消滅。
エミットされる時間が1フレーム(0.042秒)以下の時間で計算されているので、消滅の場所は若干のランダムさが見られる。
スケールの変化は、ほぼ同じ
発生源が、容易に特定しやすい。(視線が導かれる)
自然界には存在しない機械的でリニアな変化
拡大するレーザー光線のようなものには向いているかもしれない。


ライフスパン(最小値「0」のランダム値)
発生源からランダムな距離で極大に達して、消滅。
発生してすぐに消滅する物もあるので、パーティクルの存在領域全体で極大に達して消滅するパーティクルが見られる。
スケールの変化は大きく異なる。
発生源は視覚的に特定しずらい。
水中から発生した泡のよう(海底火山から出て来る泡のような感じ)
慌ただしく、発生源の暴力的な感じが加わる。


ライフスパン(最小値「0」より上のランダム値):
発生源からランダムな距離で極大に達して、消滅。
発生してからライフスパン最小値に達するまでは、消滅しない。
よって、発生源から最小値に達するまでの距離は、安定感がある。
スケールの変化は、設定値により違うが、固定値のケースと較べて幅広い。
最大値に達する(消滅する)範囲をランダム値によって設定可能。
金漁鉢のぶくぶくの泡のような感じ。
若干の安定さと、ランダムさを併せ持ち、自然な感じ。その割合もある程度コントロールできる


消滅の場所に関しては、パーティクルの速度や、フィールドの影響によっても変わってくるので実際の作業においては、著しく結果が違う可能性もある。


問題点としては、このエクスプレッションの欠点というよりパーティクル自体の欠点に起因するのだが、大きな目立つパーティクルがいきなり画面から消えてしまうので、
●泡が沸き立つようなシーンならごまかせるかもしれない。
●ひとつひとつのパーティクルをじっくり見せてしまうようなシーンだと違和感が目立つ。
(そこまでこだわらない映像もしくは、それを効果として使いたい場合は大丈夫)

また肝心のコントロール性においては、
●パーティクルの消滅箇所を決めるには、パーティクルの寿命を使って間接的にコントロールするしかない。
という欠点がある。
  

0 件のコメント:

コメントを投稿