動的な障害物と流体のインタラクションを実現するには(2)

シミュレーションは3Dテクスチャ上で行うことはここまでで周知のこと。そう、障害物の情報も同じ3Dテクスチャの次元に落とし込まなければシミュレーションの計算が行えないのだ。

ただし、障害物は単位立方体で表現されておらず、通常は3Dポリゴンモデルで表現される。

となれば、3Dポリゴンモデルを、毎フレームリアルタイムにシミュレーションと同じ次元に単位立方体化(ボクセル化)する処理を実装する必要がある。

動いて変形する3Dポリゴンのモデルを障害物として流体物理シミュレーションに組み込むならば、その3Dポリゴンモデルをボクセル化(3Dテクスチャ)に分解する必要がある

ボクセル化によって流体との衝突に影響する障害物としての情報と、その3Dモデルの動く障害物のボクセル単位の速度を生成する必要がある

このボクセル化によって2つの情報を生成する必要がある。

1つは流体との衝突に影響し密度や圧力に影響する障害物形状としての情報、2つ目は他の流体への移流に関係する、動く障害物の速度情報だ。

障害物形状の取得はイメージ的には3Dモデルの断面図を形成していくような感じになる。この情報の取得は、影生成の「ステンシルシャドウボリューム技法」のアルゴリズムを応用して取得する。

まず仮想的な視点を欲しい断面に直交させて設定し、その描画視界の近点(Near Plane)を欲しい断面の位置に設定し、遠点(Far Plane)はその3Dモデルよりも遙か遠くに設定する。この仮想視点からステンシルバッファに対し、3Dモデルのポリゴンの背面ならば"-1"、前面ならば"+1"するようにレンダリングすると、断面として切り取られて残る部分がゼロ以外の値として残る。

これを3Dモデルの最下部まで、断面形状をシミュレーション計算に必要十分な枚数取得する。

障害物の断面形状はステンシルシャドウボリューム技法の影領域生成によく似たアルゴリズムで取得する

動かない3Dオブジェクトであれば事前に計算しておけるが移動したり、手足が動くようなアニメーションをする場合には毎フレームこのレンダリングを行う必要がある

続いて障害物の速度情報の取得を行う。これは前フレームと現在フレームの頂点の移動量から逆算して求めていく。速度=距離÷時間なので対応する頂点同士の移動量と前フレームから現在までのタイムステップがわかれば頂点単位の速度は簡単に計算できる。計算した速度は頂点の付随情報として記録しておく。

障害物の速度情報の取得は頂点単位の移動量から計算

この速度情報をやはり断面図的なテクスチャに描き込んでいかなければ、シミュレーション計算に利用できない。

これは障害物の断面形状の取得の時とは違って、3Dモデルの断面の外周部分の速度情報だけが分かればいい(中はスカスカでOK)。

そこで、断面と3Dモデルの各ポリゴンとの交差線を検出を試み、検出ができたらここでジオメトリシェーダを活用してこの交差線を内包するクワッド(ポリゴン)を生成する。このクワッドの頂点には、前述したように速度情報を付随情報を仕込ませてあるので、この頂点単位の速度情報を、交差線(クワッド)として断面テクスチャにレンダリングしていく。

動く3Dモデルと断面の交差線について速度を記録していく

この交差線の生成にジオメトリシェーダを活用する

実際のところ、この3Dキャラクタのボクセル化は重い処理なので高速化のためにいくつかの工夫が必要だとしている。

例えば、手足を曲げたりするスキニングされる3Dキャラクタモデルであれば、スキニングしたあとのモデルを中間的な頂点バッファに記録しておき、ボクセル化の折にはこの情報を用いて、スキニング処理の無意味なダブリを避けることを狙う。

また、もっと大胆に表示3Dモデルよりも低ポリゴンの簡単形状モデルを用意しこれに対してボクセル化を行い頂点負荷を低減させるという手もある。流体とのインタラクションの精度は粗くなるが、もともと流体も実態の掴みにくいものなので、不自然さはほとんど感じないはずだ。

流体へのインタラクションを実現するために3Dモデルのボクセル化は必要不可欠ではあるが、実際問題その負荷は大きい。負荷低減のためにはこのような最適化のアプローチがある

NVIDIA「Smoke」デモのガーゴイル。ただし、こちらは簡易的な衝突や流体とのインタラクションを計算するための低ポリゴンモデル