您的位置:首页 > 其它

OGRE里如何实现碰撞检测

2011-08-24 17:28 841 查看
在3D游戏中,碰撞检测算得上是最复杂也是最影响游戏效果的环节了,这里简单介绍一下如何在OGRE引擎里实现简单的碰撞检测。

话不多说,先贴代码:

bool EdenCollisionManager::Collide()

{

bool collide=false;

m_KeyObject=*(m_ResearchObject.begin()); // m_Keyobjects是待检测的物体(游戏角色)

Ogre::AxisAlignedBox AABB
= m_KeyObject->getWorldBoundingBox(true);
// 获取包围盒

m_AABBSceneQuery->setBox(AABB); // 以包围盒建立场景查询

m_AABBSceneQuery->setQueryMask(ENTITY_QUERY_MASK); // 设置查询标识

Ogre::SceneQueryResult& results
= m_AABBSceneQuery->execute();
// 获取查询结果

Ogre::SceneQueryResultMovableList::iterator iter
= results.movables.begin();

if(results.movables.empty())

return
false;

else

{

for(;iter!=results.movables.end();iter++)

{

if((*iter)->getMovableType()=="Entity")

{

if(m_KeyObject->getName()==(*iter)->getName())

continue;

else

{

collide=true;

break;

}

}

}

return collide;

}

}
OK,对OGRE熟悉一点的人一眼就可以看出来,这里采用的是基于包围盒的碰撞检测方法,什么是基于包围盒的碰撞检测呢?简单点说,就是用一个立方体的盒子把物体装起来,然后用这个盒子里代替原先的物体,在场景中进行检测,按照一定的策略(比如距离)判断两两物体间是否碰撞。
包围盒法虽然简单快速,但是准确性却不太高,而且有很大的局限性。因为是采用立方体的包围盒,盒子的范围比原先的物体大,所以会造成一定的误差(特别是在物体形状不规则的情况下),这个误差随着“盒子”的体积紧包物体表面而无限接近真实结果,所以为了减少这个误差,配合着场景物体的形状,我们可以用球体、圆柱体等来代替包围盒,所有这些替代,都是为了减少误差,是碰撞检测更加精确。可以说,包围盒法检测结果的准确性依赖于包围盒的选择,包围盒的体积愈接近3D物体,结果越精确,但是在游戏中,一个场景中往往有各种大小、各种形状的物体,所以我们的包围盒往往只能折中选择。

上面的代码只是在OGRE引擎里实现碰撞检测的演示代码,下面具体讲讲包围盒法碰撞检测的算法:
包围盒法碰撞一般是使用球体或圆柱体的范围包围每个Object或测试一定范围内的碰撞。假设我们有两个Object A和B,两个Object分别被一个半径为ra,rb的球体包围,半径ra,rb来检测。我们可以简单的检测AB间的距离是否小于ra+rb,小于,则碰撞;反之则没有。
碰撞检测还有很多其他的方法,比如射线法等,甚至还有三角面级别的精确碰撞检测,这里不再详述,以后再做介绍。
优化问题
最后简单提一下碰撞检测的优化问题。
举一个简单的例子,假设一个场景中有1000个对象(object,子弹等等)。现在假设我们要对这1000个obejcts进行碰撞检测,考虑到每两个物体之间我们都要计算一次,那么总共会有1000x1000 = 1000000的计算量,这个计算量是很恐怖的,因此我们不得不对碰撞问题进行一些优化,这里介绍一下空间分割方法。
还是这个场景,但是我们现在把利用BSP树(二叉树)对场景里的object进行管理,并且将所有的object划分成一组一组,每一组50个object,共有1000 / 50 = 20组。很显然,现在我们只需要在每一组的objects里进行检测就可以了,所以现在的计算量是50 * 50 * 20 = 50000。计算量只有原来的5%!可见使用BSP树进行场景管理对我们游戏性能的提高有多大帮助了!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: