This explanation is currently available in Japanese.
ひとことで
「各粒子の周りの密度が、基準の密度と等しいこと」を拘束とし、位置ベース物理と同じように、拘束を満たすよう粒子の位置を直接直すことで液体を動かす方法です。Macklin と Müller が 2013 年に発表しました。SPH の考え方で密度を測りつつ、力ではなく位置を補正するので、大きな時間刻みでも安定し、布やロープと同じ仕組みで液体を扱えます。
ゲームでの使いどころ
- 物理エンジンに組み込まれた液体:NVIDIA FleX は、布・ロープ・剛体・液体を、すべて位置ベースの拘束として 1 つのソルバーで解きます。液体が布を濡らして重くする、布の袋に水をためる、といった相互作用も自然に扱えます。
- リアルタイムの液体演出:時間刻みを大きくとれるので、1 フレーム 1〜2 ステップで液体を動かせます。
- 大量の粒子を GPU で:各反復が粒子ごとに独立して計算できるので、GPU で数十万粒子を扱えます。
しくみ
粒子 の密度を、SPH と同じくカーネル関数 で求めます。
この密度についての拘束を
とします。位置ベース物理と同じ 3 段階で解きます。
- 予測:重力で速度を変え、仮の位置 を求めます。
- 拘束の投影(数回くり返す):
- 各粒子について、拘束をどれだけ破っているか()と、粒子を動かしたときに密度がどれだけ変わるか(勾配 )から、補正の大きさ を求めます。
- 近くの粒子との間で、 に比例した量だけ位置を動かします。
- 速度の更新: とし、位置を確定します。
補助の工夫が 3 つあります。
- 緩和項 :分母が 0 に近いときに補正が暴れないよう、小さな値を足します。
- 人工圧力 :粒子が近づきすぎると少し押し離す項です。粒子が固まるのを防ぎ、表面張力のような効果も生みます。
- XSPH 粘性:近くの粒子と速度を少しならし、動きをまとまりのあるものにします。オプションで、失われた渦を補う渦度閉じ込めも加えます。
実装のポイント
- 近傍は予測位置で 1 回だけ探す:反復のたびに近傍を探し直すと重いので、予測直後に空間ハッシュで 1 回探し、反復中は同じ近傍リストを使います。
- 反復回数:2〜5 回で十分なことが多く、回数で「縮まなさ」を調整できます。
- ヤコビ式で並列に:λ の計算と位置の補正を別々のパスに分け、全粒子の補正を求めてから一度に適用すると、GPU で並列に計算できます。
- 水面の扱い:水面の粒子は周りが少なく密度が低くなります。そのまま拘束を満たそうとすると粒子を引き寄せて固まるので、密度が基準を超えたときだけ補正する( を 0 以上に制限する)方法がよく使われます。
つまずきやすい点
- パラメータの単位:人工圧力の係数や緩和項は、カーネル関数の大きさ(粒子の間隔、影響半径)に強く依存します。論文の値をそのまま使うと、補正が大きすぎて爆発することがあります。まず小さな値から試します。
- 反復が少なすぎる:反復 1 回では拘束をほとんど満たせず、水が押しつぶされて底に沈み込みます。
- エネルギーが減りやすい:位置を直接直す方法は、動きのエネルギーが少しずつ失われ、しぶきがおとなしくなりがちです。XSPH を弱めにし、渦度閉じ込めで補います。
デモで試すこと
- 左の水の柱が崩れて右の壁にぶつかり、水面が落ち着いていきます。「ダムを崩す」でくり返せます。
- 「粒子の色」が「密度」のとき、明るい粒子ほど周りが混み合っています。左下の「内部の密度」は、ほぼ基準の 100% に保たれます。
- 「密度拘束の反復回数」を 2 に下げると、水がわずかに押しつぶされ、8 に上げると、より縮まない水になります。
- 「人工圧力」をオフにすると、粒子が固まりやすくなります。水槽の中をドラッグすると、棒でかき混ぜられます。