简体   繁体   中英

Fixing extruded mesh normals in Unity C#?

In Unity C#, I'm using a procedular mesh extrusion, based on a flat polygon's 2D vector points. This works great using the code below, except for one detail: seemingly every second triangle which connects the front from the backside of the extruded mesh is flipped, as the image shows (using a double-sided shader, I can see all the triangles do exist fine, though). How would I fix the flip of these bridging normals? Thanks!

在此处输入图像描述

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

If a face isn't shown it is as you already noticed flipped, this is due to the winding order which in unity is clockwise. The link of your triangluator already states under Troubleshooting: "If you can't see a polygon created with this utility, remember to check if the polygon is facing the opposite direction. If it is, you can change that by constructing your mesh with the vertex indices in reverse order."

EDIT:

for further clarification: in your code this would mean you have to switch

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

to

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

But be careful because the order depends on your depth (if it is higher or lower than you frontVertex)

2nd EDIT:

the normal of a triangle depends on the winding order, this means that there is a difference in the ordering.

An example:

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

the triangle of

Triangle 1,2,3

and

Triangle 1,3,2

have different normal.

三角形的绕线顺序

You have to make sure that the winding order is consistent for every triangle you draw. Alternativly you could tell your shader to disable culling (with Cull Off ),as you already said above. But this comes with a cost of computation time. Which in most cases shouldn't matter that much, but it always depends on your purpose. Besides most of the time you dont want the side effects of disabling culling.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM