Tag: pipeline
exporting mirrored animations from Motionbuilder
by eks on Mar.06, 2011, under MotionBuilder, pipeline
It’s quite easy. Basically you need to:
- plot to the skeleton;
- save one animation;
- turn on Mirror Animation for the character;
- plot back to the control rig, which then mirrors the animation;
- rotate the Character Reference model 180 degrees;
- plot back to the skeleton;
- 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:\" # could be FB application path or project path
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, changes 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.