您的位置:首页 > 其它

Bullet 物理引擎 详细分析 Dbvt (2)

2010-02-23 02:09 483 查看
开始阅读前可以先浏览一下之前框架分析





在物理模拟的场景中, 一个节点首先应该具备2种属性



物理属性 包含 质量,速度,惯性,加速度,角速度,约束,摩擦系数 等

几何属性 形状, 包围体层次,碰撞检测类型掩码。world 变换。

物理属性大部分都在collosionObject 和rigidObjec 这样的类之中。

几何属性则又一次被细分为包围体层次和形状,碰撞检测类型掩码。

为了进一步介绍Dbvt的核心函数 btDbvt::collideTV

必须首先引入btDbvtProxy。btDbvtProxy 继承自 btBroadphaseProxy。

ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy
{
	///optional filtering to cull potential collisions
	enum CollisionFilterGroups
	{
	        DefaultFilter = 1,
	        StaticFilter = 2,
	        KinematicFilter = 4,
	        DebrisFilter = 8,
    			SensorTrigger = 16,
		    	CharacterFilter = 32,
	        AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
	};
  void*	    m_clientObject;//Usually the client btCollisionObject or Rigidbody class
	short int m_collisionFilterGroup; //碰撞检测类型
	short int m_collisionFilterMask;  //碰撞检测类型掩码
	void   *	m_multiSapParentProxy;	//sweep and prune broadphase 测试研究用
	int			  m_uniqueId;//m_uniqueId 在重叠节点管理结构中要用到,非必须
	btVector3	m_aabbMin; //store the volume
	btVector3	m_aabbMax; //store the volume
}




btBroadphaseProxy
基类包含了最基本的碰撞检测类型以及对象本身支持的碰撞检测类型,关于碰撞检测类型的详细描述可以参见bullet手册的第5章节有详细描述。对象可以根
据支持的碰撞检测类型选择碰撞的对象。还包含了指向物理属性对象的指针。

再看btDbvtProxy

struct btDbvtProxy : btBroadphaseProxy
{
        /* Fields                */ 
        btDbvtNode*        leaf;       //指向Dbvt 中对应的节点
        btDbvtProxy*        links[2];  //指向双向列表的前后节点 见btDbvtBroadphase分析
        int                    stage;    //所处的队列 见btDbvtBroadphase分析
}




btDbvtProxy 是一个节点,利用了代理的设计模式,连接物理属性节点与几何节点。

本身还是重合节点管理的重要组成部分。然后再看看btDbvtTreeCollider

/* Tree collider        */ 
struct        btDbvtTreeCollider : btDbvt::ICollide
{
        btDbvtBroadphase*        pbp;
        btDbvtProxy*                proxy;
        void        Process(const  btDbvtNode* n)
        {
                Process(n,proxy->leaf);
        }
}




btDbvtTreeCollider 定义了当两个几何节点在远距状态下碰撞后的处理方法,btDbvt::ICollide
定义的是接口标准btDbvtTreeCollider
是在dbvt下的一个具体实现,开发者也可以根据自己的需要嵌入不同的处理逻辑。proxy代表的是主节点,n代表的是被比较节点。

现在进入主题
btDbvt::collideTV。这个函数的主要算法是遍历所有和目标节点重合的叶子节点,然后使用已有的处理逻辑模块
btDbvtTreeCollider 来处理这两个节点。会引入新的数据结构btHashedOverlappingPairCache,可以参见后
续的btDbvtBroadphase分析

btDbvt::collideTV(const btDbvtNode* root,
                  const btDbvtVolume& vol,
                                                                  DBVT_IPOLICY)
{
ATTRIBUTE_ALIGNED16(btDbvtVolume)                volume(vol);
btAlignedObjectArray<const btDbvtNode*>        stack;
stack.resize(0);
stack.reserve(SIMPLE_STACKSIZE); //生成一个栈用来遍历Dbvt
stack.push_back(root);                    //根节点入栈
do        {
        const btDbvtNode*        n=stack[stack.size()-1];  // 栈顶元素出栈
        stack.pop_back();                             // 栈顶元素出栈
        if(Intersect(n->volume,volume))// 如果这个节点包含了目标节点
        {
                if(n->isinternal())// 同时是内部节点,则遍历其子树
                {
                        stack.push_back(n->childs[0]);  //左孩子入栈
                        stack.push_back(n->childs[1]);  //右孩子入栈
                }
                else //如果已经是叶子节点
                {
                        policy.Process(n); // 利用既有的处理策略来处理这一对碰撞的节点
                }
        }
} while(stack.size()>0); // run until all intersect leaf node is visited .
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: