程序结构生成

问题描述 投票:1回答:3

我目前正在开发基于体素的游戏,到目前为止,我通过使用Simplex Noise创造了我的世界。现在,我想生成一些其他结构,如河流,城市和其他东西,由于我将世界(实际上是无限的)分割成64x128x64的块,因此不容易生成。我已经生成了树(叶子可以长成相邻的块),方法是为一个块生成树,再为周围的8个块生成树,因此叶子不会丢失。但是,如果我进入更高的维度可能会遇到困难,那么当我不得不计算一个块时,要考虑半径为其他16个块的块。

有没有办法做得更好?

voxel procedural-generation
3个回答
1
投票

取决于所生成结构的所需复杂度,您可能会发现首先在单独的数组中生成它很有用,甚至可能是地图(位置对内容字典,在稀疏度较高的情况下也有用),然后进行传输世界的结构?

至于自然土地特征,您可能想问一下谷歌如何在景观生成中使用分形。


0
投票

我在书上读到了一些有关这些的内容,在这种情况下,他们所做的是根据应用程序对块进行更好的划分,即:如果您要种植非常大的对象,那么将另一个对象分开可能会很有用。仅用于此特定应用的逻辑分割,例如128x128x128。

本质上,数据驻留在同一位置,您只是使用不同的逻辑划分。

说实话,从来没有做过任何体素,所以不要把我的答案太认真,只是提出想法。顺便说一下,这本书是游戏引擎宝石1,它们在体素引擎上有宝石。

关于河流,难道您不只是设定水位并让河流在山腰山梯中自动生成吗?为避免将水倒入山区告密者,您可以进行射线探测,以检查是否有N阻挡。


0
投票

我知道这个线程很旧,我很会解释,但是我会分享我的方法。

例如5x5x5棵树。您想要的是让您的噪声函数为5x5块的区域返回相同的值,以便即使在块之外,您仍然可以检查是否应该生成树。

// Here the returned value is different for every block
float value = simplexNoise(x * frequency, z * frequency) * amplitude; 

// Here it will return the same value for an area of blocks (you should use floorDiv instead of dividing, or you it will get negative coordinates wrong (-3 / 5 should be -1, not 0 like in normal division))
float value = simplexNoise(Math.floorDiv(x, 5) * frequency, Math.floorDiv(z, 5) * frequency) * amplitude;

现在我们将种一棵树。为此,我们需要检查当前块相对于树的起始位置在x y z位置的位置,因此我们可以知道该块在树的哪个部分。

if(value > 0.8) { // A certain threshold (checking if tree should be generated at this area)
    int startX = Math.floorDiv(x, 5) * 5; // flooring the x value to every 5 units to get the start position
    int startZ = Math.floorDiv(z, 5) * 5; // flooring the z value to every 5 units to get the start position
    // Getting the starting height of the trunk (middle of the tree , that's why I'm adding 2 to the starting x and starting z), which is 1 block over the grass surface
    int startY = height(startX + 2, startZ + 2) + 1;

    int relx = x - startX; // block pos relative to starting position
    int relz = z - startZ;

    for(int j = startY; j < startY + 5; j++) {
        int rely = j - startY;
        byte tile = tree[relx][rely][relz]; // Get the needing block at this part of the tree
        tiles[i][j][k] = tile;
    }
}

这里的树3d阵列几乎就像树的“预制件”,您可以使用它来知道在相对于起点的位置处设置哪个块。 (上帝,我不知道该怎么解释,将英语作为我的第五种语言也无济于事;-;随时改善我的答案或创建一个新的答案)。我已经在引擎中实现了此功能,并且完全可以正常工作。这些结构可以任意大小,而无需预先加载块。这种方法的一个问题是,树木或结构几乎可以在网格内生成,但是可以使用具有不同偏移量的多个八度音阶轻松解决。

所以回顾

for (int i = 0; i < 64; i++) {
    for (int k = 0; k < 64; k++) {
        int x = chunkPosToWorldPosX(i); // Get world position
        int z = chunkPosToWorldPosZ(k);

        // Here the returned value is different for every block
        // float value = simplexNoise(x * frequency, z * frequency) * amplitude; 

        // Here it will return the same value for an area of blocks (you should use floorDiv instead of dividing, or you it will get negative coordinates wrong (-3 / 5 should be -1, not 0 like in normal division))
        float value = simplexNoise(Math.floorDiv(x, 5) * frequency, Math.floorDiv(z, 5) * frequency) * amplitude;

        if(value > 0.8) { // A certain threshold (checking if tree should be generated at this area)
            int startX = Math.floorDiv(x, 5) * 5; // flooring the x value to every 5 units to get the start position
            int startZ = Math.floorDiv(z, 5) * 5; // flooring the z value to every 5 units to get the start position
            // Getting the starting height of the trunk (middle of the tree , that's why I'm adding 2 to the starting x and starting z), which is 1 block over the grass surface
            int startY = height(startX + 2, startZ + 2) + 1;

            int relx = x - startX; // block pos relative to starting position
            int relz = z - startZ;

            for(int j = startY; j < startY + 5; j++) {
                int rely = j - startY;
                byte tile = tree[relx][rely][relz]; // Get the needing block at this part of the tree
                tiles[i][j][k] = tile;
            }
        }
    }
}

所以'i'和'k'随块循环,而'j'则在结构内部循环。这几乎是应该如何工作的。

关于河流,我个人还没有做过,而且我不确定为什么在生成它们时为什么需要在块周围设置块(您可以只使用perlin蠕虫来解决问题),但是这几乎是相同的想法,对于您的城市也是如此。

© www.soinside.com 2019 - 2024. All rights reserved.