重新创建Maya的“Mesh-> Cleanup”以删除Python中的非流形几何

时间:2015-06-04 18:25:15

标签: python scripting mesh maya

我是使用Python编写Maya脚本的相对新手,我想知道是否有人可以提供帮助。我正在尝试遍历一堆OBJ并减少它们的多边形数量。我有那个部分在工作!问题是我偶尔会遇到错误读取"Cannot reduce polygonal object with non-manifold geometry. Cleanup the object using Mesh->Cleanup before reducing."虽然我当然可以使用Mesh-> Cleanup来手动解决问题,但我必须在千个OBJ文件的某些部分中执行此操作。

我相信在MEL中,命令将是:

polyCleanupArgList 3 { "0","1","1","0","0","0","0","0","0","1e-05","0","1e-05","0","1e-05","0","1","0" }

这是从控制台菜单中运行命令时返回的内容。我在查找MEL命令的文档时遇到了麻烦,并找到了如何将其转换为python的文档。我知道我可以用这个命令“找到”(但不能清理)非流形地理(我认为):

cmds.polyInfo( nme=True )

但实际上做类似于清理工具的任何东西目前都超出了我的理解范围。那里的任何人都有一些关于如何从Python中的脚本运行Mesh-> Cleanup命令的见解?非常感谢!

编辑:以下是我正在处理的代码的一些片段,改编自网络上的其他一些地方(具体来说,一个减少了一堆maya文件,另一个展示了如何打开) OBJ文件)。 我添加了评论“ISSUE:”以指出我目前遇到的问题点。

import os
import maya.cmds as mc
import maya.mel

#creates the search UI                
def makeWindow():
    if mc.window('UI', query=True, exists=True): mc.deleteUI('UI')
    window = mc.window('UI', widthHeight=(346, 96),   title = 'Automated Poly Reduction Tool')
    mc.columnLayout()    
    mc.radioButtonGrp('myRadBtnGrp', labelArray2=['Save changes', 'Preview changes'], numberOfRadioButtons=2, select = 2)
    mc.floatFieldGrp( 'myFltFieldGrp', numberOfFields=1, label='Amount of Reduction', extraLabel='%', value1=50)
    mc.intFieldGrp( 'myIntFldGrp', numberOfFields=2, label='Select Image Dimensions', extraLabel='W / H', value1=1280, value2=960, )
    mc.button('directoryBtn', label='get directory', command = 'getDirectory()')
    mc.button('explorerBtn', label='open image folder', command = 'openFolder()')
    mc.showWindow(window)

def openFolder():
    outputDir = mc.workspace (query = True, fileRule = True)
    path =  (outputDir[3] + '/tmp')
    if os.path.exists(path) == 1:
        os.system('start ' + path)
    else :
        mc.warning ("folder doesn't exist yet - please run tool")


#finds all the files in a directory
def getFiles(dir):
    mayaFiles = []
    for root, dirs, files in os.walk(dir):
        for file in files:
            if file.endswith('.obj'):
                mayaFiles.append( os.path.join(root, file))

    #open the first file in the list without saving the currently open scene
    mc.file(save = False)
    mc.file(mayaFiles[0], i = True) 
    processScene(mayaFiles)           

#gets directory to process
def getDirectory():
    result = mc.fileDialog2(fm = 3, okc = 'Process!')

    #set the location for the renders to save  
    #mc.workspace(fileRule = ['png', result[0]])
    mc.workspace (fileRule = ['images', result[0]])

    getFiles(result[0])

