eduardo simioni

Tag: export

exporting mirrored animations from Motionbuilder

by on Mar.06, 2011, under MotionBuilder, pipeline

It’s quite easy. Basically you need to:

  1. plot to the skeleton;
  2. save one animation;
  3. turn on Mirror Animation for the character;
  4. plot back to the control rig, which then mirrors the animation;
  5. rotate the Character Reference model 180 degrees;
  6. plot back to the skeleton;
  7. save mirrored animation.

The tricky part is just number 5 where you need to do some matrix rotation. Python for this would be something like:

from pyfbsdk import *
app = FBApplication()
char = app.CurrentCharacter
savePath = r"C:\"
filename = app.FBXFileName
skeleton = FBCharacterPlotWhere.kFBCharacterPlotOnSkeleton
ctrlrig = FBCharacterPlotWhere.kFBCharacterPlotOnControlRig

# plot to skeleton, see bellow
plotAnim(char, skeleton)

# save left animation
sOptions = FBFbxOptions(False) # false = save options
sOptions.SaveCharacter = True
sOptions.SaveControlSet = False
sOptions.SaveCharacterExtension = False
sOptions.ShowFileDialog = False
sOptions.ShowOptionsDialog = False
app.SaveCharacterRigAndAnimation(savePath + "\\" + filename + "_L", char, sOptions)

# activate mirror and plot
char.MirrorMode = True
plotAnim(char, ctrlrig)

# get reference model
refModel = FBFindModelByName("Character_Ctrl:Reference")

# rotating 180, the tricky part
# http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q28
rotateY180 = FBMatrix()
rotateY180[0] = math.cos((180*0.017453292519943295769236907684886))
rotateY180[2] = math.sin((180*0.017453292519943295769236907684886))
rotateY180[8] = -math.sin((180*0.017453292519943295769236907684886))
rotateY180[10] = math.cos((180*0.017453292519943295769236907684886))

refMT = FBMatrix()
refModel.GetMatrix(refMT)

refModel.SetMatrix( MatrixMult(rotateY180, refMT) )
scene.Evaluate()

# plot back to skeleton
plotAnim(char, skeleton)

# save again
app.SaveCharacterRigAndAnimation(savePath + "\\" + filename + "_R", char, sOptions)

The plot and multiplication functions are:

# This is from Neil3d: http://neill3d.com/mobi-skript-raschet-additivnoj-animacii?langswitch_lang=en
def MatrixMult(Ma, Mb):
    res = FBMatrix()

    for i in range(0,4):
        for j in range(0,4):
            sum=0
            for k in range(0,4):
                sum += Ma[i*4+k] * Mb[k*4+j]

            res[i*4+j] = sum
    return res

def plotAnim(char, where):
    if char.GetCharacterize:
        switchOn = char.SetCharacterizeOn(True)

    plotoBla = FBPlotOptions()
    plotoBla.ConstantKeyReducerKeepOneKey = True
    plotoBla.PlotAllTakes = True
    plotoBla.PlotOnFrame = True
    plotoBla.PlotPeriod = FBTime( 0, 0, 0, 1 )
    #plotoBla.PlotTranslationOnRootOnly = True
    plotoBla.PreciseTimeDiscontinuities = True
    #plotoBla.RotationFilterToApply = FBRotationFilter.kFBRotationFilterGimbleKiller
    plotoBla.UseConstantKeyReducer = False
    plotoBla.ConstantKeyReducerKeepOneKey  = True

    if (not char.PlotAnimation(where, plotoBla)):
        FBMessageBox( "Something went wrong", "Plot animation returned false, cannot continue", "OK", None, None )
        return False

    return char    

If you are exporting the character to a game, pay attention to the root node rotation. If you used it in the characterization, chances are it might also be rotated, and you might not want that to happen. You can also establish a convention on the name of the files, and easily detect if the animation currently open ends with _L or _R, and adapt the filename correctly.

FBApplication().SaveCharacterRigAndAnimation() is the equivalent of the Save Character Animation on the Character Controls window, which saves only the animation, without mesh. I prefer to use this when exporting only the animation from Motionbuilder to some other software, since it’s cleaner, faster and file sizes are smaller, but you could use any other function also.

Leave a Comment :, , , , , , more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!