PF を使い、ジオメトリの影を Cube 状に表現する
では、実際に PF でジオメトリの影を Cube 状にしてみましょう。以下のような手順で処理していきます。
<1>パーティクルを発生させる
<2>パーティクルを格子状に配置する
<3>配置したパーティクルのうち、影になっていない部分を削除する
<4>表示
<5>全パーティクルを削除
この、<1>〜<5>を毎フレーム繰り返せば、前回のサンプルムービー(下)のような映像表現が行えるようになります。実際にはもっと効率的だったり、賢いアルゴリズムはたくさんあるのですが、毎回作って消すというのが最もシンプルだったので、今回はこの手法を採用しました。それでは、その手順を具体的に解説していきましょう。
これより解説していく、MAXScript で PF を制御したサンプルムービー
前半:パーティクルを格子状に配置
まず最初に、インテグレーションステップを 1 フレームに設定します。今回の方法では、1 フレームに一度だけ計算を行えば良いためです。準備ができたらパーティクルを格子状に配置します。今回は<1>と<2>をまとめて Birth スクリプトオペレータで行いました。
----Birth Script----
on ChannelsUsed pCont do(
pCont.useAge = true
pCont.usePosition = true
)
on Init pCont do (
)
on Proceed pCont do (
cubeSize=5
mapSize = 200
for i in -mapSize/2 to mapSize/2 by cubeSize do (
for j in -mapSize/2 to mapSize/2 by cubeSize do (
pCont.AddParticle()
pCont.particleIndex = pCont.NumParticles()
pCont.particleAge = 0
pCont.particlePosition = [i, j, 0]
)
)
)
on Release pCont do (
)
----
ChannelsUsed や Processed 、 Release は「ハンドラ」と呼ばれ、中身は関数と同じように定義します。関数と違うのは、それぞれのハンドラは PF のイベントの中で呼ばれるという事です。ChannelsUsed ハンドラは、オペレータ内でどのようなパラメータが使用されるかを PF に知らせます。
on ChannelsUsed pCont do(
pCont.useAge = true ← エージ チャンネルを有効にします
pCont.usePosition = true ← 位置チャンネルを有効にします
)
これはほとんど、"おまじない"と同じで「こんなものなんだ」程度に軽く覚えてもらえば十分です。そして、次の Processed ハンドラがこのスクリプトオペレータの本体になります。
on Proceed pCont do (
distance=5
mapSize = 200
for i in -mapSize/2 to mapSize/2 by distance do (
for j in -mapSize/2 to mapSize/2 by distance do (
pCont.AddParticle()
pCont.particleIndex = pCont.NumParticles()
pCont.particleAge = 0
pCont.particlePosition = [i, j, 0]
)
)
)
Processed の引数の pCont は PF から渡される、パーティクル情報を管理しているコンテナです。pCont という名前の籠の中に、パーティクルが入っている状態をイメージしてください。
distance や mapSize という変数を決めた後、i と j の二重ループが回ります。ここはもう、慣れた形ですね。このループの中では、i 、j 共に -mapSize/2〜mapSize/2 までの値を順に取って、 pCont.particlePosition = [i, j, 0] でパーティクルの位置として使用しています。つまり、縦横 mapSize の範囲に、間隔 distance 置きにパーティクルを配置しています。それでは、j のループの中をより詳しく見てみましょう。
pCont.AddParticle()
AddParticle() で、コンテナ pCont にパーティクルを追加します。これが、ステップ 1 のパーティクルの発生です。
pCont.particleIndex = pCont.NumParticles()
これから操作するパーティクルを指定します。パーティクルは追加された順番に 1、2、3......と、番号が振られていくので直前に追加されたパーティクルを指定する場合は pCont に含まれているパーティクルの数を指定します。
pCont.particleAge = 0
パーティクルエージを 0 に指定します。この値は、タイムラインが進むにつれて自動的に加算されていきます。
pCont.particlePosition = [i, j, 0]
その上で、パーティクルの位置を指定します。 i,j は、先ほど説明した通りです。全ループが終わると、200×200 ユニット(デフォルトの単位はインチ)範囲のグリッド状に配置されることになります。この時の状態を表示してみましょう。Send Out をオフにして、Display を Event 001 に追加すると、Birth Script の結果を確認することができます。
Display(赤マル)を Event 001 に追加すると、Birst Script の結果が確認できる