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

さて　pythonでツールを作っていきます。
リグを組むために。

骨打ち用ツール
-

欲しい機能としては

- setJointOrient
- createNode
- mirrorJoints
- mirrorOrients
- mirrorPositios

くらいかしら。
もしかしたらmayaの標準機能で既にあるのかもしれませんが、まぁ作ろう。

setJointOrient
-
maya標準だと　OrientJointですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/bc29f640-c492-0c8e-68a6-304106da4fe4.png)

追加で欲しい機能としては、

- primary Axis にも　+/-欲しい
- secondary Axis にも　+/- 欲しい
- secondary Axis World Orientation については、aimConstraintの様に　object/ parent が欲しい

処理の大雑把な流れとしては

- 子ノードの現在の位置・向きを取得
- primary/secondaryの変化先をベクトルとしてそれぞれ取得
- vectorの投影によってdistSecondaryAxisVectorからdistPrimaryAxisVectorに直交するvectorを取得
- 外積によって残りの軸のvectorを取得
- 各軸のvectorから変化後のmatrixを作成
- matrixをセット
- 子ノードの現在の位置・向きを復元

追記：外積2回で各軸ベクトル求めた方がシンプルな気がします


```setjointOrient
import maya.cmds as cmds
import maya.api.OpenMaya as om
import maya.api.OpenMayaAnim as omAnm

def getPosition(target):
    return cmds.xform(target , q =True , ws = True, rotatePivot =True)[0:3]    

def stringToVector(axis):
    if axis == "x":
        return om.MVector.kXaxisVector 
    elif axis == "y":
        return om.MVector.kYaxisVector 
    elif axis == "z":
        return om.MVector.kZaxisVector 

    elif axis == "-x":
        return om.MVector.kXnegAxisVector
    elif axis == "-y":
        return om.MVector.kYnegAxisVector
    elif axis == "-z":
        return om.MVector.kZnegAxisVector

def axisToVector(axis,target):    
    pointMatrix = om.MMatrix(cmds.getAttr(target + ".worldMatrix[0]"))    
    axisVector = om.MTransformationMatrix(pointMatrix).setTranslation(stringToVector(axis),om.MSpace.kObject).translation(om.MSpace.kWorld)
    return axisVector.normal()

def getProjctionVector(vectorA,vectorB):
    vectorA = om.MVector(vectorA)
    vectorB = om.MVector(vectorB)

    vectorB = vectorB.normal()
    dotProduct = vectorA * vectorB
    shadowVector = vectorB * dotProduct
   
    return shadowVector

##----------------------------------------------------------------------------------
def primaryDistVector(target,primaryAimType,primaryAimTarget):
    targetPosition = om.MVector(getPosition(target))

    if primaryAimType == "next":
        chNodes = cmds.listRelatives(target,type="transform",fullPath =True)
        panretNodes = cmds.listRelatives(target,type="transform",p=True,fullPath =True)

        if chNodes != None:
            aimPosition = om.MVector(getPosition(chNodes[0]))
            
        elif chNodes == None and panretNodes != None:
            aimPosition = om.MVector(getPosition(panretNodes[0])) * -1.0

    elif primaryAimType == "object":
        aimPosition = om.MVector(getPosition(primaryAimTarget))

    distAxisVector = aimPosition - targetPosition
    distAxisVector = distAxisVector.normal()
    
    return distAxisVector

def secondaryDistVector(target,secondaryAimType,secondaryAimTarget):
    if secondaryAimType == "world":
        distAxisVector = stringToVector(secondaryAimTarget)

    elif secondaryAimType == "object":
        targetPosition = om.MVector(getPosition(target))
        aimPosition = om.MVector(getPosition(secondaryAimTarget))
        distAxisVector = aimPosition - targetPosition
        distAxisVector = distAxisVector.normal()

    elif secondaryAimType == "parent":
        parent = cmds.listRelatives(target,p=True,fullPath =True)
        distAxisVector = axisToVector(secondaryAimTarget,parent[0])

    return distAxisVector

def vectorToMatrix(axisOrder,distPrimaryAxisVector,distSecondaryAxisVector,distSideAxisVector):
    axisMatrix = []

    distPrimaryAxisVector = list(distPrimaryAxisVector)
    distPrimaryAxisVector.append(0.0)
    distSecondaryAxisVector = list(distSecondaryAxisVector)
    distSecondaryAxisVector.append(0.0)
    distSideAxisVector = list(distSideAxisVector)
    distSideAxisVector.append(0.0)

    if axisOrder == "xy":
        axisMatrix.extend(distPrimaryAxisVector)
        axisMatrix.extend(distSecondaryAxisVector)
        axisMatrix.extend(distSideAxisVector)

    elif axisOrder == "xz":
        axisMatrix.extend(distPrimaryAxisVector)
        axisMatrix.extend(distSideAxisVector)
        axisMatrix.extend(distSecondaryAxisVector)
    
    elif axisOrder == "yx":        
        axisMatrix.extend(distSecondaryAxisVector)
        axisMatrix.extend(distPrimaryAxisVector)
        axisMatrix.extend(distSideAxisVector)
        
    elif axisOrder == "yz":
        axisMatrix.extend(distSideAxisVector)
        axisMatrix.extend(distPrimaryAxisVector)        
        axisMatrix.extend(distSecondaryAxisVector)

    elif axisOrder == "zx":
        axisMatrix.extend(distSecondaryAxisVector)
        axisMatrix.extend(distSideAxisVector)
        axisMatrix.extend(distPrimaryAxisVector)
        
    elif axisOrder == "zy":
        axisMatrix.extend(distSideAxisVector)
        axisMatrix.extend(distSecondaryAxisVector)
        axisMatrix.extend(distPrimaryAxisVector)

    axisMatrix.extend([0.0,0.0,0.0,1.0])   

    return axisMatrix

def getChNodeTransform(target):
    chNodes = cmds.listRelatives(target,type="transform",fullPath =True) or []
    chNodesPosition = {}

    for node in chNodes:
        position = cmds.xform(node , q =True ,ws =True , t =True)
        rotation = cmds.xform(node , q =True ,ws =True , ro =True)
        chNodesPosition[node] = {"position":position,"rotation":rotation}

    return chNodesPosition

def restoreChNodeTransform(chNodesPosition):
    for node in list(chNodesPosition.keys()):
        cmds.xform(node ,ws =True , t = chNodesPosition[node]["position"])
        cmds.xform(node ,ws =True , ro =chNodesPosition[node]["rotation"])

##----------------------------------------------------------------------------------
def setJointOrient(joint,primaryAxis,secondaryAxis,primaryAimType,secondaryAimType,primaryAimTarget,secondaryAimTarget,primaryAxisReverse,secondaryAxisReverse):
    
    axisOrder = primaryAxis + secondaryAxis

    chNodesPosition = getChNodeTransform(joint)        
    distPrimaryAxisVector = primaryDistVector(joint,primaryAimType,primaryAimTarget)

    if primaryAxisReverse:
        distPrimaryAxisVector = distPrimaryAxisVector * -1.0

    distSecondaryAxisVector = secondaryDistVector(joint,secondaryAimType,secondaryAimTarget)
    
    if secondaryAxisReverse:
        distSecondaryAxisVector = distSecondaryAxisVector * -1.0

    shadowVector = getProjctionVector(distSecondaryAxisVector,distPrimaryAxisVector)
    distSecondaryAxisVector = (distSecondaryAxisVector - shadowVector).normal()
    
    if axisOrder == "zy" or axisOrder == "xz":
        distSideAxisVector = distSecondaryAxisVector ^ distPrimaryAxisVector
    else: 
        distSideAxisVector = distPrimaryAxisVector ^ distSecondaryAxisVector

    axisMatrix = vectorToMatrix(axisOrder,distPrimaryAxisVector,distSecondaryAxisVector,distSideAxisVector)
    setMatrix = om.MTransformationMatrix(om.MMatrix(axisMatrix)).setTranslation(om.MVector(getPosition(joint)),om.MSpace.kWorld).asMatrix()    

    cmds.xform(joint, matrix = list(setMatrix), ws = True)
    cmds.makeIdentity(joint, a =True, r=True, s =True)

    restoreChNodeTransform(chNodesPosition)
```

一部脳筋実装が見えるけれども、動くからまぁヨシ！

ここまでできたらもうリグできたも同然なので、続きは次回。