0

I am trying to group similar objects (models with transforms) in a maya project by their vertices programmatically and wanted to know if there was a value I could compute to check for similar objects ? The models I am working with is furniture from 3D houses. Example furniture

I want to group the teacups to a single group. Their names are completely different in the hierarchy, so I thought grouping them (creating a dictionary) by some geometrical similarity would help.

luii
  • 319
  • 3
  • 5
  • 16
  • Welcome to StackOverflow. Please read and follow the posting guidelines in the help documentation. [on topic](http://stackoverflow.com/help/on-topic) and [how to ask](http://stackoverflow.com/help/how-to-ask) apply here. At the very least, we need you to define "similar objects" and give some examples of how this metric would work. – Prune Jun 22 '17 at 21:12

1 Answers1

0

Comparing two meshes to detect similarities is a non-trivial problem and AFAIK Maya does not provide shortcuts for this. Also, I second Prune in saying that it is very important for you to be clear about what you mean by "similar objects": depending on the degree of similarity you aim to, you might need to implement quite complex (and/or very expensive) algorithms.

By looking at the picture you linked, though, it seems to me that you just need to detect exact duplicates of the shape nodes, which is generally easier. Here's an example of how you can achieve that:

from maya import cmds

def getGeoHash(mesh):
    mesh_data = cmds.polyEvaluate(mesh)
    # simple dictionary hashing, as suggested here:
    # https://stackoverflow.com/questions/5884066/hashing-a-dictionary
    return hash(frozenset(mesh_data.items()))

def groupSimilarMeshes():
    meshes = cmds.ls(typ='mesh', l=1)
    mesh_dict = {}
    for mesh in meshes:
        geo_hash = getGeoHash(mesh)
        if not geo_hash in mesh_dict:
            mesh_dict[geo_hash] = []
        # store the mesh transforms: there will be more than one
        # in case some meshes are instanced
        transforms = cmds.listRelatives(mesh, p=1)
        mesh_dict[geo_hash].extend(transforms)

    for key, duplicates in mesh_dict.iteritems():
        if len(duplicates) < 2:
            # non-duplicates are skipped
            continue
        cmds.group(duplicates, n='similar')

groupSimilarMeshes()

A few notes:

  • getGeoHash is the function which hashes your geometry; shapes (maya nodes of type mesh) are used, to ignore transformations
  • basic data returned by polyEvaluate is used for hashing, to keep things simple and computationally inexpensive
  • at some point you might need to refine your logic, as new exceptions emerge while using the script on different scenarios. To do that, you can add more data to your mesh_data dictionary, before hashing (ie. the bounding box size, both in 3D and UV space, the centroid coordinates, the presence of non-manifold geometry, etc.). An interesting thread with a few hints on this topic (though quite old) can be read here.
mapofemergence
  • 458
  • 3
  • 7