Home Website Youtube GitHub

Modified Mocap Tools

Hey there!
I just wanted to share something real quick: I modified the Shifter Mocap tools a bit, to accept a mapping.json file as an input instead of the hard-coded mapping list. Also it now circumvents the “you have to open the HIK window first” thingy and works with z-up scenes… :slight_smile:

I’ll just paste the code here, as I can’t attach *.py files - maybe this comes in handy for somebody :wink:

This is the mgear\shifter\mocap_tools.py

import json

import pymel.core as pm
from pymel.core.language import Mel as mel

import mgear.core.attribute as att
import mgear.core.transform as tra


def importSkeletonBiped(*args):
    # make sure the HIK plugins are loaded (prevents the part where you have to open the
    #   window first to make the import work)
    if not pm.pluginInfo('mayaHIK.mll', query=True, loaded=True):
        pm.loadPlugin('mayaHIK.mll', quiet=True)

    if not pm.pluginInfo('mayaCharacterization.mll', query=True, loaded=True):
        pm.loadPlugin('mayaCharacterization.mll', quiet=True)

    mel.eval('hikToggleWidget();mayaHIKInitStrings;')

    # prompt the user for the template file - fileDialog2 always returns a list
    lPath = pm.fileDialog2(
        caption="Select the file including the HIK reference skeleton!",
        fileFilter="Maya Files (*.ma *.mb);;Maya ASCII (*.ma);;Maya Binary (*.mb)",
        fileMode=1
    )
    if not lPath:
        return

    # finally import the file
    pm.importFile(lPath[0])


