在Unity C#中修复拉伸网格法线吗?

时间:2019-11-18 12:02:24

标签: c# unity3d mesh

在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 个答案:

答案 0 :(得分:1)

如果未显示面孔,则您已经注意到它已翻转,这是由于绕线顺序(顺时针为一)。您的triangluator的链接已在“疑难解答”下阐明: “如果看不到使用此实用程序创建的多边形,请记住检查该多边形是否朝向相反的方向。如果是相反的,则可以通过以相反顺序构造顶点的网格来更改该多边形。”

编辑:

为了进一步说明:在您的代码中,这意味着您必须进行切换

// 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;
        }

但是要小心,因为顺序取决于您的深度(如果它高于或低于frontVertex)

第二次编辑:

三角形的法线取决于绕组的顺序,这意味着顺序有所不同。

一个例子:

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),如上所述。但这带来了计算时间的代价。在大多数情况下,哪一个都不重要,但这始终取决于您的目的。除了大多数时间,您不希望禁用淘汰的副作用。