「演算子」カテゴリーアーカイブ

QuickBox2Dの衝突判定とビット単位の論理積

今更ながら周りの影響で、QucikBox2Dをいじってます。@alumican_net さんが書かれたブログがわかりやすいので拝見してますが、『 QuickBox2DやBox2DFlashAS3での衝突判定をグループ分け 』という記事で以下のような記述がありました。
自分と何かが衝突するかどうかは、自分のmaskBitsと相手のcategoryBitsの論理積をとって計算できる。結果が0なら衝突しない、0以外なら衝突する。
普段あまり使わないので「論理積ってなに?」って状態だったんで調べてみると、大重美幸さんのActionScript3.0入門ノートにわかりやすい解説がありました。
ビット単位の論理和では値を2進数に換算して各ビットごとに比較し、どちらかが1ならば1にします。たとえば、6(2進数で110)と5(2進数で101)のビット単位の論理和は7(111)になります。同様にビット単位の論理積では両方が1のときに1にし一方が0ならば0にします。6と5のビット単位の論理積は4(100)になります。
2進数における桁のシフトは2のn階乗で変化します。次のサンプルで使われているrgbToHex()はRGBの各色の値から0xFFFFFFの形式の16進数に変換する関数です。

なるほど!ということで、実際に計算してみました。


maskBits:0x0007(0111) &  categoryBits:0x0004(0100) >> 4(0100):衝突する

maskBits:0x0007(0111) &  categoryBits:0x0008(1000) >> 0(0000):衝突しない

maskBits:0x0007(0111) &  categoryBits:0x0002(0010) >> 2(0010):衝突する

maskBits:0x0007(0111) &  categoryBits: 0x00020010) >> 2(0010):衝突する


maskBits:0x0007(0111) &  categoryBits:0x0008(1000) >> 0(0000):衝突しない

maskBits:0x0007(0111) &  categoryBits: 0x00040100) >> 4(0100):衝突する

・■

maskBits:0x0001(0001) &  categoryBits: 0x00020010) >> 00000):衝突しない



maskBits: 0x00010001) &  categoryBits: 0x00040100) >> 0(0000):衝突しない

maskBits: 0x00010001) &  categoryBits: 0x00081000 >> 0(0000):衝突しない

ふむふむ。確かに先の引用通り「結果(論理積)が0なら衝突しない、0以外なら衝突する。」になっています。

そこでを categoryBits:0x0001, maskBits:0x0003 に変更してみました。すると・・・

maskBits:0x0003(0011) &  categoryBits:0x0004(0100) >> 0(0000):衝突しない


maskBits:0x0007(0111) &  categoryBits: 0x00010001) >> 1(0001):衝突する


と、基準を変えて計算すると違う結果になってしましました。
そこで色々調べてみたら、QucikBox2Dのユーザーマニュアルに次のように書いてありました。

Here is the rule for a collision to occur:

uint16 catA = fixtureA.filter.categoryBits;

uint16 maskA = fixtureA.filter.maskBits;

uint16 catB = fixtureB.filter.categoryBits;

uint16 maskB = fixtureB.filter.maskBits;

 

if ((catA & maskB) != 0 && (catB & maskA) != 0)

{

  // fixtures can collide

}

つまりAとBを比較する時に「それぞれを基準に計算した結果が、どちらも0でない場合に衝突する」ということなんんですね。上に書いたの場合とも合致しますね。納得。
以下のサイトを参考にしました。感謝。