This project has moved and is read-only. For the latest updates, please go here.

Problem with world.QueryAABB

May 6, 2012 at 1:11 PM
Edited May 6, 2012 at 1:14 PM

Hello again, in my game I am using sprite animations, so I want different animations to have different collision boxes (for example crouch and standing).

After doing some research in the forum I decided that each animation should have it's own body and I should change bodies when changing animations. I also found this discussion, and especially the last post of pnikosis in which he suggested: "The first approach is the simplest one: Call an AABB raycast before making the move. If you have obstacles, then don't allow the move, nor activate the corresponding fixture." for checking if it is allowed to change animations/bodies (because the new body could be bigger than the old and cause problems).

So in my swapAnimations code I do this:


//Save fixtures ids of anim1 - old animation to be replaced, has two body parts [rec, circle]
int[] fixturesIds = { anim1.recBodyPart.FixtureList[0].FixtureId, anim1.circleBodyPart.FixtureList[0].FixtureId };

//Collision box for anim2 - new animation
AABB collisionBox = new AABB(anim2Position, anim2.width, anim2.height);

//Flag for obstacles found
bool obstacles = false;
//Test if there are obstacles in the collision area of anim2
world.QueryAABB(found =>
     //if the fixture found is from the old animation ignore
            return true; //continue searching
            Debug.WriteLine(string.Format("Found fixture {0}", found.FixtureId));
            obstacles = true; //obstacle found
            return false; //stop searching
}, ref collisionBox);

if (!obstacles) //no obstacles, change animations
       //code that changes animations, anim1<->anim2
       return true; //swappin animations was succesfull

return false; //swapping was unsuccessful


The problem is that the QuerryAABB finds that the collisionBox is overlapping with the floor. Ok I assumed that this could be possible and it was for 0.005181 meters (0.66 pixels) in the y axis. Then I set the height of the collisionBox to be 2 pixels smaller but the problem continued, although I checked that the floor and the collisionBox were no longer overlapping in the y axis. In order for the QueryAABB to return no collision I have to make the collisionBox height 30+ pixels smaller, which is a very big difference.

For those not bored here are the AABB boxes of the collision box and floor that gives an overlapping result, while it shouldn't:

Floor: Center: {X:1,5625 Y:5,15625}, LowerBound: {X:-8,4475 Y:4,89625}, UpperBound: {X:11,5725 Y:5,41625}

CollisionBox: Center: {X:0,78125 Y:4,120202}, LowerBound: {X:0 Y:3,354577}, UpperBound: {X:1,5625 Y:4,885827}

So, are there any ideas why the QueryAABB is not accurate? Thanks.

May 6, 2012 at 6:17 PM
Edited May 6, 2012 at 6:21 PM

I am not overly familiar with the code but afair there is an issue. World.QueryAABB asks directly the broadphase for overlap. But the broadphase stores "fattened" AABBs for the proxies - fattened by a small amout (available in settings something like AABBExtension). This is done to increase stability. So your precise AABB is actually compared to the fattened AABB but reported back as the standard AABB. Actually it's not reported back, the fixture is, but I assume you do Shape.ComputeAABB for the fixture. In fact if you do FloorAABB.TestOverlap(CollisionBoxAABB) from the numbers you posted it will turn out false (if I'm doing the math correctly). You can actually do that test in your callback to be double sure.

AFAIR a related issue is that a polygon has a "skin" - available in Settings that could also lead to some visual discrepancy on the pixel level (that's actually documented in the Box2D manual).

I think reading the code in DynamicTree.cs (which is the broadphase data structure) could be of more help.

P.S: thinking in pixels is misleading. The physics should work regardless of the visual representation. If it doesn't there is either a bug or something tricky going on in the engine.