【问题标题】:Fixing extruded mesh normals in Unity C#?在 Unity C# 中修复拉伸网格法线?
【发布时间】:2019-11-19 22:06:37
【问题描述】:

在 Unity C# 中,我使用基于平面多边形的 2D 矢量点的程序网格挤压。使用下面的代码效果很好,除了一个细节:似乎每隔一个连接挤出网格的正面和背面的三角形都会翻转,如图所示(使用双面着色器,我可以看到所有三角形存在很好,虽然)。我将如何修复这些桥接法线的翻转?谢谢!

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

【问题讨论】:

    标签: c# unity3d mesh


    【解决方案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
    

    有不同的法线。

    您必须确保绘制的每个三角形的缠绕顺序都是一致的。 或者你可以告诉你的着色器禁用culling(使用Cull Off),正如你上面已经说过的。但这会带来计算时间的成本。在大多数情况下,这无关紧要,但这始终取决于您的目的。除了大多数时候你不希望禁用剔除的副作用。

    【讨论】:

    • 嗯,在二次尝试时,它仅在某些时候有效,这可能是您在 be-cafeful 笔记中提到的。想知道我需要做什么来解决这两种情况吗?
    • 您需要确保 frontVertex 始终大于或始终小于深度。最简单的方法是初始检查 frontVertex > depth 是否需要切换两个参数。在这种情况下,您不需要更改三角测量的设置
    • 谢谢。在我的程序中,frontVertex 始终为 0f,depth 始终为 0.05f,但我遇到了这些问题。怎么办?
    • 这是由于三角形的顺序,要么固定顺序,要么固定在网格中的位置(顶点位置)。有关更多信息,请查看我的第二次编辑。
    • 谢谢!我将如何做到这一点,在我正在使用的代码库中修复缠绕顺序?
    猜你喜欢
    • 2018-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-15
    • 1970-01-01
    • 2017-05-21
    • 1970-01-01
    • 2016-05-27
    相关资源
    最近更新 更多