This explanation is currently available in Japanese.
ひとことで
力を計算して加速度を積分する代わりに、まず点を動かしてみて、拘束(守るべき条件)を満たすように位置を直接直し、直した位置の変化から速度を求める物理シミュレーションの方法です。Müller らが 2007 年に発表し、布、ロープ、髪、柔らかい物体、流体まで同じ枠組みで扱えること、そして反復を途中で打ち切っても発散しないことから、ゲームの標準的な方法になりました。
ゲームでの使いどころ
- 布:マント、旗、カーテン、服。NVIDIA の PhysX Cloth、Unity の Cloth、Unreal の Chaos Cloth などの中身です。
- ロープ・髪・植物:点を一列につないで距離の拘束をかけるだけで作れます。
- 柔らかい物体:シェイプマッチングや体積の拘束と組み合わせて、ゼリーや肉の揺れを作ります。
- 流体:密度の拘束を使えば、PBF として液体も同じ仕組みで扱えます。
- キャラクターと物の接触:衝突をめり込みの押し戻しとして書けるので、布がキャラクターの体に沿う処理が簡単です。
しくみ
1 ステップは次の 3 段階です。
- 予測:重力や風などの外力で速度を更新し、その速度で仮の位置 を求めます。
- 拘束の投影:拘束 を満たすよう、位置を少しずつ直します。これを全拘束について何回かくり返します。
- 更新:直したあとの位置と、予測前の位置 の差から速度を求め、位置を確定します。
距離の拘束(2 点の距離を に保つ)なら、 で、各点を質量の逆数 の比で動かします。
一般の拘束でも、拘束の勾配 の向きに、 が 0 になる量だけ動かす、という同じ形で書けます。
布の場合は、格子状の点に 3 種類の距離の拘束をかけます。
- 伸び:上下左右の隣同士。布が伸びないようにします。
- せん断:斜めの対角線。布が平行四辺形にゆがまないようにします。
- 曲げ:1 つ飛ばしの点同士(または 2 つの三角形の角度)。布が折れ曲がりにくくなり、厚手の布らしくなります。
衝突も拘束の 1 つです。球の中に入った点は表面まで押し出す、というように、「めり込んでいない」という条件を満たす位置へ移すだけです。
実装のポイント
- 硬さ :1 回の補正で誤差の何割を直すかを 0〜1 で指定します。1 なら完全に直そうとします。
- 固定点は :質量の逆数を 0 にすると、その点は動かなくなり、相手だけが動きます。
- 反復とサブステップ:反復を増やすより、1 フレームを細かいステップに分けたほうが、同じコストでよく収束することが知られています(Small Steps)。
- GPU では並列版(ヤコビ式):拘束を同時に解くと補正がぶつかり合うので、補正を平均するか、互いに点を共有しない拘束のグループ(グラフ彩色)ごとに解きます。
つまずきやすい点
- 硬さが反復回数で変わる:同じ でも、反復を増やすと硬くなり、時間刻みを変えても硬さが変わります。物理的な硬さを指定したい場合は拡張位置ベース物理(XPBD)を使います。
- 反復が足りないと伸びる:拘束がたくさんつながった布やロープでは、補正が端まで伝わるのに多くの反復が必要です。反復が少ないと、ゴムのように伸びて見えます。
- 速い物のすり抜け:衝突を位置の押し戻しで扱うので、1 ステップで薄い物を通り抜けるほど速いと検出できません。サブステップや連続衝突判定で補います。
デモで試すこと
- 旗は、上の辺の点を固定した布です。「点と拘束を表示」をオンにすると、黄の伸びの拘束と、青の斜めのせん断の拘束が見えます。
- 「拘束の反復回数」を 1〜2 にすると、布が重さでだらりと伸びます。「最大の伸び」の数値も大きくなります。
- 赤い球をドラッグして布に押し当てると、布が球の形にまとわりつきます。衝突も「めり込んだら押し戻す」だけの拘束です。
- 「曲げの拘束」をオフにすると、布が薄く柔らかくなり、細かいしわができやすくなります。「固定する点」を「上の両端だけ」にすると、ハンモックのようにたわみます。
- 「硬さ」を下げると、同じ反復回数でも布が伸びやすくなります。