Flashで3D剛体シミュレーション

FlashPlayer11から導入されたStage3Dという機能を使って、
前からやってみたかった3Dの剛体シミュレーションを作りました。

>> View on EL-EMENT (larger)
>> View on wonderfl

>> Source code (MIT License)

 

仕組みとしては通常の2D物理エンジンを3Dに拡張しただけですが、
剛体の形状が特殊なため、衝突判定に粒子を用いています。

粒子は、ステップごとに剛体の位置と傾きから再配置します。

各リングは12個の粒子からできていて、高速化のために三次元のボクセルに格納されます。

衝突判定時には、粒子が格納されているボクセルを中心とする、
周囲27(3×3×3)個のボクセルから粒子を取り出し判定を行います。いわゆる空間分割です。

衝突応答処理には、Box2Dと同じ繰り返しソルバウォームスタート(後述) を使いました。
繰り返しソルバは、各衝突点における力を繰り返し計算し、全体として安定させる方法です。

これだけではよく分からないと思うので、次のような状態を考えてみましょう。

 

球A、球B、球Cが同時に衝突を起こしました。
球AとB、球BとC、球CとAが、
それぞれ衝突しています。

ここで、各衝突点の衝突処理を行います。

 

まずは球AB間の衝突を処理します。

ここで計算に必要なのが、球AとBそれぞれの速度です。
これらの速度を元に、球AB間に働く力を計算します。

力が計算できたら、実際にその力を球AとBに与えます。
これで球AB間の衝突処理は完了です。

次に球BC間の衝突を処理します。

同じように速度を元に力を求め、双方に与えます。
最後に球CA間についても同様に処理し、これで衝突処理は完了……

ではないんですね。実はもう少し複雑です。

最初に球AB間の力を求めた時、球AとBの速度を使いましたね。
ですがその後、球BC間の力によって球Bの速度が、
球CA間の力によって球Aの速度が変化しています。

このため球AB間の力の計算をやり直さなくてはならず、
その結果は また球AとBの速度に影響してきます。

このように、三体以上の剛体が相互作用するような場面では、
それぞれの衝突を個別に計算することはできないのです。

 

これを解決するのが、先ほど紹介した繰り返しソルバです。

この方法では、まず全ての衝突を一旦処理します。
ここまでは先程と同じです。

その後、変化した後の速度を使ってもう一度全ての衝突を処理します。
これを、処理前と後で速度が変わらなくなるまで繰り返します。

速度が変わらなくなるまでに与えた力の合計が、本来の与えるべき力となります。

 

さらにウォームスタートでは、この反復計算で得た力を次のステップでも使い回します。

衝突点を区別する必要があるので追加の情報が必要ですが、
数十段の積み重ねにも耐えられるほどの抜群の安定力を発揮します。

 

ちなみに3D表示ですが、Stage3Dがしっかりとできているので、
特に苦労はしませんでした(シェーダー部分を除く)。

ぜひとも、剛体の動きの方を見ていただければと思います。

3 Responses to “Flashで3D剛体シミュレーション”

  1.   より:

    とてもきれい。。
    sarahn様の説明、大変わかり易くとても勉強になります。大変貴重なソース付きでありがとうございます。

  2.    より:

    直前の投稿をした者です。saharan様のお名前、間違えました。。大変失礼いたしました。
    今後の更新も大変楽しみにしております。

    • saharan より:

      いえいえ、お気になさらず。

      ソースコードはあまりコメントを書いてないので分かりにくいかと思いますが、
      参考までにどうぞ。

Leave a Reply for saharan