物理の時間発展・拘束

ジョイント・拘束ソルバー

Joints / Constraint Solver

距離や角度の関係を保って鎖や機械を動かす。

9 / 10

インタラクティブデモ

デモを準備しています…

ジョイント・拘束ソルバー

ドラッグで視点を回転、Ctrl(⌘)+ スクロールでズーム。タッチ操作は 2 本指です。

ひとことで

2 つの剛体を「この点とこの点を重ねる」「この軸をそろえる」「この角度の範囲に収める」といった拘束(ジョイント)でつなぎ、それを満たすように両方の位置と向きを直す仕組みです。鎖、ドア、車輪、クレーン、ラグドール、橋など、つながった物体はすべてジョイントと、それをまとめて解く拘束ソルバーで動いています。

ゲームでの使いどころ

  • ラグドール:倒れたキャラクターの体を、肩・肘・膝などの関節(角度の制限付き)でつないだ剛体として動かします。
  • ドア・跳ね橋・レバー:蝶番(ヒンジ)のジョイントに、開く角度の制限やモーターを付けます。
  • 乗り物:車輪とサスペンション、トレーラーの連結、戦車の履帯。
  • 鎖・ロープ・吊り物:短い剛体を球関節でつないだ鎖、ランタン、クレーンのフック。
  • 物理パズル:『ティアーズ オブ ザ キングダム』のウルトラハンドのように、物同士をくっつけて乗り物や仕掛けを作る遊び。

しくみ

ジョイントの種類

  • 球関節(ボールジョイント):2 つの物体の決まった点を重ねるだけ。どの向きにも回れます(肩、鎖)。
  • 蝶番(ヒンジ):点を重ねたうえで、回転軸をそろえます。1 つの軸の周りにしか回れません(ドア、肘、車輪)。
  • スライダー(プリズマティック):1 つの方向にしか動けない(ピストン、引き出し)。
  • 固定(ウェルド):位置も向きも固定(壊れる前の部品のつなぎ目)。

さらに、角度の制限(肘は反対に曲がらない)、モーター(一定の速さで回す)、ばね(元の角度に戻ろうとする)を加えます。

拘束ソルバー

ジョイントがたくさんあると、1 つを満たすと別のものがずれます。そこで、すべてのジョイントを順番に少しずつ直すことを何回もくり返します(ガウス=ザイデル法)。直し方には大きく 2 つの流派があります。

  • 速度(インパルス)ベース:Box2D、PhysX、Bullet の方式。ジョイントの点同士の相対速度が 0 になるよう、両方の物体にインパルス(撃力)を加えます。ずれた位置は、ずれに比例した速度を足して少しずつ戻します(Baumgarte 安定化)。
  • 位置ベース(XPBD):拡張位置ベース物理を剛体に拡張した方式(Müller ら 2020)。ずれた分だけ、位置と向きを直接直し、あとから速度を求めます。デモはこちらの方式です。

どちらでも共通の考え方は、直す量を 2 つの物体で「動かしにくさ」に応じて分けることです。点 r\mathbf{r}(重心からの位置)を方向 n\mathbf{n} に動かすときの動かしにくさの逆数は、並進と回転の両方を含みます。

w=1m+(r×n)⊤ I−1 (r×n)w = \frac{1}{m} + (\mathbf{r} \times \mathbf{n})^{\top}\,\mathbf{I}^{-1}\,(\mathbf{r} \times \mathbf{n})

重い物、重心から遠くを押しても回りにくい物ほど ww が小さく、あまり動きません。

実装のポイント

  • サブステップを多めに:1 フレームを 10〜20 に分け、各ステップで 1 回ずつ解くと、鎖が伸びにくく安定します。
  • 質量比に注意:軽い鎖で非常に重い物を吊ると収束が遅くなります。現実より質量差を小さくするか、サブステップを増やします。
  • 固定点は質量無限大の物体:世界に固定された点は、質量の逆数 0 の「動かない物体」として扱うと、同じコードで書けます。
  • ワームスタート:速度ベースのソルバーでは、前のフレームのインパルスを初期値に使うと、少ない反復で収束します。

つまずきやすい点

  • 鎖が伸びる・関節が外れる:反復やサブステップが足りないと、つないだ点がずれて鎖が伸びて見えます。長い鎖は根元から先へ順に解く、根元側を重くする、などで改善します。
  • 角度の制限でがたつく:制限の端にぶつかったとき、跳ね返りすぎたり震えたりします。制限にも減衰を入れるか、制限を少し柔らかく(コンプライアンス付きに)します。
  • ラグドールの体の重なり:つながった体同士の衝突を切っておかないと、関節の近くで押し合って暴れます。

デモで試すこと

  1. 左の鎖は、8 本の棒を関節(黄の点)でつないだものです。横に持ち上げた状態から放すと、振り子のように揺れながら先のランタンの重さで伸びきります。
  2. 「1 フレームの分割数」を 1〜3 に下げると、関節のずれ(左下の数値)が大きくなり、鎖が伸びたり、関節が外れかけたりします。
  3. 「鎖の関節」を「蝶番」に切り替えると、各関節の回転軸(青緑)がそろえられ、鎖は 1 つの平面の中でしか曲がらなくなります。
  4. 右の看板は、蝶番で吊られています。「揺らす」を押すと、看板が大きく揺れますが、「看板の角度を ±35° に制限」がオンなら、その範囲で止まります。オフにすると、一回転するほど回ります。

参考資料

Gaffer On Games — Integration Basics ↗

分野全体の資料で、この項目を直接扱っているとは限りません。