平滑的体素地形

作为一个个人项目,我正在试图制造一个地形发电机,这个发电机将会创造类似Castle Story平坦地形的地形。

如果您以前没有看过,请点击这里: 在这里输入图像描述

正如你所看到的,它是块和“平滑”块的组合。

我试图去模拟这种外观是给每个表面块一个微型的高度图。 这一般起作用,但是有一些问题,产生这样的地形:

在这里输入图像描述

问题是,每个块是1x1x1,但有时高度在一个特定的位置是负的或大于1.在这种情况下,我剪辑它,并将高度设置为0或1。

为了更好地说明我的意思,下面是一个图表: 在这里输入图像描述

为了生成高度,我基本上做到:

genColumn(int x, int z) { int highestBlockY = (int)noise2d(x, z); bool is_surface = true; for(int y = max_height - 1; y >= 0; y--) { Block b; if(is_surface) { b = Block.Grass; b.HasHeightMap = true; // generate heightmap for(int ix = 0; ix < 5; ix++) { for(int iz = 0; iz < 5; iz++) { float heightHere = noise2d(x + ix / 4, z + iz / 4) - y; // clip heights if(heightHere > 1) heightHere = 1; if(heightHere < 0) heightHere = 0; b.HeightMap[ix][iz] = heightHere; } } is_surface = false; } else { b = Block.Dirt; } setBlock(x, y, z, b); } } 

也许我正在通过使用“真实的”柏林噪音值错误地处理这个问题?

任何帮助将不胜感激!

由于技术的限制,Castle Story看起来像这样:如果在整个体积中每个体素都有一个高度图,而不是每个表面体素的高度图,则存储成本将会大大增加,大约为O(n ^ 3 )可能是禁止的,而不是更有利的O(n ^ 2),其中n是代表您的世界的立方体素空间的边长。 请记住,地下体素的高度图信息隐含在网格结构中,因此高度图信息只需要明确地存储在表面上的体素上。 所以城堡故事的人们已经把顶点alignment网格间隙,以节省存储成本和网格建设的复杂性… …继续读下去。

首先,让我们看看你的select:

在这里输入图像描述

(1)会让你感到困难,因为在一个单一的体素列中,你只需要最高体素的迷你高度图信息 – 请参考第一段的原因。 看(1),右边的列有顶部和顶部的高度图信息(如果斜率足够的话,这可以应用到第三个顶部等等)。 这不好。

(2)那么可能是一个更好的select; 也就是确保角点与体素格子间隙alignment。 但是,我们如何解决极端的斜坡问题呢? 那么,我们需要select一些渐变,我们只需将它们alignment到一个垂直列,从而确保我们没有梯度可以穿过n个最顶层的体素。 由于我在下面解释的原因,45度梯度是自然界限。 所以,而不是(3),我们有(4):

在这里输入图像描述

(4)将体素的顶点捕捉到最近的网格空间是解决scheme。 视觉效果 – 对角线别名 – 可以在Castle Story的截图中看到。 体素的截止斜率是1:1的梯度,或45度(正交观察)。 从解决scheme中退步,让我们看看原因:

  • 我们可以有一个完整的,极端的斜坡的唯一方法是,如果一个体素垂直拉长…
  • ….但是没有体素的网格可以超过它的边界区域,而不管它的实际平滑的形状; 一个体素需要坐在三维网格中的一个已定义的空间中,如果不是它的确切forms,那么至less是它的轴alignment的边界框。

以这种方式来处理这个问题的另一个原因是,正如你已经发现的,不使用捕捉(离散化)会导致一系列几何复杂的表面平滑场景,这是最好的避免…这类游戏一般不需要正确的CSGalgorithm将提供的准确度,这是我们首先使用体素的全部原因:体素使得它更容易与体积一起增量工作,而不是浮点(连续)多边形相交/ CSGalgorithm。