Zach Gray zcgray-at-southern-dot-edu
matchBox9.20.mel Beta, Windows, Maya 7.01, 8.0
Copy matchBox.9.20.mel to your script path. Source the script.
Execute using matchBoxUI;
The script will attempt to install the icons in the first directory in your XMBLANGPATH, if you want them installed in some other valid icon path, select it in the directory list.
(All movies QT7 H.264, long-winded and boring. I’m a teacher, what else did you expect?)
Overview 1:37 2.98MB
Setup Basic Stuff 4:51 7.72MB (obvious)
More Features 3:36 4.74MB (boring)
Character Walkthru 9:46 20.1MB (useful, but long)
While teaching at the School of Visual Art and Design at Southern Adventist University, veteran Disney director Hendel Butoy (Rescuers Down Under, Fantasia 2000, Mickey’s Philharmagic, Story of Jesus) talked about a tool that was developed at WDFA for flipping the pose of a character to assist in creating walk cycles. We implemented this functionality using a brute force tactic on a simple character for animation tests. Each control needed to processed slightly differently depending on rotation order, parent rotation order, local axes, inverse scale, etc. The solution we came up with worked only intermittently and because of its complexity, setup was not done on other characters. Students got used to the tool on the simple character, and constantly asked if was possible on more complex characters or on their own rigs.
MatchBox is the result of an effort to develop a universal character flipper that will work with any rig, every time. While animating a walk cycle, poses will be mirror images for the opposite stride. Even though the thought process has been completed for posing the first step, it’s a time consuming process to match the pose on the opposite stride. Match box allows you to quickly reverse and match the poses for a complete cycle. If the starting or ending pose of a cycle needs to change, the leading or ending foot may change as well, requiring reposing of the entire walk sequence. While some tools exist for flipping animation data across an axis, it becomes very difficult if the character is turning a corner or walking on an arbitrary angle.
MatchBox was developed with two goals in mind. First is bullet-proof flipping, matching, and mirroring on an arbitrary plane. Second is a generic solution that can be applied to any setup at any time and is open enough to be implemented by an animator with out the assistance of a character TD.
Each character setup that I’ve encountered has been slightly different, and presents a different set of challenges. MatchBox is generic enough to work with many different control types and can be scripted during rigging, applied as a final step in rigging, or applied by an animator on a scene by scene basis. It works with referencing, multiple characters, and is completely connection based.
1. Create a reflect plane.
2. Create widgets connected to controls.
3. Connect any attributes
4. Match, Mirror, or Exchange!
You can create any number of widgets, but only one per control.
You can create any number of widget pairs, but only two can be connected.
You can create any number of reflect planes, but a widget can only be connected to a single reflect plane.
Controls must be transforms, (joints, locators, groups, curves, polygons, etc.)
You can calculate any combination of widgets, reflect planes, controls, or sets. If you had a reflect plane for the upper body, and one for the lower body, you could process them simultaneously, but they would only affect their respective widgets.
Characters that are dependant on hierarchies must be processed in hierarchy order. If a control that is deeper in the hierarchy is processed before it’s parent, the parent will offset the final position since the calculations are made in absolute world space.
Note: MatchBox will make great attempts to process the controls in the order of the hierarchy, but in some cases can be confused by multiple parent constraints or direct connections. The script will follow the constraint with the greatest weight, but will fail if there are multiple constraints on different channels of a single control. See technical info for more information. If this issue becomes relevant, I will include a widget.procssingOrderOverride attribute to allow specific processing order for troublesome controls.
Note: Widgets are simple polygon objects, and while direct editing is disabled, they can still be deformed if their parent is deformed. You must not parent them to controls that have deformers attached! For instance, if you had squash nonlinear applied to the parent control, the deformation would be applied to the widget as well. This will cause the calculation to fail. The controls may be translated, rotated, and scaled only, which should work for 95% of cases. If you do have deformation applied, place a buffer control using a constraint as to not affect the widget.
· Select an axis and hit ‘Create Plane’.
The reflect plane is simple polygon geometry. Do not modify the topology or components. The plane can be scaled to any size.
When building, it is best to leave the plane oriented to the cardan axes (xyz) splitting your character in half. It is important not to adjust the plane during setup, as the widgets are calculated using the plane.
If you delete the reflect plane, it will render any attached widgets useless. To remove from the scene, delete manually or select the plane and Clear>Remove Connected from the matchBox menu.
The widget is attached to a lambert shader named matchBoxClear. Feel free to modify, rename, or delete the shader, but only after you are done with setup. If it is removed, matchBox will create an additional shader for new planes.
· Select the reflect plane that you want to control the widgets, and press the select button in the UI.
· Choose which transforms you want to process or ignore by default.
· Choose if you want an organization layer created.
· Choose if you want an organization set created.
· Choose the initial scale for your widget. (By default, the distance from the pivot to points is unit).
Select one control and hit ‘Create Widget’ for a simple case, with no pair.
Select two widgets to set up a corresponding pair for matching, mirroring, or exchanging.
If two widgets are created, a connecting curve and annotation will be created, bearing the name of the controls. You may delete the curve and annotation, or choose not to create it at all by selecting Advanced > Disable Visual Feedback from the matchBox menu.
Hint: Hit the ‘g’ key, (repeat last command) to create additional widgets with the same settings for speedy setup.
Widgets are simple polygon geometry. Do not modify the topology or components. The widget can be scaled to any size, but must remain centered on the rotate pivot of the control, and directly parented to the control. Do not apply deformers of any kind to the widget.
Connection curves are organized in a group by reflect plane and named (reflectPlaneName+guideCurves).
You can’t place more than one widget per control. If you attempt to, you can keep the old widget or create a new. Always choose Replace unless the widget holds attributes that you need to maintain.
You can’t place a widget on a widget.
Be sure you build widgets in the default position of the control! If you have built your character where all the controls have zero rotations in the initial pose, enable Advanced > Zero Rotations from the matchBox menu, to zero the controls without re-posing your character.
Each widget allows you to explicitly specify which transforms are processed per control. Change the attribute in the channel box to enable or disable processing.
Note: The rotate channels for the widget should not be modified! These store the rotational offset of the control from world rotation. The script should calculate this correctly, but if a singularity exists for some reason (I haven’t found one) it must be edited manually. Rotation must only be in increments of 90degrees, between -180 and +180, and the widget axes must be oriented as closely as possible to the world cardan axes. If you modify the rotation and plan to apply +360 degree rotations, you will need to modify the widget.worldRotation and widget.inverseWorldRotation attributes as well as the widget.flipAxisInvert attribute. A preferable workaround would be to reorient the control to avoid the error, and rebuild the widget.
If one widget is deleted the other widget will continue to function, but the connecting curve will need to be deleted manually. To remove a widget pair, select the widget or control and select Clear > Remove Selected from the matchBox menu. You may also delete the widgets and curve manually.
The widget is attached to three lambert shaders named matchBoxRed, matchBoxGreen, and matchBoxBlue. Feel free to modify rename or delete the shader, but only after you are done with setup. If it is removed, matchBox will create additional shaders for new widgets.
· Create a pair of widgets that the attributes will be bound to for processing order.
· Select one or both widgets, and hit the select button in the matchBoxUI. This places the names of the widget in the corresponding text fields.
· Highlight one or both attributes in the channel box. If the attributes share the same name and channel box order, you may select them at the same time, if not, select them individually.
· Enter any mel code, where $v is the raw value of the corresponding attribute. Be sure to enter the inverse code for the opposite attribute. $v+2 on one widget would dictate $v-2 for the other.
· When all the fields are full, the link attributes button will activate. Hit the link attributes button to build.
Attributes are bound to widgets for processing order, but are completely independent from the widgets in all other respects.
You can only process numeric values.
Any widget can process any attribute on any object. However, it makes sense to process the attributes with the controls they are bound to. For example, it would make sense to include the attribute fingerCurl on the widget for the wrist. You may also create widgets that don’t process any transforms and place them in the hierarchy of the character to determine processing order.
If an attribute already exists and is connected, you will not be able to reconnect. It’s best to remove the attributes and build them again.
Each widget allows you to explicitly specify which attributes are processed per control. Change the attribute in the channel box to enable or disable processing.
To delete an attribute connection, select the attribute name on the widget in the channel box and select Clear > Remove Attribute from the matchBox menu. If you delete the widgets the attribute will die as well. If one attribute is removed from the widget the other attribute will continue to function and will need to be deleted as well.
Note: The delete attribute will work for any attribute on any object but will only trace the connections and remove all the trash when an attribute is selected in the channel box of the widget.
After setup is complete, select any combination of controls widgets etc. and hit an action button.
To globally ignore transforms or attributes choose options in the calculate section.
To save the current selection list to a shelf button, hit the smaller shelf action button. You will be prompted to provide an overlay name for the shelf.
Mirror: Reflects single object or mirrors a pair across reflect plane. The first selected object is the target, and the connected object will mirror that position. If a connecting curve or reflect plane is selected, creation order determines the mirror target.
Match: Match the position of the FIRST selected object. Ignores single widgets & reflect plane.
Note: You could use match widgets on separate characters to copy animation data from one character to another, or use it for FK/IK matching. You could use it as a pickup system, to lock an object to a hand without parenting. I think this has a lot of possibilities, including a smart rotate system, animation retargeting, etc. This needs some further testing, but time will tell.
Exchange: Swap match pairs across reflect plane.
Hint: Hit the ‘g’ key, (repeat last command) to perform the last action again with the same settings.
See Widget Calculation Below for more info.
Note: Character TD’s who want to script the widgets could easily do so by looking into the recent commands list. Just build a widget with the options, and grab the code from the recent command. TD’s could also create custom triggers for selection lists by grabbing the command feedback during shelf creation.
Rather than managing a list of controls and all their idiosyncrasies, it seemed more manageable to create a widget that would be parented to each control. The widget is a simple polygon object that represents the three xyz cardan axes. The tool uses rotation and connection data stored on the widget to process the transformations for the parent control.
The use of widgets has several advantages:
· Simple creation, deletion, updating, and management.
· Leaves original controls untouched.
· Transparent operation when widgets are hidden.
· Visual confirmation of world space calculation and control relationships.
· Flexible processing, where one or all controls/widgets can be processed at any time.
· Easy implementation of pose matching and animation transfer.
· Mechanism for calculating attributes as well as basic transforms.
· Calculation of all rotations takes place in word space, and is completely independent from rotation order or the parent transform matrix.
The widget setup is as follows:
· Orient the widget to match the orientation and position of the parent control. At this stage, the widget assumes the incoming rotations and local orientation of the parent, but has zero rotations.
· While maintaining overall orientation, orient the widget cardan axes to the closest corresponding world axis. For example, if a bone has yzx rotation order, and the bone is pointing down the word x axis, the y axis of the widget will point down the bone. The tool orients x axis as close as it can to the world x axis, (same for y and z) while maintaining overall orientation. So in the case of this example, the x axis will now be pointing down the bone, while keeping the perpendicular relationships. Confusing, right? The widget is oriented as close as possible to the world axis to guarantee consistency during the match operations.
· The inverse world axis order, (world vs. control) is calculated to be used later for determining +360 degree rotations.
· The widget is connected to it’s match pair and reflect plane via message attributes.
· The widget axis that is most closely aligned to the reflection plane vector is noted, and inverted. This allows controls to be reflected properly.
· The widgets are connected visually using a curve, and annotated in creation order. Creation order is relevant only when mirroring or matching while selecting the reflect plane. Mirror/match order is overridden by selection order.
Widget calculation is as follows:
· The selection list is processed to determine the widgets for processing. You can select any number and combination of widgets, controls, sets, connection curves, or reflect planes.
· The selection list is then sorted by hierarchy depth. This prevents processing (which takes place in world space) from being overridden by parent controls. Constraints that affect position are traced to determine true hierarchy depth. (Direct connections are not yet implemented.)
· World transforms are calculated one object at a time, then stored for deferred processing. This avoids any parent objects altering the position of the child objects.
· World transforms are calculated using vectors determined by the widgets. The vectors are found by referring to a specific widget point and the widget rotate pivot.
· The source and target vectors are normalized based on the rotate pivot.
· The vectors are then flipped processed thru a reflection matrix generated by calculating the face normal of the reflect plane. (Thanks to Jeff Knox for writing the matrix)
· The reflection axis is inverted based on previous setup information.
· Translate data is flipped thru the same matrix, and the offset of the plane is added back to the normalized translate.
· The angle and axis required to rotate x source into x target is calculated, then applied to the control in world space rotation. This works because the widget was oriented to world space during setup. This repeats until each vector is oriented to the target vector.
· All of the pre-calculated transformations are then applied in hierarchy order.
· Attributes are attached to widgets, but any attribute can be connected to any widget.
· Attributes follow the processing order of the widget they are attached to.
· Message attributes are connected from the control to the widget.
· Custom mel can be added for dealing with special cases, where $v represents the raw value. Appropriate uses would be -$v; pow $v 2; $v+2; Be sure to write the inverse of your expression for the opposite attribute. If $v+2 on the source, be sure $v-2 on the destination. The mel can be changed at any time by editing the string in the extra attributes of the widget.
· Attributes are processed after the transforms for the control attached to the widget, and then in creation order.
Thanks to Aaron Adams for the first pass and structure of the UI. Matt Schiller for ideas and testing. Jesse Rademacher for use of rig. Michael Hutchinson and Jeff Knox for earlier implementations of the idea. Thanks to Hendel Butoy for the inspiration and teaching us all how to animate.