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.