kefren
kefren

Reputation: 1112

Mesh manipulation very slow

My program receives a Mesh at runtime. The mesh can be made of over 200k vertices. I need to reverse it (inside-out). I reverse the indices, but I also need to invert the normals. So far, I used this loop:

Vector3[] newnormals = new Vector3[mesh.normals.Length];
for (int i=0;i<mesh.normals.Length;i++)
{
    newnormals[i] = -mesh.normals[i];
}

revMesh.normals = newnormals;

where "mesh" is the original Mesh, and of course "revMesh" is the reversed one. I don't know why, but this loop is incredibly slow. it takes many seconds on my i7. If I substitute it with

revMesh.RecalculateNormals();

the execution time goes down to under 100 ms.…

Why is my routine so inefficient? Is there some way to speed it up?

Upvotes: 4

Views: 256

Answers (2)

rutter
rutter

Reputation: 11452

The main problem here is that reading mesh.normals does not directly access the array. Unity creates a copy of that array and passes you the copy. You read mesh.normals twice per loop iteration, so for a mesh with 200k normals you will be creating 400k copies of that array. That may run very slowly, indeed.

It will be much faster to ask Unity for one copy of the array, do your work on it, and then pass the data back to Unity once that's done.

Unity's internal classes have a few properties that return fresh copies each time they are read. It's always good to check the manual if you're not sure.

Upvotes: 2

Mohammad Zamanian
Mohammad Zamanian

Reputation: 771

Maybe getting mesh.normals[i] in each iteration makes it slow, try:

Vector3[] newnormals= revMesh.normals;
for (int i=0;i<newnormals.Length;i++)
    newnormals[i] = -newnormals[i];
revMesh.normals = newnormals;

Note: To make changes to the normals it is important to copy the normals from the Mesh. Once the normals have been copied and changed the normals can be reassigned back to the Mesh.

https://docs.unity3d.com/ScriptReference/Mesh-normals.html

You could also do: (didn't test but i think it works)

using System.Linq;
revMesh.triangles = revMesh.triangles.Reverse().ToArray();

Upvotes: 4

Related Questions