Detect and link identical objects

Hello everyone!
After entering into 7DayFPS this past week, I realised how tedious and time consuming it can be when you forget to link duplicate objects. As i briefly thought about the issue, I realised that, the reason a game developer would want to link the objects is because they are all the same data, and thus if he wished to change the model later, he’d most likely wish to modify all instances of the object.
Thus, it wouldn’t be too hard to link identical objects, because they would be identical.

So, here is my proposal for a “LINK - IDENTICAL” addon.

  • Loop through each object in the scene with selected objects’ material(s)
  • Create a list of objects with the same polycount.
  • Perform random sampling of mesh data OR check every vertex for identical position (slower)
  • If same polycounts, material and vertex positions, highly likely to be an instance (although not linked)

I don’t know if this already exists, or how much anyone would want it, but i would be interested in hearing from you all.

here’s a rough script, which checks SOME properties for equality:

print()

import bpy

mesh_obs = [ob for ob in bpy.data.objects if ob.type == 'MESH']
mesh_remove = []

for i, ob in enumerate(mesh_obs):
    print(i, ob.name)
    mesh = ob.data
    
    for sub_ob in mesh_obs[i+1:]:
        
        me = sub_ob.data
        
        print("Comparing mesh %s and %s - " % (mesh.name, me.name), end="")
        
        if mesh == me:
            print("skipping")
            continue
        
        if  len(mesh.materials) != len(me.materials) or \
            len(mesh.polygons) != len(me.polygons) or \
            len(mesh.vertices) != len(me.vertices) or \
            len(mesh.edges) != len(me.edges) or \
            len(mesh.loops) != len(mesh.loops) or \
            mesh.uv_layers.active != me.uv_layers.active:
               print("unequal")
        else:
            for mat_a, mat_b in zip(mesh.materials, me.materials):
                if mat_a != mat_b:
                    print("unequal")
                    break
            else:
                for p1, p2 in zip(mesh.vertices, me.vertices):
                    if p1.co != p2.co:
                        print("unequal")
                        break
                else:
                    print("equal")
                    sub_ob.data = ob.data
                    
                    if me not in mesh_remove:
                        mesh_remove.append(me)

print(list(mesh_remove))
for me in mesh_remove:
    bpy.data.meshes.remove(me)
    
# optional clearing of unused mesh data blocks
for me in bpy.data.meshes:
    if me.users == 0:
        bpy.data.meshes.remove(me)

i wonder if this should be done in C code, as one could use memcmp for the entire mesh data block. Data should be equal if a mesh has been duplicated without linking.

That, is a good idea!
I would otherwise create a class that could perform comparison operations;

item_a = LinkIdentity(object_a)
item_b = LinkIdentity(object_b)

print(item_a == item_b)

Also, your script is along the right lines, but i can foresee some issues whereby one linked items which they didn’t (for whatever reason) wish to link.
Therefore, I think taking the current object, finding all objects with same material then comparing data would be faster and safer.s

excluding meshes from my script is as easy as this:

instead of using all
mesh_obs = [ob for ob in bpy.data.objects if ob.type == ‘MESH’]

it could use selected only:
mesh_obs = [ob for ob in bpy.data.objects if ob.type == ‘MESH’ and ob.select]

and checks could be reduced to material and poly-count by removing additional tests from above script

You can already do this with CTRL-L in the interface.

But there is no auto-detection of duplicate mesh data Atom!

Ctrl-L on all object in scene, link object data will make all objects use ONE mesh, no matter if there has been duplicates or different meshes

I think that I may end up making this. Once exams are over, of course!

i made an script to do this some time ago in my last job ( without bmesh ). the problem of compare the vertex position ( in local position ) is that a modeller could rotate the object in edit mode. i didn’t implement the idea, but it may works. recalculate the center position of the mesh, and compare vertex distances with regard to this center. several vertices could have the same round distance, for example, but the total amount is the same. to calculate the rotation between the two object we could use quaternions, with a unique vector of the object. even with a average vector of the vertices with some distances.

what do you think about??

Hi, Did you or anyone else ever end up making this script? It would be incredibly useful!

Hi, I am also looking for some script to use looking into the mesh data, but instead of knowing if it is the same mesh on two objects. I already know they are the same but one of them have been rotated in edit mode and I want to know the deegres it has been rotated. Is this poosible?