mayaの環境を構築していく　5日目

一番面倒な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
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/5d18137e-759c-ccff-a9bb-f3d07ebc2534.png)

向きはrotation込みであってそう。
スケールに -1 が入ってしまっているのでちょっと気持ち悪いので、最終的に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

    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かなんかで公開していこうかと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/80267e6f-7f64-ac57-f9ce-7a491b1051c6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/0b9896a2-b9cd-daea-e789-5f81ce150b9d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/c980bcd8-ad81-4b0c-7603-a30bac0c0a10.png)


ちょっと回り道してしまった感がありますが、これがあるとないで後々の作業に大きく影響が出るので。
ここまでくればもうリグ環境出来たも同然なので、続きは次回