0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

MayaAdvent Calendar 2023

Day 19

maya skinWeight import をちょっと何とかする3

Last updated at Posted at 2023-12-19

もうちょっとだけなんとか

具体的には
前回は objectA から objectB だったんですけども、
objectA_left から objectB_right へ
ジョイント名は left_joint から right_joint へ

ただし前回のままだと、 left_joint right_joint を両方使用してる場合はおかしくなるので
ジョイント名は left_joint から right_joint へ
ジョイント名は right_joint から left_joint へ

基本的には前回のやつのインフルエンス書き換え部分を何とかすれば良いはず

改修

import maya.cmds as cmds
from xml.etree import ElementTree

def getSkinClusterNode(target):
    history = cmds.listHistory(target,pruneDagObjects =True)    
    skinNode = cmds.ls(history,type = "skinCluster") or None
    
    if skinNode != None:
        return skinNode[0]

    return None

def getBindInfo(filePath):
    tree = ElementTree.parse(filePath)
    root = tree.getroot()
    skinBindDict = {}
    
    ##weights を見つける
    for e in root.findall('weights'):
        #それぞれのパラメーターを取得
        inf = e.get("source")
        shape = e.get("shape")
        deformer = e.get("deformer")
    
        if deformer in list(skinBindDict.keys()):
            if inf not in skinBindDict[deformer]["inf"]:
                skinBindDict[deformer]["inf"].append(inf)
        else:
            skinBindDict[deformer] = {
                                        "inf":[inf],
                                        "shape":shape
                                        }
    return skinBindDict
                                        
def importSkinWeight(filePath,fileName):
    skinBindDict = getBindInfo(filePath+fileName)

    for deformerNode in list(skinBindDict.keys()):        
        target = skinBindDict[deformerNode]["shape"]
        infs = skinBindDict[deformerNode]["inf"]
        
        #skinClusterの有無確認
        targetSkinNode = getSkinClusterNode(target)

        if targetSkinNode == None:
            targetSkinNode = cmds.skinCluster(infs,target,normalizeWeights = 1,toSelectedBones =True,name = deformerNode)[0]
        else:
            #現在のインフルエンスを取得して、addInfするための差分を取る
            curInfs = cmds.skinCluster(targetSkinNode, q =True, inf =True) 
            addInfs = list(set(infs) - set(curInfs))
 
            for inf in addInfs:
                cmds.skinCluster(targetSkinNode, e =True, ai = inf, weight = 0)

        cmds.deformerWeights(fileName, path = filePath, deformer = targetSkinNode, method = "index",im = True)            
        cmds.skinCluster(targetSkinNode,e =True,forceNormalizeWeights = True)

##前回のはそのままにして別ものとして改修-------------------------------------------
def switchSkinWeight(source,target,leftString,rightString):
    #sourceのスキニング情報を書き出す
    sourceSkinNode = getSkinClusterNode(source)
    if sourceSkinNode == None:
        return

    #書き出し場所はひとまずmayaのuserAppDir
    tmpExportPath = cmds.internalVar(userAppDir=True) + 'temp/'
    tmpFileName = "tempSkinWeight.xml"
    cmds.deformerWeights(
                            tmpFileName, 
                            path = tmpExportPath, 
                            deformer = sourceSkinNode, 
                            format ="XML",ex = True
                            )        

    targetShape = cmds.listRelatives(target,type = "shape")[0]

    #sourceのXMLを読み込む
    tree = ElementTree.parse(tmpExportPath+tmpFileName)
    root = tree.getroot()    
    
    for e in root.findall('shape'):
        e.set("name",targetShape)
        
    for e in root.findall('weights'):
        targetInf = e.get("source")

        if leftString in targetInf:
        #左なので右化
            replaceInf = targetInf.replace(leftString,rightString)            
        elif rightString in targetInf:
        #右なので左化
            replaceInf = targetInf.replace(rightString,leftString)                        
        else:
        #右でも左でもないのでそのまま
            replaceInf = targetInf
        
        replaceInf = targetInf.replace(searchString,replaceString)
        e.set("source",replaceInf)
        e.set("shape",targetShape)
        
        #skinCluster名も念のため調整
        e.set("deformer",target + "_skinCluster")
    
    #XMLファイルとして保存する(上書き)
    tree.write(tmpExportPath + tmpFileName, encoding='UTF-8')

    #XMLファイルを読み込ませる
    importSkinWeight(tmpExportPath,tmpFileName)

    #一応一時ファイルとしては削除
    os.remove(tmpExportPath+tmpFileName)

制限事項と改修案

左右のjointを区別するためのネーミングルール必須

単純なネーミングでの識別ではなく、jointのラベルを使った入れ替えとかどうだろか
その為にはシーン内 or ツリー内のjointを全取得してラベルをkeyとしたdictつくるとか?

うん?これでヒトネタ書けそうな気もしますね

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?