Transfer the vertex order addon

Copy vert ids addon.



Get it from here
This blender addon makes it possible to transfer mesh vert IDs, from mesh A to mesh B, if both of them have the same topology (same vertex count, same polygon count, shape can be different).
With vert IDs copied you will be able to transfer mesh attributes like uv, weights, colors etc. by using Data Transfer modifier (and using’Topology’ vertices matching).

7 Likes

Thks JoseConseco, little feature but GREAT IDEA!
Congratulations: The best add-on are always some simple features like this! :eyebrowlift:

EDIT: but in python names are always without uppercase!

this name is better compatible with Blender Add-Ons naming :
mesh_copy_vert_ids.py

Byebye

Thank you so much for this add-on! You’re a life-saver. I can’t believe this hasn’t gotten more attention, considering how many people were asking to be able to do what your add-on does?

perhaps it’s an issue with the naming? coming from other apps I was searching high and low for a way to … transfer the vertex order. :wink:

this should be standard in blender - i wonder if it would be possible to somehow have this functionality in the data transfer modifier?

Renamed to : transfer the vertex order.
I think this is not popular because it is very specialized addon, and not much people require this functionality, maybe?

A good addition to the Meshtransfer addon that can transfer shapes between mesh with different vertice count

1 Like

This is a brilliant thing! I’ve been looking for a long time. Thank you very much.

Thanks for the Addon! :slight_smile:

Oh … and I REALLY hope you will bring this to 2.8 :wink:

I added version for blender 2.8. Located in:

4 Likes

Many thanks !

sweet, many thanks :slight_smile:
very helpful if you accidentally messed up the vertex order

Thanks for this! I had a subdivided high poly mesh from a different software, and its low poly counterpart, and couldn’t use a multiresolution reshape cause the vertices were all out of order between that other software and blender’s subdivision. With this it works!

But it is unusably slow for a very high poly mesh like that, when transferring by topology. In particular, list constructions in “sortOtherVerts” that use an “in list” check.

I changed the lists in “sortOtherVerts” to dicts and stored the values as keys, so that the “in” checks in that function become O(1). I have no idea if this is 100% correct, and if there’s other consequences, quite likely there are, but it works now relatively quickly! For a 1mil vertex mesh, it needed approx. 3 hours to complete, and it went down to 10 minutes! The ids of the connected part turned out correct, but I didn’t check loose parts very thoroughly. They seemed fine at first glance.

Again, I have no idea what issues this might cause, would you consider checking? It’s a rare case I expect, but it might be useful to someone else too.

Here’s the modified function, from the 2.79 version :

    @staticmethod
    def sortOtherVerts(preocessedVertsIdDict, allVerts):
        """Prevet verts on other islands from being all shuffled"""
        processedVerts = {} #dicts instead of lists
        processedIDs = {}

        count = 0   #just a count so that I can print progress
        lendict = len(preocessedVertsIdDict)  #length of the dict so I can print progress and not have to do it inside the loop
        for v,id in preocessedVertsIdDict.items():
            msg = "Part 2/5 : Copying vertex, %i of %i" %(count, lendict)
            sys.stdout.write(msg + chr(8)*len(msg))
            sys.stdout.flush()
            count += 1
            processedVerts[v]=id   #no reason to store id here too, might as well be 1
            processedIDs[id]=1  #just 1, i only want the dict keys so the in is quick
        sys.stdout.write("\n")
        sys.stdout.flush()


        notProcessedVerts = {}  #same 
        notProcessedVertsIds = {}
        count = 0
        lendict = len(allVerts)
        for v in allVerts:
            msg = "Part 3/5 : Gathering unused vertices, %i of %i" %(count, lendict)
            sys.stdout.write(msg + chr(8)*len(msg))
            sys.stdout.flush()
            count += 1
            if v not in processedVerts:
                notProcessedVerts[v]=v.index
                notProcessedVertsIds[v.index]=1
        sys.stdout.write("\n")
        sys.stdout.flush()


        spareIDS = []  #there's no in check for this list, no need for any change
        count = 0
        for i in range(len(allVerts)):
            msg = "Part 4/5 : Gathering unused IDs, %i of %i" %(count, lendict)
            sys.stdout.write(msg + chr(8)*len(msg))
            sys.stdout.flush()
            count += 1
            if (i not in processedIDs and i not in notProcessedVertsIds):
                spareIDS.append(i)
        sys.stdout.write("\n")
        sys.stdout.flush()

        count = 0
        lendict = len(notProcessedVerts)
        for v in notProcessedVerts:
            msg = "Part 5/5 : Assigning unused ids, %i of %i" %(count, lendict)
            count += 1
            sys.stdout.write(msg + chr(8)*len(msg))
            sys.stdout.flush()

            if v.index in processedIDs:  # if duplicated id found if not processed verts
                v.index = spareIDS.pop(0)  # what if list is empty??
        sys.stdout.write("\n")
        sys.stdout.flush()

I guess dict comprehensions would be better, but I wanted to print some progress messages from inside the loops, to see what’s going on.

Cool, I have merged this into gumroad versions (without all the printing values, and made dicts from list comprehensions so it should be even faster). I haven’t used it on so heavy meshes before, but I guess dict is way faster for searching values.

1 Like