Mocappys

Your Guide to Capturing and Editing Motion

  • MotionBuilder Tutorials
  • Motion Capture Guides
  • Academy
  • Contact
  • About
  • Search Results
You are here: Home / MotionBuilder Tutorials / How to T-Pose and Characterize your Character Using MotionBuilder Python

How to T-Pose and Characterize your Character Using MotionBuilder Python

By Mocappy 8 Comments

Table of Contents

Toggle
  • Why use MotionBuilder Python?
  • Writing the Code
    • Import Python Modules
    • Convert XML to Python Dictionary
    • Get Character Joint Name from XML Template Dictionary
    • Create IK Effector
    • Create Pole Vector Object
    • Create IK Constraint
    • T-Pose Character Limb
    • T-Pose Character
    • Characterize Character
    • Delete IK Helpers using Namespace
    • Run the code
    • Next Step…

Before we can start applying all that lovely motion capture we got from our Xsens MVN mocap system to our characters, we’re going to need to put them in a T-Pose and Characterize them…I know, I know…ANOTHER tutorial on how to T-Pose and Characterize a character in MotionBuilder…

BUT WAIT, this one’s different…

What if you’re working on a project with multiple characters and tight deadlines (and let’s be honest, on those kinds of projects, you’re probably going to be doing this more than once) then you’re going to want a way to do this automatically…

…which is exactly where Python scriping in MotionBuilder comes in!

Now, I’ve already made a video showing how to t-pose and characterize your character manually, so in this video I’ll show you how to write a script to do everything automatically:

  • Centre your character in the scene
  • Create IK constraints for the arms and legs
  • Use those constraints to T-pose the character
  • Create a Character asset
  • Complete the Character Mapping using the Skeleton Definition XML file
  • And Characterize it

And even if you don’t use python scripting in MotionBuilder, you can still learn a new way to T-Pose your character using Chain IK Constraints.

Why use MotionBuilder Python?

The idea for this came from the guys over at Rigging Dojo who made a video showing how to t-pose a character in Maya using IK. I thought this was a great alternative to manually rotating the limbs into a T-Pose, and, as this is the kind of thing you’ll do again and again, it’s also the perfect job for a python script.

The great thing about scripts is, you can get them to do all the boring, repetitive stuff, so you can spend more time doing the interesting, creative stuff. Also, because the script won’t miss a step or forget to do something, your characters will always work in the same way, making them easier for everyone to work with.

AND not only all of that, but you’ll also be able to give the script to someone who’s never used MotionBuilder before and they’ll be able to use it to set up a character with no training. Just a couple of button clicks and away they go…

Writing the Code

Import Python Modules

The first thing we’ll need to do is import a couple of modules we’ll use later

from pyfbsdk import *
import xml.etree.ElementTree as etree
import os
import pprint

Convert XML to Python Dictionary

Next, we’ll need a fuction to convert the Skeleton Definition XML file to a python dictionary. These are the XML files stored in your windows “user\AppData\Roaming\Autodesk\HIKCharacterizationTool6\template” folder. To use you’re own XML template file, just pass it the name of your XML file.

def convert_skeleton_definition_xml_to_dict(xmlFileName):
    """
    Convert Skeleton Definition XML file to Python Dictionary
    Uses Default MotionBuilder HIKCharacterizationTool6/template filepath
    """
    # Get path to XML template file
    xmlFilePath = os.path.join(os.path.expanduser("~"), "AppData", "Roaming", "Autodesk", "HIKCharacterizationTool6", "template", xmlFileName)
    # Parse XML file
    parsedXmlFile = etree.parse(xmlFilePath)
    # Create empty dictionary
    skelDefDict = {}
    # Add parsed XML to dcitionary
    for line in parsedXmlFile.iter("item"):
        jointName = line.attrib.get("value")
        if jointName:
            slotName = line.attrib.get("key")
            skelDefDict[slotName] = jointName
    
    return skelDefDict

