#!BPY """ Name: 'Symmetry Map' Blender: 248.1 Group: 'Object' Tooltip: 'Tool to symmetrize a mesh and bone weights over the x axis' """ __author__ = "Ivo Grigull" __url__ = ["www.ivogrigull.com"] __version__ = "0.1" __bpydoc__ = """\ Symmetry Map - symmetrize a mesh and bone weights over the x axis -------------------------------------------------------------------- Menu: Object->Scripts->Symmetry Map This script is useful if you want to make modifications to a symmetricak mesh after you have applied a mirror modifier. usage: Your mesh needs to be totally symmetrical to start with, ideally you have just applied a mirror modifier. Now you can run the script and choose 'Create Map'. It will take a while (about 2 minutes for my character). The map is saved as a property of the object. However you can save and load the map to a file for later reuse in case the info gets lost or corrupted. Once the map is generated, you can choose 'Symm. L->R' etc. from the menu to mirror the mesh. Note: it will not work on the default monkey, as he is not 100% symmetrical. You will first have to cut one half and apply a new mirror modifier in order to make it work properly. This caused me quite some headache before figuring it out ;) Menu explanation: Create Map - Generate a symmetry map (takes long time, but only needs to be done once) Remove Map - Remove the map property from the object Symm. L->R - Copy point positions from left to right Symm. R->L - Copy point positions from right to left Weight L->R - Symmetrize weights from left to right Weight R->L - Symmetrize weights from right to left Save Map - Save the mapping to a file Load Map - Load the mapping from a file Sel midpoints - Select the midpoints Cntr. midpoints - Center the midpoints positions on the x axis # -------------------------------------------------------------------------- # ***** BEGIN GPL LICENSE BLOCK ***** # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # ***** END GPL LICENCE BLOCK ***** # """ import Blender from Blender import Window import BPyMesh def createSymmetryMap(): ob = Blender.Object.GetSelected()[0] verts = ob.getData(mesh=1).verts edges = ob.getData(mesh=1).edges dict = {} list = [] for n in range( len(edges) ): v1 = edges[n].v1.co.copy() v2 = edges[n].v2.co.copy() v1.x *= -1 v2.x *= -1 # if not (edges[n].v1.co.x == 0.0 and edges[n].v2.co.x == 0.0) : for i in range( len(edges) ): if v1 == edges[i].v1.co and v2 == edges[i].v2.co: if edges[n].v1.co.x > edges[i].v1.co.x: tuple = edges[n].index, edges[i].index else: tuple = edges[i].index, edges[n].index list.append( tuple ) checklist = [] final = [] for n in list: v1l = edges[ n[0] ].v1.index v2l = edges[ n[0] ].v2.index v1r = edges[ n[1] ].v1.index v2r = edges[ n[1] ].v2.index if (not v1l in checklist) and (not v1r in checklist): checklist.append( v1l ) checklist.append( v1r ) if verts[v1l].co.x > verts[v1r].co.x: tuple = v1l, v1r else: tuple = v1r, v1l final.append(tuple) verts[v1r].co = verts[v1l].co.copy() verts[v1r].co.x *= -1 if not v2l in checklist and not v2r in checklist: checklist.append( v2l ) checklist.append( v2r ) if verts[v2l].co.x > verts[v2r].co.x: tuple = v2l, v2r else: tuple = v2r, v2l final.append(tuple) verts[v2r].co = verts[v2l].co.copy() verts[v2r].co.x *= -1 l = [] for n in final: # verts[ n[1] ].co.x = verts[ n[0] ].co.x * -2 if not verts[ n[0] ].co.x == 0.0: verts[ n[0] ].sel =1 l.append(n[0]) l.append(n[1]) ob.properties['SymmetryMap'] = l def deleteMap(): ob = Blender.Object.GetSelected()[0] if not 'SymmetryMap' in ob.properties.keys(): return 'No symmetry map found' del ob.properties['SymmetryMap'] def saveMap(filename): ob = Blender.Object.GetSelected()[0] if not 'SymmetryMap' in ob.properties.keys(): return 'No symmetry map found' map = ob.properties['SymmetryMap'] file = open( filename, 'w') file.writelines( str( ob.name ) + '\n' ) file.writelines( str( len(map)) + '\n' ) for f in range( 0, len(map)) : file.writelines( str(map[f]) + '\n' ) file.close() def loadMap(filename): file = open( filename, 'r') print file.readline() count = int(file.readline()) map = [] for n in range( 0, count ): map.append( int( file.readline() ) ) file.close() ob = Blender.Object.GetSelected()[0] ob.properties['SymmetryMap'] = map # for n in range( 0, len(map) ): # print map[n] def symmetrizeMesh(side): ob = Blender.Object.GetSelected()[0] if not 'SymmetryMap' in ob.properties.keys(): return 'No symmetry map found' me = ob.getData(mesh=1) verts = me.verts map = ob.properties['SymmetryMap'] if side == 'r': for n in range( (len(map) /2) ): verts[ map[n*2] ].co = verts[ map[(n*2)+1]]. co.copy() verts[ map[n*2] ].co.x *= -1 else: for n in range( (len(map) /2) ): verts[ map[(n*2)+1] ].co = verts[ map[n*2]]. co.copy() verts[ map[(n*2)+1] ].co.x *= -1 Blender.Redraw() Blender.Window.RedrawAll() def symmetrizeWeights(side): ob = Blender.Object.GetSelected()[0] if not 'SymmetryMap' in ob.properties.keys(): return 'No symmetry map found' me = ob.getData(mesh=1) map = ob.properties['SymmetryMap'] groupNames, vWeightDict= BPyMesh.meshWeight2Dict( me ) if side == 'r': for n in range( (len(map) /2) ): dict = vWeightDict[ map[ (n*2)+1 ] ].copy() newdict = {} if len(dict.keys() ) > 0: for i in dict.keys(): #print 'renaming...R' if i.find('.R') != -1: newname = i.replace( '.R', '.L' ) else: if i.find('.L') != -1: newname = i.replace( '.L', '.R' ) else: newname = i newdict[newname] = dict[i] vWeightDict[ map[(n*2)] ] = newdict.copy() else: # first we need to copy the corresponding weights from the other side for n in range( (len(map) /2) ): dict = vWeightDict[ map[ (n*2)+1 ] ].copy() for i in dict.keys(): if i.find('.L') != -1: newname = i.replace('.L', '.R') vWeightDict[ map[ (n*2) ] ][newname] = vWeightDict[ map[ (n*2)+1 ] ][i] for n in range( (len(map) /2) ): dict = vWeightDict[ map[ (n*2) ] ].copy() newdict = {} if len(dict.keys() ) > 0: for i in dict.keys(): #print 'renaming...L' if i.find('.L') != -1: newname = i.replace( '.L', '.R' ) else: if i.find('.R') != -1: newname = i.replace( '.R', '.L' ) else: newname = i newdict[newname] = dict[i] vWeightDict[ map[(n*2)+1] ] = newdict.copy() BPyMesh.dict2MeshWeight(me, groupNames, vWeightDict) Blender.Redraw() def centerMidPoints(): in_editmode = Window.EditMode() if in_editmode: Window.EditMode(0) ob = Blender.Object.GetSelected()[0] if not 'SymmetryMap' in ob.properties.keys(): return 'No symmetry map found' verts = ob.getData(mesh=1).verts map = ob.properties['SymmetryMap'] for n in verts: if n.index not in map: n.co.x = 0.0 if in_editmode: Window.EditMode(1) def selectMidPoints(): in_editmode = Window.EditMode() if in_editmode: Window.EditMode(0) ob = Blender.Object.GetSelected()[0] if not 'SymmetryMap' in ob.properties.keys(): return 'No symmetry map found' verts = ob.getData(mesh=1).verts map = ob.properties['SymmetryMap'] for n in verts: if n.index not in map: n.sel = 1 if in_editmode: Window.EditMode(1) def printsel(): in_editmode = Window.EditMode() if in_editmode: Window.EditMode(0) ob = Blender.Object.GetSelected()[0] verts = ob.getData(mesh=1).verts sel = [f for f in verts if f.sel] index = sel[0].index print index map = ob.properties['SymmetryMap'] r = -1 for n in range( 0, len(map)/2 ): if map[n*2] == index: r = n*2 break print r if r != -1: verts[ map[r+1] ].sel = 1 # verts[index].sel = 0 # print [ map[(index/2)+1] ] if in_editmode: Window.EditMode(1) def main(): menu = [ ('Create Map', 0), ('Remove Map', 5), ('Symm. L->R', 3), ('Symm. R->L', 4), ('Weight L->R', 8), ('Weight R->L', 9), ('Sel midpoints', 10), ('Cntr. midpoints', 6), ('Save Map', 2), ('Load Map', 1) ] choice = Blender.Draw.PupTreeMenu( menu ) if choice == 0: createSymmetryMap() if choice == 1: Blender.Window.FileSelector ( loadMap, 'LOAD FILE' ) if choice == 2: Blender.Window.FileSelector ( saveMap, 'SAVE FILE' ) if choice == 3: print symmetrizeMesh('l') if choice == 4: print symmetrizeMesh('r') if choice == 5: deleteMap() if choice == 6: print centerMidPoints() if choice == 7: printsel() if choice == 8: symmetrizeWeights('l') if choice == 9: symmetrizeWeights('r') if choice == 10: print selectMidPoints() if __name__=='__main__': main()