Collision filtering confusion

General discussion about the R.U.B.E editor
Post Reply
Oscar
Posts: 14
Joined: Sun Dec 23, 2012 3:56 pm

Collision filtering confusion

Post by Oscar »

Hey,

I'm sure this is a really simple question but I must admit I'm really confused by collision filtering in rube. In the filtering tutorial available on the site you mention how a fixture can collide with other fixtures by code such as:
BOUNDARY | FRIENDLY_SHIP | ENEMY_SHIP etc. However, I can't figure how to translate this way of thinking into Rube? You can only set numbers in the filter mask bits field etc which is 65535 by default.

To make a simple example. I have a circle, square and a polygon and floor in a simple scene. What settings would I use on my fixtures to make the circle and the square collide, but the polygon would collide with neither? Also, the floor (and everything else) must collide with all of these shapes. As soon as I change the mask bits field to anything else the body will just fall through the floor. Attached a screenshot to get a better grasp.

Thanks
Attachments
Skärmavbild 2013-01-22 kl. 19.58.28.png
Skärmavbild 2013-01-22 kl. 19.58.28.png (210.62 KiB) Viewed 9369 times
iforce2d
Site Admin
Posts: 861
Joined: Sat Dec 22, 2012 7:20 pm

Re: Collision filtering confusion

Post by iforce2d »

You need to have an understanding of binary numbers to get how these work. I'm assuming you do, but just for anyone else who comes to this thread in future I'll start from the basics.

"Power of two" numbers are the sequence 1, 2, 4, 8, 16, 32, etc... and you can represent any whole number by adding up a combination of these, for example 13 would be (8 + 4 + 1)

Binary represents a number by using a sequence of 0 or 1 to show which power of two numbers should be added together. Typically this is written with the largest power of two on the left, and the smallest power of two is always 1, and will be on the right. For example, 13 = (8 + 4 + 1) would be 1101

The bitflags used in Box2D are 16 bit binary numbers, so you could write zero as 0000000000000000, or for our example of 13 it would be 0000000000001101

If every bit in the bitflag is on, we get 1111111111111111 which adds up to 65535

When two bitflags are compared, each position in the sequence is checked with the same position in the other sequence, and if they are both 1 then the test passes. Here are some examples (I will use the code format to keep the bit positions aligned)

Code: Select all

// this bitflag test will fail, because there are no position which both have a 1
0000000000000000 = 0
1111111111111111 = 65535

// this bitflag test will pass, because the last position is 1 for both
0000000000000001 = 1
1111111111111111 = 65535

// this bitflag test will fail, because there are no position which both have a 1
0000000000000001 = 1
0000000000000010 = 2

// this bitflag test will pass, because there are positions with 1 for both
0000000000001100 = 12
0000000000001101 = 13

// this bitflag test will fail, because there are no positions which both have a 1
0000000000000010 = 2
0000000000001101 = 13
That should help to understand the bitflag test between two flags. Now in Box2D there are two of these tests happening. The categoryBits of one fixture are tested with the maskBits of the other, and vice versa. They both need to pass in order for the fixtures to collide. This lets you set up a huge range of possibilities, although it is rather unintuitive.

When choosing numbers for categories, you would typically want to make sure the numbers are a power of two, so they only have one 1 bit in the flag. That's why we went with 1, 2, 4 etc for the entity categories. Then to combine categories you can just add them up (in the code example we used the bitwise OR operator, but if we know we only have one of each bit, we can also just add them).

You can also remove bits from a flag by subtracting, as long as you know the bit is already a 1. For example if you start with 65535 (which has all bits set) you can subtract 2 to get 65533, which would then fail a bitflag test with the number 2. Note that you can only do this if you know the 2 bit was already set, so we could not subtract 2 again, which is why this is usually done with bitwise AND operator.

So as far as making settings in RUBE, I usually follow a few simple rules that keep me out of trouble most of the time.
- choose a single power of two number for the category (1, 2, 4, 8, etc)
- start with 65535 for the mask, and subtract the category that you don't want to collide with

In your case, you could first set the category bits so that circle=1, square=2, pentagon=4.
To make the pentagon collide with neither of them, you would set the polygons maskBits to 65535 - 1 - 2 = 65532.
Then you would find that because the circle and the ground are both category 1, the pentagon will fall through the ground, which I guess is what you got ;) If you want the circle and the ground to behave separately, you would need to have a separate category for them. So maybe circle=2, square=4, pentagon=8 is what you need, and set the mask in the pentagon accordingly (65535 - 2 - 4).

I am hoping to improve on this in future versions of RUBE, so maybe we can set names for the bitplanes or something, and use checkboxes or some other more visual display to turn them on and off.
Oscar
Posts: 14
Joined: Sun Dec 23, 2012 3:56 pm

Re: Collision filtering confusion

Post by Oscar »

Thanks, that really sorted stuff out for me! That trick you do in rube should be really handy. If you ever implement improved functionality for handling this in rube I know I'll be one happy guy :P Keep up the good work.
Post Reply