Get Character Joint Name from XML Template Dictionary

Once we have the Skeleton Definition file as a dictionary, we can use the character asset “slot name” (which is always the same) to find the joint name (which could be different for each character).

def get_char_joint_from_slot_name(templateDict,
                                slotName
                                ):
    """
    Get joint in character using MotionBuilder character slot name
    """
    # Get name of joint from MotionBuilder character slot
    charJointName = templateDict.get(slotName)
    # Find joint object using joint name
    charJointObj = FBFindModelByLabelName(charJointName)
    
    return charJointObj

Create IK Effector

For this example, we’re going to create a Null object to use as the IK Effector. Then, we’ll align the null with the end joint in the limb, for example, the wrist.

def create_ik_effector(endJointObj):
    """
    Create IK Effector using Null Object
    Set Object Name
    Align IK Effector to wrist/ankle
    """
    # Create name for IK effector including namespace and suffix
    effectorName = ikHelperNamesapce + endJointObj.Name + "_ikEffector"
    # Create Null object
    effector = FBModelNull(effectorName)
    # Show Null
    effector.Show = True
    # Set Null Size
    effector.Size = 300
    # Get Gloabl Traslation of End Joint
    endJointObjVecotr3d = FBVector3d()
    endJointObj.GetVector(endJointObjVecotr3d, FBModelTransformationType.kModelTranslation, True)
    # Align IK Effector Null to End Joint
    effector.SetVector(endJointObjVecotr3d, FBModelTransformationType.kModelTranslation, True)
    
    return effector

Create Pole Vector Object

We’ll use another Null object to create our Pole Vector object and align that to the elbow joint using “SetMatrix”. This will make sure the translation and rotation of the null matches the elbow, so it will straighten the elbow correctly when we translate it later.

def create_pole_vector(endJointObj):
    """
    Create Pole Vector using Null Object
    Set Object Name
    Align Pole Vector to elbow/knee
    """
    # Create name for Pole Vector including namespace and suffix
    poleVectorName = ikHelperNamesapce + endJointObj.Name + "_poleVector"
    # Create Null object
    pv = FBModelNull(poleVectorName)
    # Show Null
    pv.Show = True
    # Set Null Size
    pv.Size = 300
    # Get Matrix for middle joint
    jointMatrix = FBMatrix()
    endJointObj.Parent.GetMatrix(jointMatrix)
    # Align Pole Vector Null to Middle Joint
    pv.SetMatrix(jointMatrix)
    
    return pv

Create IK Constraint

Now we’ve got an IK Effector and Pole Vector, we can create a “Chain IK” constraint and add them to it.

def create_ik_constraint(endJointObj, 
                        effector, 
                        pv 
                        ):
    """
    Create Chain IK Constraint
    Set Constraint Name
    Populate Constraint
    Activate Constraint
    """
    # Get constraint name
    constraintName = ikHelperNamesapce + endJointObj.Name + "_poleVector"
    # Get first joint in joint chain
    firstJoint = endJointObj.Parent.Parent
    # Find Chain IK in FBConstraintManager
    constraintManager = FBConstraintManager()
    for constTypeIndex in range(constraintManager.TypeGetCount()):
        if constraintManager.TypeGetName(constTypeIndex) == "Chain IK":
            # Create Chain IK Constraint
            chainIk = constraintManager.TypeCreateConstraint(constTypeIndex)
            # Set constraint name including namespace
            chainIk.LongName = constraintName
            # Populate Constraint
            for refGroupIndex in range(chainIk.ReferenceGroupGetCount()):
                if chainIk.ReferenceGroupGetName(refGroupIndex) == "First Joint":
                    chainIk.ReferenceAdd(refGroupIndex, firstJoint)
                elif chainIk.ReferenceGroupGetName(refGroupIndex) == "End Joint":
                    chainIk.ReferenceAdd(refGroupIndex, endJointObj)
                elif chainIk.ReferenceGroupGetName(refGroupIndex) == "Effector":
                    chainIk.ReferenceAdd(refGroupIndex, effector)
                elif chainIk.ReferenceGroupGetName(refGroupIndex) == "Pole Vector Object":
                    chainIk.ReferenceAdd(refGroupIndex, pv)
            # Activate (Snap) Constrtaint
            chainIk.Snap()
    
    return chainIk

