優先および実行順序

[変化量](Amount Change)サブオペレータを含む出力タイプのサブオペレータには、優先順位と実行順序を定義するオプションがあります。複雑なセットアップを作成する場合、それらのオプションに注意を払うことは重要です。

データの修正および処理の順序は、出力サブオペレータによって定義します。出力サブオペレータは、データ修正を制御します。データ フローで上に位置するサブオペレータからパーティクル データを引き出し、そのデータをパーティクルのプロパティとして設定します。

[実行順序](Execution Order)値が同じになっている出力サブオペレータは、同じ入力データを処理します。[実行順序](Execution Order)値が同じ場合は、出力サブオペレータがアップストリームからデータを引き出す順序が[優先順序](Priority Order)値によって定義されます。すべてのデータが引き出された後にのみ、データがパーティクルのプロパティに適用されます。

各サブオペレータの[実行順序](Execution Order)値が異なる場合、それらのサブオペレータは、同じ入力サブオペレータからデータを引き出したとしても、異なる入力データを処理します。これは、実行順序の値が低い出力サブオペレータが、いずれかのパーティクル プロパティのデータを変更することがあるからです。実行順序の値が高い出力サブオペレータがデータを引き出すときには、それらのデータがすでに変更されていることになります。

次の例について考えてください。パーティクルがイベントに到達したら、すべての新しいパーティクルの初期値を計算する必要があるとします。次に、(パーティクルがイベント内で新しいかどうかに関係なく)すべてのフレームでパーティクルのプロパティを変更し、この変更の間、すべてのパーティクルで初期値を設定する必要があります。

このシナリオには 2 つのデータ ストリームがあります。1 つ目のストリームでは初期値を計算し、2 つ目のストリームではパーティクルのプロパティを変更します。1 つ目のストリームの出力サブオペレータでは[実行順序](Execution Order)の値を 1 にする必要があり、ほとんどの場合そのフィルタ入力は[入力スタンダード](Input Standard) [イベント中新規](New In Event)に設定されます。2 つ目のストリームの出力サブオペレータでは、[実行順序](Execution Order)を 2 に設定します。

別のシナリオについても考えてみます。すべてのパーティクルの速度データを分析するとします。条件に応じて、パーティクルのサブセットを 2 つ定義し、それぞれの速度が異なった方法で変更されるようにします。このシナリオでは、実行順序が同じになっている 2 つの出力サブオペレータを使用する必要があります。この方法により、初期入力速度の値が各出力サブオペレータで同じになるよう保証できます。

ちなみに[変化量](Amount Change)サブオペレータは、パーティクルの数を変更するため、他のサブオペレータと[実行順序](Execution Order)の値を同じにすることはできません。プログラムの保護機能により、そのように設定できないようにしています。

さらに、[優先および実行順序](Priority And Execution)領域には、[事前](Pre)/[標準](Normal)/[事後](Post)ラジオ ボタンもあります。このオプションにより、上位レベルでの処理順序を定義します。[事前](Pre)に設定すると、現在のイベントのオペレータが実行されるよりも前に、出力が実行されます。[標準](Normal)に設定すると、出力サブオペレータが通常の順序で、つまり同じイベント内の他のオペレータの合間に実行されます。[事後](Post)に設定すると、このパーティクル システムのすべてのオペレータとすべてのテストがこのインテグレーション ステップでそのジョブを終了した後に、出力が処理されます。

[事前](Pre)/[標準](Post)/[事後](Post)の使用例については、組み込みファイル CollisionAsBody.max を開いてください。

この例では、[データ](Data)オペレータを使用して「安くて速い」フルボディ衝突を作成します。おそらくご存じのとおり、3ds Max のパーティクル システムは、衝突とディフレクタに関してはパーティクルをポイント エンティティとして扱います。したがって、パーティクルに視認できるサイズのシェイプがある場合、そのシェイプがディフレクタのサーフェスに浸透し、全体的な視覚効果を損なう可能性があります。例では、パーティクル データをワイヤリングして、パーティクルの位置を相互浸透量だけオフセットする方法を示しています。

まず、浸透を回避するために必要とされる位置オフセットとして、実際の値を保存するカスタム データ チャネルを作成します。すべての新しいパーティクルについて、この値をゼロにします。データ ブロック 01 を参照してください。

他のすべてのオペレータおよびテストがそれぞれのジョブを終了したら、浸透量を計算し、[事後](Post)フェーズでパーティクル位置をオフセットします。この方法により、浸透が回避されるようにパーティクルの位置が調整され、パーティクルのレンダリング準備が整います。右側の出力オペレータは、[事後](Post)フェーズにそれぞれのジョブを実行します。

次に、[事前](Pre)フェーズでオフセットなしの元の位置にパーティクルを戻し、何もなかったかのようにして衝突テストでジョブが続行されるようにする必要があります。

履歴従属

パーティクル システムは、本質的に履歴従属です。言い換えると、たとえばフレーム 100 でのパーティクル システムの状態を判別できるようにするには、最初のパーティクルが発生して以降のすべての前フレームの状態をソフトウェアで計算する必要があります。これは、パーティクルのプロパティ(たとえば、パーティクルの位置)の変更が、速度などの他のパラメータにおける定常的な変更のために累積するからです。

ただし、特定のセットアップにおいてパーティクルのプロパティは履歴従属ではなく、パーティクルの現在状態から計算できます。たとえば、カメラなどの物体を「見ている」場合、またはパーティクルの速度に追従する場合の、パーティクルの向きというプロパティです。ここで、パーティクルの向きは、カメラのほうを向いている場合のパーティクルの位置、またはパーティクルの速度に応じて異なります。この場合は、パーティクルの現在の向きを計算するためにパーティクルの履歴すべてを知っている必要はありません。必要なのは、現在の速度と位置の情報だけです。

そのような意味で、パーティクルの向きを計算するオペレータは履歴従属ではありません。このタイプのオペレータは、現在のフレームに到達するためにシステムが前のすべてのフレームを調べる間、何もする必要がありません。このオペレータは、最後のフレームでのみ処理を実行し、最後のフレームのパーティクルの位置/速度の分析、および対応するパーティクルの向きの計算を行います。

出力サブオペレータの結果がパーティクルの履歴に依存しないことが明白な場合は、[履歴従属](History-Dependent)オプションをオフにすることができます。これにより、[データ](Data)オペレータが最後のフレームでのみ処理を実行するようになるため、全体的な計算速度が上がります。