Physics & constraints

Position Based Dynamics / PBD

位置ベース物理

位置を補正して布や紐の拘束を守る。

5 / 10

Interactive demo

Preparing the demo…

Position Based Dynamics / PBD

Drag to orbit, Ctrl/⌘ + scroll to zoom. Use two fingers on touch screens.

This explanation is currently available in Japanese.

ひとことで

力を計算して加速度を積分する代わりに、まず点を動かしてみて、拘束(守るべき条件)を満たすように位置を直接直し、直した位置の変化から速度を求める物理シミュレーションの方法です。Müller らが 2007 年に発表し、布、ロープ、髪、柔らかい物体、流体まで同じ枠組みで扱えること、そして反復を途中で打ち切っても発散しないことから、ゲームの標準的な方法になりました。

ゲームでの使いどころ

  • 布:マント、旗、カーテン、服。NVIDIA の PhysX Cloth、Unity の Cloth、Unreal の Chaos Cloth などの中身です。
  • ロープ・髪・植物:点を一列につないで距離の拘束をかけるだけで作れます。
  • 柔らかい物体:シェイプマッチングや体積の拘束と組み合わせて、ゼリーや肉の揺れを作ります。
  • 流体:密度の拘束を使えば、PBF として液体も同じ仕組みで扱えます。
  • キャラクターと物の接触:衝突をめり込みの押し戻しとして書けるので、布がキャラクターの体に沿う処理が簡単です。

しくみ

1 ステップは次の 3 段階です。

  1. 予測:重力や風などの外力で速度を更新し、その速度で仮の位置 p\mathbf{p} を求めます。
  2. 拘束の投影:拘束 C(p)=0C(\mathbf{p}) = 0 を満たすよう、位置を少しずつ直します。これを全拘束について何回かくり返します。
  3. 更新:直したあとの位置と、予測前の位置 x\mathbf{x} の差から速度を求め、位置を確定します。
v←p−xΔt,x←p\mathbf{v} \leftarrow \frac{\mathbf{p} - \mathbf{x}}{\Delta t}, \qquad \mathbf{x} \leftarrow \mathbf{p}

距離の拘束(2 点の距離を LL に保つ)なら、C=∣p1−p2∣−LC = |\mathbf{p}_1 - \mathbf{p}_2| - L で、各点を質量の逆数 wiw_i の比で動かします。

Δp1=−w1w1+w2 C n,Δp2=+w2w1+w2 C n,n=p1−p2∣p1−p2∣\Delta\mathbf{p}_1 = -\frac{w_1}{w_1 + w_2}\,C\,\mathbf{n}, \qquad \Delta\mathbf{p}_2 = +\frac{w_2}{w_1 + w_2}\,C\,\mathbf{n}, \qquad \mathbf{n} = \frac{\mathbf{p}_1 - \mathbf{p}_2}{|\mathbf{p}_1 - \mathbf{p}_2|}

一般の拘束でも、拘束の勾配 ∇C\nabla C の向きに、CC が 0 になる量だけ動かす、という同じ形で書けます。

布の場合は、格子状の点に 3 種類の距離の拘束をかけます。

  • 伸び:上下左右の隣同士。布が伸びないようにします。
  • せん断:斜めの対角線。布が平行四辺形にゆがまないようにします。
  • 曲げ:1 つ飛ばしの点同士(または 2 つの三角形の角度)。布が折れ曲がりにくくなり、厚手の布らしくなります。

衝突も拘束の 1 つです。球の中に入った点は表面まで押し出す、というように、「めり込んでいない」という条件を満たす位置へ移すだけです。

実装のポイント

  • 硬さ kk:1 回の補正で誤差の何割を直すかを 0〜1 で指定します。1 なら完全に直そうとします。
  • 固定点は w=0w = 0:質量の逆数を 0 にすると、その点は動かなくなり、相手だけが動きます。
  • 反復とサブステップ:反復を増やすより、1 フレームを細かいステップに分けたほうが、同じコストでよく収束することが知られています(Small Steps)。
  • GPU では並列版(ヤコビ式):拘束を同時に解くと補正がぶつかり合うので、補正を平均するか、互いに点を共有しない拘束のグループ(グラフ彩色)ごとに解きます。

つまずきやすい点

  • 硬さが反復回数で変わる:同じ kk でも、反復を増やすと硬くなり、時間刻みを変えても硬さが変わります。物理的な硬さを指定したい場合は拡張位置ベース物理(XPBD)を使います。
  • 反復が足りないと伸びる:拘束がたくさんつながった布やロープでは、補正が端まで伝わるのに多くの反復が必要です。反復が少ないと、ゴムのように伸びて見えます。
  • 速い物のすり抜け:衝突を位置の押し戻しで扱うので、1 ステップで薄い物を通り抜けるほど速いと検出できません。サブステップや連続衝突判定で補います。

デモで試すこと

  1. 旗は、上の辺の点を固定した布です。「点と拘束を表示」をオンにすると、黄の伸びの拘束と、青の斜めのせん断の拘束が見えます。
  2. 「拘束の反復回数」を 1〜2 にすると、布が重さでだらりと伸びます。「最大の伸び」の数値も大きくなります。
  3. 赤い球をドラッグして布に押し当てると、布が球の形にまとわりつきます。衝突も「めり込んだら押し戻す」だけの拘束です。
  4. 「曲げの拘束」をオフにすると、布が薄く柔らかくなり、細かいしわができやすくなります。「固定する点」を「上の両端だけ」にすると、ハンモックのようにたわみます。
  5. 「硬さ」を下げると、同じ反復回数でも布が伸びやすくなります。

References

Gaffer On Games — Integration Basics ↗

A general reference for this subcategory.