T-Pose Character Limb

Now we’ve created a Chain IK Constraint, we can use it to T-Pose our characters arms and legs.

def t_pose_limb(endJoint, 
                isArm
                ):
    """
    T-Pose Character Limb using Chain IK
    Create IK Effector
    Create Pole Vector
    Create Chain IK
    Calculate Limb length using Joint Roll/Twist Axis
        Offset in X for arms
        Offset in Y for legs
    """
    # Get first joint in chain
    firstJoint = endJoint.Parent.Parent
    # Create IK Effector
    leftArmEffector = create_ik_effector(endJoint)
    # Create Pole Vector
    leftArmPv = create_pole_vector(endJoint)
    # Create Chain IK
    leftChainIk = create_ik_constraint(endJoint, leftArmEffector, leftArmPv)
    # Calulate Length of Limb
    leftLimbLength = endJoint.Parent.Translation[1] + endJoint.Translation[1]
    # Get Gloabl Translation of First Joint
    firstJointVector3d = FBVector3d()
    firstJoint.GetVector(firstJointVector3d, FBModelTransformationType.kModelTranslation, True)
    # Get Global offset Poistion for IK Effector and Pole Vector
    if isArm:
        # Check if Left/Right arm
        if firstJointVector3d[0]<0:
            xOffset = firstJointVector3d[0] + leftLimbLength*-1
        else:
            xOffset = firstJointVector3d[0] + leftLimbLength
        ikOffsetVector3d = FBVector3d(xOffset, firstJointVector3d[1], firstJointVector3d[2])
        pvOffsetVector3d = FBVector3d(firstJointVector3d[0], firstJointVector3d[1], -50)
    else:
        yOffset = firstJointVector3d[1] + leftLimbLength*-1
        ikOffsetVector3d = FBVector3d(firstJointVector3d[0], yOffset, firstJointVector3d[2])
        pvOffsetVector3d = FBVector3d(firstJointVector3d[0], firstJointVector3d[1], 50)
    # Offset IK Effector and Pole Vector tranlation in Gloabl Space
    leftArmEffector.SetVector(ikOffsetVector3d, FBModelTransformationType.kModelTranslation, True)
    leftArmPv.SetVector(pvOffsetVector3d, FBModelTransformationType.kModelTranslation, True)
    # Zero Pole Vector roation values in Gloabl space
    leftArmPv.SetVector(FBVector3d(), FBModelTransformationType.kModelRotation, True)

T-Pose Character

The last thing we need to do is combine all of the above to T-Pose our character and centre it in the scene.

def t_pose_character(skeletonDefinitionDictionary):
    """
    Centre Character in Scene
    Zero Joint Rotations Locally
    Put Charcter in T-Pose using Chain IK
    """
    # Get Character Hips Object  
    charHipsObj = get_char_joint_from_slot_name(skeletonDefinitionDictionary, "Hips")
    charHipsObj.Selected = True
    if not charHipsObj:
        print "ERROR"
    else:
        # Centre Character in Scene
        charHipsVector3d = FBVector3d()
        charHipsObj.GetVector(charHipsVector3d, FBModelTransformationType.kModelTranslation, True)
        charZeroHipVector3d = FBVector3d(0.0, charHipsVector3d[1], 0.0)
        charHipsObj.SetVector(charZeroHipVector3d, FBModelTransformationType.kModelTranslation, True)
    # Zero Joint Rotations Locally
    for skeleton in FBSystem().Scene.ModelSkeletons:
        skeleton.Rotation = FBVector3d(0, 0, 0)
    # Evaluate scene to register new joint rotations
    FBSystem().Scene.Evaluate()
    # T-Pose Character Limbs
    charLeftHand = get_char_joint_from_slot_name(skeletonDefinitionDictionary, "LeftHand")
    t_pose_limb(charLeftHand, True)
    charLeftHand = get_char_joint_from_slot_name(skeletonDefinitionDictionary, "RightHand")
    t_pose_limb(charLeftHand, True)
    charLeftHand = get_char_joint_from_slot_name(skeletonDefinitionDictionary, "LeftFoot")
    t_pose_limb(charLeftHand, False)
    charLeftHand = get_char_joint_from_slot_name(skeletonDefinitionDictionary, "RightFoot")
    t_pose_limb(charLeftHand, False)

