def project_curves_onto_mesh(mesh, curves_grp, direction): # projected_curves = [] mesh = mesh old_meshes = [] for i, curve in enumerate(curves_grp.getChildren()): try: if (not type(curve.getShape()) is pm.NurbsCurve): continue except: continue while True: nv = len(mesh.vtx) mesh = delete_vertex(mesh) if (len(mesh.vtx) == nv): break projected_curves = pm.polyProjectCurve(mesh, curve, direction=direction)[0] pm.delete(projected_curves.getChildren()[1:]) projected_curve = projected_curves.getChildren()[0] split_mesh = pm.polySplit(mesh, detachEdges=0, projectedCurve=projected_curve) # print projected_curve split_mesh = split_mesh[0] pm.delete(split_mesh, ch=True) old_meshes.append(mesh) mesh = split_mesh if (projected_curves): pm.delete(projected_curves) # if( i == 10 ) : return for old_mesh in old_meshes: try: pm.delete(old_mesh) except: pm.warning('Could not delete %s' % (old_mesh)) pm.polyTriangulate(mesh) # pm.polyQuad( mesh ) # -ver 1 -trm 0 -p 50 -vct 0 -tct 0 -shp 0.5326 -keepBorder 1 -keepMapBorder 1 -keepColorBorder 1 -keepFaceGroupBorder 1 -keepHardEdge 1 -keepCreaseEdge 1 -keepBorderWeight 0.5 -keepMapBorderWeight 0.5 -keepColorBorderWeight 0.5 -keepFaceGroupBorderWeight 0.5 -keepHardEdgeWeight 0.5 -keepCreaseEdgeWeight 0.5 -useVirtualSymmetry 0 -symmetryTolerance 0.01 -sx 0 -sy 1 -sz 0 -sw 0 -preserveTopology 1 -keepQuadsWeight 1 -vertexMapName "" -replaceOriginal 1 -cachingReduce 1 -ch 1 # pm.polyReduce( mesh, ver=True, trm=False, p=50, replaceOriginal=True, kb=True, kbw=1.0, kmb=True, kmw=1.0, kfb=True, kfw=1.0, kqw=1.0 ) pm.polySoftEdge(mesh, a=180, ch=True) pm.delete(mesh, ch=True)
def project_curves_onto_mesh( mesh, curves_grp, direction ) : # projected_curves = [] mesh = mesh old_meshes = [] for i, curve in enumerate( curves_grp.getChildren( ) ) : try : if( not type(curve.getShape()) is pm.NurbsCurve ) : continue except : continue while True : nv = len(mesh.vtx) mesh = delete_vertex(mesh) if( len(mesh.vtx) == nv ) : break projected_curves = pm.polyProjectCurve( mesh, curve, direction=direction )[0] pm.delete( projected_curves.getChildren()[1:] ) projected_curve = projected_curves.getChildren()[0] split_mesh = pm.polySplit( mesh, detachEdges=0, projectedCurve=projected_curve ) # print projected_curve split_mesh = split_mesh[0] pm.delete( split_mesh, ch=True ) old_meshes.append( mesh ) mesh = split_mesh if( projected_curves ) : pm.delete( projected_curves ) # if( i == 10 ) : return for old_mesh in old_meshes : try : pm.delete( old_mesh ) except : pm.warning( 'Could not delete %s' % (old_mesh) ) pm.polyTriangulate( mesh ) # pm.polyQuad( mesh ) # -ver 1 -trm 0 -p 50 -vct 0 -tct 0 -shp 0.5326 -keepBorder 1 -keepMapBorder 1 -keepColorBorder 1 -keepFaceGroupBorder 1 -keepHardEdge 1 -keepCreaseEdge 1 -keepBorderWeight 0.5 -keepMapBorderWeight 0.5 -keepColorBorderWeight 0.5 -keepFaceGroupBorderWeight 0.5 -keepHardEdgeWeight 0.5 -keepCreaseEdgeWeight 0.5 -useVirtualSymmetry 0 -symmetryTolerance 0.01 -sx 0 -sy 1 -sz 0 -sw 0 -preserveTopology 1 -keepQuadsWeight 1 -vertexMapName "" -replaceOriginal 1 -cachingReduce 1 -ch 1 # pm.polyReduce( mesh, ver=True, trm=False, p=50, replaceOriginal=True, kb=True, kbw=1.0, kmb=True, kmw=1.0, kfb=True, kfw=1.0, kqw=1.0 ) pm.polySoftEdge( mesh, a=180, ch=True ) pm.delete( mesh, ch=True )
def __create_clean_object( obj ) : dup_obj = obj.duplicate()[0] ok_type_list = [ pm.Transform ] for dup_child in dup_obj.getChildren( ad=True, type='transform' ) : ok = True if( not type(dup_child) in ok_type_list ) : ok = False if( FFU_E_SETTINGS.get( 'hidden_ignore_bool' ).value ) : if( not dup_child.isVisible() ) : ok = False if( ok ) : dup_child_translation = dup_child.getTranslation() dup_child_rotation = dup_child.getRotation() for i, axis in enumerate( [ 'x', 'y', 'z' ] ) : flipsetting = 'flip'+axis if( FFU_E_FFEXPORT_SETTINGS.get(flipsetting).value ) : dup_child_translation[i] = -dup_child_translation[i] # dup_child_rotation[i] = -dup_child_rotation[i] dup_child.setTranslation( dup_child_translation ) dup_child.setRotation( dup_child_rotation ) if( type( dup_child.getShape() ) == pm.Mesh ) : # removed this to try fixing positions by applying appropriate flipping - see above # dup_child.setPivots( ( 0,0,0 ), ws=True ) # pm.makeIdentity( dup_child, translate=True, apply=True ) try : pm.polyTriangulate( dup_child ) except : pm.warning( 'Could not triangulate %s' % ( dup_child ) ) # pm.delete( dup_child, ch=True ) # pm.bakePartialHistory( dup_child, prePostDeformers=True ) else : pm.delete( dup_child ) return dup_obj
def triangulate(): pma.polyTriangulate()
def bake( self, modelsPath="", highSuffix="", xnormalExe="", xmlFiles="", cageSuffix="", typeSuffixes="", cageOffset=None ): try: cmds.progressWindow( endProgress=True ) except: pass #print( "..." ) cmds.progressWindow(isInterruptable=1) if highSuffix=="": highSuffix="_hi" if cageSuffix=="": cageSuffix= "_cage" if cageOffset==None: cageOffset=2.0 if typeSuffixes=="": typeSuffixes=['normals','heights','vcols', 'occlusion', 'curvature', 'cavity'] typeOfTypeSuffixes = type(typeSuffixes) if typeOfTypeSuffixes==type( "a_string" ) or typeOfTypeSuffixes==type( u"a_unicode_string" ): typeSuffixes = typeSuffixes.split(",") xnormal_exe = xnormalExe.replace("\\","/") folder_with_high_models = modelsPath.replace("\\","/") xml_files = xmlFiles.split(',') objExt = ".obj" ## Set pythons current working directory os.chdir( folder_with_high_models ) ## Get the selected objects, store as both an original selection ## and a copy of the original selection, objs osel = pm.ls(selection=True) objs = osel[:] scriptIsCanceled = False cancelCheckSleepTimeStartup = 0.5 cancelCheckSleepTime = 0.01 for obj in objs: time.sleep( cancelCheckSleepTimeStartup ) if cmds.progressWindow(query=1, isCancelled=1): print( "Script canceled by user, eg. escape key." ) scriptIsCanceled = True break try: ## try each obj ## Select the object and set up some basic variables, ## such as the name and the python cwd pm.select( obj ) obj_name = obj.name() cwd = os.getcwd() cwdUni = unicode(cwd) ## Triangulate before export print( obj ) tri_op = pm.polyTriangulate( obj ) ## Export lo, triangulated export_target_including_file_and_path = os.getcwd().replace("\\","/") + "/" + obj_name + objExt pm.select( obj ) pm.exportSelected( export_target_including_file_and_path,sh = 1, pr = 1, typ = "OBJexport", es = 1, force=True ) print( obj ) try: cageOffsetCustom = obj.mmmmBakerCageOffset.get() except: cageOffsetCustom = cageOffset print( "no custom cage offset found, using default" ) trans_op = pm.polyMoveVertex( obj, localTranslateZ=cageOffsetCustom ) ## Export Cage export_target_including_file_and_path = \ os.getcwd().replace("\\","/") + "/" + obj_name + cageSuffix + objExt pm.select( obj ) pm.exportSelected( export_target_including_file_and_path, sh = 1, pr = 1, typ = "OBJexport", es = 1, force=True ) ## Cleanup cage offset and triangulation pm.delete( trans_op ) pm.delete( tri_op ) #if obj_name.endswith( lo_suffix ): # high_name = obj_name.replace( lo_suffix, highSuffix ) #else: high_name = obj_name + highSuffix for i, xml_file in enumerate(xml_files): time.sleep( cancelCheckSleepTime ) if cmds.progressWindow(query=1, isCancelled=1): scriptIsCanceled=True print( "Script canceled by user, eg. escape key." ) break pm.select( obj ) pm.mel.eval( "ConvertSelectionToUVs;" ) uvs = pm.ls(selection=True, flatten=True) coUV = pm.polyEditUV( uvs, query=True ) coU, coV = coUV[::2], coUV[1::2] pm.select(obj) """" for c in coU: if c >= 0.0 and c < 1.0: udim1001=True if c >= 1.0 and c < 2.0: udim1002=True if c >= 2.0 and c < 3.0: udim1003=True if c >= 3.0 and c < 4.0: udim1004=True """ dictOfUsedUvRanges = {} for cIndex in xrange( len(coU) ): tu = coU[cIndex] tv = coV[cIndex] tuInt = math.floor( tu ) tvInt = math.floor( tv ) dictOfUsedUvRanges[ tuInt,tvInt ] = int( 1000 + (tuInt+1) + (tvInt*10) ) #print( "length of dictionary:") #print( len( dictOfUsedUvRanges.keys() ) ) #break for keyRange, udim in dictOfUsedUvRanges.items(): uInKey = keyRange[0] vInKey = keyRange[1] uOffset = uInKey * -1.0 vOffset = vInKey * -1.0 if uOffset==0.0: uOffset=0.0 #in case of negative 0.0, f*****g hell! if vOffset==0.0: vOffset=0.0 #in case of negative 0.0, f*****g hell! # do something similar for vOffset. ## edit xml export with uOffset and uOffset here! """" if udim1001==True: uOffsets.append( 0.0 ) if udim1002==True: uOffsets.append( -1.0 ) if udim1003==True: uOffsets.append( -2.0 ) if udim1004==True: uOffsets.append( -3.0 ) for uOffset in uOffsets: """ time.sleep( cancelCheckSleepTime ) if cmds.progressWindow(query=1, isCancelled=1): scriptIsCanceled=True print( "Script canceled by user, eg. escape key." ) break xml_file_abs = os.path.join( cwdUni, xml_file ) print( xml_file_abs ) xml_file_modified = u'tmp_mmmmBaker.xml' xml_file_modified_abs = os.path.join( cwdUni, xml_file_modified ) xml_in_mem = '' with open( xml_file_abs, 'r' ) as fh: xml_in_mem = fh.read() xml_in_mem = xml_in_mem.replace( 'UOffset="0.', 'UOffset="' + str(uOffset) ) xml_in_mem = xml_in_mem.replace( 'VOffset="0.', 'VOffset="' + str(vOffset) ) uOffsetAsInt = int( -1 * uOffset) vOffsetAsInt = int( -1 * uOffset) folder_with_high_models__no_trailing_slash = \ folder_with_high_models if folder_with_high_models__no_trailing_slash.endswith("/"): folder_with_high_models__no_trailing_slash =\ folder_with_high_models__no_trailing_slash[:-1] xml_in_mem = xml_in_mem.replace( "C:\\Users\\Public\\mmmmBaker", folder_with_high_models.replace("/","\\") ) root = XmlTree.fromstring(xml_in_mem) ## Print the entire xml tree for reference' #print( XmlTree.tostring( root ) ) ## find used udims on objects ## find u offset and v offset for low objects ## set up a list to run a for loop for to ## handle each udim found ## find low object ## find cage object ## find use cage option # ## find hi objects ## find output with open( xml_file_modified_abs, 'w' ) as fh: fh.write( xml_in_mem ) print( obj ) ##print( xml_in_mem ) print( uOffsetAsInt, vOffsetAsInt ) try: lo_to_copy_for_replacement = obj_name + objExt cage_to_copy_for_replacement = obj_name + cageSuffix + objExt hi_to_copy_for_replacement = obj_name + highSuffix + objExt shutil.copy2(lo_to_copy_for_replacement, "replaceme_lo" + objExt) shutil.copy2(hi_to_copy_for_replacement, "replaceme_hi" + objExt) shutil.copy2(cage_to_copy_for_replacement, "replaceme_cage" + objExt) print( "xnormal subprocess starting...") print( xnormal_exe + " " + str(xml_file_modified) ) subprocess.check_call( [ xnormal_exe, str(xml_file_modified) ] ) print( "xnormal subprocess complete! Continuing...") for typeSuffix in typeSuffixes: try: baked_name = "replaceme_" + typeSuffix + ".exr" proper_name = obj_name + "_" + "xml"+str(i).zfill(2) + "_" + "udim" + str( udim ) + "_" + typeSuffix + ".exr" shutil.copy2( baked_name, proper_name ) except: print( traceback.format_exc() ) except: print( traceback.format_exc() ) except: ## except each obj print( traceback.format_exc() ) pm.select( osel ) ## Do something here to attempt to combine/composite textures together. ## Until then, just tell the user to use the photoshop action ## which should be provided with MmmmTools ## Add some explaination for how to use the action cmds.progressWindow( endProgress=True ) if not scriptIsCanceled: print( "Baking complete!") print( "Baked (or at least attempted to bake) " + str( len(objs) ) + " objects." )
def bake(self, modelsPath="", highSuffix="", xnormalExe="", xmlFiles="", cageSuffix="", typeSuffixes="", cageOffset=None): try: cmds.progressWindow(endProgress=True) except: pass #print( "..." ) cmds.progressWindow(isInterruptable=1) if highSuffix == "": highSuffix = "_hi" if cageSuffix == "": cageSuffix = "_cage" if cageOffset == None: cageOffset = 2.0 if typeSuffixes == "": typeSuffixes = [ 'normals', 'heights', 'vcols', 'occlusion', 'curvature', 'cavity' ] typeOfTypeSuffixes = type(typeSuffixes) if typeOfTypeSuffixes == type( "a_string") or typeOfTypeSuffixes == type(u"a_unicode_string"): typeSuffixes = typeSuffixes.split(",") xnormal_exe = xnormalExe.replace("\\", "/") folder_with_high_models = modelsPath.replace("\\", "/") xml_files = xmlFiles.split(',') objExt = ".obj" ## Set pythons current working directory os.chdir(folder_with_high_models) ## Get the selected objects, store as both an original selection ## and a copy of the original selection, objs osel = pm.ls(selection=True) objs = osel[:] scriptIsCanceled = False cancelCheckSleepTimeStartup = 0.5 cancelCheckSleepTime = 0.01 for obj in objs: time.sleep(cancelCheckSleepTimeStartup) if cmds.progressWindow(query=1, isCancelled=1): print("Script canceled by user, eg. escape key.") scriptIsCanceled = True break try: ## try each obj ## Select the object and set up some basic variables, ## such as the name and the python cwd pm.select(obj) obj_name = obj.name() cwd = os.getcwd() cwdUni = unicode(cwd) ## Triangulate before export print(obj) tri_op = pm.polyTriangulate(obj) ## Export lo, triangulated export_target_including_file_and_path = os.getcwd().replace( "\\", "/") + "/" + obj_name + objExt pm.select(obj) pm.exportSelected(export_target_including_file_and_path, sh=1, pr=1, typ="OBJexport", es=1, force=True) print(obj) try: cageOffsetCustom = obj.mmmmBakerCageOffset.get() except: cageOffsetCustom = cageOffset print("no custom cage offset found, using default") trans_op = pm.polyMoveVertex(obj, localTranslateZ=cageOffsetCustom) ## Export Cage export_target_including_file_and_path = \ os.getcwd().replace("\\","/") + "/" + obj_name + cageSuffix + objExt pm.select(obj) pm.exportSelected(export_target_including_file_and_path, sh=1, pr=1, typ="OBJexport", es=1, force=True) ## Cleanup cage offset and triangulation pm.delete(trans_op) pm.delete(tri_op) #if obj_name.endswith( lo_suffix ): # high_name = obj_name.replace( lo_suffix, highSuffix ) #else: high_name = obj_name + highSuffix for i, xml_file in enumerate(xml_files): time.sleep(cancelCheckSleepTime) if cmds.progressWindow(query=1, isCancelled=1): scriptIsCanceled = True print("Script canceled by user, eg. escape key.") break pm.select(obj) pm.mel.eval("ConvertSelectionToUVs;") uvs = pm.ls(selection=True, flatten=True) coUV = pm.polyEditUV(uvs, query=True) coU, coV = coUV[::2], coUV[1::2] pm.select(obj) """" for c in coU: if c >= 0.0 and c < 1.0: udim1001=True if c >= 1.0 and c < 2.0: udim1002=True if c >= 2.0 and c < 3.0: udim1003=True if c >= 3.0 and c < 4.0: udim1004=True """ dictOfUsedUvRanges = {} for cIndex in xrange(len(coU)): tu = coU[cIndex] tv = coV[cIndex] tuInt = math.floor(tu) tvInt = math.floor(tv) dictOfUsedUvRanges[tuInt, tvInt] = int(1000 + (tuInt + 1) + (tvInt * 10)) #print( "length of dictionary:") #print( len( dictOfUsedUvRanges.keys() ) ) #break for keyRange, udim in dictOfUsedUvRanges.items(): uInKey = keyRange[0] vInKey = keyRange[1] uOffset = uInKey * -1.0 vOffset = vInKey * -1.0 if uOffset == 0.0: uOffset = 0.0 #in case of negative 0.0, f*****g hell! if vOffset == 0.0: vOffset = 0.0 #in case of negative 0.0, f*****g hell! # do something similar for vOffset. ## edit xml export with uOffset and uOffset here! """" if udim1001==True: uOffsets.append( 0.0 ) if udim1002==True: uOffsets.append( -1.0 ) if udim1003==True: uOffsets.append( -2.0 ) if udim1004==True: uOffsets.append( -3.0 ) for uOffset in uOffsets: """ time.sleep(cancelCheckSleepTime) if cmds.progressWindow(query=1, isCancelled=1): scriptIsCanceled = True print("Script canceled by user, eg. escape key.") break xml_file_abs = os.path.join(cwdUni, xml_file) print(xml_file_abs) xml_file_modified = u'tmp_mmmmBaker.xml' xml_file_modified_abs = os.path.join( cwdUni, xml_file_modified) xml_in_mem = '' with open(xml_file_abs, 'r') as fh: xml_in_mem = fh.read() xml_in_mem = xml_in_mem.replace( 'UOffset="0.', 'UOffset="' + str(uOffset)) xml_in_mem = xml_in_mem.replace( 'VOffset="0.', 'VOffset="' + str(vOffset)) uOffsetAsInt = int(-1 * uOffset) vOffsetAsInt = int(-1 * uOffset) folder_with_high_models__no_trailing_slash = \ folder_with_high_models if folder_with_high_models__no_trailing_slash.endswith( "/"): folder_with_high_models__no_trailing_slash =\ folder_with_high_models__no_trailing_slash[:-1] xml_in_mem = xml_in_mem.replace( "C:\\Users\\Public\\mmmmBaker", folder_with_high_models.replace("/", "\\")) root = XmlTree.fromstring(xml_in_mem) ## Print the entire xml tree for reference' #print( XmlTree.tostring( root ) ) ## find used udims on objects ## find u offset and v offset for low objects ## set up a list to run a for loop for to ## handle each udim found ## find low object ## find cage object ## find use cage option # ## find hi objects ## find output with open(xml_file_modified_abs, 'w') as fh: fh.write(xml_in_mem) print(obj) ##print( xml_in_mem ) print(uOffsetAsInt, vOffsetAsInt) try: lo_to_copy_for_replacement = obj_name + objExt cage_to_copy_for_replacement = obj_name + cageSuffix + objExt hi_to_copy_for_replacement = obj_name + highSuffix + objExt shutil.copy2(lo_to_copy_for_replacement, "replaceme_lo" + objExt) shutil.copy2(hi_to_copy_for_replacement, "replaceme_hi" + objExt) shutil.copy2(cage_to_copy_for_replacement, "replaceme_cage" + objExt) print("xnormal subprocess starting...") print(xnormal_exe + " " + str(xml_file_modified)) subprocess.check_call( [xnormal_exe, str(xml_file_modified)]) print( "xnormal subprocess complete! Continuing...") for typeSuffix in typeSuffixes: try: baked_name = "replaceme_" + typeSuffix + ".exr" proper_name = obj_name + "_" + "xml" + str( i).zfill(2) + "_" + "udim" + str( udim) + "_" + typeSuffix + ".exr" shutil.copy2(baked_name, proper_name) except: print(traceback.format_exc()) except: print(traceback.format_exc()) except: ## except each obj print(traceback.format_exc()) pm.select(osel) ## Do something here to attempt to combine/composite textures together. ## Until then, just tell the user to use the photoshop action ## which should be provided with MmmmTools ## Add some explaination for how to use the action cmds.progressWindow(endProgress=True) if not scriptIsCanceled: print("Baking complete!") print("Baked (or at least attempted to bake) " + str(len(objs)) + " objects.")
def project_curves_onto_mesh2( mesh, source_mesh, direction ) : # duplicate sources_mesh dup_source_mesh = pm.duplicate( source_mesh )[0] dup_source_mesh.setParent(None) # create curve around mesh edge_curves = [] for edge in mesh.getShape().e : edge_curves.append( pm.curve( # name=n, degree=1, ws=True, point=[ v.getPosition(space='world') for v in edge.connectedVertices() ] ) ) merged_curve = pm.attachCurve( edge_curves, method=1, keepMultipleKnots=False, ch=False )[0] merged_curve = pm.duplicate( merged_curve ) pm.delete( edge_curves ) # project curve onto dup_source_mesh projected_curves = projected_curves = pm.polyProjectCurve( dup_source_mesh, merged_curve, direction=direction )[0] # pm.delete( projected_curves.getChildren()[1:] ) projected_curve = projected_curves.getChildren()[0] split_mesh = pm.polySplit( dup_source_mesh, detachEdges=0, projectedCurve=projected_curve ) split_mesh = split_mesh[0] # delete faces not within mesh bounds # faces_to_delete = [] pm.select(None) for face in split_mesh.f : face_center = ( 0.0, 0.0, 0.0 ) for v in face.connectedVertices() : face_center += v.getPosition( space='world' ) face_center /= len( face.connectedVertices() ) if( point_in_rect_bb( face_center, mesh.getBoundingBox( space='world' ) ) ) : # faces_to_delete.append( face ) dot = face.getNormal( space='world' ).dot( mesh.f[0].getNormal( space='world' ) ) if( dot > 0.0 ) : pm.select(face, add=True) # for face in faces_to_delete : # dot = face.getNormal( space='world' ).dot( mesh.f[0].getNormal( space='world' ) ) # if( dot > 0.0 ) : # pm.select(face, add=True) pm.runtime.InvertSelection() pm.delete() # transfer UVs from mesh to dup_source_mesh pm.transferAttributes( mesh, split_mesh, transferUVs=2 ) # assign mesh material to dup_source_mesh # rename dup_source_mesh to mesh pm.delete( split_mesh, ch=True ) n = mesh.name() p = mesh.getParent() pm.delete( mesh ) split_mesh.rename( n ) for attr in split_mesh.listAttr() : if attr.isLocked() : attr.setLocked(False) # cleanup pm.delete( projected_curves ) pm.delete( merged_curve ) pm.delete( dup_source_mesh ) # split_mesh.centerPivots( True ) # t = split_mesh.getPivots( worldSpace=1 )[0] # split_mesh.setTranslation((-t[0], -t[1], -t[2]), space='world') # pm.makeIdentity( split_mesh, apply=True ) # split_mesh.setParent( p ) # split_mesh.setTranslation( ( 0,0,0 ) ) # pm.makeIdentity( split_mesh, apply=True ) # position bodge split_mesh.setTranslation( ( 0, 0, 1 ), space='world' ) split_mesh.setParent( p ) pm.polyTriangulate( split_mesh ) if( not split_mesh.hasAttr( THU_MFT_SPRITE_ATTR ) ) : split_mesh.addAttr( THU_MFT_SPRITE_ATTR, dt='string' ) split_mesh.setAttr( THU_MFT_SPRITE_ATTR, split_mesh.name().replace( '.png', '' ) )
def project_curves_onto_mesh2(mesh, source_mesh, direction): # duplicate sources_mesh dup_source_mesh = pm.duplicate(source_mesh)[0] dup_source_mesh.setParent(None) # create curve around mesh edge_curves = [] for edge in mesh.getShape().e: edge_curves.append( pm.curve( # name=n, degree=1, ws=True, point=[ v.getPosition(space='world') for v in edge.connectedVertices() ])) merged_curve = pm.attachCurve(edge_curves, method=1, keepMultipleKnots=False, ch=False)[0] merged_curve = pm.duplicate(merged_curve) pm.delete(edge_curves) # project curve onto dup_source_mesh projected_curves = projected_curves = pm.polyProjectCurve( dup_source_mesh, merged_curve, direction=direction)[0] # pm.delete( projected_curves.getChildren()[1:] ) projected_curve = projected_curves.getChildren()[0] split_mesh = pm.polySplit(dup_source_mesh, detachEdges=0, projectedCurve=projected_curve) split_mesh = split_mesh[0] # delete faces not within mesh bounds # faces_to_delete = [] pm.select(None) for face in split_mesh.f: face_center = (0.0, 0.0, 0.0) for v in face.connectedVertices(): face_center += v.getPosition(space='world') face_center /= len(face.connectedVertices()) if (point_in_rect_bb(face_center, mesh.getBoundingBox(space='world'))): # faces_to_delete.append( face ) dot = face.getNormal(space='world').dot( mesh.f[0].getNormal(space='world')) if (dot > 0.0): pm.select(face, add=True) # for face in faces_to_delete : # dot = face.getNormal( space='world' ).dot( mesh.f[0].getNormal( space='world' ) ) # if( dot > 0.0 ) : # pm.select(face, add=True) pm.runtime.InvertSelection() pm.delete() # transfer UVs from mesh to dup_source_mesh pm.transferAttributes(mesh, split_mesh, transferUVs=2) # assign mesh material to dup_source_mesh # rename dup_source_mesh to mesh pm.delete(split_mesh, ch=True) n = mesh.name() p = mesh.getParent() pm.delete(mesh) split_mesh.rename(n) for attr in split_mesh.listAttr(): if attr.isLocked(): attr.setLocked(False) # cleanup pm.delete(projected_curves) pm.delete(merged_curve) pm.delete(dup_source_mesh) # split_mesh.centerPivots( True ) # t = split_mesh.getPivots( worldSpace=1 )[0] # split_mesh.setTranslation((-t[0], -t[1], -t[2]), space='world') # pm.makeIdentity( split_mesh, apply=True ) # split_mesh.setParent( p ) # split_mesh.setTranslation( ( 0,0,0 ) ) # pm.makeIdentity( split_mesh, apply=True ) # position bodge split_mesh.setTranslation((0, 0, 1), space='world') split_mesh.setParent(p) pm.polyTriangulate(split_mesh) if (not split_mesh.hasAttr(THU_MFT_SPRITE_ATTR)): split_mesh.addAttr(THU_MFT_SPRITE_ATTR, dt='string') split_mesh.setAttr(THU_MFT_SPRITE_ATTR, split_mesh.name().replace('.png', ''))