[Maya Binding] 3 点 IK スケルトンのプロポーショナル ストレッチ - ノード エディタとコマンド ラインの組み合わせ

序文

この原則は以前にこのドキュメントで言及されていますが、それは純粋に自己宣伝製品であり、おそらくあなたが書いたことを理解できるのはあなただけです. 次に、このアイデアに従って実装します。この記事の主な目的は、ノード エディターを確認することです。Maya ノード エディタのフィーリングは本当に厄介です。

  • このシリーズは外国のチュートリアルから掘り下げたもので、私のような色のペンには適していません。操作は非常に高速です。

コード

私はまだコードが最も明確だと思います。コードを最初に置いてください

def add_ik_stretch(side, part, ik_chain, base_ctrl, local_ctrl, world_ctrl,primary_axis):
    base_name = side +'_' + part
    # start to end distance
    limb_dist = cmds.createNode('distanceBetween', name=base_name+'_DIST')
    # cinditon node
    limb_cnd = cmds.createNode('condition', name=base_name+'CND')
    # allocate locater, get transform node
    start_LOC = cmds.spaceLocator(name=base_name+'_start_LOC')[0]
    end_LOC = cmds.spaceLocator(name=base_name+'_end_LOC')[0]

    stretch_mdn = cmds.createNode('multiplyDivide', name=base_name+'_stretch_MDN')

    # calculate section length
    length_a = distance_between(ik_chain[0],ik_chain[1])
    length_b = distance_between(ik_chain[1], ik_chain[2])
    total_length = length_b + length_a

    # measure start-end desired direct distance
    # move the loc first
    cmds.pointConstraint(base_ctrl, start_LOC, maintainOffset=False)
    cmds.pointConstraint(local_ctrl, end_LOC, maintainOffset=False)
    connectAttr(start_LOC, 'worldMatrix[0]', limb_dist, 'inMatrix1')
    connectAttr(end_LOC, 'worldMatrix[0]', limb_dist, 'inMatrix2')

    # length ratio
    connectAttr(limb_dist, 'distance', stretch_mdn,'input1X')
    cmds.setAttr(stretch_mdn+'.input2X', total_length)#set devision
    cmds.setAttr(stretch_mdn+'.operation', 2)

    connectAttr(limb_dist,'distance',limb_cnd,'firstTerm')
    connectAttr(stretch_mdn,'outputX', limb_cnd,'colorIfTrueR')
    cmds.setAttr(limb_cnd+'.secondTerm', total_length)
    cmds.setAttr(limb_cnd+'.operation',3)

    # switch stretch
    cmds.addAtter(world_ctrl, attributeType='double', min=0, max=1,
                  defaultValue=1, keyable=True, longName='stretch')
    up_name = 'up' + part.title()
    lo_name = 'lo' + part.title()
    cmds.addAtter(world_ctrl, attributeType='double',
                  defaultValue=1, keyable=True, longName='up_name')
    cmds.addAtter(world_ctrl, attributeType='double',
                  defaultValue=1, keyable=True, longName='lo_name')

    stretch_bta = cmds.createNode('blendTwoAttr', name = base_name+'_BTA')
    cmds.setAttr(stretch_bta+'.input[0]', 1)
    connectAttr(limb_cnd,'outColorR',stretch_bta,'input[1]')
    connectAttr(world_ctrl,'stretch',stretch_bta,'attributesBlender')
    up_pma = cmds.createNode('plusMinusAverage', name=up_name+'_PMA')
    lo_pma = cmds.createNode('plusMinusAverage', name=lo_name + '_PMA')
    connectAttr(world_ctrl, up_name, up_pma, 'input1D[0]')
    connectAttr(world_ctrl, lo_name, lo_pma, 'input1D[0]')
    connectAttr(stretch_bta, 'output', up_pma, 'input1D[1]')
    connectAttr(stretch_bta, 'output', lo_pma, 'input1D[1]')
    cmds.setAttr(up_pma+'.input1D[2]', -1)
    cmds.setAttr(lo_pma + '.input1D[2]', -1)

    connectAttr(up_pma,'output1D',
                ik_chain[0],'scale'+primary_axis[-1])
    connectAttr(lo_pma,'output1D',
                ik_chain[1],'scale'+primary_axis[-1])

    return_dict = {
    
    'measure_locs': [start_LOC, end_LOC],
                   'total_length': total_length,
                   'mdn': stretch_mdn,
                   'cnd': limb_cnd}
    return return_dict

プロセス説明

エフェクター変換情報を取得する

最初に 2 つのロケータを作成し、ロケータを開始エフェクタと終了エフェクタの位置に移動します。
start_effector の位置は base_ctrl(start_effector) であらかじめ記録されています.
ここに画像の説明を挿入
同様に end_effector は local_ctrl で記録されています. この local_ctrl の機能は手を制御することですが, ここには手の関節は追加されていません.
ここに画像の説明を挿入

  • ロケータをエフェクタに移す
    cmds.pointConstraint(base_ctrl, start_LOC, maintainOffset=False)
    cmds.pointConstraint(local_ctrl, end_LOC, maintainOffset=False)

