平滑体素地形


13

作为个人项目,我正在尝试制作一个地形生成器,以创建看起来像《城堡物语》平滑地形的地形。

如果您以前没有看过,请在这里: 在此处输入图片说明

如您所见,它是块和“平滑”块的组合。

我试图模仿这种外观的方法是为每个表面块提供一个迷你高度图。通常这是可行的,但存在一些问题,产生如下所示的地形:

在此处输入图片说明

问题是每个块都是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);
    }
}

也许我通过使用“真实的”珀林噪声值来错误地解决了这一问题?

任何帮助将不胜感激!

Answers:


11

由于技术限制,《城堡物语》看起来像这样:整个体积中每个体素都有一个高度图,而不是每个表面体素只有一个高度图,存储成本将大大增加,大约为O(n ^ 3 )相对于更有利的O(n ^ 2)而言可能是禁止的,其中n是代表您的世界的立方体素空间的边长。请记住,地下体素的高度图信息在网格结构中是隐式的,因此仅需要为位于表面上的那些体素显式存储高度图信息。因此,Castle Story的家伙已经将顶点捕捉到网格空隙中,以节省存储成本和网格构造复杂性……请继续阅读。

首先,让我们看看您的选择:

在此处输入图片说明

(1)将使您感到困难,因为在单个体素列中,您只需要最顶部体素的迷你高度图信息-原因请返回第一段。看一下(1),右边的列同时具有最顶部和第二个自上而下的高度图信息(如果斜率足够极端,则这可能适用于第三个自上而下等等)。不好

(2)可能是一个更好的选择;也就是说,确保角顶点捕捉到体素网格空隙。但是,我们如何解决极端坡度问题呢?好吧,我们需要选择一些渐变,在该渐变中我们可以简单地捕捉到垂直列,从而确保没有可以穿过n个最上层体素的渐变。由于以下原因,45度渐变是自然截止。因此,除了(3)之外,我们还有(4):

在此处输入图片说明

(4)将体素的角顶点捕捉到最近的网格空隙是解决方案。视觉效果-对角线锯齿-可以在您的《城堡物语》屏幕截图中看到。体素的截止坡度为1:1梯度或45度(正交观察)。从解决方案开始倒退,让我们看一下原因:

  • 我们要保持不间断的极端坡度的唯一方法是如果将体素垂直拉长...
  • ....但是,无论体素的实际平滑形状如何,体素的网格都不能超出其边界区域。体素需要坐在3D网格的定义空间中,如果不是因为其确切形式,则至少要考虑其与轴对齐的边界框。

采用这种方法的另一个原因是,正如您已经发现的那样,不使用捕捉(离散化)会导致一系列几何上复杂的表面平滑场景,最好完全避免...这类游戏通常不需要正确的CSG算法将提供的准确性的程度,这就是我们首先使用体素的全部原因:与浮点(连续)多边形相交/ CSG算法相比,体素使处理体积增量工作容易得多。 。


我只是尝试实现这一点,但我遇到了一些困惑-您所说的“空隙”是什么意思?您是说整数网格坐标吗?
无题

@ThomasBradworth。“介于事物之间的空间。” 对于2D,如果您有一个单元格网格,则将有(n + 1)x(n + 1)个间隙。这直接扩展到3D。它们是绑定每个单元的“顶点”,通常在多个单元/体素之间共享。如果将其煮沸至1D(一条线),则如果单元格和间隙都表示为数组,则单元格0将以间隙0和间隙1为界,而单元格1将以间隙1和间隙2为界...等
工程师

谢谢回复!我确实尝试这样做,但是得到了一些不利的结果。刚开始,我只是尝试对边缘的高度值进行四舍五入(当x为0或4或z为0或4时),但这使我:i.imgur.com/eQW7Y.pngpastebin.com/Lr8vyyHB)接下来,我尝试平滑中间的点,因此添加了一个“修复高度函数”:pastebin.com/AazQ07Xm但是,这也给了我更多角度但也很糟糕的结果: i.imgur.com/q1JVP .png 我的噪波功能也许有问题?
无题

@ThomasBradsworth不幸的是,我觉得您对我花了一个多小时编写和编辑的答案只读了一半。忘记噪音;此外,如果您不了解噪声函数,请暂时将其从方程式中删除。您的问题在于如何构建单个体素网格数据,而噪声与之无关,因为您可以在没有噪声的情况下创建高度图。使用最简单的测试用例,即对高度数组进行硬编码。然后查看结果,并调整网格生成算法。重复直到达到预期效果。然后放回噪音,并进行检查。
工程师

您是在说我应该只存储转角的高度值,而不是存储“中间”点的高度值吗?
无题
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.