チュートリアル -ParticleFlow のパーティクル モーションのシーン オブジェクトへの転送
この簡単なチュートリアルでは、パーティクル フローを使用してシーン オブジェクトを動かす方法の基本について説明します。オブジェクトは、ライトからヘルパーおよびメッシュ
オブジェクトまであらゆるオブジェクトが対象になります。
この例では、ファイヤ効果を割り当てた大量の周囲効果ギズモを動かして、ティーポットが湯気を立てる様子をシミュレートします。
全体の流れ - 設定
|
[作成](Create)パネルの[ヘルパー](Helpers) > [環境効果の装置](Atmospheric Apparatus) > [球体ギズモ](Sphere
Gizmo)に移動します。
|
任意の半径を持った SphereGizmo01 というオブジェクトを 1 つ作成します。
|
Shift-移動コマンドを使用して 29 と入力し、球体ギズモのコピー(インスタンスではありません)を 30 作成します。
|
[発生](Birth)オペレータを使用して開始フレームから終了フレームまで 20.0 のレートでパーティクル を生成する パーティクル フローを作成します。
|
Speed オペレータを使用して、パーティクルを加速させます。多少の変動を与え、よりランダムな感じを出します。
|
表示をジオメトリに設定します。
|
[エージ テスト](Age Test)を追加し、50 フレームを過ぎたらパーティクルを消滅させます。別のイベントの Delete オペレータにワイヤリングします。
|
さらに動きを出す場合は、フォースと風を追加します。
|
シーンが完璧に動作するように、[環境](Environment)ダイアログ ボックスで[火の効果](Fire Effect)を指定し、30 の球体ギズモすべてを割り当てます。思い通りの結果になるように、カラーの設定や密度などをいろいろ試してみます。
|
ティーポットを作成し、パーティクル フローを注ぎ口に位置づけて、蒸気が正しい場所から出るようにします。
|
[スクリプト オペレータ](Script Operator)コード:
|
on ChannelsUsed pCont do
(
pCont.useTM = true
pCont.useAge = true
)
on Init pCont do
(
global My_Atmospheric_Gizmos_01 = $SphereGizmo*
My_Atmospheric_Gizmos_01.pos = [0,0,-100000]
)
on Proceed pCont do
(
partcount = pCont.NumParticles()
count = amin #(partcount, My_Atmospheric_Gizmos_01.count)
for i in 1 to count do
(
pCont.particleIndex = i
My_Atmospheric_Gizmos_01[i].transform = pCont.ParticleTM
My_Atmospheric_Gizmos_01[i].radius = 10 + pCont.ParticleAge*2
)
)
on Release pCont do ( )
|
結果:
|
ステップごとの解説
on ChannelsUsed pCont do
(
ChannelsUsed ハンドラは、[スクリプト オペレータ](Script Operator)が使用するチャネルを定義します。アクセスする必要のあるプロパティを指定せずに、パーティクル
コンテナからパーティクル関連の値を取得したり、設定することはできません。このように、パーティクル フローは、[スクリプト オペレータ](Script Operator)にすべてのチャネルを与える必要はなく(パーティクル
フローには任意の数のチャネルが存在します)、実際に必要となるチャネルだけを与えます。これによりメモリが節約されます。
パラメータ pCont には、パーティクル コンテナが含まれます。
パーティクルからシーン オブジェクトへの変換をすべてコピーしたいので、そのチャネルに対するアクセスが必要になります。
さらによい結果を得るためには、パーティクルのエージを読み取ってギズモの半径プロパティに割り当て、時間の経過に伴いギズモが拡大するようにします。
Init ハンドラは[スクリプト オペレータ](Script Operator)の初期化に使用します。パラメータ pCont にはパーティクル コンテナが含まれます。
global My_Atmospheric_Gizmos_01 = $SphereGizmo*
パーティクルが駆動するシーン オブジェクトの配列を入れるグローバル変数を定義します。この場合、共通の基本名を使用して、シーンからすべての SphereGizmo を収集します。
My_Atmospheric_Gizmos_01.pos = [0,0,-100000]
アニメーションの第 1 フレームのシーンからギズモを削除するには、カメラの視野から取り除きます。 ここでは、下の方に移動させます。
[スクリプト オペレータ](Script Operator)がパーティクル フローによって評価されるたびに、Proceed ハンドラが呼び出されます。ハンドラには、スクリプトの実際の本体が含まれています。パラメータ
pContには、オペレータの適用先であるすべてのパーティクルを収めたパーティクル コンテナが含まれています。
partcount = pCont.NumParticles()
まず、現在のイベント内のパーティクルの数を読み込みます。イベント内のパーティクル数は 0 の場合も数百万の場合もあります。
count = amin #(partcount, My_Atmospheric_Gizmos_01.count)
次に、パーティクルの数を収集されたギズモの数と比べます。 amin() 関数は、配列内の最小値を返します。
同じことを次のように表現できます。
|
if partcount < My_Atmospheric_Gizmos_01.count then
count = partcount
else
count = My_Atmospheric_Gizmos_01.count
|
見てわかるとおり、最初のコードの方が短いです。また、常に最小値を選び出すので、必要に応じて値の数が 2 つより多い場合でも使用することができます。
|
必要な理由
|
アニメーションの最初の方では、パーティクルの数が限られており、ギズモの数より少ないためです。しばらくたつと、パーティクルの数はギズモの数より多くなります。どちらの場合も、ギズモとパーティクルの「ペア」がほしいわけですが、パーティクルやギズモの一部は、アニメーションの特定部分においては対応するパートナーを持たない可能性があります。これらのオブジェクトの最小数を知っていれば、処理できるペアの数を得られます。
|
シーン内でパーティクルとギズモのペアが可能な回数だけ、次のコードを繰り返します。
パーティクルからデータを読み込むには、それを現在のものにする必要があります。そのためには、現在のイベントの particleContainer の particleIndex
プロパティ にインデックス i を割り当てます。その後、パーティクル関連の問い合わせや割り当ては i 番目のパーティクルだけに対して行われます。
My_Atmospheric_Gizmos_01[i].transform = pCont.ParticleTM
これで、現在の i 番目のパーティクルの変換行列を配列内の i 番目のギズモに割り当てることができます。上記の便利な amin テストのおかげで、i はパーティクルとギズモの数のどちらとも等しいか、それより少ないことが保証されます。
My_Atmospheric_Gizmos_01[i].radius = 10 + pCont.ParticleAge*2
最後に、i 番目のギズモの半径を、10 単位に i 番目のパーティクルのエージの倍を加えたものに変更します。10 はギズモの最小サイズです(particleAge
が 0 の場合)。たとえばエージが 10 の場合、ギズモの半径は 30 単位になります。さまざまな値を試してみると、異なる湯気の動きが得られます。
)
)
on Release pCont do ()