2
1

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-02-11

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

骨打ち用ツール

欲しい機能としては

  • setJointOrient
  • createNode
  • mirrorJoints
  • mirrorOrients
  • mirrorPositios

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

setJointOrient

maya標準だと OrientJointですね。
image.png

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

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

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

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

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

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)

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

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

2
1
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
2
1