在Unity C#中修复挤出网格的法线?

3
在Unity C#中,我正在使用基于平面多边形的2D向量点的程序化网格挤出。除了一个细节外,下面的代码运行良好:连接挤出网格前后的每个第二个三角形似乎都被翻转了,正如图片所示(使用双面着色器,我可以看到所有的三角形都存在,但是有些方向不对)。我该如何修复这些桥接法线的翻转?谢谢!

enter image description here

// Extrusion functionality via
// https://forum.unity.com/threads/trying-extrude-a-2d-polygon-to-create-a-mesh.102629/
// with Triangulator based on
// http://wiki.unity3d.com/index.php?title=Triangulator

public static Mesh GetExtrudedMeshFromPoints(Vector2[] points, float depth)
{
    const float frontVertex = 0f;

    Triangulator triangulator = new Triangulator(points);
    int[] tris = triangulator.Triangulate();

    Mesh m = new Mesh();
    Vector3[] vertices = new Vector3[points.Length*2];

    for (int i = 0; i < points.Length; i++)
    {
        vertices[i].x = points[i].x;
        vertices[i].y = points[i].y;
        vertices[i].z = frontVertex;
        vertices[i+points.Length].x = points[i].x;
        vertices[i+points.Length].y = points[i].y;
        vertices[i+points.Length].z = depth;
    }

    int[] triangles = new int[tris.Length*2+points.Length*6];
    int count_tris = 0;

    // Front vertices
    for (int i = 0; i < tris.Length; i += 3)
    {
        triangles[i]   = tris[i];
        triangles[i+1] = tris[i+1];
        triangles[i+2] = tris[i+2];
    } 

    count_tris += tris.Length;
    // Back vertices
    for (int i = 0; i < tris.Length; i += 3)
    {
        triangles[count_tris+i]   = tris[i+2] + points.Length;
        triangles[count_tris+i+1] = tris[i+1] + points.Length;
        triangles[count_tris+i+2] = tris[i]   + points.Length;
    }

    count_tris += tris.Length;
    // Triangles around the perimeter of the object
    for (int i = 0; i < points.Length; i++)
    {
        int n = (i+1) % points.Length;
        triangles[count_tris]   = i;
        triangles[count_tris+1] = i + points.Length;
        triangles[count_tris+2] = n;
        triangles[count_tris+3] = n;
        triangles[count_tris+4] = n + points.Length;
        triangles[count_tris+5] = i + points.Length;
        count_tris += 6;
    }

    m.vertices = vertices;
    m.triangles = triangles;

    m.RecalculateNormals();
    m.RecalculateBounds();
    m.Optimize();

    return m;
}
1个回答

1
如果人脸没有显示出来,你可能已经注意到它被翻转了,这是由于Unity中的绕序是顺时针方向。你的三角形链接在故障排除下已经说明:

“如果您无法看到使用此实用程序创建的多边形,请记得检查多边形是否面向相反的方向。如果是这样,您可以通过以相反的顺序构造网格来更改它。”

编辑:

为了进一步澄清,在你的代码中,这意味着你需要交换顶点索引的顺序。

// Triangles around the perimeter of the object
        for (int i = 0; i < points.Length; i++)
        {
            int n = (i + 1) % points.Length;
            triangles[count_tris] = i;
            triangles[count_tris + 1] = i + points.Length;
            triangles[count_tris + 2] = n;
            triangles[count_tris + 3] = n;
            triangles[count_tris + 4] = n + points.Length;
            triangles[count_tris + 5] = i + points.Length;
            count_tris += 6;
        }

// Triangles around the perimeter of the object
        for (int i = 0; i < points.Length; i++)
        {
            int n = (i + 1) % points.Length;
            triangles[count_tris] = n;
            triangles[count_tris + 1] = i + points.Length;
            triangles[count_tris + 2] = i;
            triangles[count_tris + 3] = n;
            triangles[count_tris + 4] = n + points.Length;
            triangles[count_tris + 5] = i + points.Length;
            count_tris += 6;
        }

但是要小心,因为顺序取决于您的深度(如果它比前面的顶点高或低)。

第二次编辑:

三角形的法向量依赖于绕序方向,这意味着排序有所区别。

例如:

1: Vector2(1f, 1f);
2: Vector2(1f, 0f);
3: Vector2(0f, 0f);

三角形

Triangle 1,2,3

并且

Triangle 1,3,2

有不同的正常。

Winding order of Triangles

你必须确保绘制的每个三角形的绕序一致。 或者,你可以告诉你的着色器禁用culling(使用Cull Off),就像你上面已经说过的那样。但这会带来计算时间的成本。在大多数情况下,这不应该太重要,但这始终取决于你的目的。此外,大多数时候你不想禁用剔除的副作用。

Hmm,在第二次尝试时,它只有时候有效,这可能就是你在警告中提到的。不知道我需要做什么才能让它适用于两种情况? - Philipp Lenssen
你需要确保frontVertex始终大于或小于depth。 最简单的方法是进行初始检查,如果frontVertex>depth,则需要交换两个参数。在这种情况下,您无需更改三角剖分的设置。 - nkazz
谢谢。在我的程序中,frontVertex始终为0f,深度始终为0.05f,但我仍然遇到了这些问题。该怎么办? - Philipp Lenssen
这是由于三角形的顺序问题,您可以修复顺序或网格中的位置(顶点位置)以解决。如需更多信息,请查看我的第二次编辑。 - nkazz
谢谢!我该如何修复我正在使用的代码库中的绕组顺序? - Philipp Lenssen
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接