序文
この原則は以前にこのドキュメントで言及されていますが、それは純粋に自己宣伝製品であり、おそらくあなたが書いたことを理解できるのはあなただけです. 次に、このアイデアに従って実装します。この記事の主な目的は、ノード エディターを確認することです。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]=1
world_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ファイルを配置しました.