碰撞检测系统

碰撞检测系统

1、固体物体本质上是固态的,它通常不会做出不可能的事情,例如穿透对方。程序员需花许多精力,才能确保不会互相穿透。这是任何游戏引擎的核心元件之一,碰撞检测系统(collision detection system)

2、碰撞系统通常紧密地和物理引擎(physics engine)整合。游戏引擎所所指的“物理”更精确地说应该称为刚体动力学(rigid body dynamics)模拟。刚体(rigid body)是理想化、无限坚硬、不变形的固体物体。动力学(dynamics)子是一个过程,计算刚体怎样在力(force)的影响下随时间移动及作用。

3、动力学模拟需大量使用碰撞检测系统,以正确地模拟物体的多种物理行为。布娃娃式死亡就是使用了物理效果。

4、物理模拟是多变的,难以预测的。物理引擎的引入会对工程产生多方面的影响。用于动力学模拟的碰撞模型,可能需要比非物理驱动的模拟更细致。

5、游戏引擎的碰撞/物理系统可占一个游戏引擎源代码中显著的百分比。

6、游戏引擎碰撞检测系统的主要用途在于,判断游戏世界中的物体有否接触(contact)。每个逻辑对象会以一个或多个几简单的何形状代表。例如球体、长方体、胶囊。也可秀更复杂的形状。碰撞系统判断在某指定时刻中,这些图形是否相交。因此,本质上是几何相交测试器。

7、碰撞系统不仅要回答图形是否相交,也提供接触的想关信息。刚体动力学模拟是碰撞系统的最苛求的客户,就算一些游戏无物理系统,也可能会大量使用碰撞检测引擎。一个可碰撞体通常拆分为形状和变换。多个可碰撞体共享一个形状描述能节省内存空间。

8、碰撞系统通常会通过一个名为碰撞世界(collision world)的数据结构,管理其所有的可碰撞实体。碰撞世界只需要包含游戏对象中有可能碰撞的可碰撞体。那么碰撞系统便不需要遍历无关的数据结构。

9、动力学系统的“世界”数据结构通常会与碰撞系统共享,模拟中每人刚体通常会关联至碰撞系统里的一个可碰撞体。碰撞世界有时候称为碰撞/物理世界,或直接称之为物理世界(physics world)

10、在二维空间中,形状含其面积,而其边界则是由1条曲线、或3条以上直线所定义。在三维空间中,形状含体积,其边界不是曲面便是由多边形所组成的。

11、凸形状的定义是,由形状内发射的光线不会穿越形状表面2次或以上。碰撞原型(collision primitive)可作为基本组件构成更复杂的形状。

  1)球体(sphere):最高效的碰撞原型

  2)胶囊体(capsule)

  3)轴对刘包围盒(axis-aligned bounding box,AABB):一个矩形的体积,6个面都与坐标系统的轴平行。AABB可以方便地由两个点定义:一个点是盒子在3个主轴上最小的坐标,而另一个则是最大的坐标。AABB的主要优点在于,可以高速地测试和另一AABB是否相交。而AABB的最大限制在于,它们必须一直保持与轴对齐,才能维持这个运算上的优势。

  4)定向包围盒(oriented bounding box,OBB):我们允许对齐的盒子在其坐标系中旋转,便会得到定向包围盒。

  5)离散定向多胞形(discrete oriented polytyope,DOP):是比AABB,OBB更泛化的形状。DOP是凸的胞形,用来逼近物体的形状。AABB是一个6-DOP,其各个平面法矢量与坐标轴平等。OBB也是6-DOP。

  6)任意凸体积(arbitrary convex volume):凸体积的相交测试比上面几种原型都更耗时。

  7)多边形汤(polygon soup):有些碰撞系统也会支持完全任意、非凸的形状。这些形状通常是由三角形或其他简单多边形所构成的。多用于地形或建筑物。 多边形汤做碰撞检测最费时。通常仅把多边形汤用在不参与动力学模拟的物体。多边形汤无内我之分。

  8)复合形状(compoun shape):用一组形状来逼近物体形状。

