Using MotionBuilder Python To Cast Real-Time Shadows

Using Python To Quickly Add A Real Time Shadow To Your MotionBuilder Scene.

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.

Add a Comment

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.