Data set/get performance issue with RhinoCommon API

I am running into a performance problem when I update the vertices of a mesh object (using RhinoCommon API) as per the logic below:

        for(int vid = 0; vid < _displayMesh.Vertices.Count; vid++) {
            Point3f displVert = _displayMesh.Vertices.ElementAt(vid);
            Point3f baseVert = _baseMesh.Vertices.ElementAt(vid);
            IS_ManagedVector displVec = displVerts.ElementAt(vid);
            displVert.X = (float)(baseVert.X + displVec.GetX() * displScale);
            displVert.Y = (float)(baseVert.Y + displVec.GetY() * displScale);
            displVert.Z = (float)(baseVert.Z + displVec.GetZ() * displScale);
            _displayMesh.Vertices.SetVertex(vid, displVert);
        }

All the above objects except the displVec is a Rhino object. _displayMesh and _baseMesh are Rhino meshes. Basically I update the _displayMesh using the vertices of _baseMesh and a vector displVec scaled by displScale. The mesh has 33K vertices and 66K faces. The loop seems to be taking about 2 minutes.

I do have another piece of code which does something similar and updates the mesh normals. Even that is slow. It seems like the getters and setters of the mesh is the cause for the slowness, but I am not sure. Ideally it would be nice if the Mesh or the MeshVertexList class supported such point-wise transformations, so that they will be done natively in Rhino.

Any idea why it is so slow and how I can fix it?

Srini

I think that the following would be more efficient. You basically get a local copy of all vertices, update them in-place, then clear the mesh and set vertices in one operation, instead of accessing the Mesh object

The same approach can be used for normals using the SetNormals(IEnumerable<Vector3f>) method

Point3f[] vertices = _displayMesh.Vertices.ToPoint3fArray();
Point3f[] baseVertices = _baseMesh.Vertices.ToPoint3fArray();
for(int i = 0; i < vertices.Length; ++i)
{
    Point3f displVert = vertices[i];
    Point3f baseVert = baseVertices[i];
    IS_ManagedVector displVec = displVerts.ElementAt(vid);
    displVert.X = (float)(baseVert.X + displVec.GetX() * displScale);
    displVert.Y = (float)(baseVert.Y + displVec.GetY() * displScale);
    displVert.Z = (float)(baseVert.Z + displVec.GetZ() * displScale);
    vertices[i] = displVert;
}

_displayMesh.Vertices.Clear();
_displayMesh.Vertices.AddVertices(vertices);
2 Likes

Thanks Menno, that worked!