TT Lab
はじめる
学ぶ 学習パス コース

物理エンジンの骨組み

箱が沈み込まないように

TT Labで続きを見る

一言でいうと

速度だけを直しても、すでにめり込んだ重なりは消えません。位置を別に押す必要がありますが、強く押しすぎると震えるので、余裕(スロップ)を置いて、少しずつ押さなければなりません。接触が複数あれば、同じステップの中で、何度も繰り返して解きます。

なぜ必要なのか

前のモジュールの力積は、速度を直します。床に触れた箱の下向きの速度を0にすれば、それ以上下がりません。ところが、その箱は、すでに少しめり込んだ状態です。重なりに気づく時点が、すでに重なったあとだからです。

速度が0になったので、箱は、そのめり込んだ位置に、そのままとどまります。次のステップで、重力がもう一度速度を与え、位置が少し下がり、また0になります。少しずつ沈みます。箱を複数積むと、下のほうが押しつぶされて、互いにめり込んだまま固まります。

どう動くのか

位置補正は、重なった分を、逆質量の比率で分けて、両側を押し出すことです(コードブロックの中の韓国語は、補正量と物体を表すプレースホルダーです)。

보정량 = max(깊이 - slop, 0) / (inv_m1 + inv_m2) * percent
물체1 을 -n 방향으로 보정량 * inv_m1 만큼
물체2 을 +n 방향으로 보정량 * inv_m2 만큼

ここには、2つのつまみがあります。percentは、1ステップで何パーセントを戻すかです。1.0にすると、一度にすべて押し出しますが、そうすると、物体が弾かれて、次のステップでまたぶつかる振動が生じます。普通は、0.2から0.8の間を使います。

slopは、無視する重なりの余裕です。普通、0.005から0.01くらいを置きますが、これがないと、重なりを0にしようとする補正が、毎ステップごく小さな値で起き続けて、物体が微細に震えます。重なりを正確に0にしようとせず、ごく薄く重なった状態にしておくことが、むしろ安定します。

位置補正が、速度に触れないことも重要です。位置だけを動かすので、エネルギーを生み出しません。速度まで変えると、補正が物体を押す力になって、山が自分で跳ね上がります。

反復回数は、接触が複数あるときに必要です。箱が3つ積まれていれば、接触は3つ(床-1、1-2、2-3)ですが、これらは互いに絡み合っています。一番上の箱を押すと、真ん中が押しつぶされ、真ん中を直すと、下が押しつぶされます。接触を1つずつ順番に解くと、あとで解いたものが、先に解いたものを壊します。

正確な解法は、すべての接触を1つの連立方程式として解くことですが、高価です。そのため、エンジンは、同じ巡回を何度も繰り返します。繰り返すほど、正解に近づき、繰り返しを止める地点が、そのまま、精度とコストのトレードオフです。これを逐次力積(sequential impulse)と呼び、Erin CattoがBox2Dで整理してから、事実上の標準になりました。箱の山がどれだけ固く見えるかは、この反復回数に、ほとんどそのまま左右されます。

位置補正のほかにも、道があります。バウムガルテ安定化は、重なりの一部を、速度の目標値に混ぜ込む方法です。「相対速度を0にする」の代わりに、「相対速度をbeta * 깊이 / dtにする」(プレースホルダーは、深さです)と、目標を変えると、速度の解法の中で、重なりも一緒に押し出されます。実装が簡単で、広く使われましたが、エネルギーを系に入れてしまう副作用があるので、山が微細に揺れる原因になることもあります。

そのため、最近のエンジンは、分割力積(split impulse)を使います。速度を直す力積と、位置を直す力積を、別に置き、位置用の力積は、実際の速度に反映しないのです。重なりは押し出されつつ、エネルギーは入ってこないので、2つの方式の長所だけが残ります。このラボの位置補正は、そのアイデアを、最も単純に縮めた形です。

現場での姿

山が時間とともにだんだん低くなる現象は、反復回数が足りないのです。下のほうの接触がすべて解ける前にステップが終わって、毎ステップ少しずつ押しつぶされます。反復を増やすと、目に見えて良くなりますが、コストもそのぶんかかります。

もう1つは、スリープ(sleeping)です。山が安定すると、計算は回り続けるのに、結果はほとんど変わりません。エンジンは、速度がしきい値の下で、一定時間保たれると、その物体を計算から外し、何かが触れたら、起こします。箱1,000個が積まれたシーンが、実際に動く理由が、これです。

最後に、山の安定性を何で測るかを、決めておくと良いです。目で見て揺れないという言葉は、判定の基準にならないからです。ラボで使う方法は、2つあります。1つは、接触の最大のめり込みの深さが、スロップの近くにとどまるかで、もう1つは、連続する2つのフレームの絵の差が、0に収束するかです。後者は、人が見るのと同じものを測るので、とくに役に立ちます。数字が少しずつ動いても、画面で同じピクセルなら、人にとっては止まっています。

そして、この層のルールを1つ覚えておいてください。正確さより、揺れないことが先です。重なりを正確に0にしようとする試みが震えを生み、1ステップですべて戻そうとする試みが跳ねを生みます。少し重なったまま静かに立っている山のほうが、正確に接しているのに微細に振動している山より、優れています。

次のラボですること

位置補正の関数を作り、補正なしで回した箱がめり込んだまま固まることと、補正をオンにしたときにスロップまで戻ってくることを、数字で比べます。次に、箱3つで、反復回数を1、4、10に変えながら、めり込みの深さが減ることを確認し、最後に、箱5つが落ちて積み重なり、安定する過程を、12枚の絵に残します。