【问题标题】:Collision detection in a voxel world?体素世界中的碰撞检测?
【发布时间】:2017-05-28 14:33:43
【问题描述】:

我一直在研究体素游戏有一段时间了,它使用的是我编写的算法。但是,我仍然坚持碰撞检测;因为我真的不知道从哪里开始。体素引擎并不复杂。

我只需要计算高度图的高度。

以这张脸为例:(请原谅我的糟糕形象)

假设我相对于多边形的位置是 0.5,0.5(中心)。此时我将如何计算 y 位置?

【问题讨论】:

  • 也许我错了,但体素的边长通常不是 1 个单位(例如像素),因此每个体素都有一个唯一的位置 (x,y,z),坐标相同在其 3D 空间中独一无二。碰撞检测应该“只”需要检查位置是否已经包含体素。
  • 对不起,我应该更清楚一点:我所说的体素不是指它以体素渲染,而是一切都基于立方体(有点像我的世界是如何做到的)
  • 您的图像是错误的还是您真的在 Y = 0 时有三个角,在 Y = 1 时有一个角?如果是这样,那不是体素,那是六面体。如果是这种情况,在六面体中,您通常对任何事情都使用三线性插值。搜索双线性插值。也就是说,Simon Kraemer 是绝对正确的,这不是一个好的碰撞检测方案。需要太多操作。在任何情况下,您都希望使用诸如碰撞盒之类的东西,以减少计算量。排除一开始的大部分碰撞。八叉树结构不会是一个坏主意。
  • 我绝对不会对游戏中的每个立方体都使用这个计算,所以不用担心。
  • 如果图片有误,您还没有回答。这个很重要。如果我们有一个六面体,我们做三线性插值,如果我们有一个体素,我们可以简单地添加值,正如西蒙所说。

标签: c++ collision


【解决方案1】:

在我看来,这张照片更像是“高度图”,而不是体素。如果这是真的并且只有一个角是“1”,那么您必须定义如何为中间部分建模。

使用锐边三角测量,您可以以两种变体结束:

 ___        ___
|\  |      |  /|
| \ |      | / |
|__\|  vs  |/__|

在第一种情况下,整个中间边缘是 Y=0,所以您在 [0.5, 0.5] 处的点也在 Y=0 处,在第二种情况下,中间边缘从 0 到 1 线性变化,并且在 [0.5 , 0.5] Y=0.5。

或者您可以使用更复杂的方法来定义内部特定的 [x,y] 高度,例如一些 B 样条、加权平均等。

但是如果你的地图有足够好的分辨率,我会以另一种方式分割它,体素之间的边缘在 +-0.5,+-0.5,并且选择“体素”的高度低于 ([0.5, 0.5 ] 是 4 个体素的交叉点,很难说哪个会被选中,但 Y=0 或 1)。

如果你需要比 0/1 更高的分辨率,你可以将中间点 Y 计算为四个的平均值,然后每个带有中间点的边形成一个三角形,在那里你可以计算 [x,y] Y 而没有歧义(在你的情况 [0.5, 0.5] 正好在中间点,所以 Y=0.25 ((0+0+0+1)/4))。像这样:

 ___
|\ /|
| X |
|/_\|

【讨论】:

  • 是的,图片是高度图。我应该澄清这一点。对不起
  • @Anonymus 那么你不应该谈论体素:体素是 volume 的有限元素,但高度图只定义了一个 表面。使用体素进行碰撞检测始终等同于使用边界框进行碰撞检测,不需要插值。
  • @Anonymus:我猜你在做某种光线投射?将高度列渲染为高体素?像旧的DOS intro "mars" 和类似的?或者也许是一些立方体行进算法来为每个列创建立方体,就像你提到的 Minecraft 一样。所以这可能就是你使用“体素”的原因......但这些解决方案通常会将各种东西混合在一起,以适合特定目的。只要您希望“表面上的碰撞”高度图数据就足够了,渲染是另一回事。
【解决方案2】:

感谢 Ped7g,我们终于找到了高度图的实际问题。

首先我想指出,这与体素完全无关。您的引擎碰巧使用体素,但您的问题无关紧要。 碰撞检测也是如此。虽然它与您想要使用的东西相关,但您基本上忽略了实际问题。

其次,像 Ped7g 这样的三角剖分提出了工作,但我看到了一个缺点,它基本上会产生一个由三角形组成的表面。 对于您的示例和三角测量

 ___        
|\  |    
| \ |    
|__\|

左下角的三角形将平放在地面上,只有右上角有一个斜坡。 更复杂的三角剖分看起来会更好,但仍然由三角形表面组成,并且还需要您使用多组重心坐标。

在正方形内插值的常用方法是Bilinear Interpolation,每个角都会影响每个点,公式很简单。

给定 0..1 中的 λx 和 λz 表示您在单位正方形中的相对位置(在 x 和 z 上)以及角上的高度 y00、y01、y10 和 y11,高度很简单

y = (1-λx)(1-λz)y00 + (1-λx)(λz)y01 + (λx)(1-λz)y10 + (λx)(λz)y11

请注意,这将在边缘创建线条。双线性插值的优点是速度。一个缺点是在边缘上,高度不会平滑,即不可微分。如果你想要这样,你需要更复杂的方法来考虑相邻的正方形。 Ped7g 提到了 B-Splines,可以使用 B-Splines 曲面,但需要一段时间才能实现,而且速度很快,不建议初学者使用(但如果您有兴趣,click on this link。第 8 章包含您需要的内容,但您最好在此之前阅读其他章节)。一个好的中间立场是Bicubic Interpolation。该链接包含双三次和双线性插值的视觉比较。

如果您是初学者,我建议您使用双线性。

【讨论】:

  • 谢谢!这个答案真的帮助了我!很抱歉造成混乱,我还是这个网站的新手,并不真正知道如何以一种好的方式提出我的问题。
猜你喜欢
  • 1970-01-01
  • 2012-04-03
  • 1970-01-01
  • 1970-01-01
  • 2013-08-25
  • 1970-01-01
  • 2015-02-01
  • 2014-02-04
  • 1970-01-01
相关资源
最近更新 更多