Search code examples
pythonmayamaya-api

Separate polygon shells into separate meshes in Maya API


Is there a way to separate two polygon shells in Maya API (OpenMaya)? Just like the cmds.polySeparate function (which i cannot use because it returns the separate nodes in random order, so I cannot know which one to delete and which one to keep in my script. Moreover I'd like rely only on the API and don't mix it with the cmds).

Reading the documentations I thought that OpenMaya.MFnMesh.extractFaces what was I was looking for, but (differently from what the docs seems to say) it just cuts the selected chunk but leaves it in the same node.


Solution

  • Seems like there is no clean way to do this with the API.

    Since I needed to separate the mesh to delete the part I didn't need, I decided to maintain the vertices and the polygons that I wanted to remove from the mesh and create a new mesh without them.

    As you can see in this function I just keep the "good" vertices and polygons and then I update the vertices IDs in the poly_connects list.

    def regenerate_mesh(source_mesh, vertices_to_delete, poly_to_delete):
        points = source_mesh.getPoints(om.MSpace.kWorld)
        num_points = len(points)
        i = 0
        while i < num_points:
            p1 = points[i]
            for p2 in vertices_to_delete['points']:
                if p1.x == p2.x and p1.y == p2.y and p1.z == p2.z:
                    points.remove(i)
                    num_points -= 1
                    break
            else:
                i += 1
    
        polygon_counts, polygon_connects = source_mesh.getVertices()
    
        i = j = 0
        polygon_counts_length = len(polygon_counts)
    
        while i < polygon_counts_length:
            k = 0
            for poly in poly_to_delete:
                if poly == polygon_connects[j:j+polygon_counts[i]]:
                    for l in range(polygon_counts[i]):
                        polygon_connects.remove(j)
                    polygon_counts.remove(i)
                    polygon_counts_length -= 1
                    break
            else:
                while k < polygon_counts[i]:
                    if polygon_connects[j+k] in vertices_to_delete['indices']:
                        for l in range(polygon_counts[i]):
                            polygon_connects.remove(j)
                        polygon_counts.remove(i)
                        polygon_counts_length -= 1
                        break
                    k += 1
                else:
                    j += k
                    i += 1
    
        # update indices
        for vertex in sorted(vertices_to_delete['indices'], reverse=True):
            for index, new_vertex in enumerate(polygon_connects):
                if new_vertex > vertex:
                    polygon_connects[index] -= 1
        new_mesh = om.MFnMesh()
        new_mesh.create(points, polygon_counts, polygon_connects)
    

    If someone find a cleaner way I will be happy to know and mark it as the solution!