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.