Maya:使用父约束连接两个关节链
Maya: Connect two Joint chains with Parent Constraint
所以这是我一直在研究的 IK 脊柱构建器的片段。我已经弄清楚如何制作列表以将绑定复制到 IK 链中,但我一直坚持的是我想要我的列表和循环到父约束绑定层次结构中的每个关节到它在 ik 中的相应关节层次结构:
import maya.cmds as cmds
def linkJointChain(lookFor='joint'):
namePref = 'ct_'
limbPref = 'spine'
ctlName = namePref + limbPref
#list selection to get the joint and their children
root = cmds.ls(sl=True)[0] # adding a zero bracket makes sure it counts the head of the herarchy too
child = cmds.listRelatives(root,ad=1,type='joint')
child.append(root)
child.reverse()
limbJnt = child
print(child)
#list all joints in chain, this list will be refrenced by all the commands beneath it
root = cmds.ls(sl=True)[0]
child = cmds.listRelatives(root,ad=1,f=True,children=True,type='joint')
#rename the joints
for j, name in enumerate(child):
cmds.rename(name,namePref + limbPref + 'AJ{0}_BIND_JNT'.format(len(child)-j))
print(child)
#rename beggining and end joints to start and end respectivly
root = cmds.ls(sl=True)
child = cmds.listRelatives(root,ad=1,f=True,children=True,type='joint')
cmds.rename(child[0],ctlName +'AJ_BIND_END_JNT')
cmds.rename(root,ctlName + 'AJ_BIND_START_JNT')
#duplicate bound chain for ik spine
root = cmds.ls(sl=True)
IKChain = cmds.duplicate(root,n=ctlName + 'AJ_IK_START_JNT')
IKList = cmds.listRelatives(ctlName + 'AJ_IK_START_JNT', ad=True,pa=True)
for IKn, name in enumerate(IKList):
cmds.rename(name, ctlName +'AJ{0}_IK_JNT'.format(len(IKList)-IKn))
print(IKList)
#select IK chain, then,set joints size for easy grabbing on IK chain
cmds.select(ctlName +'AJ_IK_START_JNT')
IKRoot = cmds.ls(sl=True)[0]
IKChild = cmds.listRelatives(ctlName +'AJ_IK_START_JNT', ad=True,pa=True)
IKChild.append(IKRoot)
for r in IKChild:
cmds.setAttr(r + '.radius', 1.5)
#parent constrain bound spine to ik spine
ikJntChain=cmds.listRelatives(ctlName +'AJ_IK_START_JNT',ad=1,type='joint')
ikJntChain.append(ctlName +'AJ_IK_START_JNT') #try appending your other joint chain to create a double list with which to append
ikJntChain.reverse()
ikLimbJnt = ikJntChain
boundJntChain=cmds.listRelatives(ctlName +'AJ_BIND_START_JNT',ad=1,type='joint')
boundJntChain.append(ctlName +'AJ_BIND_START_JNT') #try appending your other joint chain to create a double list with which to append
boundJntChain.reverse()
boundLimbJnt = boundJntChain
limbJnt = ikJntChain+boundJntChain
print(limbJnt)
for j in limbJnt:
spineCons = cmds.parentConstraint(ikJntChain[0],boundJntChain[0])
#ikParChain = cmds.parentConstraint(j,ikJntChain)
linkJointChain()
该脚本具有 listRelatives 的硬编码名称,因为完整脚本读取关节链并在重命名列表中的第一个和最后一个关节后在开始和结束关节处放置控件,我知道它与cmds.parentConstraint
中的括号
下面的示例将从头开始创建 2 个独立的关节链,然后将父约束应用于每个关节,以便一个链驱动另一个:
import maya.cmds as cmds
joint_count = 10
# Create 1st joint chain 'a'.
chain_a = [
cmds.joint(position=[0, i * -2 + ((joint_count - 1) * 2), 0], name="a#")
for i in range(joint_count)]
cmds.select(clear=True) # Need to clear selection so the next chain doesn't accidentally parent to chain a.
# Create 2nd joint chain 'b'.
chain_b = [
cmds.joint(position=[0, i * -2 + ((joint_count - 1) * 2), -10], name="b#")
for i in range(joint_count)]
# Use `zip` to iterate through both lists at the same time.
for jnt_a, jnt_b in zip(chain_a, chain_b):
cmds.parentConstraint(jnt_a, jnt_b, maintainOffset=True) # Constraint b->a
主要思想是你得到 2 个列表,每个列表都有自己的关节。然后将这 2 个列表传递给 zip
,这样当您遍历它时,它将首先通过第一个关节,然后是第二个关节,依此类推。
要使其正常工作,您必须确保两个列表的长度相同,并且都使用相同的联合顺序。这样你就不必硬编码任何东西,而是可以按程序进行(例如,你可以将 joint_count
更改为任何数字,它仍然有效)。
实际上你甚至不需要使用 zip
并且可以通过像这样替换结尾来达到同样的效果:
for i in range(len(chain_a)):
cmds.parentConstraint(chain_a[i], chain_b[i], maintainOffset=True) # Constraint b->a
虽然用zip
感觉更'pythonic'.
所以这是我一直在研究的 IK 脊柱构建器的片段。我已经弄清楚如何制作列表以将绑定复制到 IK 链中,但我一直坚持的是我想要我的列表和循环到父约束绑定层次结构中的每个关节到它在 ik 中的相应关节层次结构:
import maya.cmds as cmds
def linkJointChain(lookFor='joint'):
namePref = 'ct_'
limbPref = 'spine'
ctlName = namePref + limbPref
#list selection to get the joint and their children
root = cmds.ls(sl=True)[0] # adding a zero bracket makes sure it counts the head of the herarchy too
child = cmds.listRelatives(root,ad=1,type='joint')
child.append(root)
child.reverse()
limbJnt = child
print(child)
#list all joints in chain, this list will be refrenced by all the commands beneath it
root = cmds.ls(sl=True)[0]
child = cmds.listRelatives(root,ad=1,f=True,children=True,type='joint')
#rename the joints
for j, name in enumerate(child):
cmds.rename(name,namePref + limbPref + 'AJ{0}_BIND_JNT'.format(len(child)-j))
print(child)
#rename beggining and end joints to start and end respectivly
root = cmds.ls(sl=True)
child = cmds.listRelatives(root,ad=1,f=True,children=True,type='joint')
cmds.rename(child[0],ctlName +'AJ_BIND_END_JNT')
cmds.rename(root,ctlName + 'AJ_BIND_START_JNT')
#duplicate bound chain for ik spine
root = cmds.ls(sl=True)
IKChain = cmds.duplicate(root,n=ctlName + 'AJ_IK_START_JNT')
IKList = cmds.listRelatives(ctlName + 'AJ_IK_START_JNT', ad=True,pa=True)
for IKn, name in enumerate(IKList):
cmds.rename(name, ctlName +'AJ{0}_IK_JNT'.format(len(IKList)-IKn))
print(IKList)
#select IK chain, then,set joints size for easy grabbing on IK chain
cmds.select(ctlName +'AJ_IK_START_JNT')
IKRoot = cmds.ls(sl=True)[0]
IKChild = cmds.listRelatives(ctlName +'AJ_IK_START_JNT', ad=True,pa=True)
IKChild.append(IKRoot)
for r in IKChild:
cmds.setAttr(r + '.radius', 1.5)
#parent constrain bound spine to ik spine
ikJntChain=cmds.listRelatives(ctlName +'AJ_IK_START_JNT',ad=1,type='joint')
ikJntChain.append(ctlName +'AJ_IK_START_JNT') #try appending your other joint chain to create a double list with which to append
ikJntChain.reverse()
ikLimbJnt = ikJntChain
boundJntChain=cmds.listRelatives(ctlName +'AJ_BIND_START_JNT',ad=1,type='joint')
boundJntChain.append(ctlName +'AJ_BIND_START_JNT') #try appending your other joint chain to create a double list with which to append
boundJntChain.reverse()
boundLimbJnt = boundJntChain
limbJnt = ikJntChain+boundJntChain
print(limbJnt)
for j in limbJnt:
spineCons = cmds.parentConstraint(ikJntChain[0],boundJntChain[0])
#ikParChain = cmds.parentConstraint(j,ikJntChain)
linkJointChain()
该脚本具有 listRelatives 的硬编码名称,因为完整脚本读取关节链并在重命名列表中的第一个和最后一个关节后在开始和结束关节处放置控件,我知道它与cmds.parentConstraint
中的括号下面的示例将从头开始创建 2 个独立的关节链,然后将父约束应用于每个关节,以便一个链驱动另一个:
import maya.cmds as cmds
joint_count = 10
# Create 1st joint chain 'a'.
chain_a = [
cmds.joint(position=[0, i * -2 + ((joint_count - 1) * 2), 0], name="a#")
for i in range(joint_count)]
cmds.select(clear=True) # Need to clear selection so the next chain doesn't accidentally parent to chain a.
# Create 2nd joint chain 'b'.
chain_b = [
cmds.joint(position=[0, i * -2 + ((joint_count - 1) * 2), -10], name="b#")
for i in range(joint_count)]
# Use `zip` to iterate through both lists at the same time.
for jnt_a, jnt_b in zip(chain_a, chain_b):
cmds.parentConstraint(jnt_a, jnt_b, maintainOffset=True) # Constraint b->a
主要思想是你得到 2 个列表,每个列表都有自己的关节。然后将这 2 个列表传递给 zip
,这样当您遍历它时,它将首先通过第一个关节,然后是第二个关节,依此类推。
要使其正常工作,您必须确保两个列表的长度相同,并且都使用相同的联合顺序。这样你就不必硬编码任何东西,而是可以按程序进行(例如,你可以将 joint_count
更改为任何数字,它仍然有效)。
实际上你甚至不需要使用 zip
并且可以通过像这样替换结尾来达到同样的效果:
for i in range(len(chain_a)):
cmds.parentConstraint(chain_a[i], chain_b[i], maintainOffset=True) # Constraint b->a
虽然用zip
感觉更'pythonic'.