3D碰撞/物体检测如何工作?
我一直在想这个。 在像GTA那样有数千个物品的游戏中,一旦你在健康包里,游戏是如何知道的?
每个对象都不可能有一个事件监听器? 迭代也不好? 我只是想知道如何实际完成。
没有人回答这个问题,但是大的世界常常是通过使用沿着四叉树或kd树的线来进行空间分割的,这使得在线性时间(分数功率或最坏的情况下)find最近的邻居的search时间O(N ^( 2/3))为3D游戏)。 这些方法通常被称为二进制空间分区的BSP 。
关于碰撞检测,每个对象通常还具有与其关联的边界体积网格(形成凸包的多边形集合)。 这些高度简化的网格(有时只是一个立方体)不会被绘制,而是用于检测碰撞。 最基本的方法是创build一个平面,该平面垂直于连接每个对象的中点和与该线中点处的线相交的平面的线。 如果一个物体的边界体在这个平面的两边都有点,这是一个碰撞(你只需要在平面上testing两个边界体中的一个)。 另一种方法是增强的GJK距离algorithm。 如果你想要一个教程,请查看NeHe Productions的OpenGL课程#30 。
有意义的是,边界卷也可以用于其他优化,比如所谓的遮挡查询 。 这是确定哪些对象位于其他对象(遮挡物)之后的过程,因此不需要处理/呈现。 边界体积也可以用于截锥体剔除 ,这是确定哪些对象在透视观察体积之外(太接近,太远或超出视野angular度)的过程,因此不需要被渲染。
正如Kylotan指出的那样,使用边界体积可能会在检测到遮挡时产生误报,而对于某些types的物体(如环形面)(例如通过圆环中的孔)则完全不起作用。 有这样的对象正确的阻塞是门户剔除的整个其他线程。
另一个四叉树四 叉树和八 叉树是使用空间分割来实现这一点的stream行方式。 后面的例子显示,在一对一对的蛮力search冲突中,处理减less了97%。
游戏物理引擎中常见的技术是扫除和清除方法。 这在David Baraff的SIGGRAPH笔记中有解释(请参阅Motion with Constraints章节)。 Havok绝对使用这个,我认为这是Bullet中的一个选项,但我不确定PhysX。
这个想法是,你可以看看每个轴上的AABB(轴alignment的边界框)的重叠; 如果两个物体AABB的投影在所有三个轴上重叠,那么AABB必须重叠。 您可以通过对AABB的起点和终点进行sorting来相对快速地检查每个轴; 帧之间有很多时间上的一致性,因为通常大多数对象的移动速度都不是很快,所以sorting没有多大改变。
一旦扫描和修剪检测到AABB之间的重叠,你可以做更详细的检查对象,例如球与盒。 如果详细检查发现碰撞,则可以通过施加力量来解决碰撞,和/或触发游戏事件或发挥音效。
正确。 通常情况下,每个对象都没有事件监听器。 内存中通常有一个非二叉树结构,它可以模仿你的游戏地图。 想象一下地铁/地下地图。 这个内存结构是游戏中的东西的集合。 你是玩家,怪物和物品,你可以拾取或物品可能会爆炸,并对你有害。 所以当玩家在游戏中移动时,玩家对象指针在游戏/地图内存结构中移动。
看看我应该如何让我的游戏实体了解周围的事物?
我想推荐Christer Ericson的实时碰撞检测书。 它介绍了碰撞检测的基础知识,同时为当代的研究工作提供参考。
实时碰撞检测(交互式三维技术中的Morgan Kaufmann系列)
有很多优化可以使用。 首先 – 任何对象(例如索引为i)都是以立方体为界的,中心坐标为CXi
, CYi
和尺寸为Si
其次,碰撞检测的工作原理是:
a)找出所有具有条件的对立方体i,j: Abs(CXi-CXj)<(Si+Sj) AND Abs(CYi-CYj)<(Si+Sj)
b)现在我们只与a)中的对一起工作。 我们更精确地计算它们之间的距离,就像Sqrt(Sqr(CXi-CXj)+Sqr(CYi-CYj))
,现在这些对象被表示为几个简单graphics的集合 – 立方体,球体,圆锥体 – 我们使用几何公式检查这些数字交叉点。
c)来自b)的具有检测到的交叉点的物体被处理为与物理计算等的碰撞