Reputation: 1112
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
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
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.
You could also do: (didn't test but i think it works)
using System.Linq;
revMesh.triangles = revMesh.triangles.Reverse().ToArray();
Upvotes: 4