この簡単なチュートリアルでは、パーティクル フローを使用してシーン オブジェクトを動かす方法の基本について説明します。オブジェクトは、ライトからヘルパーおよびメッシュ オブジェクトまであらゆるオブジェクトが対象になります。
この例では、ファイヤ効果を割り当てた大量の周囲効果ギズモを動かして、ティーポットが湯気を立てる様子をシミュレートします。
全体の流れ - 設定
[作成] (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 には、パーティクル コンテナが含まれます。
pCont.useTM = true
パーティクルからシーン オブジェクトへの変換をすべてコピーしたいので、そのチャネルに対するアクセスが必要になります。
pCont.useAge = true
さらによい結果を得るためには、パーティクルのエージを読み取ってギズモの半径プロパティに割り当て、時間の経過に伴いギズモが拡大するようにします。
)
on Init pCont do
(
Init ハンドラは[スクリプト オペレータ] (Script Operator)の初期化に使用します。パラメータ pCont にはパーティクル コンテナが含まれます。
global My_Atmospheric_Gizmos_01 = $SphereGizmo*
パーティクルが駆動するシーン オブジェクトの配列を入れるグローバル変数を定義します。この場合、共通の基本名を使用して、シーンからすべての SphereGizmo を収集します。
My_Atmospheric_Gizmos_01.pos = [0,0,-100000]
アニメーションの第 1 フレームのシーンからギズモを削除するには、カメラの視野から取り除きます。 ここでは、下の方に移動させます。
)
on Proceed pCont do
(
[スクリプト オペレータ] (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 つより多い場合でも使用することができます。
必要な理由
アニメーションの最初の方では、パーティクルの数が限られており、ギズモの数より少ないためです。しばらくたつと、パーティクルの数はギズモの数より多くなります。どちらの場合も、ギズモとパーティクルの「ペア」がほしいわけですが、パーティクルやギズモの一部は、アニメーションの特定部分においては対応するパートナーを持たない可能性があります。これらのオブジェクトの最小数を知っていれば、処理できるペアの数を得られます。
for i in 1 to count do
(
シーン内でパーティクルとギズモのペアが可能な回数だけ、次のコードを繰り返します。
pCont.particleIndex = i
パーティクルからデータを読み込むには、それを現在のものにする必要があります。そのためには、現在のイベントの 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 ()