いくつかの距離値を計算する

  • エフェクタ間の距離を取得します。エフェクタの距離は、元の IKhandeler を長くすると予想されるターゲットです。この数値はより重要です。limb_dist.distance
    ここに画像の説明を挿入
     # start to end distance
    limb_dist = cmds.createNode('distanceBetween', name=base_name+'_DIST')
    ···
    connectAttr(start_LOC, 'worldMatrix[0]', limb_dist, 'inMatrix1')
    connectAttr(end_LOC, 'worldMatrix[0]', limb_dist, 'inMatrix2')
  • 上腕と下腕の距離とその合計をモデル化するtotal_length

    length_a = distance_between(ik_chain[0],ik_chain[1])
    length_b = distance_between(ik_chain[1], ik_chain[2])
    total_length = length_b + length_a
    

伸縮率を取得する

ヒント: 以下の関数はconnectAttr()cmds メソッドを自分で書き直したもので、関数は同じです。

    stretch_mdn = cmds.createNode('multiplyDivide', name=base_name+'_stretch_MDN')
    ···
    # length ratio
    connectAttr(limb_dist, 'distance', stretch_mdn,'input1X')
    cmds.setAttr(stretch_mdn+'.input2X', total_length)#set devision
    cmds.setAttr(stretch_mdn+'.operation', 2)

ここに画像の説明を挿入
はいstretch ratio = effectors的距离/模型手臂长、この部分はノード「multiplyDivide」で完了します。リアルタイム計算を実現したい場合は、ノードを使用する必要があり、モデルの腕の長さの定数などの定数値でない限り、オフラインで計算できます。

伸縮率の条件分岐切り替え

     # cinditon node
    limb_cnd = cmds.createNode('condition', name=base_name+'CND')
    ···
    connectAttr(limb_dist,'distance',limb_cnd,'firstTerm')
    connectAttr(stretch_mdn,'outputX', limb_cnd,'colorIfTrueR')
    cmds.setAttr(limb_cnd+'.secondTerm', total_length)
    cmds.setAttr(limb_cnd+'.operation',3)

理由:effectors距离>=模型手臂总长有効な場合は の前に計算されstrech ratio、それ以外の場合は 1 です。
ここに画像の説明を挿入

エンド エフェクターにいくつかの属性を追加する

ここで追加する新しいアトリビュートは、local_ctrl の親コントローラー world_ctrl にあり、これら 2 つのピボット ワールド位置は同じです。

    # switch stretch
    cmds.addAtter(world_ctrl, attributeType='double', min=0, max=1,
                  defaultValue=1, keyable=True, longName='stretch')
    up_name = 'up' + part.title()
    lo_name = 'lo' + part.title()
    cmds.addAtter(world_ctrl, attributeType='double',
                  defaultValue=1, keyable=True, longName='up_name')
    cmds.addAtter(world_ctrl, attributeType='double',
                  defaultValue=1, keyable=True, longName='lo_name')

ここに画像の説明を挿入

  • Stretch: IK 全体のストレッチまたは非ストレッチの混合比率
  • up Arm: 上腕のストレッチ係数
  • lo Arm:前腕も同様

関節ストレッチの達成

    stretch_bta = cmds.createNode('blendTwoAttr', name = base_name+'_BTA')
    cmds.setAttr(stretch_bta+'.input[0]', 1)
    connectAttr(limb_cnd,'outColorR',stretch_bta,'input[1]')
    connectAttr(world_ctrl,'stretch',stretch_bta,'attributesBlender')

ここに画像の説明を挿入

  • 1 つの落とし穴: 純粋なノード エディターでは、BTA ノードの入力を有効にする必要があり、有効にしないと定数を入力できません。input[0]=1world_ctrlde ストレッチ係数が 0 の場合は、同じ措置を講じます
    -ここに画像の説明を挿入

パーツの伸びを求め上下骨格のスケーリングを実現

 up_pma = cmds.createNode('plusMinusAverage', name=up_name+'_PMA')
    lo_pma = cmds.createNode('plusMinusAverage', name=lo_name + '_PMA')
    connectAttr(world_ctrl, up_name, up_pma, 'input1D[0]')
    connectAttr(world_ctrl, lo_name, lo_pma, 'input1D[0]')
    connectAttr(stretch_bta, 'output', up_pma, 'input1D[1]')
    connectAttr(stretch_bta, 'output', lo_pma, 'input1D[1]')
    cmds.setAttr(up_pma+'.input1D[2]', -1)
    cmds.setAttr(lo_pma + '.input1D[2]', -1)

ここに画像の説明を挿入
ここに画像の説明を挿入
IK ジョイントのスケールは、上図に従って上腕と下腕のスケーリング ファクターで減衰されたストレッチ比率を使用して、ストレッチを実現します。

    connectAttr(up_pma,'output1D',
                ik_chain[0],'scale'+primary_axis[-1])
    connectAttr(lo_pma,'output1D',
                ik_chain[1],'scale'+primary_axis[-1])

終わり

以上が一般的なソート処理であり、まだ多くの詳細が語られていないため、忘れてしまうことを恐れています.2020年以降にのみ開くことができるノードエディターバージョンにも、同じ機能を持つmbファイルを配置しました.
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/qq_43544518/article/details/130007498