#moves through the selected files and does the work
def processScene(mayaFiles):
    errorLog = ""
    errorCount = 0
    for i in range (0, len(mayaFiles), 1):    

        #are we saving the reduction or just testing?
        saveQuery = mc.radioButtonGrp('myRadBtnGrp', query = True, select = True)

        if saveQuery == 1:
            #mc.file(save = True)
            #ISSUE: I NEED TO OUTPUT TO A DIRECTORY TO EXPORT AN OBJ FILE, THE CODE IN THIS IF STATEMENT DOESN'T CURRENTLY WORK
            geo = mc.ls( geometry=True )
            mc.select( all=True )
            outputDir = mc.workspace (query = True, fileRule = True)
            path =  mayaFiles[i];
            mc.file(path,pr=1,typ="OBJexport",es=1,op="groups=0; ptgroups=0; materials=0; smoothing=0; normals=0")
            print path;
            mc.file(save = False)
            mc.file(mayaFiles[i], open = True, force = True) 
        if saveQuery == 2:
            mc.file(save = False)
            mc.file(mayaFiles[i], open = True, force = True) 
        print  'currently working on ' + mayaFiles[i]          

        #move camera to front view
        mc.setAttr ('persp.translateX', 0)
        mc.setAttr ('persp.translateY', 0)
        mc.setAttr ('persp.translateZ', 0)
        mc.setAttr ("persp.rotateX", 0)
        mc.setAttr ("persp.rotateY", 0)
        mc.setAttr ("persp.rotateZ", 0)

        #set to full perspective window
        maya.mel.eval('setNamedPanelLayout("Single Perspective View")')

        #set image resolution
        width = mc.intFieldGrp( 'myIntFldGrp', query = True, value1 = True )
        height = mc.intFieldGrp( 'myIntFldGrp', query = True, value2 = True )
        mc.setAttr ('defaultResolution.width', width)
        mc.setAttr ('defaultResolution.height', height)

        #select all geo
        geo = mc.ls( geometry=True )
        mc.select (geo, replace = True)

        #and fit to frame
        mc.viewFit( 'persp', all=False )

        #get name of file for use in image name
        fileName = os.path.splitext(mc.file(query = True, sceneName = True, shortName = True))
        imageNameBefore =  (str(i) + '_before_' + fileName[0])
        mc.setAttr('defaultRenderGlobals.imageFilePrefix', imageNameBefore, type = 'string')

        #set the render globals to png
        mc.setAttr('defaultRenderGlobals.imageFormat', 32) 

        #render
        mc.hwRender()

        #if more than one thing is selected, iterate over all selected objects individually
        if len(geo) != 1:
            for item in geo:
                #check the geo is polygonal
                if mc.nodeType(item) == 'mesh':
                    #ISSUE: I NEED TO RUN CLEANUP HERE SO I DON'T HAVE TO TRY/CATCH ANYMORE
                    #run reduction      
                    mc.select (item, replace = True)  
                    try:
                        reduction = mc.floatFieldGrp( 'myFltFieldGrp', query = True, value = True)
                        mc.polyReduce(percentage = reduction[0], uvWeights=False, colorWeights=False, keepQuadsWeight = True, keepBorder = True, keepMapBorder= True, keepOriginalVertices = True,keepHardEdge = True,compactness=0.5, triangulate = False, replaceOriginal = True, cachingReduce = True, ch = True)
                    except:
                        #print "ERROR ON FILE " + mayaFiles[i];
                        errorLog = errorLog + mayaFiles[i] + ", "
                        errorCount = errorCount + 1
                        pass
        else:
            try:
                reduction = mc.floatFieldGrp( 'myFltFieldGrp', query = True, value = True)
                mc.polyReduce(percentage = reduction[0], uvWeights=False, colorWeights=False, keepQuadsWeight = True, keepBorder = True, keepMapBorder= True, keepOriginalVertices = True,keepHardEdge = True,compactness=0.5, triangulate = False, replaceOriginal = True, cachingReduce = True, ch = True)
            except:
                errorLog = errorLog + mayaFiles[i] + ", "
                errorCount = errorCount + 1
                pass
        #store second screen shot
        imageNameAfter =  (str(i) + '_after_' + fileName[0])
        mc.setAttr('defaultRenderGlobals.imageFilePrefix', imageNameAfter, type = 'string')
        mc.hwRender()
    print "Error count is : " + str(errorCount) + " and files are " + errorLog
makeWindow()

1 个答案:

答案 0 :(得分:2)

这个工具有点像噩梦。

你可以在(Program Files or /Applications) /Autodesk/Maya20XX/scripts/others/polyCleanupArgList.mel中看到内脏。但是你要调用polyCleanup而不是polyCleanupArgList:argList函数只是格式化清理命令的长丑陋的标志字符串。