12、碰撞测试

  1)点与球体相交。生成一个自球心至该点的分离矢量s,然后量度该矢量的长度。若长度大于球体半径,则该点位于球体之外,否则就是球体之内。

  2)球体与球体相交。求两球心距离,若大于r1+r2,则不相交,否则相交。

  3)分享轴定理(separating axis theorem)。若能找到一个轴,两个凸形状于该轴上的投影不重叠,就能确定两个形状不相交。若这样的轴不存在,并且那些形状是凸的,则可以确定两个形状相交。(若形状为凹的,就算找不到分离轴,形状也可能不相交。这就是我们偏好在碰撞系统中仅使用凸形状的原因之一。)其中分离线是把两个物体分开的直线。它必须垂直由分离轴。在三维空间中,分离线成为分离平面。计算时,需要找出每一个潜在的分离轴,用于计算两物体是否在些轴上分离。

  4)AABB与AABB相交。由于AABB的面与一组坐标轴平行,所以若存在分离轴,它必然是3个坐标轴之一。我们可以将分离轴定理应用于AABB。

  5)检测凸碰撞,GJK算法。GJK算法可以高效地检测任意凸多胞形(polytope)。GJK算法依赖于闵可夫斯基差(Minkowski difference):把A图形中的所有点,与B图形中的所有点成对相减,得出的集合便是闵可夫斯基差。用处在于,当两个形状相交,闵可夫斯基差会包含原点。

13、如何实现代码选择合适的碰撞测试函数。许多引擎使用双分派(double dispatch),单分派的也有(虚函数调用)。双分派可以实现为二维查找表,或先调用A的虚函数,再调用B的虚函数。通常引擎中会有一个碰撞代码,所有的碰撞都由代理来完成。

14、当场景中包含体积小且速度快的物体时,容易发生子弹穿纸问题(bullet through paper),也叫隧穿(tunneling)。避免此问题的方法之一是扫掠形状(swept shape)。测试相交时,由测试碰撞世界的静态快照,改为测试形状从上一个快照的位置及定向移动至当前快照所形成的扫掠形状。处理隧穿问题的另一方法为连续碰撞检测(continuous collision detection,CCD)。CCD的目标是对两上移动何物于某时间区间内,求得最早的冲击时间(time of impact,TOI)。

15、性能优化

  1)时间一致性(temporal coherency)。也称为帧一致性。当碰撞体以正常速率移动,在两时步中其位置及定向通常会很接近。通过跨越多帧把结果缓存,我们可以避免每帧重新计算一些类型的信息。

  2)空间划分(space partitioning)。如果两个物体分属不同的区域,那么显然两物体不会碰撞。常用法有八叉树。

  3)三阶段法。粗略阶段->中间阶段->精确阶段

16、碰撞查询(collision query)。或称为投射(cast),用于判断若假想的物体或光线沿线段运行是否会碰到世界中的物体。投射的物体并不真正存在于碰撞世界,完全不影响世界中的其它物体。

17、最简单的碰撞投射是光线投射(ray cast)。可用于角色A是否能直接看见角色B。若投射的是球体,则称为球体投射(sphere cast),更一般的情况称为形状投射(shape cast)。无论投射什么类型的凸形状,都有可能产生多个接触点。

18、phantom是一种虚拟碰撞体。 用于判断碰撞体是否位于指定体积里。phantom与正常碰撞体的唯一区别是,phantom对于碰撞世界中其他碰撞体来说是“透明”的。

19 、碰撞过滤(collision filtering)

  1)碰撞掩码及碰撞层。为碰撞体分类,指明哪些碰撞体之间可以发生碰撞。

  2)碰撞回调。用于程序动态决定哪些碰撞体间可以发生碰撞。

  3)碰撞材质(collision material)。把每个碰撞表面关联至一组属性。可以是音效、粒子效果、物理属性。

猜你喜欢

转载自www.cnblogs.com/yxnchinahlj/p/9766656.html