计算网格的缩小级细节

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

我正试图创建随机化的地形网格,就像我在下面的截图中所做的那样。

Randomly Generated Terrain Mesh

然而,我面临的问题是,当我试图减少三角形和顶点的数量(细节级别)。

我知道要做到这一点,我可以直接跳过顶点,例如。上面的网格是全细节网格,其顶点是这样生成的。

0->1->2->3->4->5->6->7->8->9->...。

为了生成更低的细节,我可以跳过顶点,只要跳过的顶点不超过顶点的长度,所以我可以做以下的生成来降低细节。

0->2->4->6->8->10->12->14->16-> ...

或。

0->4->8->12->16->20->24->28->32->...。

使用二维数组和嵌套循环使这个问题变得微不足道,因为在二维坐标xy上的每次迭代都可以通过增量来实现。1, 2, 4, 8, 然而,我处理的是1D格式的2D数组。

我有下面的代码,它可以执行并几乎正确地生成上面截图中的网格,不幸的是它似乎缺少了左上角(3d z轴)的一行顶点,如下图所示。missing line of vertices

下面的Execute(int, int)方法的一个注意事项是,任何对NativeArray的访问,如果不是标记为[ReadOnly],则会抛出一个异常,如果该数组访问的索引超出了它的批量大小。

public struct int6
{
    public int a, b, c, d, e, f;
    public int6(int a, int b, int c, int d, int e, int f) { this.a = a; this.b = b; this.c = c; this.d = d; this.e = e; this.f = f; }
}

public class MeshGeneratorJob2
{
    [ReadOnly] public static int width = 241;
    [ReadOnly] public static int height = 241;
    [ReadOnly] public static float topLeftX = (width - 1) / -2f;
    [ReadOnly] public static float topLeftZ = (height - 1) / 2f;
    [ReadOnly] public static NativeArray<float> heightMap = new NativeArray<float>(width * height, Allocator.TempJob);
    public static NativeArray<float> heightCurveSamples;
    public static NativeArray<float3> vertices = new NativeArray<float3>(width * height, Allocator.TempJob);
    public static NativeArray<int6> triangles = new NativeArray<int6>((width - 1) * (height - 1), Allocator.TempJob);
    public static NativeArray<float2> uvs = new NativeArray<float2>(width * height, Allocator.TempJob);

    public void Execute()
    {
        for (int i = 0; i < vertices.Length; i += 5)
        {
            Execute(i, 5);
        }
    }

    private void Execute(int startIndex, int count)
    {
        for (int vertexIndex = startIndex; vertexIndex < startIndex + count; vertexIndex++)
        {
            int x = vertexIndex % width;
            int y = vertexIndex / width;

            vertices[vertexIndex] = new float3(topLeftX + x, heightMap[vertexIndex] * 16.67f, topLeftZ - y);
            uvs[vertexIndex] = new float2(x / (float)width, y / (float)height);

            if (vertexIndex < triangles.Length && x < width - 1 && y < height - 1)
            {
                triangles[vertexIndex] = new int6(vertexIndex, vertexIndex + width + 1, vertexIndex + width,
                                                  vertexIndex + width + 1, vertexIndex, vertexIndex + 1);
            }
        }
    }
}
c# unity3d mesh heightmap
1个回答
1
投票

我想出了以下的解决方案来解决这个问题。

我解决的第一个问题是使用一个嵌套for循环y, x,y总是从startIndex开始。

然而,这引起了一个问题,因为vertexIndex可能高于三角形的长度,所以我在提供的startIndex处计算了当前的vertexIndex,如下所示:这里我引入了一个增量器的值,它同时递增x和y循环,而不是y++,x++,然而在这个例子中,增量器是1,本质上是一样的。

 int vertexIndex = (int)(math.ceil((float)width / incrementer) * math.ceil((float)startIndex / incrementer));

然而计算vertexIndex时又引起了另一个问题,在设置顶点时又引起了越界异常,这是由于startIndex被count递增,而count与增量器不一样。

为了解决这个问题,我在方法的开始添加了以下代码,以在需要时将startIndex四舍五入到下一个递增的count。

startIndex += startIndex % incrementer;

然后我得到以下代码。

public struct int6
{
    public int a, b, c, d, e, f;
    public int6(int a, int b, int c, int d, int e, int f) { this.a = a; this.b = b; this.c = c; this.d = d; this.e = e; this.f = f; }
}

public class MeshGeneratorJob2
{
    public static int width = 241;
    public static int height = 241;
    public static float topLeftX = (width - 1) / -2f;
    public static float topLeftZ = (height - 1) / 2f;
    public static int increment = 1;
    public static NativeArray<float> heightMap = new NativeArray<float>(width * height, Allocator.TempJob);
    public static NativeArray<float> heightCurveSamples;
    public static NativeArray<float3> vertices = new NativeArray<float3>(width * height, Allocator.TempJob);
    public static NativeArray<int6> triangles = new NativeArray<int6>((width - 1) * (height - 1), Allocator.TempJob);
    public static NativeArray<float2> uvs = new NativeArray<float2>(width * height, Allocator.TempJob);

    public void Execute()
    {
        for (int i = 0; i < vertices.Length; i += 5)
        {
            Execute(i, 5);
        }
    }

    private void Execute(int startIndex, int count)
    {
        startIndex += startIndex % increment;
        int vertexIndex = (int)(math.ceil((float)width / increment) * math.ceil((float)startIndex / increment));
        for (int y = startIndex; y < startIndex + count && y < height; y++)
        {
            for (int x = 0; x < width; x += increment)
            {
                vertices[vertexIndex] = new float3(topLeftX + x, heightMap[vertexIndex] * 16.67f, topLeftZ - y);
                uvs[vertexIndex] = new float2(x / (float)width, y / (float)height);

                if (vertexIndex < triangles.Length && x < width - 1 && y < height - 1)
                {
                    triangles[vertexIndex] = new int6(vertexIndex, vertexIndex + width + 1, vertexIndex + width,
                                                      vertexIndex + width + 1, vertexIndex, vertexIndex + 1);
                }
                vertexIndex++;
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.