[Maya] .offsetParentMatrixをmel/Pythonスクリプトで取り扱う場合の研究

解決策から、、画像のような状態でよかった。関数はこんな感じ

global proc _Input_Lines(){
    print("_Input_Lines \n");
    
    _offsetParentMatrix_Value_Input("Dummy_calf_l",-15.216,0);
    _offsetParentMatrix_Value_Input("Dummy_calf_r",15.216,0);
    _offsetParentMatrix_Value_Input("Dummy_foot_l",-7.821,-0.047);
    _offsetParentMatrix_Value_Input("Dummy_foot_r",7.821,0.047);
}

global proc _offsetParentMatrix_Value_Input(string $NodeName,float $X,float $Y){
    print("_offsetParentMatrix_Value_Input \n");
    string $LocatorName="OffsetParentMatrix_locator_"+$NodeName;
    print("$LocatorName= "+$LocatorName+" \n");
    spaceLocator -position 0.0 0.0 0.0 -name $LocatorName;
    $LocatorNameTransX = $LocatorName+".translateX";
    print("$LocatorNameTransX= "+$LocatorNameTransX+" \n");
    setAttr $LocatorNameTransX $X;
    $LocatorNameTransY = $LocatorName+".translateY";
    print("$LocatorNameTransY= "+$LocatorNameTransY+" \n");
    setAttr $LocatorNameTransY $Y;
    $LocatorName_worldMatrix0 = $LocatorName+".worldMatrix[0]";
    print("$LocatorName_worldMatrix0= "+$LocatorName_worldMatrix0+" \n");
    $NodeName_offsetParentMatrix = $NodeName+".offsetParentMatrix";
    print("$NodeName_offsetParentMatrix= "+$NodeName_offsetParentMatrix+" \n");
    connectAttr -f $LocatorName_worldMatrix0 $NodeName_offsetParentMatrix;
}

で大丈夫そう

————————————————–下は参考サイトの例————————————————-

この関数を

import os
import stat
import maya.cmds as cmds
#import maya.OpenMaya as OpenMaya
import maya.api.OpenMaya as OpenMaya
def func_offsetParentMatrix(node,driver):
    mult = cmds.createNode("multMatrix")

    offset = matrix_to_list(
        OpenMaya.MMatrix(cmds.getAttr("{}.worldMatrix[0]".format(node)))
        * OpenMaya.MMatrix(cmds.getAttr("{}.matrix".format(node))).inverse()
        * OpenMaya.MMatrix(cmds.getAttr("{}.worldInverseMatrix[0]".format(driver)))
    )
    cmds.setAttr("{}.matrixIn[0]".format(mult), offset, type="matrix")

    cmds.connectAttr("{}.worldMatrix[0]".format(driver), "{}.matrixIn[1]".format(mult))

    parent = cmds.listRelatives(node, parent=True, path=True)
    if parent:
        cmds.connectAttr("{}.worldInverseMatrix[0]".format(parent[0]), "{}.matrixIn[2]".format(mult))

    cmds.connectAttr(
        "{}.matrixSum".format(mult), "{}.offsetParentMatrix".format(node)
    )
    
def matrix_to_list(mtx):
    lst=[]
    for row in range(0,4):
        for col in range(0,4):
            lst.append(mtx.getElement(row,col))
    return lst
    
def list_to_matrix(lst):
    mtx=OpenMaya.MMatrix(lst)
    # OpenMaya.MScriptUtil.createMatrixFromList(lst, mtx)
    return mtx

こう使った。

global proc Func_TEST_offsetParentMatrix_Proc(){    
    print("Func_TEST_offsetParentMatrix_Proc");
    spaceLocator -position -15.216 0.0 0.0 -name "calf_l_OffsetMatrix_locator_l" -absolute;
    func_offsetParentMatrix_Python_Proc("Dummy_calf_telescopic_l","calf_l_OffsetMatrix_locator_l");
}
    
global proc func_offsetParentMatrix_Python_Proc(string $node,string $driver){
    print("func_offsetParentMatrix");
    python("import func_offsetParentMatrix");
	python("import importlib");
	python("importlib.reload(func_offsetParentMatrix)");
    python("func_offsetParentMatrix.func_offsetParentMatrix('"+$node+"','"+$driver+"')");
}

参考

offsetParentMatrixの記事
https://www.chadvernon.com/blog/space-switching-offset-parent-matrix/

matrix_to_list
https://gist.github.com/rjmoggach/4ea80af3104a3517d3a2a46293acf043

maya PythonのOpenMaya の Vector で任意の座標からもっとも近い線分上の点を求める

こんな感じの状態、

# -*- coding: utf-8 -*-
import maya.cmds as cmds
from maya import OpenMaya
#任意の1点と線分の両端の座標から線分上のもっとも近い点を返す
def xGetClosestPoint(myPoint, begin, end):
    myVector3D = OpenMaya.MVector(myPoint[0] - begin[0], myPoint[1] - begin[1], myPoint[2] - begin[2])
    baseVector3D = OpenMaya.MVector(end[0] - begin[0], end[1] - begin[1], end[2] - begin[2])
    nDotProduct = myVector3D * baseVector3D
    print("nDotProduct= "+str(nDotProduct))
    if (nDotProduct > 0):
        print("Big if")
        nBaseLength = baseVector3D.length()
        print("nBaseLength= "+str(nBaseLength))
        nProjection = nDotProduct / nBaseLength
        
        if (nProjection < nBaseLength):
            print("small if")
            scaleValue = nProjection / nBaseLength
            print("scaleValue= "+str(scaleValue))
            baseVector3D = baseVector3D * scaleValue
            
            return [begin[0] + baseVector3D[0], begin[1] + baseVector3D[1], begin[2] + baseVector3D[2]]
        else:
            print("small else")
            return end

    else:
        print("Big else")
        return begin;
    

sel = cmds.ls(sl =True)

# get Translate
start = cmds.xform(sel[0],q=1 ,ws =True,t=True)
mid = cmds.xform(sel[1],q=1 ,ws =True,t=True)
end = cmds.xform(sel[2],q=1 ,ws =True,t=True)

# Vector for Translate
#startV = OpenMaya.MVector(start[0] ,start[1],start[2])
#midV = OpenMaya.MVector(mid[0] ,mid[1],mid[2])
#midV = OpenMaya.MVector(end[0] ,end[1],end[2])

c_vPos = xGetClosestPoint(mid, start, end)
cmds.xform("pSphere1",ws =True,translation=(c_vPos[0], c_vPos[1], c_vPos[2]) )

線状に乗った!!

参考URL

野中文雄先生の任意の座標からもっとも近い線分上の点を求める

http://www.fumiononaka.com/TechNotes/Flash/FN1104002.html

MAYAチュートリアル:Pythonで極ベクトルを正しく配置する方法