Box2D Fixture doesn’t get the same category and mask bits of its FixtureDef

Tags: , ,



This is quite bizarre in my opinion. I create fixtures based on a fixtureDef. I use the libGDX version of Box2D. This is my code:

System.out.println("category bits of fixtureDef: " + fixtureDef.filter.categoryBits);
System.out.println("mask bits of fixtureDef: " + fixtureDef.filter.maskBits);
System.out.println("category bits of fixtureDef: " + fixtureDef_leftPropeller.filter.categoryBits);
System.out.println("mask bits of fixtureDef: " + fixtureDef_leftPropeller.filter.maskBits);
System.out.println("category bits of fixtureDef: " + fixtureDef_rightPropeller.filter.categoryBits);
System.out.println("mask bits of fixtureDef: " + fixtureDef_rightPropeller.filter.maskBits);

Body body = world.createBody(Res.bodyDef_dynamic);
fixture = body.createFixture(fixtureDef);
fixture_leftPropeller = body.createFixture(fixtureDef_leftPropeller);
fixture_rightPropeller = body.createFixture(fixtureDef_rightPropeller);
body.setTransform(pos.x * Drone2D.MPP, pos.y * Drone2D.MPP, 0);
body.setUserData(drone);

System.out.println(" ");

for (Fixture fix : body.getFixtureList()) {
    System.out.println("category bits of fixture: " + fix.getFilterData().categoryBits);
    System.out.println("mask bits of fixture: " + fix.getFilterData().maskBits);
}

The output of this code is:

category bits of fixtureDef: 2
mask bits of fixtureDef: 11
category bits of fixtureDef: 2
mask bits of fixtureDef: 11
category bits of fixtureDef: 2
mask bits of fixtureDef: 11

category bits of fixture: 4
mask bits of fixture: -1
category bits of fixture: 4
mask bits of fixture: -1
category bits of fixture: 4
mask bits of fixture: -1

WHAT? How can the filtering bits of my fixture not be the same of the fixtureDef they were created with?

I have also found this out: The mask that these fixtures get is instead the mask of the body that I have destroyed prior to creating these new fixtures.

Still, this should not happen.

Does anybody know what could lead to this sort of behavior?

Edit:

I found out that this filter scrambling phenomenon happens with every single body in my game.

My current work around is the following function, which seems to be sufficient:

public static void fixFixtureFilter(Fixture fixture, short maskBits, short categoryBits) {
    Filter filter = fixture.getFilterData();
    filter.maskBits = maskBits;
    filter.categoryBits = categoryBits;
    fixture.setFilterData(filter);
}

Still, something must be very wrong with my B2D world.

Answer

UPDATE

It seems that this issue is already tracked here and has been fixed in the new 1.9.13 release (see the release notes. So this problem can be fixed by updating your libGDX version to 1.9.13.


I just tested this in my project and found the same behavior that you described. I’m setting the maskBits of my FixutreDef to 9, but when I create the Body and check the fixtures with the debuger the maskBits of the Fixture are set to -1. So this bug seems to be reproducable.

But if I change the maskBits of the FixtureDef, to avoid a specific category of fixtures (I tested it with enemy fixtures), they indeed do no longer collide with the created Fixture (what is not possible if it realy has the maskBits set to -1, because that would mean that the fixture collides with every other object).

So the maskBits of the fixtures in libGDX seem to be wrong, while the maskBits of the fixtures in Box2D seem to be correct, which could be possible, because libGDX uses a java wrapper for Box2D, which is implemented in native methods (in C I think).

Therefore the collision detection is working, but the java wrappers show the wrong values (maybe because of wrong references, because you said that “The mask that these fixtures get is instead the mask of the body that I have destroyed prior to creating these new fixtures”).
This problem might just be a bug in libGDX, which is quite hard to find, because everything seems to be working at first (until you debug it).


You should add this bug to libGDX’s issue tracker, so it can be fixed. But unfortunately this could take some time, so you probably need to keep your workarround for some time, or just ignore it, because the collision detection is working anyways.



Source: stackoverflow