Characterize Character

Once we have our character in a T-Pose, this script will add a character to the scene, rename it, complete the character mapping using the Skeleton Definition template dictionary we created earlier, activate the Characterization and make it the current character in the scene. It will also return any errors if things go wrong.

def characterize_character(skeletonDefinitionDictionary,
                        characterName
                        ):
    """
    Create Character
    Complete Character Mapping using XML Template file
    Characterize Character
    Set Character to Current Character
    """
    # Create New Character
    newCharacter = FBCharacter(characterName)
    # Complete Character Mapping
    charSlotNameJointNameDict = convert_skeleton_definition_xml_to_dict("HIK.xml")
    for slotName, jointName in charSlotNameJointNameDict.items():
        mappingSlot = newCharacter.PropertyList.Find(slotName + "Link")
        jointObj = FBFindModelByLabelName(jointName)
        if jointObj:
            mappingSlot.append(jointObj)
    # Characterize
    characterized = newCharacter.SetCharacterizeOn(True)
    if not characterized:
        # Get Characterization Error
        print newCharacter.GetCharacterizeError()
    else:
        # Set Character to Current Character
        FBApplication().CurrentCharacter = newCharacter
    
        delete_ik_helpers(ikHelperNamesapce[:-1])
    
    return newCharacter

Delete IK Helpers using Namespace

Last thing to do is delete the “IK Helpers” we created to T-Pose the character. As we added them into a namespace, we can use that namespace to find and delete them.

def delete_ik_helpers(ikHelperNamespace):
    FBSystem().Scene.NamespaceDelete(ikHelperNamespace)

Run the code

The only thing left to do is to run the code.

ikHelperNamesapce = "ikHelper:"
charSkelDefDict = convert_skeleton_definition_xml_to_dict("HIK.xml")
 
##t_pose_character(charSkelDefDict)
##characterize_character(charSkelDefDict, "nigel") 

Next Step…

If you wanted to take this one step further, you could add a script to create a UI with a couple of buttons and use the FBMessageBoxGetUserValue to get the character name…but where’s the fun if I give you all the code here 🙂

And don’t foget to let me know in the comments below if you’d you like to see more python scripting tutorials for MotionBuilder, or if you have any questions or suggestions on the above.

Till next time…

Tweet

Filed Under: MotionBuilder Tutorials

« How to Use an Xsens MVN Mocap System
How to Use MotionBuilder Story Tool to Create a Cut-Scene »

