一番面倒なsetJointOrientの部分が出来たので、UI作りつつ他の機能もさっさか作っていきます。
-
createNode
エッジループの中心や特定のvtx位置などにjointを作成したい -
mirrorJoints
maya標準のmirrorJointだと、1個ずつしかできないので面倒。
複数に対応させたい -
mirrorOrients
左右jointがそろっている状態で、jointOrientを左右揃えたい。 -
mirrorPositions
左右jointがそろっている状態で、joint位置を揃えたい
といった内容のツールを作成したい
mirrorOrients/mirrorPositions
骨半分いじった後に毎回 削除して mirrorJointsは面倒なので。
特定の点を支点として、特定の軸方向に反転させる処理をmatrixでやってみる。
位置に関しては、支点の位置と軸に対して -1 スケールすれば良いんじゃないかしら。
ひとまず 支点 = 原点という想定でやってみる
def mirrorMatrix(source,mirrorAxis):
curMatrix = om.MMatrix(cmds.getAttr(source+".worldMatrix[0]"))
if mirrorAxis == "x":
mirrorScale = [-1.0,1.0,1.0]
elif mirrorAxis == "y":
mirrorScale = [1.0,-1.0,1.0]
elif mirrorAxis == "z":
mirrorScale = [1.0,1.0,-1.0]
mirrorScaleMatrix = om.MTransformationMatrix(om.MMatrix.kIdentity).setScale(mirrorScale,om.MSpace.kWorld).asMatrix()
dist_matrix = curMatrix * mirrorScaleMatrix
return dist_matrix
dist_matrix = mirrorMatrix("locator1","x")
node = cmds.createNode("joint")
cmds.xform(node, matrix = list(dist_matrix), ws = True)
対称の位置がとれました。
これだけでも十分つかえますが、原点以外が支点となる場合もあるのでオプション追加。
支点が world または 任意のノードを指定できるようにする。
def mirrorMatrix(source,pivot,mirrorAxis):
curMatrix = om.MMatrix(cmds.getAttr(source+".worldMatrix[0]"))
if mirrorAxis == "x":
mirrorScale = [-1.0,1.0,1.0]
elif mirrorAxis == "y":
mirrorScale = [1.0,-1.0,1.0]
elif mirrorAxis == "z":
mirrorScale = [1.0,1.0,-1.0]
mirrorScaleMatrix = om.MTransformationMatrix(om.MMatrix.kIdentity).setScale(mirrorScale,om.MSpace.kWorld).asMatrix()
if pivot == "world":
pivotMatrix = om.MMatrix.kIdentity
else:
pivotMatrix = om.MMatrix(cmds.getAttr(pivot+".worldMatrix[0]"))
pivotMatrix_inverse = pivotMatrix.inverse()
dist_matrix = curMatrix * pivotMatrix_inverse * mirrorScaleMatrix * pivotMatrix
return dist_matrix
位置は取れたので回転を追加したい。
mirrorJoints のbehaviorのrotationの挙動のみを再現したい。
軸の向きが全て反転されれば良いと考えると、オブジェクト空間でscaleを全部-1 してしまえばどうだろうか
def mirrorMatrix(source,pivot,mirrorAxis):
curMatrix = om.MMatrix(cmds.getAttr(source+".worldMatrix[0]"))
if mirrorAxis == "x":
mirrorScale = [-1.0,1.0,1.0]
elif mirrorAxis == "y":
mirrorScale = [1.0,-1.0,1.0]
elif mirrorAxis == "z":
mirrorScale = [1.0,1.0,-1.0]
mirrorScaleMatrix = om.MTransformationMatrix(om.MMatrix.kIdentity).setScale(mirrorScale,om.MSpace.kWorld).asMatrix()
if pivot == "world":
pivotMatrix = om.MMatrix.kIdentity
else:
pivotMatrix = om.MMatrix(cmds.getAttr(pivot+".worldMatrix[0]"))
pivotMatrix_inverse = pivotMatrix.inverse()
dist_matrix = curMatrix * pivotMatrix_inverse * mirrorScaleMatrix * pivotMatrix
dist_matrix = om.MTransformationMatrix(dist_matrix).setScale([-1.0,-1.0,-1.0],om.MSpace.kObject).asMatrix()
return dist_matrix
向きはrotation込みであってそう。
スケールに -1 が入ってしまっているのでちょっと気持ち悪いので、最終的にworld空間でのスケールを1に戻す。
def mirrorMatrix(source,pivot,mirrorAxis):
curMatrix = om.MMatrix(cmds.getAttr(source+".worldMatrix[0]"))
if mirrorAxis == "x":
mirrorScale = [-1.0,1.0,1.0]
elif mirrorAxis == "y":
mirrorScale = [1.0,-1.0,1.0]
elif mirrorAxis == "z":
mirrorScale = [1.0,1.0,-1.0]
mirrorScaleMatrix = om.MTransformationMatrix(om.MMatrix.kIdentity).setScale(mirrorScale,om.MSpace.kWorld).asMatrix()
if pivot == "world":
pivotMatrix = om.MMatrix.kIdentity
else:
pivotMatrix = om.MMatrix(cmds.getAttr(pivot+".worldMatrix[0]"))
pivotMatrix_inverse = pivotMatrix.inverse()
dist_matrix = curMatrix * pivotMatrix_inverse * mirrorScaleMatrix * pivotMatrix
dist_matrix = om.MTransformationMatrix(dist_matrix).setScale([-1.0,-1.0,-1.0],om.MSpace.kObject).asMatrix()
dist_matrix = om.MTransformationMatrix(dist_matrix).setScale([1.0,1.0,1.0],om.MSpace.kWorld).asMatrix()
return dist_matrix
matrixとれたので、位置と回転に分離してみる
def getMirrorPosition(source,pivot,mirrorAxis):
setMatrix = mirrorMatrix(source,pivot,mirrorAxis)
mirrorPosition = om.MTransformationMatrix(setMatrix).translation(om.MSpace.kWorld)
return mirrorPosition
def getMirrorOrient(source,pivot,mirrorAxis):
setMatrix = mirrorMatrix(source,pivot,mirrorAxis)
mirrorOrient = om.MTransformationMatrix(setMatrix).rotation(False)
return mirrorOrient
位置の方は問題なさそう。
回転の方がおかしい。
matrixの時点では問題なかったので
om.MTransformationMatrix(setMatrix).rotation(False)
ここが何かおかしいらしい。
OpenMaya.MTransformationMatrix.rotation(asQuaternion=False)
Returns the transformation's rotation component as either an Euler rotation or a quaternion.
とのこと。
('A)助けてインターネット
OpenMaya.MTransformationMatrix.rotation(asQuaternion=False) で返ってくるのは radian なので、angleに変換が必要らしい。
def getMirrorPosition(source,pivot,mirrorAxis):
setMatrix = mirrorMatrix(source,pivot,mirrorAxis)
mirrorPosition = om.MTransformationMatrix(setMatrix).translation(om.MSpace.kWorld)
return mirrorPosition
def getMirrorOrient(source,pivot,mirrorAxis):
setMatrix = mirrorMatrix(source,pivot,mirrorAxis)
mirrorOrient = om.MTransformationMatrix(setMatrix).rotation(False)
return [om.MAngle(mirrorOrient.x).asDegrees(), om.MAngle(mirrorOrient.y).asDegrees(), om.MAngle(mirrorOrient.z).asDegrees()]
無事回転もとれた。
あとはこれらをツールに組み込んで行くのですが、長くなるので割愛。
後日 githubかなんかで公開していこうかと思います。
ちょっと回り道してしまった感がありますが、これがあるとないで後々の作業に大きく影響が出るので。
ここまでくればもうリグ環境出来たも同然なので、続きは次回