地形物体碰撞检测

Terrain Object collision detection

我在过去几年编写了自己的 3D 游戏引擎,并想实际将其用于游戏。

我偶然发现了以下问题:

我的游戏中有多架飞机,但让我们谈谈一架飞机。 飞机自然无法潜入地下,在地势之下飞行。 因此,我需要实现一些东西来检测 plane/jet 和我的地面之间的碰撞。

给出的信息如下:

  1. 地形网格[二维数组;根据 x,z 坐标存储高度]
  2. 我的飞机的Hitbox(它和我的飞机一起移动,所以边界等都已经计算好了)

关于碰撞箱: 我想知道使用哪种方法。就性能而言最好的似乎是具有不同半径的简单球体。

关于地面:图形上,地面被细分为三角形:

所以我现在需要的是最佳类型的碰撞箱(球体,AABB,...)和相应的最有效的计算。

我的尝试是获取每个周围的三角形并计算从那个三角形到我的碰撞框球体每个中心的距离。如果距离小于半径,则已成功检测到碰撞。但是当我的平面上有多达 10/20 个球体并且要检查 100 个三角形时,这将花费很多时间。

另一个尝试是获取每个碰撞盒球体到地面的垂直距离。这个需要更少的计算,但在接近陡峭的表面时会失败。

如果有人能帮助我实现一个高效的 plane/terrain 碰撞检测版本,我将非常高兴 :)

  1. 渲染地形

    也许您可以尝试 来提高准确性。

  2. 读取深度纹理

    您可以将 glReadPixelsGL_DEPTH_COMPONENTGL_FLOAT 一起使用。这会将深度缓冲区复制到 CPU 端内存中。所以现在你也可以在 CPU 侧进行碰撞或任何与视图中地面相关的计算...

  3. 使用深度缓冲区作为纹理

    所以用 glTexImage2D 将它复制回 GPU。我知道这很慢(但很可能比你当前的碰撞计算快得多。如果你没有使用 Intel HD Graphics 你可以改为 #2,#3 使用 FBO 作为深度,这会将深度缓冲区直接渲染到纹理。但在 Intel 上,这不能可靠地工作(或根本不能)。

  4. 现在使用 GLSL 渲染对象(屏幕外)

    在片段着色器内部,只需将渲染位置与深度(附加为纹理)进行比较。如果波纹管在某处输出碰撞。如果在计算着色器中完成,则可以将结果存储在某些纹理中。或者您可以为此使用一些附件或 FBO

    如果您不能使用 FBO,您可以渲染到 "screen",并使用特定颜色编码的冲突。然后用 glReadPixels 阅读它并扫描它以处理你在 CPU 方面的任何碰撞逻辑...

    不要在这个过程中写入深度缓冲区!!!并且也不要使用 CULL_FACE 因为这可能会错过对象背面的一些碰撞。

  5. 现在正常渲染对象

    如果您不在 #4 中渲染,或者您将碰撞编码到屏幕缓冲区,您需要 overwrite/render 这些东西。否则不需要此步骤。但是碰撞检测后的渲染是好的,因为在碰撞的情况下你很可能改变对象 position/orientation/mesh 并且已经渲染的对象可能会阻碍改变的对象。

[注释]

CPUGPU之间复制图像很慢所以使用FBO如果可以的话渲染到纹理。

如果您不熟悉多通道渲染,请参阅一些 QA 以获取灵感:

  • Render filled complex polygons with large number of vertices with OpenGL

这仅在视图中有效...但您可以只进行碰撞渲染过程(每个对象)。渲染相机设置为从上到下(鸟瞰图)并仅覆盖物体周围的区域......此外,你不需要太大的分辨率,所以它应该相对较快......所以你可以将屏幕分成正方形区域(使用 glViewport)在单帧中测试更多对象以尽可能降低同步时间(使用较少的 glReadPixel 调用)。此外,您不需要任何顶点颜色或纹理。