copySkinWeights って便利なんですが、そのまま使うには少々イラっとする事も。
制限
- 転送先のオブジェクトはスキニングされている必要がある
- 転送元のインフルエンスは転送先にもすべて登録されていなければならない
smoothBindをselected joints で実行して add influenceを繰り返して調整していく身としては、
とても面倒なので1クリックで実行したいです。
設計
- 転送元のskinClusterからinfluenceを取得
- 転送先のオブジェクトがスキニング済みかチェック
- 未スキニングならsmoothBind実行
- バインド済みならば転送元influenceをaddInf
- copySkinWeights実行
んー個別の処理はそんなに問題ない気がしますね。
実装
- 転送元のskinClusterからinfluenceを取得
まずはskinClusterを取得して・・・
なんかskinClusterを狙い撃ちで検索するコマンドがあったような
あった! けど! melのみか!
あとは使えそうなのはこの辺かしら
とりあえず listHistory でいいか。
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 copySkinWeights(source,target):
sourceSkinNode = getSkinClusterNode(source)
sourceInfs = cmds.skinCluster(sourceSkinNode, q =True, inf =True)
- 転送先のオブジェクトがスキニング済みかチェック
これはさっきのskinCluster取得を再利用ですね。
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 copySkinWeights(source,target):
sourceSkinNode = getSkinClusterNode(source)
sourceInfs = cmds.skinCluster(sourceSkinNode, q =True, inf =True)
targetSkinNode = getSkinClusterNode(target)
if targetSkinNode == None:
pass
else:
pass
-
未スキニングならsmoothBind実行
こっちはskinClsuterのオプションに注意しつつ実行
skinMethod とか normalizeWeights とか toSelectedBones とか
真面目にやるなら転送元のskinClusterから取得するんでしょうな。 -
バインド済みならば転送元influenceをaddInf
なにも考えずにaddInfでも良い気がするけど、転送先の既存influenceと重複すると怒られるので
念のため差分取って必要なinfluenceだけaddInfに。
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 copySkinWeights(source,target):
sourceSkinNode = getSkinClusterNode(source)
sourceInfs = cmds.skinCluster(sourceSkinNode, q =True, inf =True)
targetSkinNode = getSkinClusterNode(target)
if targetSkinNode == None:
targetSkinNode = cmds.skinCluster(sourceInfs,target,normalizeWeights = 1,toSelectedBones =True)[0]
else:
targetInfs = cmds.skinCluster(targetSkinNode, q =True, inf =True)
addInfs = list(set(sourceInfs) - set(targetInfs))
for inf in addInfs:
cmds.skinCluster(targetSkinNode, e =True, ai = inf, weight = 0)
一旦テストしてみる
sphere1を雑にバインドし、
未バインド状態のsphere2に対して実行
copySkinWeights("pSphere1","pSphere2")
バインドされましたね。
次に別のジョイントであらかじめsphere2をバインドして実行
追加されましたね。
- copySkinWeights実行
念のためオプションを確認してみる
ツール化するなら sampleSpace とか uvSpace とか色々使えそうだけれども
ひとまずいつも使っているオプションで固定
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 copySkinWeights(source,target):
sourceSkinNode = getSkinClusterNode(source)
sourceInfs = cmds.skinCluster(sourceSkinNode, q =True, inf =True)
targetSkinNode = getSkinClusterNode(target)
if targetSkinNode == None:
targetSkinNode = cmds.skinCluster(sourceInfs,target,normalizeWeights = 1,toSelectedBones =True)[0]
else:
targetInfs = cmds.skinCluster(targetSkinNode, q =True, inf =True)
addInfs = list(set(sourceInfs) - set(targetInfs))
for inf in addInfs:
cmds.skinCluster(targetSkinNode, e =True, ai = inf, weight = 0)
cmds.copySkinWeights(
ss=sourceSkinNode,
ds=targetSkinNode,
sampleSpace = 0,
noMirror = True,
smooth = False,
normalize =True,
surfaceAssociation = "closestPoint",
influenceAssociation = ["name","closestJoint","closestBone"]
)
を大丈夫そうかな?
ひとまず完成。
不具合
ポリゴン -> ポリゴン OK
ナーブスカーブ -> ナーブスカーブ OK
ポリゴン -> ナーブスカーブ OK
ポリゴン -> ナーブスサーフェス うなくいかない
ナーブスサーフェス -> ポリゴン うなくいかない
ナーブスサーフェス -> ナーブスサーフェス うなくいかない
で やばいのが
ナーブスサーフェス -> ナーブスカーブ 落ちる
図らずも地雷を発見。
コマンドとか関わらず
nurbsSurface から nurbsCurveに対してcopySkinWeightsを実行するとmayaが即落ちする
気を付けてくださいね!
※この時、スクリプトエディタの内容も飛んだのですが 記事書きつつだったのでセーフ!