我正试图创建随机化的地形网格,就像我在下面的截图中所做的那样。
然而,我面临的问题是,当我试图减少三角形和顶点的数量(细节级别)。
我知道要做到这一点,我可以直接跳过顶点,例如。上面的网格是全细节网格,其顶点是这样生成的。
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轴)的一行顶点,如下图所示。
下面的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);
}
}
}
}
我想出了以下的解决方案来解决这个问题。
我解决的第一个问题是使用一个嵌套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++;
}
}
}
}