def characterizeBiped(*args):
    # prompt the user for the characterization file
    lPath = pm.fileDialog2(
        caption="Select the characterization mapping file!",
        fileFilter="JSON Files (*.json)",
        fileMode=1
    )
    if not lPath:
        return

    try:
        # read the json file and fill the mapping arrays
        with open(lPath[0]) as mappingFile:
            data = json.loads(mappingFile.read())

            globalCtlName = data["globalCtl"]

            # fill the lists from the file
            skelFK = []
            skelPrefix = data["skelFK"]["prefix"]
            for joint in data["skelFK"]["joints"]:
                skelFK.append(skelPrefix + joint)

            gearFK = data["gearFK"]
            alignFK = data["alignFK"]
            alignIK = data["alignIK"]
            skelIK = data["skelIK"]
            gearIK = data["gearIK"]

    except Exception:
        pm.displayWarning("Error during import of mapping.json")
        return

    try:
        gCtl = pm.PyNode(globalCtlName)
        if not gCtl.hasAttr("mocapAttach"):
            mocapAttach = att.addAttribute(
                gCtl,
                "mocapAttach",
                "float",
                1.0,
                minValue=0.0,
                maxValue=1.0
            )
        else:
            mocapAttach = gCtl.attr("mocapAttach")

    except Exception:
        pm.displayWarning(
            "Global control with name %s is not in the scene!" % globalCtlName)
        return

    # if the scene is z-up, rotate the global control to fit the y-up HIK template first
    if pm.upAxis(query=True, axis=True) == "z":
        gCtl.setRotation((-90, 0, 0), 'world')

    # Align skeleton
    for a, b in zip(skelFK, gearFK):
        oA = getPyNode(a)
        oB = getPyNode(b)

        if not oA or not oB:
            continue

        tra.matchWorldTransform(oB, oA)

    # Constrain FK controls
    for a, b in zip(skelFK, gearFK):
        oA = getPyNode(a)
        oB = getPyNode(b)

        if not oA or not oB:
            continue

        cns = pm.parentConstraint(oA, oB, mo=True)

        pb_node = pm.createNode("pairBlend")

        pm.connectAttr(cns + ".constraintRotateX", pb_node + ".inRotateX2")
        pm.connectAttr(cns + ".constraintRotateY", pb_node + ".inRotateY2")
        pm.connectAttr(cns + ".constraintRotateZ", pb_node + ".inRotateZ2")
        pm.connectAttr(pb_node + ".outRotateX", oB + ".rotateX", f=True)
        pm.connectAttr(pb_node + ".outRotateY", oB + ".rotateY", f=True)
        pm.connectAttr(pb_node + ".outRotateZ", oB + ".rotateZ", f=True)
        pm.setKeyframe(oB, at="rotateX")
        pm.setKeyframe(oB, at="rotateY")
        pm.setKeyframe(oB, at="rotateZ")

        pm.connectAttr(cns + ".constraintTranslateX",
                       pb_node + ".inTranslateX2")
        pm.connectAttr(cns + ".constraintTranslateY",
                       pb_node + ".inTranslateY2")
        pm.connectAttr(cns + ".constraintTranslateZ",
                       pb_node + ".inTranslateZ2")
        pm.connectAttr(pb_node + ".outTranslateX", oB + ".translateX", f=True)
        pm.connectAttr(pb_node + ".outTranslateY", oB + ".translateY", f=True)
        pm.connectAttr(pb_node + ".outTranslateZ", oB + ".translateZ", f=True)
        pm.setKeyframe(oB, at="translateX")
        pm.setKeyframe(oB, at="translateY")
        pm.setKeyframe(oB, at="translateZ")

        pm.connectAttr(mocapAttach, pb_node.attr("weight"))

    # Align IK controls with FK controls
    for a, b in zip(alignIK, alignFK):
        oA = getPyNode(a)
        oB = getPyNode(b)

        if not oA or not oB:
            continue

        tra.matchWorldTransform(oB, oA)
        if a in [u"arm_L0_upv_ctl", u"arm_R0_upv_ctl"]:
            oA.attr("tz").set(-3)
        if a == u"arm_L0_ikcns_ctl":
            oA.attr("rx").set((oA.attr("rx").get() + 90))
        if a == u"arm_R0_ikcns_ctl":
            oA.attr("rx").set((oA.attr("rx").get() - 90))

    # constrain IK controls
    for a, b in zip(skelIK, gearIK):
        oA = getPyNode(a)
        oB = getPyNode(b)

        if not oA or not oB:
            continue

        pb_node = pm.createNode("pairBlend")
        try:
            if b in (u"leg_L0_upv_ctl", u"leg_R0_upv_ctl"):
                att.lockAttribute(pm.PyNode(b), lock=False, keyable=True)
            if b in (u"leg_L0_mid_ctl",
                     u"leg_R0_mid_ctl",
                     u"arm_L0_mid_ctl",
                     u"arm_R0_mid_ctl"):
                cns = pm.pointConstraint(oA, oB, mo=True)
            else:
                cns = pm.parentConstraint(oA, oB, mo=True)
            pm.connectAttr(cns + ".constraintRotateX", pb_node + ".inRotateX2")
            pm.connectAttr(cns + ".constraintRotateY", pb_node + ".inRotateY2")
            pm.connectAttr(cns + ".constraintRotateZ", pb_node + ".inRotateZ2")
            pm.connectAttr(pb_node + ".outRotateX", oB + ".rotateX", f=True)
            pm.connectAttr(pb_node + ".outRotateY", oB + ".rotateY", f=True)
            pm.connectAttr(pb_node + ".outRotateZ", oB + ".rotateZ", f=True)
            pm.setKeyframe(oB, at="rotateX")
            pm.setKeyframe(oB, at="rotateY")
            pm.setKeyframe(oB, at="rotateZ")

        except Exception:
            cns = pm.pointConstraint(oA, oB, mo=True)

        pm.connectAttr(cns + ".constraintTranslateX",
                       pb_node + ".inTranslateX2")
        pm.connectAttr(cns + ".constraintTranslateY",
                       pb_node + ".inTranslateY2")
        pm.connectAttr(cns + ".constraintTranslateZ",
                       pb_node + ".inTranslateZ2")
        pm.connectAttr(pb_node + ".outTranslateX", oB + ".translateX", f=True)
        pm.connectAttr(pb_node + ".outTranslateY", oB + ".translateY", f=True)
        pm.connectAttr(pb_node + ".outTranslateZ", oB + ".translateZ", f=True)
        pm.setKeyframe(oB, at="translateX")
        pm.setKeyframe(oB, at="translateY")
        pm.setKeyframe(oB, at="translateZ")

        pm.connectAttr(mocapAttach, pb_node.attr("weight"))

    # create the control rig - this will update the definition with some obscured stuff,
    #   which is later needed to not make the skeleton collapse
    mel.eval('hikCreateControlRig();')

    # rotate everything back into z-up mode
    if pm.upAxis(query=True, axis=True) == "z":
        gCtl.setRotation((0, 0, 0), 'world')

        try:
            ctlReferenceRoot = pm.PyNode(skelPrefix + "Ctrl_Reference")
            ctlReferenceRoot.setRotation((90, 0, 0), 'world')

        except Exception:
            pm.displayWarning("Could not find control reference root!")


