Scene Management --- Collision Detection

来源:互联网 发布:js 判断chrome 编辑:程序博客网 时间:2024/05/16 14:59

Scene Management --- Collision Detection 

仅供个人学习使用,请勿转载,勿用于任何商业用途。 

    没有碰撞检测的引擎是不完整的。碰撞检测是引擎的基础服务之一,需要为渲染,物理仿真,AI和游戏逻辑都等众多子系统提供服务。由于碰撞检测本身设计到大量数学运算,以及各个子系统对碰撞检测需求的不同,使得它成了最难实现的部分。

    碰撞检测需要解决的问题是物体之间是否发生了碰撞,在什么时刻发生了碰撞,碰撞位置在什么地方以及碰撞点法线的方向,得到的碰撞数据越多,计算量也越大。考虑两个物体碰撞检测的问题,假设每一帧都通过遍历2个物体中的所有三角形来判断是否发生碰撞,那代价一定是相当大的。于是人们用一些简单的,便于处理的几何体近似实际模型,以减少计算量,这就是常说的包围体BV(bounding volume)。常见的包围体有AABB,球体,OBB,Hull等等。包围体减少了碰撞检测的计算量,特别是对于没有相交的物体来说,让他们很快就排除在后续计算之外,也就是常说的early rejection。前面所说的几种包围体,精度逐渐增高,所需计算量也随之增加。可以先计算两个物体初级包围体(比如包围球)是否相交,如果相交,再进一步计算精度高一级的包围体(AABB或者OBB)是否相交,以次类推,直到满意的精度(比如三角形级别)为止,我把这个方法称为BV LOD。对于实际相交的物体来说,虽然这些额外的包围盒测试会带来负载,但考虑到场景中有大量物体且彼此之间没有碰撞时,包围盒可以大大减少总体计算时间。

    除了上面说所的BV LOD,层次包围盒(Bounding volume hierachies)也是常用的加速方法。BVH与quadtree局部细分的思想很类似,用多个BV来近似实际模型。以人物模型为例,第一级BV空间范围包含了整个模型,第二级BV由多个小BV组成,每一个对应着模型的一个子部分,比如头,手,躯干。每个子部分又可以划分为更多子BV,直到你满意的细分粒度为止。对BVH来说,每级的BV类型可以不一样也可以相同,比如第一,二级都用AABB,而第三级改用球体等等,最终的数据将是一种树形结构。当对两个物体进行检测时,先从跟节点开始,然后逐步细分,检测子BV是否相交。至于是否同时对2个物体进行细分测试,还是先对其中一个进行细分,则要根据实际情况来定。当然,BVH也可以和BV LOD结合起来一起使用。

    上面介绍了基本的碰撞检测算法,但当物体很多时,单靠上面两种方法还是无法满足需要。因此,与裁剪系统一样,需要在更高的层次对场景进行空间划分,这也是我为什么把碰撞检测也归为scene management的原因。上次说过quadtree几乎是最适合户外场景裁剪的结构,那么是否对碰撞检测也一样呢?我相信你可能已经见过很多引擎就是把两者合二为一的,可实际上,对裁剪有效的数据结构却并不是碰撞检测的最优结构。对裁剪来说,如果某个网格在视锥之内,那么这个网格内的所有物体就是可见的;而对碰撞检测来说,需要做的是依次检查每个网格内的所有物体之间是否有碰撞。换句话说,对于裁剪系统,网格内物体的多少基本不会影响裁剪效率,而对碰撞检测,性能就与物体多少紧密相关。所以我们需要的是一种空间上不均匀,但能最大程度保证空间内物体均匀的数据结构,比如BSP或者K-d tree。此外,碰撞检测还有一个非常非常重要,也是非常显而易见的特性:永远不需要计算静态物体之间是否发生了碰撞!假设场景中有n个静态物体和一个动态物体,排除静态物体间相互碰撞可能性让计算量从O((n+1)!)降低到了O(n)。再假设我们以K-d tree划分场景,每个叶节点只有n个物体,那么每次计算这个动态物体是否发生了碰撞的时间代价几乎就是一个可预知的常量!Wow就是这个方法的最好例子,在wow里,动态物体(人物)之间是不会发生碰撞的,所以不管场景中有多少玩家,都不对碰撞检测造成影响。但是如果你希望动态物体之间也能碰撞怎么办?大量的动态物体很有可能会破坏k-d tree的平衡性。最好的方法就是把静态物体(场景)和动态物体(玩家)分开,放到不同的数据结构中。仍然用k-d tree来组织静态场景,但用一些更动态的结构来组织动态物体,比如动态的k-d tree,ABT等等。这样,就能仍然保证每个物体碰撞检测的代价是一个可预测的常量。

    小结:Scene management的三篇文章在很高的层次上介绍了关于游戏引擎的一些核心技术,我的目的不是讲解实现细节,而是让对于scene management不太了解的人知道scene management是什么以及如何来做。感性的说,如果你读完之后,知道scene management = scene tree + culling tree + static object tree + danamic object tree,那么我的目的就达到了。至于用什么数据结构来实现这些“tree“,是否可以把其中的某些tree合并,则是你在实现scene management时应该考虑的:)

     我不是Scene management方面的专家,因此如果有任何错误,不清楚的地方,不同观点或者更好的想法,欢迎留言,我们可以一起讨论。