Blender.Mesh.Mesh.__copy__() is broken?

Hi guys and python gurus,

I’ve found something rather weird, the copy function of the Mesh class of the Blender.Mesh module does not seem to create faithful copies of the Mesh objects. In other words, the vert and face list it creates in the new Mesh object are not identical to those of the old Mesh object. The indices of the verts are almost certainly different from the old Mesh object. I discovered this problem when I was trying to duplicate both a Mesh object (it’s data actually) and its vertex groups.

The new Mesh object’s vertex membership w.r.t the groups are very very wrong.

I think there is an error, because I wrote my own function for duplicating the Mesh data by recreating an NMesh object and manually copying exactly every single vertex and face from the old Mesh object, and use the same vertex groups from the old Mesh object and this worked without a problem – except that it’s extremely slow (actually, the vertex copy is very fast, the face copy is dead slow).

I’d like to know if this is indeed a bug, or just a feature, and if I’m doing anything wrong, could someone please give me some pointers.

Thanks a lot!

-D

can you upload an example?, it calls blenders own mesh copy function and it shouldent be re-ordering AFAIK

You know what … I cannot reproduce that error!! Guess we can just forget about it until next time. Did you also know that Blender’s FileSelector sometimes crashes when the path is more than 5 directories deep? I get these crashes on my cvs built blender, but not the ones downloaded from Blender.org.

-D

Hey Didu, making a small testcase is often a good way to see if its realy a big or not.

About the file selector, There was some bug but I thaught it was resolved. I use more the 5 level deep dirs here. I think its more likely to be the path length

Yes you are right, I can replicate the problem now, I’ve created a simple test case and a python script to replicate it, please download at:

http://www.csse.unimelb.edu.au/~jingy/download/problem.blend.gz

Once you unzip it, select the female mesh, then run the script. The script uses Blender.Mesh.Mesh.copy to replicate the mesh and it also copies and reassigns the vertex groups. Once the mesh is replicated, change the new mesh into edit mode, and look at the vertices in groups such as “Right Eye”, “Right Shin”, “Left Shoulder”, etc (make sure you click the “Select” button in “Vertex Groups” panel to high light the vertex groups). Compare these vert groups with the original mesh, you’ll see the problem.

Um … interesting.

-D

Yo need a function to verify the mesh isnt the same, I added a simple one, It reports the mesh as being the same with the example you gave.


import Blender

def replicateMesh(meshObj):
        """
        """

        data = meshObj.getData(False, True)
        print data
        vgroups = {}

        for gName in data.getVertGroupNames():
                vIndices = []
                for vi in data.getVertsFromGroup(gName):
                        vIndices.append(vi)

                vgroups[gName] = vIndices

        newMeshData = data.__copy__()
        newObj = Blender.Object.New('Mesh')
        newObj.link(newMeshData)

        for gName in vgroups.keys():
                newMeshData.addVertGroup(gName)
                newMeshData.assignVertsToGroup(gName, vgroups[gName], 1.0, Blender.Mesh.AssignModes.REPLACE)

        Blender.Scene.GetCurrent().link(newObj)
        Blender.Scene.GetCurrent().update()
        newObj.select(1)
        Blender.Redraw()

        return newObj

def compare_mesh(me1, me2):
        print len(me1.verts), len(me2.verts)
        print len(me1.verts) == len(me2.verts)

        if len(me1.verts) != len(me2.verts):
                print 'different vert leng1rhrhrt11th'
                return False
        if len(me1.edges) != len(me2.edges):
                print 'different edge length'
                return False
        if len(me1.faces) != len(me2.faces):
                print 'different face length'
                return False


        for i in xrange(len(me1.verts)):
                v1 = me1.verts[i]
                v2 = me2.verts[i]

                if v1.co != v2.co:
                        print 'vert locations differ'
                        return False


        for i in xrange(len(me1.faces)):
                f1 = me1.faces[i]
                f2 = me2.faces[i]


                if f1.cent != f2.cent:
                        print 'face locations differ'
                        return False
        return True

#-----------------------------------------------
if __name__ == '__main__':
        chosenMesh = None
        for obj in Blender.Scene.GetCurrent().objects:
                if obj.getType() == 'Mesh' and obj.isSelected():
                        chosenMesh = obj
                        break
        if chosenMesh != None:
                chosenMesh.select(0)
                new_ob = replicateMesh(chosenMesh)
                #me1 = chosenMesh.getData(mesh=1)
                #me2 = me1.copy()
                #print compare_mesh(me1, me2)

                print 'comparing...',
                print compare_mesh(new_ob.getData(mesh=1), chosenMesh.getData(mesh=1))

        else:
                print 'no chosen mesh found'

You are right … the two meshes are the same, I even added code to test the indices of the vertices. But then how come the vertices in each vertex group are different? :confused:

Edit: never mind, I think I know why, the vertex groups for the new mesh has to be assigned in the exact same order as they are returned by the getVertGroupNames function of the old mesh object. I don’t understand why it has to be this way though.

-D

(your weight copy function?)

if your realy want- do Object.Duplicate - that will deal with vertex groups for you.

Weight functions? I did know I had any, Here are the two lines I use for assigning vertex groups:


newMeshData.addVertGroup(gName)
newMeshData.assignVertsToGroup(gName, vgroups[gName], 1.0, Blender.Mesh.AssignModes.REPLACE)

The only “weight” thing as far as I can tell is that “1.0” in the second line. According to the docs, it’s supposed to be the influence of that group has on the vertices in that group.

Other than that, I don’t see any weight functions at all. Most of the wrong vertex groups are not even close. For example, the “Right Eye” group includes the right eye and one of the shins – they are almost as far from each other as it gets.


if your realy want- do Object.Duplicate - that will deal with vertex groups for you.[/quote]

I was seriously considering that option before I found out the order of the vertex groups actually mattered ... but why should it matter, especially given the way I assign them? :confused:

-P

Try using object.copy() as well, rather then Object.New() - that way the object will have the vgroups (I think)

It may be possibly to not even touch the weights… have a look at Mesh.c too and see how it deals with copying.

object.copy() ? Is this part of the new API? I cannot find the copy() function in Blender.Object or Blender.Object.Object .

Thanks a lot for the pointers!

.copy() and .copy() are in CVS, This may take a bit of working out, I could debug but prefer to let didu work in this… I have my own problems to debug…
Your a smart man! :wink:

But if you can shot there a bug Ill look at fixing.