3D碰撞/物体检测如何工作?

时间:2009-12-25 05:32:28

标签: algorithm data-structures 3d collision-detection

我总是想知道这一点。在像GTA这样的游戏中,有成千上万个物体,一旦你在健康包上,游戏怎么知道呢?

每个对象都不可能有一个事件监听器?迭代也不好?我只是想知道它是如何完成的。

6 个答案:

答案 0 :(得分:59)

对此没有一个答案,但是大型世界通常通过使用quadtreekd-tree的线条进行空间划分,这样可以在线性时间内找到最近邻居的搜索时间(分数幂) ,或者最坏的是O(N ^(2/3))用于3D游戏)。这些方法通常被称为 BSP ,用于二进制空间分区。

关于碰撞检测,每个对象通常还具有与其相关联的边界体网格(形成凸包的多边形集)。这些高度简化的网格(有时只是一个立方体)不是绘制的,而是用于检测碰撞。最基本的方法是创建一个平面,该平面垂直于连接每个对象的中点的线与在线的中点处与线相交的平面。如果对象的边界体积在此平面的两侧都有点,则它是一个碰撞(您只需要测试两个边界体积中的一个相对于该平面)。另一种方法是增强的GJK距离算法。如果您想要深入了解教程,请查看NeHe Productions' OpenGL lesson #30

毫无疑问,边界卷也可用于其他优化,例如所谓的遮挡查询。这是确定哪些对象在其他对象(遮挡物)后面的过程,因此不需要处理/渲染。边界体积也可以用于视锥体剔除,这是确定哪些物体在透视观察体积之外(太近,太远或超出视野角度)的过程,因此不需要渲染。


正如Kylotan所指出的那样,使用边界体积可以在检测到遮挡时产生误报,并且根本不能用于某些类型的物体,例如环形(例如,通过环形孔中的洞观察)。正确遮挡这些对象是 portal-culling 上的另一个线程。

答案 1 :(得分:9)

Quadtrees and Octreesanother quadtree是使用空间分区来实现此目的的流行方式。后一个例子显示,对于碰撞,逐对蛮力搜索的处理减少了97%。

答案 2 :(得分:4)

游戏物理引擎中的常用技术是扫描和修剪方法。这在David Baraff's SIGGRAPH notes中有解释(参见Motion with Constraints章节)。 Havok绝对使用它,我认为这是Bullet中的一个选项,但我不确定PhysX。

这个想法是你可以在每个轴上查看AABB(轴对齐的边界框)的重叠;如果两个对象的AABB的投影在所有三个轴上重叠,则AABB必须重叠。您可以通过对AABB的起点和终点进行排序来相对快速地检查每个轴;帧之间存在很多时间相干性,因为通常大多数对象移动速度都不快,因此排序变化不大。

一旦扫描和修剪检测到AABB之间的重叠,您可以对对象进行更详细的检查,例如球体与盒子。如果详细检查显示发生碰撞,则可以通过施加力来解决碰撞,和/或触发游戏事件或播放声音效果。

答案 3 :(得分:2)

正确。通常,每个对象都没有事件侦听器。通常在内存中存在一个模仿游戏地图的非二叉树结构。想象一下地铁/地下地图。 这个记忆结构是游戏中的一些东西。你是玩家,怪物和物品,你可以拾取或物品,可能爆炸,你伤害。因此,当玩家在游戏中移动时,玩家对象指针在游戏/地图存储器结构中移动。

请参阅How should I have my game entities knowledgeable of the things around them?

答案 4 :(得分:1)

可以使用很多优化。 首先 - 任何对象(例如索引i)都以立方体为界,中心坐标为CXiCYi,大小为Si 其次 - 碰撞检测与估计一起使用:

a)找到条件为Abs(CXi-CXj)<(Si+Sj) AND Abs(CYi-CYj)<(Si+Sj)

的所有对立方体i,j

b)现在我们只使用a)中的对子。我们更精确地计算它们之间的距离,类似于Sqrt(Sqr(CXi-CXj)+Sqr(CYi-CYj)),现在表示为几组简单图形的对象 - 立方体,球体,圆锥体 - 我们使用几何公式来检查这些图形交叉点。

c)来自b)的具有检测到的交叉点的物体被处理为与物理计算等的碰撞。

答案 5 :(得分:1)

我想推荐Christer Ericson关于实时碰撞检测的实用书籍。它介绍了碰撞检测的基础知识,同时提供了当代研究工作的参考资料。

Real-Time Collision Detection (The Morgan Kaufmann Series in Interactive 3-D Technology)