Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Flipping mesh for performance

Discussion in 'Scripting' started by msklywenn, Jul 15, 2017.

  1. msklywenn

    msklywenn

    Joined:
    Nov 28, 2014
    Posts:
    67
    Hello,

    We compose the enemies of our game by constructing them out of a small subset of meshes and materials. I recently noticed in the frame debugguer that Unity doesn't like transforms with negative scales. So I started doing a script to generate meshes with flipped vertices to replace those and avoid those warnings. Coupled with instancing, it greatly reduces our draw call count!

    Unfortunately, I seem to be missing something as the result isn't exactly what I expected it to be.

    Code (CSharp):
    1.     Mesh FlipMesh(Mesh mesh, Vector3 scale) // scale = -1 or 1 per component, will also be applied to transform
    2.     {
    3.         vertices.Clear();
    4.         normals.Clear();
    5.         mesh.GetVertices(vertices);
    6.         mesh.GetNormals(normals);
    7.  
    8.         for (int i = 0; i < vertices.Count; i++)
    9.             vertices[i] = Vector3.Scale(vertices[i], scale);
    10.         for (int i = 0; i < normals.Count; i++)
    11.             normals[i] = Vector3.Scale(normals[i], scale);
    12.  
    13.         Mesh fixedMesh = new Mesh();
    14.  
    15.         fixedMesh.vertices = vertices.ToArray();
    16.         fixedMesh.normals = normals.ToArray();
    17.  
    18.         fixedMesh.uv = mesh.uv;
    19.         if (mesh.uv2 != null)
    20.             fixedMesh.uv2 = mesh.uv2;
    21.         if (mesh.colors != null)
    22.             fixedMesh.colors = mesh.colors;
    23.         else if (mesh.colors32 != null)
    24.             fixedMesh.colors32 = mesh.colors32;
    25.  
    26.         fixedMesh.subMeshCount = mesh.subMeshCount;
    27.         for (int i = 0; i < mesh.subMeshCount; i++)
    28.             fixedMesh.SetIndices(mesh.GetIndices(i), mesh.GetTopology(i), i);
    29.  
    30.         fixedMesh.RecalculateTangents();
    31.         fixedMesh.RecalculateBounds();
    32.  
    33.         return fixedMesh;
    34.     }
    It works on some enemies but I sometimes get weird results, like this :
    pasted_image_at_2017_07_15_04_19_pm_720.png

    I noticed on this one that if I manually flip the Y scale on the transform, I get something back that is close to the original but not quite and darker.
    pasted_image_at_2017_07_15_04_20_pm_720.png

    Any idea of what I would be missing ?
     
  2. msklywenn

    msklywenn

    Joined:
    Nov 28, 2014
    Posts:
    67
    Well, while making a gif, I found the issue: I also needed to change the winding order. Here's the updated code for anyone who would care!

    Code (CSharp):
    1.     Mesh FlipMesh(Mesh mesh, Vector3 scale) // scale = -1 or 1 per component, will also be applied to transform
    2.     {
    3.         vertices.Clear();
    4.         normals.Clear();
    5.         mesh.GetVertices(vertices);
    6.         mesh.GetNormals(normals);
    7.  
    8.         for (int i = 0; i < vertices.Count; i++)
    9.             vertices[i] = Vector3.Scale(vertices[i], scale);
    10.         for (int i = 0; i < normals.Count; i++)
    11.             normals[i] = Vector3.Scale(normals[i], scale);
    12.  
    13.         Mesh fixedMesh = new Mesh();
    14.  
    15.         fixedMesh.vertices = vertices.ToArray();
    16.         fixedMesh.normals = normals.ToArray();
    17.  
    18.         fixedMesh.uv = mesh.uv;
    19.         if (mesh.uv2 != null)
    20.             fixedMesh.uv2 = mesh.uv2;
    21.         if (mesh.colors != null)
    22.             fixedMesh.colors = mesh.colors;
    23.         else if (mesh.colors32 != null)
    24.             fixedMesh.colors32 = mesh.colors32;
    25.  
    26.         fixedMesh.subMeshCount = mesh.subMeshCount;
    27.         for (int i = 0; i < mesh.subMeshCount; i++)
    28.         {
    29.             indices.Clear();
    30.             mesh.GetIndices(indices, i);
    31.             MeshTopology topology = mesh.GetTopology(i);
    32.             switch (topology)
    33.             {
    34.                 case MeshTopology.Triangles:
    35.                 {
    36.                     for (int j = 0; j < indices.Count; j += 3)
    37.                     {
    38.                         int s = indices[j];
    39.                         indices[j] = indices[j + 2];
    40.                         indices[j + 2] = s;
    41.                     }
    42.                     break;
    43.                 }
    44.  
    45.                 default:
    46.                 {
    47.                     Debug.LogError("Unsupported topology: " + topology);
    48.                     break;
    49.                 }
    50.             }
    51.             fixedMesh.SetIndices(indices.ToArray(), topology, i);
    52.         }
    53.  
    54.         fixedMesh.RecalculateTangents();
    55.         fixedMesh.RecalculateBounds();
    56.  
    57.         return fixedMesh;
    58.     }
     
    AeOngDev, sylon and Gametyme like this.