现实世界应用中的碰撞问题

16
这是我的问题。我正在创建一个游戏,想知道如何进行碰撞检测。我有几种情况需要分析并找到最佳解决方案。
事先声明,我没有使用任何第三方物理库,而是要在内部实现(因为这是教育项目,我没有时间表,我想学习)。
我有两种类型的网格需要进行碰撞检测:
1)静态网格(在屏幕上移动,但没有任何动画)
2)皮肤/骨骼网格(有动画)
目前我有这个解决方案(很粗略):
首先,我对一些包围整个网格的边界体(在我的情况下是胶囊体)进行测试,之后:
1)对于静态网格,我手动将它们分成块(在建模程序中),对于每个块,我使用球体/AABB测试。(效果不错,但是切割每个网格有点乱:P)(我尝试了一种自动通过平面划分网格的系统,但结果不好:()
2)对于动画网格,我目前在运行时将网格分成x块(其中x是骨骼数量)。每个块包含受该骨骼主要影响的顶点。(有时效果不错,有时效果非常糟糕:|)
请注意,网格的分割是在加载时完成的而不是每次运行时(否则它会像幻灯片一样运行)。
问题是:
对于这两种情况,什么是最合理的想法?有没有材料可以供我学习这些方法?(带有一些源代码和解释更好(语言不重要,当我理解算法时,实现很容易))你能为什么该解决方案优于其他解决方案提供论据吗?我听说了很多关于kd树、八叉树等的讨论,虽然我理解它们的结构,但我不知道它们在碰撞检测场景中的效用。
感谢您的回答!
编辑:试图在网上找到一个具有一些解释的K-Dop示例。仍然没有找到任何线索?我对如何使用其他类型的边界体有效地测试K-Dop感兴趣,但网络上的文档似乎非常缺乏。 :(

4个回答

6
在进行复杂碰撞检测之前,您应该执行基本检测。使用球体或矩形作为边界体是最好的选择。如果这样检测到了碰撞,则可以转向更复杂的方法。我的意思是简单往往更好,更快。包装边界体和分割网格是昂贵的,更不用说复杂了。不过你似乎已经在正确的轨道上了。与游戏编程一样,有多种碰撞检测的方法。我的建议是从简单开始。拿一个立方体来完善你的程序,然后理论上你应该能够使用任何其他模型。至于示例,我会查看gamedev.net,因为他们有一些不错的文章。我的自制碰撞检测大部分是许多方法的组合,所以我无法推荐终极资源。

2
显然,我首先对网格的完整包围体(在我的情况下是胶囊形)进行测试,然后再着手处理需要理解的复杂部分,这也是本问题讨论的主题。 - feal87

5
许多当前AAA游戏中最常用的方法是对于StaticMeshes使用"k-DOP"简化碰撞,而对于SkeletalMeshes使用简化的物理体表示。
如果您搜索"kDOP collision"或"discrete orientation polytopes",您应该能够找到足够的参考资料。这基本上是一个边界体,由从外部向网格移动的几个平面定义,直到发生三角形碰撞。kDOP中的"k"定义了使用多少个平面,根据您的几何和"k",您可以得到非常好的近似值。
对于SkeletalMeshes,最常见的技术是定义附加到特定骨骼的简单几何体。这种几何模型可以用于对动画网格进行相当准确的碰撞检测。
如果您需要每个三角形的碰撞检测,则"Separating Axis Theorem"是您选择的搜索词。这对于特定情况很有用,但你75%的碰撞检测需求应该可以用以上提到的方法解决。
请记住,您很可能需要比边界体更高级别的早期碰撞拒绝。一旦在世界中有大量对象,您将需要使用"空间分区"来尽早拒绝进一步测试的对象组。

很好的回答。有很多值得参考的东西。明天我会进行详细搜索并开始实施,然后在这个帖子上报告更多进展。暂时给一个赞!谢谢。 - feal87
我正在搜索整个网络,但仍然没有找到一个带有K-Dop解释的可行示例。只有许多理论论文(需要付费才能查看)。有任何线索吗?:( - feal87
D-Collide似乎是一个实现kDop的开源碰撞库,因此这可能值得一看,以获取实现示例。http://d-collide.ematia.de/这个gamedev.net线程涵盖了许多实现细节:http://www.gamedev.net/community/forums/topic.asp?topic_id=430895&whichpage=1&#2866170 - DarthCoder

3
回答这个问题关键在于您需要多精确。
显然,球形边界框是最简单的。另一方面,您有完整的三角形网格-网格碰撞检测,每次对象移动时都必须进行。
游戏开发物理引擎依赖于近似的艺术(我几年前曾在GameDev.net的数学和物理论坛上潜水)。
我的观点是,您需要为每个对象关联某种边界椭球体。一个对象可以是一般的多网格对象、网格或子网格网格。这应该提供'相当'的近似值。

我的意思是,对于简单的物体(如球体、胶囊体、OOBB、AABB、椭球体等),这样做还可以。 如果我想为一个复杂的物体(如飞船或人)制作碰撞树,我需要将网格分成多个部分。这是基本问题。 最好的方法是如何划分网格并在系统中使用它们?我有自己的系统,所以可以随心所欲地移动数据,但我想知道最常接受的方法,这样我就可以避免尝试无用的东西。 - feal87
@feal87:我不知道常见/公认的方法。但是我会在每个“足够有趣”的对象及其子对象的创建时间,在元数据中生成一个椭球体,允许递归以细化细节。 - Paul Nathan

2

建议阅读Christer Ericson的书,《实时碰撞检测》,他详细讨论了这些问题。

在阅读文章时,请记住,在实际游戏应用中,您将在内存和时间的硬性限制下工作——每帧只有16.6毫秒!因此,请谨慎对待任何没有严肃讨论其算法的内存和CPU占用的文章或论文。


谢谢您的建议,如果我在网上找不到任何信息,我将来会考虑它。 - feal87
+1 对Christer的书表示赞同。它是一本优秀的参考书,涵盖的领域比标题所示更广泛。 - zebrabox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接