Box2D 碰撞过滤规则

原文链接:http://blog.csdn.net/zhangxaochen/article/details/8071232


首先注意这个函数:
左旋肉碱正品装 减肥非胶囊瘦身减肥产品 中草药成分 男女通用

看这里: http://is.gd/VoBVUJ

virtual bool ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB);


函数实现位于 b2WorldCallbacks.cpp line:24

bool b2ContactFilter::ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB)
{
    const b2Filter& filterA = fixtureA->GetFilterData();
    const b2Filter& filterB = fixtureB->GetFilterData();

    if (filterA.groupIndex == filterB.groupIndex && filterA.groupIndex != 0)
    {
        return filterA.groupIndex > 0;
    }

    bool collide = (filterA.maskBits & filterB.categoryBits) != 0 && (filterA.categoryBits & filterB.maskBits) != 0;
    return collide;
}


这是默认的碰撞过滤回调函数。
由函数实现可以看出, 当 filterA.groupIndex == filterB.groupIndex 时, 若二者 groupIndex >0, 两个fixture一定碰撞; 若 groupIndex<0,二者一定不碰撞。

如果两个 fixture 的 groupIndex 不相等, 那么再判断 二者中是否有一方的 maskBits 包含了另一方的 categoryBits, 即代码里的“&运算”不为零——如果是,返回 true; 否则返回 false。

由此可以看出:
1. 默认的碰撞标记优先级为: groupIndex 高于 maskBits+categoryBits
2. (filterA.maskBits & filterB.categoryBits) != 0 && (filterA.categoryBits & filterB.maskBits) != 0 表示A, B 的 maskBits, categoryBits,必须互相包含包含对方, 函数才返回 true。 举例说明: 如果 filterA.categoryBits=1, filterB.categoryBits=2, filterA.maskBits=3, filterB.maskBits=2, 那么虽然 (3&2)!=0, 但是 (2&1)==0, 所以AB不会碰撞。假设这里的A、B分别代表“一种”而不是“一个”fixture的话,那么可以判定 A种种内相互碰撞, B种种内也相互碰撞。

===================================================
那么, 怎么使用自定义 ShouldCollide 函数呢?
简单的演示一下。
1. 自定义 b2ContactFilter 的一个子类:

class MyContactFilter : public b2ContactFilter{
public:
 virtual bool ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB){
  return true; //不管谁谁,大家都碰撞
 }
};


2. 在你 new b2World(gravity) 的地方,紧接着添加:
 

 MyContactFilter* cf=new MyContactFilter;
  _world->SetContactFilter(cf);


这样一来,不管你怎么设定 fixture 的 groupIndex, maskBits, categoryBits 所有的 body 都会碰撞。
【注意】 在 box2d 里面, b2World, b2ContactFilter, b2ContactListener 是少有的几个不被引擎管理, 而需要自己 new 的类, 一定要记得在析构函数中 delete 他们。 如果 自定义的 contactFilter 不是成员变量,可以在析构函数里这么释放:

  delete _world->GetContactManager().m_contactFilter;


======================================================
再来看看一个引擎里的例子: TestCpp - Box2DTestBed 里的 CollisionFiltering.h (函数实现都在这个头文件里了)
我们只看文件开始定义的这几个常量:

const int16    k_smallGroup = 1;
const int16 k_largeGroup = -1;

const uint16 k_defaultCategory = 0x0001;
const uint16 k_triangleCategory = 0x0002;
const uint16 k_boxCategory = 0x0004;
const uint16 k_circleCategory = 0x0008;

const uint16 k_triangleMask = 0xFFFF;
const uint16 k_boxMask = 0xFFFF ^ k_triangleCategory;
const uint16 k_circleMask = 0xFFFF;


假设我们没有去覆写 ShouldCollide, 就用的引擎默认的函数。可以看出,smallGroup (对应场景里的小物体 ) 必然碰撞,因为 k_smallGroup = 1 大于 0; k_largeGroup (大物体) 互相一定不碰撞, 因为 -1<0 。

而对于大小物体之间,因为
k_triangleMask = 0xFFFF;
k_boxMask = 0xFFFF ^ k_triangleCategory; // 这样 boxMask 就不“包含” triangleCategory  了
k_circleMask = 0xFFFF;

所以小三角和大方块不碰撞,大三角和小方块也不碰撞, 其他的大物体和小物体都会碰撞

 

原文链接:http://blog.csdn.net/zhangxaochen/article/details/8071232

{{OVER}}

你可能感兴趣的:(filter,delete,Class,引擎)