Using MotionBuilder Python To Cast Real-Time Shadows

I was watching a great series on YouTube by a MotionBuilder animator named Bryan Brewer. I highly recommend his series to anyone starting out with MotionBuilder or to anyone who uses MotionBuilder and is looking for tips. While watching the fore mentioned videos, I noticed how nice it was to have a shadow in the scene. I kept looking at the character’s silhouette and shadow’s silhouette, comparing the two and the space they create.
Creating real time shadows in MotionBuilder has been around for a while but I thought it would be fun to figure out a quick script that would add them to any scene I have open.
MotionBuilder has a shader called “Live Shadow”, this can be applied to a object and that will allow the object to receive real-time shadows.
You Can Read Up On MotionBuilder Live Shadow Shader Here.
The Script creates a Live Shadow shader, a ground plane which the Live Shadow shader will be applied to, a light that will produce shadows and a sphere used as a controller that can adjust the shadow direction and length within your scene.
Here is a video demo of the script in action followed by the script itself. I added as many comments to the script as I felt would be needed in hopes to help you break it down.
import pyfbsdk as fb
##Set Up Real-Time Shadows To The Scene
def CreateShadowCastingLight():
##Add Ground Plain
groundplane = fb.FBModelPlane( 'GroundPlane' )
groundplane.Translation = fb.FBVector3d( 0, 0, 0 )
##Scale The Ground So That It Cover A Large Area
groundplane.SetVector( fb.FBVector3d( 5, 5, 5 ), fb.FBModelTransformationType.kModelScaling, False )
groundplane.Show = True
groundplane.PropertyList.Find( 'Pickable' ).Data = False
# Create shader.
groundplane_shader = fb.FBShaderShadowLive( 'GroundPlane_ShadowCaster_Shader' )
groundplane_shader.ReplaceAll( groundplane )
##Ensure Display Mode For Models Within Scene Is Correct
for i in fb.FBSystem().Scene.Components:
i.ShadingMode = fb.FBModelShadingMode.kFBModelShadingAll
##Create Sphere To Be A Controler For The Shadow Casting Light
shadowlight_CTRL = fb.FBCreateObject( 'Browsing/Templates/Elements/Primitives', 'Sphere', 'Sphere' )
shadowlight_CTRL.Name = "shadowlight_CTRL"
##Set The Initial Location And Size Of The shadowlight_CTRL
shadowlight_CTRL.SetVector( fb.FBVector3d( 1, 1, 1 ), fb.FBModelTransformationType.kModelScaling, True )
shadowlight_CTRL.SetVector( fb.FBVector3d( 180, 240, 50 ), fb.FBModelTransformationType.kModelTranslation, True )
##Make shadowlight_CTRL Visible
shadowlight_CTRL.Show = True
##Parent shadowlight_CTRL To groundplane
groundplane.ConnectSrc( shadowlight_CTRL )
##Create Shadow Casting Light
shadowlight = fb.FBLight( 'GroundPlane_ShadowCaster' )
shadowlight.Translation = fb.FBVector3d( 0, -12, 0 )
shadowlight.SetVector( fb.FBVector3d(1,1,1), fb.FBModelTransformationType.kModelScaling, True )
shadowlight.PropertyList.Find( 'Scaling Inheritance' ).Data = 2
shadowlight.Show = True
shadowlight.CastLightOnObject = False
##Add The Light To The Shader So That It Casts Shadows
groundplane_shader.Lights.append( shadowlight )
##Parent shadowlight To shadowlight_CTRL
shadowlight_CTRL.ConnectSrc( shadowlight )
##Add Flat Yellow Material To The Controller For The Shadow Casting Light
ShadowLight_CTRL_Material = fb.FBMaterial( "shadowlight_CTRL_Material" )
ShadowLight_CTRL_Material.Emissive = fb.FBColor( 1, 1, 0 )
ShadowLight_CTRL_Material.Ambient = fb.FBColor( 0, 0, 0 )
ShadowLight_CTRL_Material.Diffuse = fb.FBColor( 0, 0, 0 )
ShadowLight_CTRL_Material.Specular = fb.FBColor( 0, 0, 0 )
shadowlight_CTRL.Materials.append( ShadowLight_CTRL_Material )
##Add Real-Time Shadows
CreateShadowCastingLight()
This was a great excuse to use learn about using python to create shaders, materials, a sphere (lol), and assigning a parent/child without using constraints. I had a lot of fun with this simple little script and I hope you were able to learn something from it as well. If you know of a better way to script this type of process please feel free to share in the comments below. 🙂
Thanks for reading and as always I hope this helps.