Don't wanna be here? Send us removal request.
Text
Use Python to Automate a Character to Scene Origin in Motionbuilder for all Takes
Tumblr media
Building Motion Sets are a lot of repetitive work, the more I build sets the more I try to build tools to reduce the main repetitive tasks. I wrote a nice script for Motionbuilder's Python to automate creating a Character Track, adding a clip to the track, calculating the transform offset required to align the character to the scene's origin (center of scene) and then plot it back to the character. This is a lot of clicks over a large motion set - it can save hours of work. Let's have a look at the script: from pyfbsdk import * ''' Author: Kieren Hovasapian Company: Moonjump Pty Ltd References: Vic Debaie http://www.vicdebaie.com/blog/save-all-story-clips-to-new-takes-with-motionbuilder-python-script/ Batch Center All Takes Send take to Story (make sure that it selects entire control rig hierarchy) Calculates position of the offset required Applies new position Plots back to Control Rig on Same Take ''' ## Scene Refresh Bug Workaround def SceneRefresh(): FBPlayerControl().GotoNextKey() FBSystem().Scene.Evaluate() FBPlayerControl().GotoPreviousKey() FBSystem().Scene.Evaluate() def plotCharacter(): ## Deal With The User's Story Mode Activity FBStory().Mute = False SceneRefresh() ## Plot Options lPlotClipOptions = FBPlotOptions() lPlotClipOptions.ConstantKeyReducerKeepOneKey = False lPlotClipOptions.PlotAllTakes = False lPlotClipOptions.PlotOnFrame = True lPlotClipOptions.PlotPeriod = FBTime( 0, 0, 0, 1 ) lPlotClipOptions.PlotTranslationOnRootOnly = False lPlotClipOptions.PreciseTimeDiscontinuities = False lPlotClipOptions.RotationFilterToApply = FBRotationFilter.kFBRotationFilterUnroll lPlotClipOptions.UseConstantKeyReducer = False ## Plot Story Clip On Current Character lChar = FBApplication().CurrentCharacter print(lChar.Name) lChar.PlotAnimation(FBCharacterPlotWhere.kFBCharacterPlotOnControlRig,lPlotClipOptions ) ## Function to select all models in the scene def selectAllModels(): for component in FBSystem().Scene.Components: if isinstance(component, FBModel): component.Selected = True def processTake(take): FBSystem().CurrentTake = take print(f"Processing take: {take.Name}") # Select everything in the scene selectAllModels() ## Create A Character Animation Track Within The Root Folder Of Story lTrack = FBStoryTrack(FBStoryTrackType.kFBStoryTrackCharacter, FBStory().RootFolder) lTrack.Details.append(character) # Insert current take in the newly created track clip = lTrack.CopyTakeIntoTrack(FBSystem().CurrentTake.LocalTimeSpan, FBSystem().CurrentTake) clip.GhostEnable = True clip.Selected = True original_translation = FBVector3d(clip.Translation) original_rotation = FBVector3d(clip.Rotation) print(f"Original Translation: {original_translation}, {original_translation}, {original_translation}") # Subtract the original translation to recenter clip.Translation = FBVector3d( clip.Translation + original_translation, clip.Translation + original_translation, clip.Translation + original_translation ) plotCharacter() # Clean up by removing the track after plotting FBStory().RootFolder.Tracks.remove(lTrack) print(f"Completed take: {take.Name}") character = FBApplication().CurrentCharacter if not character: print("No character selected. Please select a character.") else: for take in FBSystem().Scene.Takes: processTake(take) print("Processing complete.") I'd like to thank Vic DeBaie as well for some helpful utility script snippets to help jiggle the scene as well, otherwise repeating this over many takes the scene takes start to breakdown and stop behaving properly. The jiggle works quite well as a quick refresh. To use this script, open the Window > Python Editor and in the bottom panel paste this script in. Now click the Green play button. Read the full article
0 notes
Text
Baking Secondary Motion (Fake Physics) for Games - Improving Performance with Motionbuilder
Tumblr media
Physics can be expensive to render in game and yes we have powerful engines that can handle much more than they used to, but we should still try to create performant assets where possible, things like jiggles on a character, props in the world baked down or things that shouldn't be simulating where possible. I wanted to show how in Motionbuilder we can create secondary motion which can be convincing the player that it's actually physics based and not pre-canned movement. This is important in game development where we can pre-emptively decide what would be "physics based" and not required so we can look at saving the rendering budget by creating custom bones to bake this secondary motion onto, i.e bags, pouches, weapon slots etc... things that would naturally wobble or move when the player or object moves. In this first video you can see I have made a simple backpack placeholder with a trusty box. On the left is the original, middle is an overlay so you can see the difference applied and the right this applied motion. Let's have a look at how this is setup. The first thing you might notice is that each prop has a skeleton node, I do this over Nulls in Motionbuilder as Nulls don't have customizable looks like the Skeleton Node. This makes it easy for anyone who's working on it to see. Note: the Skeleton Node (for the prop you're working on) should be parented to a skeletal bone that is closest to the movement and placement of that prop.) So you won't place a hip prop parented to a spine, you should parent that hip prop Skeletal Node bone to that Upper Leg bone … or wherever is closer. Setup the Relation Constraint To setup this secondary motion we create a new RELATION constraint and drag the setup Skeleton Node with a box (or other object to reference the prop) parented to that Skeleton Node. Drag the Skeleton Node to the relation canvas and set it as Receiver. Drag that skeleton node again as a Sender.  Now we can begin the setup, we achieve this through Damp nodes. There are special nodes for both Rotation and Position as well as Numbers and 3D Damping.  We will use Rotation Damp and a Number Damp (you can also use Position Damp, but I only want to effect the Y Axis which is a Number and not a Vector3.  Connect the Rotation Vector Parameter to the R slot in the Rotation Damp node and then that Result to the Rotation Receiver Node's Input Slot. You can add a Number Damp Node to the Relation Canvas as well as we will do the same for the Translation Vector.  You'll notice that the Vector to Number is split into Numbers so we can individually change those values. You can actually skip those nodes creation by just connecting the Translation Slot from the Sender to the Damp Number Input and the Result to the input of the Translation Slot of the Receiver. This will connect it automatically to the X slot but for our case the hip slot should move up and down and not back and forward, so I disconnect (right mouse click for disconnect option) and then connect to the Y Axis. Repeat for the other side.   Now we can set the values of the Damping Node. I have played around with values for a while, but remember these values also depend on the scale of your scene and rig. For testing purposes you can always play the scene in Loop and then make adjustments live. To set values on nodes, you can right mouse click on a slot entry and then click Set Value. Now you can enter values that are required, once enter you'll see the scene start updating with these nice secondary movements. The inertia from the backpack in this video is pretty noticeable and provides a nice subtle movement and weight to the punch. On the left you can see the backpack is completely static and doesn't provide much weight to the punch. With the motion applied you can see the weight that trails the backpack on the bottom - the same goes for the pouch on the right upper leg too. Baking the Skeletal Node with the Motion Now that we have the motion we want, a nice secondary layer of motion let's look at how to bake this motion to the Skeletal Node so we can use it in Engine.  Some considerations first.  It's important to note that adding this Skeletal Node to the current Skeletal Tree of your rig will break it when importing it back into your engine, this is because your other motions don't have this custom bone we made in it and the Engine (usually) will display an error that the bone count is wrong. You CAN fix this pre-emptively.  When you create you're rig to begin with add IK and Prop nodes that are present in the tree to begin with. If you plan to use weapons in each hand and have weapons on display on your back or for any other reason - count how many props you have and then create double that amount for future use in case you need those bones. Otherwise it will be a lot of work to add these bones in to the rig afterwards and it's best to lock those decisions down before hand. Make sure you read the important considerations before continuing... Okay, let's continue. From these video you can see we bake the Skeletal Node (Sword-Node) down but selecting it (notice the timeline has no keys yet, it's totally driven by the Relation Constraint).  Click the Animation dropdown under the Key Controls panel, and select Plot Selected (All Properties) this is because we only want to bake the keys for the Sword-Node not the entire take, otherwise every single bone and object will be plotted to the timeline. Sometimes this is handy if you're ready to finalise the scene - I prefer this to baking to Skeleton, that way I can stay in the Control Rig while working. Now the keys have been plotted to the timeline for the take and it has all our secondary motion applied. You can toggle the Relation constraint to test and see that it works still without the Relation driving it. In fact if Relation is still active, it will layer another Secondary Motion on top of the Motion already, which in most cases exaggerates the effect and won't look good. Copy Motion from our Skeletal Node to Main Skeletal Rig Designated Prop Bone Now we need to move that motion we have created to our main skeleton. There are ways to streamline this in production but for the sake of this tutorial I wanted to make it clear and provide step by step instructions so you can follow along. But how do we move or connect our bone to this main skeletal bone? Easy! From our Skeletal Tree for our Rig, you can see we have a Prop bone, we need to connect this bone to copy the motion from the Sword-Node bone we made which currently has the keyframes. You might ask why don't you just use this Prop bone from the start, well it's easy to mess up and I like to use temp objects until the motion is ready and then apply it to the main skeleton.  We first create a new Relation for the Prop bone and we are simply going to set the Prop as the Receiver and the Sword-Node as the Sender and connect the Rotation and Position vectors directly, no nodes needed in between. You'll see that the prop follows the Sword-Node now, but there's no data. You can then repeat the process of Plotting Selected. Or create a Character Extension to auto plot this as part of the Control Rig. For now let's just use Plot Selected to keep it simple for this tutorial. Once processed you'll see the Prop bone now has the motion. The Prop bone doesn't have the temp mesh (box) parented to it so you can move it there or leave it and remove the Sword-Node from the Skeletal Tree to keep it clean.  Now you can export to Engine and parent an object to the Prop bone and see the new Secondary Motion with no physics calculations needed. You can also rely on the fact that since it doesn't use physics it won't break in Engine and require more work fixing it - a win win. I hope you found this article interesting, if you can't see these videos make sure you're reading it from moonjump.com and I'll see you all in the next article. Read the full article
0 notes
Text
4 Arm Setup in Motionbuilder - Replicating Destiny's Fallen
Tumblr media
I have been experimenting recently trying to create different rigs and always loved the look of the Fallen from Destiny. However I've been intrigued into creating a 4 arm animation system in Motionbuilder. My idea was to setup the main arms in line with the normal human biped standards for HumanIK. This mean aligning the top arms with the X axis and setting up the bone connections to HumanIK character definition. Once the character has been defined in Motionbuilder the next step was to setup a custom relation to mimic the arm data from the main arms. So it would go: MainArm -> rotation linked to -> SecondaryArm This would be replicated for the entire tree of each arm bone. Once these relations have been setup you'll see that the bottom arms will now the top arms motion, however we would want to edit it and change the offset of the rotation in case of penetration or changing the look. The best way to achieve this is to add a Rotation Add node to the relation constraint.
Tumblr media
Once all the bones have been linked this way we can apply some test motion capture to see what the result would look like. I applied the Box_Jab previs motion capture from Motionbuilder's previs folder and this is the result so far. But what if we wanted to add custom animation simply copying the rotation from one arm to the other wouldn't work, say we wanted to create a take with a roar or provoking the player. Let's take a look at how we can achieve that with Chain IK. Above you can see the Chain IK setup with the first and end joint in the arm - normally the UpperArm and Hand and then we create an effector or where we want the IK to reach to, and then a Pole Vector to control the elbow orientation. You can add a floor in to calculate when the object is passing through it to limit it as well. This creates a nice looking and easy to control system that will benefit from the IK setup. I've also added another Relation to copy the rotation of the effector to the hand so it's easier to pose without jumping around between bones. Take a look. That's it for this look at creating a rig with 4 arms in Motionbuilder. There's many more options to consider like damping rotation from the main arms to the secondary arms to create a delay which looks nice for idles. I hope you've found this interesting and if you have please leave a comment down below! *Destiny Fallen model obtained from CGTrader for free by author 3DGeneralist. Read the full article
1 note · View note