Comments

  1. Dave says

    April 22, 2021 at 10:47

    Thank you for publishing this, I’ve been looking for a good starter tutorial on MB scripting for a while, this made it all a breeze.

    Reply
    • Mocappy says

      April 22, 2021 at 21:34

      Excellent! Good to hear it’s helped get you get started. There’s a lot you can do with scripting, and a LOT of the less creative, repetitive work you can save your self!

      I was thinking of creating a course to expand on this a little – basically the entire character set up process from beginning to end, but using python. It’s a good way to learn how to find and work on objects in the scene, plus do some simple file IO…

      If you’re interested, keep an eye on the academy

      Reply
  2. LL says

    September 30, 2021 at 08:59

    Excellent blog and very helpful that I learned a lot. Thanks for sharing it.

    Would you like to do tutorial about how to save skeleton definition Template and save with XML file in python?

    Reply
    • Mocappy says

      October 7, 2021 at 21:48

      Thank you. And yes, yes I would…

      https://mocappys.com/how-to-create-a-skeleton-definition-file-in-motionbuilder-using-python/

      Reply
  3. Aaron Low says

    March 29, 2022 at 19:05

    Thanks for the tutorial. I am attempting to repurpose the Characterization function to automate Vicon skeleton set ups.
    I am currently debugging a solution by exploring scrubbing namespaces as I suspect the longName are usually the issues in these factors.

    What factors should I be looking for in debugging characterization. I print the slot and joint names. So I know the xml file is read and working properly(Even made a custom XML for the same skeleton)

    I suspect this relates to
    jointObj = FBFindModelByLabelName(jointName)

    As this is finding all of this type, and if there are three people with that name it can cause issues.
    So I need to search through the children more than just whole scene.

    Thanks again for the video!

    Reply
    • Mocappy says

      March 30, 2022 at 18:25

      Hi Aaron,

      First, I would keep namespaces if you can, especially if you have multiple charcter rigs in your scene. It means you can keep the joint names the same for all your characters (handy for scripting, etc) and use the namespace to avoid naming conflicts, deleting after the fact, etc.

      For Vicon skeletons, I think they usually come namespaced with the performer name, apart from the top node, so you’ll need to find that and add it to the same namespace.

      This characterization script isn’t set up for namespaces, but if you wanted to use them (and I’d highly recommend you do), you could pass the performer name as the character name. This will name your Character to match the performer. Then change the newCharacter LongName to characterName+”:”+characterName for consitency and help with other scripts later 😉

      Last thing to do is, when you FBFindModelByLabelName, you’ll need to use the LongName to include the namespace (characterName+”:”+jointName) to make sure you’re getting the joints for that character only – if you wanted, you could also add some more code here to catch “if not jointObj: print “Can’t Find”, jointName

      Hopefully this will help

      Reply

Trackbacks

  1. How to Write a Skeleton Definition File Using Python - Mocappys says:
    August 31, 2023 at 12:24

    […] MotionBuilder’s Character Definition tab. To do this, I reworked the XML parse code from the Python Characterization Tool to create a list of slot property names we need to find in FBCharacter – basically the […]

    Reply
  2. How to Rig a Character for MotionBuilder - Mocappys says:
    January 17, 2024 at 12:17

    […] you’ve finished you’ll have a rig you can export to MotionBuilder ready to Characterize, apply some mocap and start […]

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Search Site

Ready to Dive into MotionBuilder and Start Editing Mocap But Feel Overwhelmed?

edit mocap motionbuilder

Your complete step-by-step guide to creating production ready animations for video games and simulations.
…Even if you’ve never used MotionBuilder.
By the end of this comprehensive, hands-on course, you’ll be creating production-ready animations that blend together seamlessly.
<< Learn More >>


Hi, I’m Simon Kay

My aim for this site is to share everything I’ve learned over the last 20+ years using MotionBuilder to help bring hundreds of characters to life at some of the world’s leading VFX, Video Game and Motion Capture Studios, including DNEG, Sony Interactive, and Centroid Motion Capture.

 

Top Posts:

  • How to Rig a Character for MotionBuilder
  • Retargeting Animation In MotionBuilder
  • Understanding MotionBuilder's Control Rig
  • How to Mocap a Performer using a Vicon System
  • How to Characterize your Character in MotionBuilder
  • Creating an In-Place Looping Animation in MotionBuilder
  • How to plan a Motion Capture Shoot – Mocap Shot List
  • How to Realign Motion Capture
  • How to Characterize a 3DS Max Biped in MotionBuilder
  • Quick Start Guide to Motion Capture

Follow:

  • E-mail
  • LinkedIn
  • RSS
  • Twitter
  • YouTube

Copyright © 2025 Mocappys.com