def bakeMocap(*args):
    start = pm.playbackOptions(query=True, min=True)
    end = pm.playbackOptions(query=True, max=True)

    # at least one control must be selected to determine the namespace
    if pm.selected() and pm.selected()[0].name()[-3:].lower() == "ctl":

        if ":" in pm.selected()[0].name():
            namespace = pm.selected()[0].name()[:pm.selected()[
                0].name().rindex(':') + 1]

        else:
            namespace = ""

        try:
            controls = pm.PyNode("%srig_controllers_grp" % namespace).members()

        except Exception:
            pm.displayWarning("Could not find controls group select set!")
            return

        # Using a custom bake system because bakeResults is
        # slow with pairblend nodes.
        for x in range(int(start), int(end + 1)):
            pm.currentTime(x)
            pm.setKeyframe(controls)

    else:
        pm.displayWarning("Please select at least one control of the rig to "
                          "determine which character should be baked!")


def getPyNode(name):
    try:
        object = pm.PyNode(name)
        return object

    except Exception:
        pm.displayWarning("Can't find %s in the scene! Skipping!!" % name)
        return False

And this is the json file with the default mapping (as it was implemented before, just extracted):

{
“skelFK”: {
“prefix”: “mGear_Mocap_interface_”,
“joints”: [
“Hips”,
“LeftUpLeg”,
“LeftLeg”,
“LeftFoot”,
“LeftToeBase”,
“RightUpLeg”,
“RightLeg”,
“RightFoot”,
“RightToeBase”,
“Spine”,
“Spine1”,
“Spine2”,
“LeftShoulder”,
“LeftArm”,
“LeftForeArm”,
“LeftHand”,
“LeftHandThumb1”,
“LeftHandThumb2”,
“LeftHandThumb3”,
“LeftHandIndex1”,
“LeftHandIndex2”,
“LeftHandIndex3”,
“LeftHandMiddle1”,
“LeftHandMiddle2”,
“LeftHandMiddle3”,
“LeftHandRing1”,
“LeftHandRing2”,
“LeftHandRing3”,
“LeftHandPinky1”,
“LeftHandPinky2”,
“LeftHandPinky3”,
“RightShoulder”,
“RightArm”,
“RightForeArm”,
“RightHand”,
“RightHandThumb1”,
“RightHandThumb2”,
“RightHandThumb3”,
“RightHandIndex1”,
“RightHandIndex2”,
“RightHandIndex3”,
“RightHandMiddle1”,
“RightHandMiddle2”,
“RightHandMiddle3”,
“RightHandRing1”,
“RightHandRing2”,
“RightHandRing3”,
“RightHandPinky1”,
“RightHandPinky2”,
“RightHandPinky3”,
“Neck”,
“Neck1”,
“Head”
]
},
“gearFK”: [
“body_C0_ctl”,
“leg_L0_fk0_ctl”,
“leg_L0_fk1_ctl”,
“leg_L0_fk2_ctl”,
“foot_L0_fk0_ctl”,
“leg_R0_fk0_ctl”,
“leg_R0_fk1_ctl”,
“leg_R0_fk2_ctl”,
“foot_R0_fk0_ctl”,
“spine_C0_fk0_ctl”,
“spine_C0_fk1_ctl”,
“spine_C0_fk2_ctl”,
“shoulder_L0_ctl”,
“arm_L0_fk0_ctl”,
“arm_L0_fk1_ctl”,
“arm_L0_fk2_ctl”,
“thumb_L0_fk0_ctl”,
“thumb_L0_fk1_ctl”,
“thumb_L0_fk2_ctl”,
“finger_L0_fk0_ctl”,
“finger_L0_fk1_ctl”,
“finger_L0_fk2_ctl”,
“finger_L1_fk0_ctl”,
“finger_L1_fk1_ctl”,
“finger_L1_fk2_ctl”,
“finger_L2_fk0_ctl”,
“finger_L2_fk1_ctl”,
“finger_L2_fk2_ctl”,
“finger_L3_fk0_ctl”,
“finger_L3_fk1_ctl”,
“finger_L3_fk2_ctl”,
“shoulder_R0_ctl”,
“arm_R0_fk0_ctl”,
“arm_R0_fk1_ctl”,
“arm_R0_fk2_ctl”,
“thumb_R0_fk0_ctl”,
“thumb_R0_fk1_ctl”,
“thumb_R0_fk2_ctl”,
“finger_R0_fk0_ctl”,
“finger_R0_fk1_ctl”,
“finger_R0_fk2_ctl”,
“finger_R1_fk0_ctl”,
“finger_R1_fk1_ctl”,
“finger_R1_fk2_ctl”,
“finger_R2_fk0_ctl”,
“finger_R2_fk1_ctl”,
“finger_R2_fk2_ctl”,
“finger_R3_fk0_ctl”,
“finger_R3_fk1_ctl”,
“finger_R3_fk2_ctl”,
“neck_C0_fk0_ctl”,
“neck_C0_fk1_ctl”,
“neck_C0_head_ctl”
],
“alignFK”: [
“arm_L0_fk2_ctl”,
“arm_L0_ikcns_ctl”,
“arm_L0_fk1_ctl”,
“arm_R0_fk2_ctl”,
“arm_R0_ikcns_ctl”,
“arm_R0_fk1_ctl”
],
“alignIK”: [
“arm_L0_ikcns_ctl”,
“arm_L0_ik_ctl”,
“arm_L0_upv_ctl”,
“arm_R0_ikcns_ctl”,
“arm_R0_ik_ctl”,
“arm_R0_upv_ctl”
],
“skelIK”: [
“mGear_Mocap_interface_LeftFoot”,
“mGear_Mocap_interface_RightFoot”,
“mGear_Mocap_interface_LeftUpLeg”,
“mGear_Mocap_interface_RightUpLeg”,
“mGear_Mocap_interface_LeftHand”,

    "mGear_Mocap_interface_LeftForeArm",
    "mGear_Mocap_interface_RightHand",
    "mGear_Mocap_interface_RightForeArm",
    "mGear_Mocap_interface_LeftLeg",
    "mGear_Mocap_interface_RightLeg",

    "mGear_Mocap_interface_LeftForeArm",
    "mGear_Mocap_interface_RightForeArm"
],
"gearIK": [
    "leg_L0_ik_ctl",
    "leg_R0_ik_ctl",
    "leg_L0_upv_ctl",
    "leg_R0_upv_ctl",
    "arm_L0_ik_ctl",
    "arm_L0_upv_ctl",
    "arm_R0_ik_ctl",
    "arm_R0_upv_ctl",
    "leg_L0_mid_ctl",
    "leg_R0_mid_ctl",
    "arm_L0_mid_ctl",
    "arm_R0_mid_ctl"
]

}

6 Likes