MOBU: Retriving cluster shapes from character face?

Hi,

I’m working with the Character Face in MotionBuilder from Python and I’m wondering if there is an easy way to get and set cluster shapes? Maybe using the constraint parent class?

“Getting and Setting” would ideally mean retriving and applying transformation data directly on the character face, but if I could simply restore any cluster shape onto the clustered bones that would do the trick (you can already snap the current pose onto a cluster shape with FBCharacterFace.ClusterShapeSnap())

Right now I’m “stuck”, in that I’m doing crazy work arounds to get where I need to be :slight_smile: So any help would be greatly appreciated!

Wrote something that works (although not very pretty). I ask so many questions here, so I thought I would share for once :slight_smile:

Some Classes:

class JointData:
    def __init__(self, joint):
        self.joint = joint
        self.transformMatrix = FBMatrix()

    def store_transforms(self):
        self.joint.GetMatrix(self.transformMatrix, 1, False)

    def restore_transforms(self):
        self.joint.SetMatrix(jointData.transformMatrix, 1, False)  

class PoseData:
    def __init__(self):
        self.poseIndex = None
        self.jointDataList = []

Getting the pose data:


# Find the character Face and assosiated data
charFace = FBSystem().Scene.CharacterFaces[0]
charFace.Active = False
clusterGrpId = 0
numPoses = charFace.ClusterShapeGetCount(clusterGrpId)

# Create an expression attribute, that we will use to restore shapes on the face
expId = charFace.ExpressionAdd('shape_restorer')
expName = charFace.ExpressionGetName(expId)
shape_restorer = charFace.PropertyList.Find(expName)
shape_restorer.Data = 100.0

# Create a list that will hold all the poses
poseDataList = []

# Loop through the poses on the face and store out pose bone transformations
for poseid in range(numPoses):
    charFace.ExpressionSetShapeWeight(expId, clusterGrpId, poseid, 100.0)
    FBSystem().Scene.Evaluate()

    # Create the pose data
    poseData = PoseData()
    poseData.poseIndex = poseid
    poseDataList.append(poseData)

    # Loop through all the pose joints and store their transformations
    for joint in getPoseJoints():
        # Read the transformation matrix and store it into joint data
        jointData = JointData(joint)
        jointData.store_transforms()
        poseData.jointDataList.append(jointData)
        
    charFace.ExpressionSetShapeWeight(expId, clusterGrpId, poseid, 0.0)

charFace.ExpressionRemove(expId)
FBSystem().Scene.Evaluate()

Restoring the pose data:

# Now restore the poses on the charatcer face #
for pose in poseDataList:
    for jointData in pose.jointDataList:
        jointData.restore_transforms()
    FBSystem().Scene.Evaluate()    
    charFace.ClusterShapeSnap(clusterGrpId,pose.poseIndex)