Box2D: B2Contact.getFixtureA, B2Contact.getFixtureB メソッドの内容順序に注意
Box2D での衝突判定処理を行なっていたところ、どうもたびたび実行結果が異なる、という状況が発生しました。私の考えが抜けていたことが原因であり、まとめてみますと大した内容ではないのですが、一応としてメモしておきます。
調査内容
Box2D にて、衝突し合っている物体に関する調査を行うためには B2Contact クラスを利用します。例えば Haxe では以下のように記述して B2Contact インスタンス一式を取得し、衝突し合っている二物体の取得調査を行ないます。
var b2Contact:B2Contact = b2world.getContactList(); while(b2Contact != null){ var fixtureA = b2Contact.getFixtureA(); var fixtureB = b2Contact.getFixtureB(); b2Contact = b2Contact.getNext(); }
衝突し合ったニ物体はそれぞれ、fixtureA と fixtureB どちらに代入されるかはわかりません。「丸い物体」と「四角い物体」が衝突し合ったとして、丸い物体が fixtureA に 四角い物体が fixtureB になる事もあれば、丸い物体が fixtureB に 四角い物体が fixtureA になる場合もあります。
ここで、fixtureA と fixtureB の内容が逆になると B2Contact から得られる衝突詳細データも逆になる点に注意が必要です。
B2Contact.getManifold().m_localPlaneNormal の値を調べることで、fixtureA が fixtureB に対しどの方向から衝突しているのか判定できますが、fixtureA と fixtureB の内容が逆になると どの方向から衝突しているのかの結果も逆になります。
例えば 丸い物体が上から衝突、四角い物体が下から衝突し、fixtureA に丸い物体、fixtureB に四角い物体が代入されると、結果は以下となります。
丸い物体(fixtureA)は四角い物体(fixtureB)に対し「上」から衝突している
対して、fixtureA に四角い物体、fixtureB に丸い物体が代入されると結果は以下となります。
四角い物体(fixtureA)は丸い物体(fixtureB)に対し「下」から衝突している
まとめ
fixtureA と fixtureB には、どちらに何が入るのかわからないという点と、fixtureA と fixtureB が逆になると得られる結果も逆になる、という考慮を行わず処理を作成したため、たびたび実行結果が異なる、という事態が発生してしまいました。
以前 b2Manifold に関する調査を行いましたが、今回の内容を考慮せず行ったものなので、すみません おそらく内容に誤りがあります。
Box2DFlash v2.1a 調査3 : b2Manifold 調査
http://www.dango-itimi.com/blog/archives/2011/001082.html