Core Concepts

Last Updated: 08.21.2020


_images/mrs_x400.png

People use language differently. This is our attempt to shed light on what we mean with the language we use in helping users make the most use our tools.

We also have a general site terminology article if you don't find what you need here.

RigBlocks

The way we've set things up is that the metaClass cgmRigBlock (cgm.core.mrs.RigBlocks.cgmRigBlock) is our template object for rig creation. These are used to generate the controls, wiring and structures of our rigs. At the end of the rig process, the rig itself can be exported off to keep all the extra data and nodes out of production assets.


Current RigBlocks

Let's talk about the current rigBlock spread and their profiles which let's you specify what sub type of block you're dealing with. When you start messing with these you'll see other options in the ui that we're playing with. I'm only going to talk about the ones that are more tested for now.

Block Status Description
Master Production Root block. Almost all rig structures should be under a master
Limb Production Arm,Finger,Thumb,Nub,Plantigrade,Digigrade,Ungulate,Unigrade,
Segment Production Spine, Tail, Tentacle, Ear Up
Hand Early Alpha BlockFrame
Brow Active Dev Facial brow setup
Eye Active Dev Eye setup
Muzzle Active Dev Mouth, nose, jaw
Handle Production Simple, snapPoint, shaperList, box, more...
eyeMain Active Dev Way to manually place master control.

Basics

  • Rig block types are not subclasses. Instead each block is tagged with it's type which then tells it which module it uses.

    • After experimenting a lot over the years with subclasses and dealing with specific reloads
  • At build how a given rigBlock of a type is setup is specified by two on creation flags which will both have their own core concept sections:

    • blockProfile | This is what helps specify a spine segment rigBlock from a tail for example.
    • buildProfile | This mainly affects joint/roll counts

Dag Structure

So, we start with a the dag. A few basic concepts

  • The actual rigBlock as maya sees it is a dag node with a curve shape - currently using a shape we call locatorForm
  • This dag has the core attributes of the rigBlock. There are some attributes that are shared among the different rigBlock types and many that are only on those given rigBlock types.
  • State Nulls are dags that hold the dags,shapes and other bits for a given state of a rigBlock. States are covered in another fundamentals sections.
  • No transform nulls are state nulls that hold those items for a given state we don't want to be transformed in anyway. Things like | track curves, curve/surface track dags and more

Core Settings

  • attachPoint | Where the rig should attach to on it's blockParent's rig * Base | Attach to the base of the parent block * End | Attach to the end of the parent block * Closest | Attach to the closest joint of the parent block * Surface | Planned but not implemented
  • baseSize | The stored base size values on a given rigBlock

Block work

Active Block

The active block is the rigBlock that is loaded to the mrsBuilder ui. Several calls require an active block or it can be a point of context via the Push menu. Also the active block blockDat section works off the active block and has no function without it.

You can set the active block a couple of ways.

  • Top bar of setup | There is a button << which when pressed with a selected block will set that block as the active block
  • Right click menu | right clicking a selected rigBlock in the scroll list will provide an option To Active which will make that block the active block
  • Utilites | Contextual Section | There is a button To Active that does the same.

blockDat

BlockDat is the what we call the core data set of a rigblock. It comprises everything necessary for the replication of a given rigblock.


blockFrame

BlockFrames are a special kind of rigBlock. These are designed to help layout other blocks.

Some important notes:

  • They never go beyond the define state even though they changes states like the others. The have a flag that just passes the block through those processes
  • They are intended as a framework that you can get rid of after you're happy with the subBlocks. It's just to aid their placement you don't even have to mirror the frame you can just get one side's subblocks good and then push them as they are

More info on the site article.


blockMirror

A rigBlock may have a single blockMirror rigblock connected to it. This sets up a relationship for block mirroring functions as well as rig mirroring after build.


blockParent

The rigblock that would be seen like a hierarchical parent to another block. However it's more of a controller block rather than a parent as it can be connected to that parent rigblock in multiple ways at rig.


blockState

The given state of a rigblock. Check the post more more info.


Rigblock

A rigblock is our rigging guide. They are setup and controlled by mrsBuilder. You can find more information at the post for the concept.


Template

_images/horse_02.png

Horse Template - 04.19

A collection of connected rigblocks usually saved as a file in order to generate an asset rig. Currently you can work off others templates though we have plans to have a fuller config system for blocks to come online sometime in 2019


Build Profiles

Build profiles are our way of defining how we want our rigBlocks to build.

The idea is to allow you to save the same templates with different build options so you could customize similar proportioned rigs for different use cases. Need different LOD options with different join counts for your main character and side NPCs? No problem. Just create the custom build profiles for your templates and quickly build different rigs using the same template.

Profile Status Description
unityLow In development Mobile game development
unityMed Testing Typical game projects
unityToon In development Squash and stretch game dev
hik Planned User is looking into requirements to implement
Commercial Planned No holds bar deformer options

BlockDat

BlockDat is the what we call the core data set of a rigblock. It comprises everything necessary for the replication of a given rigblock.

How data is stored

We currently store data to a rigBlock as an indexed json Dict. That looks something like this:

{u'baseName': u'middle',
 u'blockScale': 1.037493482218997,
 u'blockState': u'form',
 u'blockType': u'limb',
 u'define': {u'orients': [[52.22471587773368,
                           -71.93779744222662,
                           -16.535790332436875],
                          [52.22471587773368,
                           -71.93779744222662,
                           -16.535790332436875],
                          [52.22471587773368,
                           -71.93779744222662,
                           -16.535790332436875],
                          [5.389233579525813,
                           -78.6114656770376,
                           -3.2547763552193154]],
             u'positions': [[-74.79985247829057,
                             89.59468401000198,
                             6.8309683204825085],
                            [-67.3221197598987,
                             96.5377039202826,
                             5.137624991826678],
                            [-66.42490656915008,
                             95.59145818175912,
                             5.888416325692915],
                            [-62.11273142938996,
                             96.97845763451818,
                             3.656240724223191]],
             u'scales': [[2.1279380321502686,
                          1.6460264921188354,
                          1.886982262134552],
                         [1.0, 1.0, 1.0],
                         [1.0, 1.0, 1.0],
                         [1.0, 1.0, 1.0]]},
 u'orient': [52.22471587773366, -71.93779744222662, -16.53579033243688],
 u'position': [-66.74114618435289, 95.68534753799752, 4.876879197491775],
 u'rootOrientHelper': [0.0, 0.0, 0.0],
 u'scale': [1.037493482218997, 1.037493482218997, 1.037493482218997],
 u'form': {u'loftCurves': {u'0': {u'p': [-62.11273142938995,
                                             96.97845763451818,
                                             3.6562407242231947]},
                               u'1': {u'p': [-66.74114618435289,
                                             95.68534753799753,
                                             4.876879197491785]},
                               u'3': {u'p': [-69.4273789294334,
                                             93.65512839221766,
                                             5.528241587126501]},
                               u'4': {u'p': [-72.11361973321017,
                                             91.62490315578187,
                                             6.179605930847902]},
                               u'5': {u'p': [-75.0427217839515,
                                             89.95100176945735,
                                             6.939970093867182],
                                      u's': [0.43219668963492186,
                                             0.432196689634922,
                                             0.4321966896349216],
                                      u't': [-2.5891706859925808e-15,
                                             0.4447799814925754,
                                             -1.6077368156588644e-14]}},
               u'orientHelpers': {},
               u'orients': [[34.22581051559483,
                             -72.67783981267927,
                             -19.86320553000147],
                            [52.22471587773368,
                             -71.93779744222662,
                             -16.535790332436875],
                            [52.22471587773368,
                             -71.93779744222662,
                             -16.535790332436875],
                            [52.22471587773368,
                             -71.93779744222662,
                             -16.535790332436875],
                            [52.22471587773368,
                             -71.93779744222662,
                             -16.535790332436875],
                            [52.22471587773368,
                             -71.93779744222662,
                             -16.535790332436875]],
               u'positions': [[-62.112731429389946,
                               96.97845763451815,
                               3.656240724223186],
                              [-66.74114618435289,
                               95.68534753799752,
                               4.876879197491773],
                              [-66.74114618435287,
                               95.68534753799753,
                               4.876879197491779],
                              [-69.4273789294334,
                               93.65512839221766,
                               5.528241587126499],
                              [-72.11361973321016,
                               91.62490315578185,
                               6.1796059308479006],
                              [-74.79985247829057,
                               89.59468401000197,
                               6.830968320482507]],
               u'scales': [[1.0, 1.0000000000000002, 0.9999999999999997],
                           [1.0, 1.0, 1.0],
                           [1.0, 1.0000000000000002, 1.0],
                           [1.0, 1.0, 1.0],
                           [1.0, 1.0, 1.0],
                           [1.0000000000000002,
                            1.0000000000000002,
                            1.0000000000000002]],
               u'subShapers': {u'0': {u'o': [[34.22581051559291,
                                              -72.67783981267887,
                                              -19.863205529999515]],

Let's break it down a bit.

  • version | when this rigBlock was made originally
  • The first level of data is root data
  • Then each state has a dict * Sorted by ordered index lists for the handles of that state * Sub shapers and others have sub dicts further still
  • ud | these are a simple collection of userdefined attributes on the rigBlock

For example, let's look at the form state data.

  • orientHelpers is empty because this block doesn't have data there
  • orients | indexed list of form handle orients
  • positions | indexed list of form handle positions
  • scales | indexed list of form handle scales
  • loftCurves | this is a keyed sub dict which has data indexed by the handle's list index
    • This sub dict has data that it finds:
      • p - position
      • s - scale
      • r - rotate
      • t - tranlsate
      • o - orient
  • subShapers
    • Keyed sub dicts with data per subShaper

BlockFrame

BlockFrames are a special kind of rigBlock. These are designed to help layout other blocks.

Some important notes:

  • They never go beyond the define state even though they changes states like the others. The have a flag that just passes the block through those processes
  • They are intended as a framework that you can get rid of after you're happy with the subBlocks. It's just to aid their placement you don't even have to mirror the frame you can just get one side's subblocks good and then push them as they are

Special Calls

The intention is that blockFrames in the future share the special calls framework to make things work together nicely.

These are from the HAND .


verify_drivers

Builds the drivers from our eventual rigBlocks to be driven by the system


verify_subBlocks

Checks and/or rebuilds the rigBlocks driven by this rigBlock. Typically LIMB block fingers or thumbs.


subBlock_align

Call to snap/shape rig blocks to the blockFrame.

mBlockArg str/mNode | What we want to process. If none, it does them all. If a rigBlock passed that has this as it's blockFrame, will use that one.

templateScale enum | Whether to scale the template loft curves or not


UI

_images/blockFrame_ui.png

prerig tearoff

Again, we need some special options for blockFrames as they work differently than the define>>>rig setup or or base rigBlocks. Here's the example from

Has right click menu via mrsBuilder.

  • Verify Drivers | Rebuilds the drivers. If you change the finger count for example you'd want to do this
  • Sub
    • Verify | Make sure we have the driven rigBlocks we expect
    • Rebuild | Force a rebuild on the sub blocks
    • Snap | Position and orient relevant handles
    • Shape | Cast shape the loft curves as well as position and orient relevant handles

First iteration

The first attempt at this is the HAND which creates LIMB blocks with the blockProfile of finger/thumb.


MetaData

We have a class we did a couple of years ago that goes into this in much more detail which you can find here. However some basis of knowledge is important for you to understand how things work. I'm going to cover a portion of that here but if you want deeper knowledge you should check out that class.

People define metadata differently. For our purposes metadata is our means of storing and retrieving data. This is core to how rigBlocks function as the calls change their processes based on the data stored on a given block.

First of all a few bits about how we have implemented meta

  • We built our foundation on Mark Jackson's fantastic red9 toolset and specifically his MetaClass. Most of our metaclass nodes are subclassed to his. We've been working with him for years and push bugs/fixes/optimizations to him that get put into his main branch and pull his fixes to our core. red9's base package is included with the cgmToolbox.
  • This setup is very object oriented and allows for a number of useful items
    • mClass instance wiring | This means that nodes that are wired and tagged with a specific attribute return instances rather than strings when coding
    • Caching | several years ago he implemented node caching which improved speed a great deal.
    • Json support | He's got json built in with string attributes

We use this data to do things like:

  • Store node relationships one to another
  • Store other information via index managed methods
  • Set toggles that are picked up by our build process

What ways do we store our data:

  • Json | String dictionary setup for complex data
  • Multimessage | Standard maya method for wiring lots of nodes
  • Message | Single message connection attribute
  • msgList/datList | This was our answer to having index managed message lists. It is a managed system for handling message connections and other data lists (strings,floats,etc) in connectable indexed lists. It does this as a series of single message attributes sharing a base name and treated as a single list by our system. You'll see these calls all over our code base
  • Bool | Simple flag for yes/no setup options - hasBallJoint
  • Enum | Multiple option setup attribute - ikSetup type, segment type, etc
  • ``Int``| Whole number value options - joint counts, roll counts, etc
  • Float | Floating point value options - shape offset for example

Why was it necessary to do msgLists? Maya has a bug that comes up not infrequently in versions where multimessage connected objects duplicate their wiring even when you have index matters or other options set. When you need very specific data lists | say a joint chain and you don't want that list if joints getting messed up you need a solution. This was ours.

It seemed a better answer than accounting for the bug creeping up in different iterations of maya.

Last year we added the datList support mainly for name work but it's expanded some. For our MRS joint naming we use something called name tagging so that a given node is tagged in a way that when you mNode.doName() for example it is able to detect it's appropriate name by how it's tagged. Name's are inherited hierarchically and via connections.

This may be unwieldy at times but it's served it's purposes over the years. We'll go into more detail on these concepts when we get to a Workshop on making your own rigBlocks.


Post Processes

Generally speaking there are a number of post process we want to hit after we do a rig build. Let's walk through them.

Most of what we do will be done via MRS Builder.


Rig Prep

_images/mrsBuilder_topPostMenu.png

These items work on a puppet wide basis where as the contextual menu items work by selected rigBlock and context.

You can find more info on the special ui section

Gather Rig Blocks

mrsBuilder>Post>Gather Blocks

Use the post call to group all the rig blocks we've got laying around in our scene under an easily hideable group. You'd want to delete these for any rig files.

I try to keep my template files at the skeleton state and don't keep them in the built rig files.


Mirror Verify

mrsBuilder>Post>Mirror verify

If you want mirroring to work, you need to run this. This call walks our rig and maps our mirror setup following Red9's mirror setup. It does this by:

  • Walking our module/puppet setup to get our hierarchical relationship
  • Maps mirror modules/controls it can figure out
  • Indexes Controls to follow this order
  • Verifies all controls have the Red9
  • Gather Space Drivers
  • Grabs and space driver objects that aren't where we want them and puts them in the hierarchy. This is for our dynParent setup. Target objects don't know where to go at creation and need to be collected at the end.

Up to Date?

mrsBuilder>Post>Up to date?

Rudimentary call at this point. Eventually we'd like this to do more than what it does. What it does do is:

  • Check each rig module's version against the stored __version__ dat on the rig Module
  • Let's you know what isn't up to date.

Much room for expansion here.


Gather Space Drivers

mrsBuilder>Post>Gather space driver

Clean up call to gather world space dynParent group drivers to our puppet.


Qss

mrsBuilder>Post>Qss...

  • ``Bake set ``| makes a bake set (currently targetting Unity workflow)
  • Delete set | Same but for deleting stuff
  • ``Export Set ``| Implemented in Dec 2018. This attempts to gather geo and joints in an export set

isHistoricallyInteresting

mrsBuilder>Post>Is Historically Interesting>

We're experimenting with this one on Brad (Rigging Dojo) recommendation. We turn off the ihi attribute on all nodes in our scene which makes our channel box much much cleaner. This is our first implementation and could use some work.

Warning

Current implementation is scene wide


Puppetmesh

mrsBuilder>Post>Puppet Mesh>

An idea we're playing with. It generates an part-based or unified mesh to use for modeling ref or a skinning frame

  • Unified | Creates a unified mesh from all of the prerig loft meshes of the entire puppet so you have one mesh
  • Unified[Skinned] | ...skinned to the bind skeleton
  • Parts Mesh | Creates a separate mesh per part...
  • Parts Mesh[Skinned] | ...skinned to the bind skeleton
  • ProxyMesh[Parented] | ...parented
  • Delete | Delete whatever we have stored as the puppet mesh

Utilities | Contextual

Remember contextual items work per rigBlock based on context. Not puppet wide unless you're in a masterSelect/below setup.


Verify Proxy

mrsBuilder>Utilities-Contextual > Rig > Verify Proxy

Creates the proxy mesh you've seen. It also replaces the direct control shapes of the rig with transparent proxy mesh shapes for easy selection

You can modify the root geo option on some rigBlocks by the proxyGeoRoot attributes. See shared settings for more info.


Reset Controls

``mrsBuilder>Utilities-Contextual > Rig > Reset Controls `` Reset all the rig controls of the puppet.


Query Nodes

mrsBuilder>Utilities-Contextual > Rig > Query Nodes

RigNodes thing we're playing with. During rig creation all the nodes created during the rig process are wired to the module so that we can cleanly delete them.

You can query them though note, there are a LOT of nodes. This will be very helpful information as we dig into rig optimization.

Here's an example report on a leg rig module.

# cgm.core.mrs.lib.block_utils : ---------------------------------------------------------------------------------------------------- #
|rigNodes_get| >>  aimConstraint : 22
|rigNodes_get| >>  blendTwoAttr : 9
|rigNodes_get| >>  clamp : 3
|rigNodes_get| >>  closestPointOnSurface : 12
|rigNodes_get| >>  cluster : 2
|rigNodes_get| >>  clusterHandle : 14
|rigNodes_get| >>  condition : 67
|rigNodes_get| >>  curveFromSurfaceIso : 4
|rigNodes_get| >>  curveInfo : 3
|rigNodes_get| >>  dagPose : 4
|rigNodes_get| >>  distanceDimShape : 6
|rigNodes_get| >>  follicle : 44
|rigNodes_get| >>  group : 95
|rigNodes_get| >>  groupId : 11
|rigNodes_get| >>  groupParts : 11
|rigNodes_get| >>  ikEffector : 3
|rigNodes_get| >>  ikHandle : 3
|rigNodes_get| >>  joint : 53
|rigNodes_get| >>  locator : 30
|rigNodes_get| >>  materialInfo : 1
|rigNodes_get| >>  multiplyDivide : 31
|rigNodes_get| >>  nurbsCurve : 429
|rigNodes_get| >>  nurbsSurface : 12
|rigNodes_get| >>  objectSet : 12
|rigNodes_get| >>  orientConstraint : 14
|rigNodes_get| >>  parentConstraint : 12
|rigNodes_get| >>  phong : 1
|rigNodes_get| >>  plusMinusAverage : 32
|rigNodes_get| >>  pointConstraint : 9
|rigNodes_get| >>  pointOnCurveInfo : 12
|rigNodes_get| >>  poleVectorConstraint : 1
|rigNodes_get| >>  rebuildCurve : 4
|rigNodes_get| >>  setRange : 3
|rigNodes_get| >>  shadingEngine : 1
|rigNodes_get| >>  skinCluster : 4
|rigNodes_get| >>  transform : 65
|rigNodes_get| >>  tweak : 5
|rigNodes_get| >>  unitConversion : 19
|rigNodes_get| >>  Total: 1063 | (node: 'L_leg_limbBlock' | mClass: cgmRigBlock | class: <class 'cgm.core.mrs.RigBlocks.cgmRigBlock'>)

Connect/Disconnect Rig

mrsBuilder>Utilities-Contextual > Rig Connect > [Connect][Disconnect]

Because we have a separate rig structure from the bind one, this connects and disconnects that setup


Other bits

Here's a running list of other stuff we do.

  • Delete rigBlock group
  • Shaders
    • Delete duplicate shader nodes.
    • Check paths for relative pathing

And after that?

  • We'd skin in a final mesh if we had one
  • Throw it to some animators for testing and iterate
  • Generate a proxy mesh for a modeler to work from and tweak our template when we got the final mesh and rebuild.

After we rig, we're done. Right? Right?!

After we think we have everything how we want it, we should check our controls again.

When we think we have it all, then it's best to do a little test animation or throw it to an animator to get some notes for the inevitable next iteration.




Guide Shapes

RigBlock Guide shapes are our word for handles we using during our build process to make the magic happen. These are used for things like:

  • Defining points of articulation
  • Visualizing asset forms, bounding boxes and joint chains

Things to remember:

  • Handles are often colored by their side so they may not always look exactly like what you see here
  • Some only show up based on your rigBlock settings and state

Define

_images/segment_define.PNG

Segment define state

The define state is the state of minimal information | points in space, vectors and volume.


RigBlock Root

_images/rigBlock_root.png

The most common shape for the rigBlock root 1 is the locator form. Currently they are almost always white in color to make them easily visible.

These are the core dag node of the rigBlock. Moving it will move your all the sub handles of a rigBlock (providing you haven't constrained anything anywhere).


Define Handles

Some rigBlock types have main handles 2 to define a few items.

_images/define_handle.png
  • Size | Scaling the end in some cases drives the bounding box size
  • Length | The distance from start to end defines the. Often the start is just defined by the rigBlock dag at the define state.
  • Sometimes there is extra information on the handles. See the marked image above.

Some of the common handles we use are:

  • End | The end point of the rigBlock. 2 on right side of image
  • RP | the vector of the rotation plane for our block 4
  • Up | the up vector for our block 4
  • Lever | Where we want our lever to be | think clavicle or the lever like hinge at the base of a finger in the hand

Visual Define Helpers

At times we use special handles with define handles to help show more information but not necessarily directly interact with.

Vector Vector helpers are cylinders you rotate - 4 and 5. They are to help see vectors in 3d when we start getting more complicated.

_images/vectorHandles.gif

Bounding Box

The bounding box 3 is simply to show a visual volume which is only there to be helpful with sizing assets when you don't have a mesh to work from.

  • They are usually hidden or template locked at the form state
  • If they prove cumbersome to users in time we may revisit.
_images/boundingBox_02282019.png

Joint Labels

Most main handles of our rigBlocks have jointLabels 6 to help you know what you're looking at.

Note

You can control the visibility of these via the vis menu.


Form

_images/segment_form.PNG

Segment form state

The form state is the state of shape | proportion, form.

Here is a segment with shapers and 2 sub shapers at the form state. We'll use this to walk through the shapers of this state.


Form Handles

The dark rounded corner handles 1 (color will vary by side). They are used for big movements and scaling. Sub shaper handles are controlled by these. What that means is that if we take one of the handles and move and scale it...

Note

  • Our other form handles are unaffected
  • The form of our loft mesh however does change and scale to blend between the shape and form of handle before and after.

Loft Handles

These are the actual curve handles 2 that our form loft runs through. Here's what happens when I take the last step and move and scale one of the loft handles.

Again, note the other loft handles are unaffected

The loft handles are what we use to really shape our proxy. For our purposes we spend a good bit of time here as it is a good way to play with character looks before committing to modeling time as well as testing proportions.

Note

You can change the cvs on these however that data isn't currently stored in our blockDat so rebuilding will wipe it


Orient Helper

This arrow shape 3 controls the 'up' of our segment root for rigBlock aiming and joint aiming.

You can see it all of the images above.

Note

There is a function to snap the RP define handle if one exists to the plane defined by the orient helper.


Template Loft Mesh

This surface is really important.

  • It is the nurbs surface loft created driven by the other form handles
  • It is used for proxy mesh creation and control curve casting. At rig creation this surface is used to cast rays at to find curves to then offset and connect to other curves on the surface to create the controls of our character which is how they match our form so well.
  • You can affect its shape via the loft handles and the settings to some degree.

Prerig

_images/segment_prerig.PNG

Segment form state

The prerig state is the state of dags- points of articulation, joint chains, important controls

This is our segment in prerig state and I visually toggled .template mode on to only look at the prerig stuff.


Prerig Handle

_images/prerig_handles.PNG

The default prerig handle is a two part control. There is a split so that we don't have to have our rig dags match our joints unless we want to.

Dag Handle The cubeOpen control shape 1. This dag is to define our actual points of articulation structure.

Joint Handle The locatorForm shape is the joint handle 2. The prerig joint loft runs through these.

  • When the joint count matches the handle count these are the exact positions that will be used
  • When the count is different, the splits will happen along a curve very similar to the joint loft

Prerig IK Orientation handle

_images/prerig_specialHandle.png

Sometimes there are special prerig handles that are designated by a colored 3d axis.

This denotes that this is an orientation handle. For example, the ik wrist, ankle would use this controls orientation rather than the joint.

Note

These are important controls. When you see these, orient matters. The y up is used for joint orientation actions.


Joint Loft

The much thinner lofted surface 2 running through our joint handles is for visualizing the joint chain.


Face Handles

_images/face_handles.gif

There are several layers of face prerig handles.

Dag Handle

The lolipop looking handle. This is our affector that makes other stuff move. This doesn't actually become a rig control but just acts as a helper for moving the other prerig bits.

Handle

These actually matter for the rig.

  • Squircle | These will be the control shapes for our major controls. Size and position them how you want. Most blocks have an offset value you push them off the surface.
  • Locator Form | These are the dags for the control handles. This is where the pivot for those handle transformations will be. Generally you want them to be right with the joint chain but it's not a requirement. At rig time, the ribbons will use joints from these as influences.

Joint Helper

These are for each joint. Changing the joint number on the block will require rebuilding the prerig state to get an accurate represntation here.

  • 3d Axis | The represents the joint orient and position for the skeleton state as well as rig. Most blocks have an jointDepth attribute to push these together into the mesh.
  • Semi Circle | This is the direct shape for the joint. When rigged, this will be the direct controller shape for this joint. Most blocks have an direct offset attribute to push these together offset from the proxy surface.

Special Handles

These are optional handles that only create under certain conditions

Cog Helper

_images/cog_helper.png

This is our Cog helper. There are two parts to it, the dag and the shape.

  • If you select the pyramids, that's the shape and you can move it it irrespective of the dag.
  • The dag is represented by the curve text 'cog'. You can pick walk up once from the shape to get it and move both
  • At rig time:
    • The dag is where the rig Cog dag is generated from
    • The cog shape uses our shape helper
  • It only builds if we have addCog True on your rigBlock
  • The joint loft represents what our joint chain will be at the skeleton state

Possibilities

Specific joint handles

We've toyed with the idea of having exact joint handles at the prerig state and we may end up doing that. Our main concern is that you'd have to rebuild the prerig state everytime you changed the count and the way we currently do the state load it will break your data.

You can manually move joints at the skeleton state if you just want to move a roll joint.


Space Pivots

_images/spacePivot_example.png

Space Pivot Shape

Space Pivots are our solution for having a visible constrainable space for use with our dynParent system

Originally I added this concept on Morpheus 1 as a way to have a constrainable space when animating. Say you want your hand to follow something and still have control over it. Well that's what this was designed to address. They are added to our dynamic parent system as dynamic targets.

MRS currently utilized these mainly on IK controls though they are optional item for building.

Note

  • We have calls to switch space without that snapping via the marking menu and mrsAnimate.
  • The are created with a constrain group one level above their main dag level

Shared attributes

Define

addCog

bool | Whether to add a cog helper to our rigBlock


attachIndex

int | Parent joint index if attachPoint mode is index and only then


attachPoint

enum | Where we want our rigBlock to attach to it's blockParent

  • base | 0 index on the blockParent
  • end | -1 index on the blockParent
  • closest | closest joint/dag on the blockParent
  • index |
  • surface | NOT IMPLEMENTED

baseSize

float3 | The stored base size values on a given rigBlock


Form

loftShape

enum | What shape to use for our loft. We've got a number of options

_images/loftShapes_labeled_2.png

Lofted Shapes

  • TriNeg [1]
  • TriPos [2]
  • TriDown [3]
  • TriUp [4]
  • Digit [5]
  • SquareRoundDown [6]
  • SquareRoundUp [7]
  • SquircleDiamond [8]
  • WidNeg [9]
  • WidePos [10]
  • WideDown [11]
  • WideUp [12]
  • Circle [13]
  • SquareNeg [14]
  • SquarePos [15]
  • SquareDown [16]
  • SquareUp [17]
  • Squircle [18]
  • SquircleNeg [19]
  • SquirclePos [20]
  • SquircleNeg [21]
  • SquircleUp [22]
  • Diamond [23]
  • Square [24]
_images/limb_loftShapes.png

Here are some arm limbs of circle and square type.


loftShapeStart/End

enum | Pick the start (lever) or end (foot/pad) loft shape.

_images/leg_loftSwap.gif

loftList

enum datList | Option to set the loft shape per handle.

_images/arm_loftList.gif

loftSetup

enum | Pick the kind of loft setup you want

  • default | One shape for all handles
  • loftList | See above

loftDegree

enum | Linear/cubic loft

_images/limb_degree.gif

loftSides

int | Number of sides for the loft. Only visible with cubic mode.

_images/limb_loftSides.gif

loftSplit

int | Sub split on the loft

_images/loftSplit.gif

numShapers

int | The number of shapers for a given section or block to help define it

On Limb this acts as numSubShaper does on Segment

_images/limb_numControls.gif

Note

you must change setting and rebuild form to see changes.


numSubShapers

int | The number of sub shapers between each main shaper


Skeleton

numRoll

int | A main value for how many roll joints per segment of joints.


rollCount

int/datList | A datList chain of attributes to set the roll count per segment of our LIMB. Currently


Prerig

buildEnd

enum | If we want an end joint or not. Adds a handle to our count. For game work we often don?t want extra joints that don?t do anything. As an example with a finger, you don?t really need that last tip joint for skinning most of the time. This is for allowing that to be removed without affecting our setup.


conDirectOffset

float | Distance direct controls offset from surface


controlOffset

float | Distance main control shapes offset from surface


jointDepth

float | Distance joint dags and shapes inset from surface


numControls

int | The number of controls for a given block. Note, you must change setting and rebuild form to see changes.


Rig

Settings for the rig setup type.


buildSDK

enum | Whether you want sdk groups on

  • none | No sdk setup
  • dag | Sdk groups on controls
  • only | No rig structure, just direct controls and sdk groups (NOT FULLY IMPLEMENTED)

ikSetup

enum | What kinda of ik setup for this particular rigBlock

  • none | No IK
  • rp | Rotation plane setup
  • spline | Not fully implemented as ribbons work for the most part. Future proofing
  • ribbon | Uses our ribbon setup which has a myriad of options

ikBase

enum | The kind of ik base we want.

  • none | No special base setup
  • cube | Cube shape base (depreciating)
  • simple | Simple handle at the end
  • hips | Does some special setup to have have localized hip control on the segment

ikEnd

enum | The kind of ik end we want.

  • default | Simple ik end shape. Cube created at end of the ik chain
  • bank | bank setup added at the end of the block
  • foot | Assumes you will have at least a ball. Single Toe setup possible too
  • pad | Assumes animal like setup with a bank
  • hand | Future proofing for hand setup we want to do
  • tipBase | IK pivot at the second to last prerig handle
  • tipMid | IK Pivot at the mid point of the chain
  • tipEnd | IK Pivot at the end of the chain

foot The foot setup can be done with buildToe

_images/limb_footToe.gif

or not...

_images/limb_footNoToe1.gif

ikOrientToWorld

bool | Toggles whether to setup aim down closest axis setup to the ik controls of the rigBlock.

At rig setup, the last prerig handle is used to figure out the closest vector to a world axis. This rotation value is used as zero for that control and there is an extra setup to allow for non zero reset values on control's base transforum attributes.


numSpacePivots

int | number of space pivots to use for controls. When 0, they won't be added but constain groups will replace where those would have been


proxyDirect

bool | Whether to use proxyShapes for direct controls where possible


ribbonAim

enum |

  • none | just attach to the ribbon with no aim
  • stable | Stablized aiming with the out vector being another follicle on the surface
  • stableBlend | Blended aim down the chain where every joint except start/end blend their aim forward and back. This option sometimes gives better results

ribbonConnectBy(TESTING)

enum | How we want our rig dags to connect to our ribbon.

  • constraint | connect by constraint
  • matrix | NOT IMPLEMENTED

ribbonParam

enum |

  • fixed -Fixed attachment to our ribbon
  • floating | Float on the surface in an even distribution
  • blend | Add option to blend between two

settingsDirection

enum | Which direction from the settings targed position we want our settings cast relative to the joint axis.

  • up
  • down
  • out
  • in
_images/limb_settingsDirection.png

Note

On a left limb, the out /in would be reversed


settingsPlace

enum | Where we want this rigBlock's setting placed at rig time

  • start
  • end
  • cog | just use the cog shape. Used on default spine for example

spaceSwitch_direct

bool | Whether to setup space switching on direct controls

Not sure on the speed hit on this so have it off by default.


scaleSetup

bool | Whether to setup for scaling


squash

enum | Options for seeing up squash and stretch

  • none | no squash stretch setup
  • Simple | only use aim measure
  • Single | single channel measuring (out)
  • both | independent channels. Churro squash/stretch

squashExtraControl

bool | Whether to wire up ability to turn off squash stretch and set scale factor per joint


squashMeasure

bool |

  • None | no squash setup
  • arcLength | Use a curve to measure the length of the segment as it's more consistent than
  • pointDist | Per joint measuring on aim

squashFactorMax

float | Peak influence on squash and stretch on the segment chain. Most often 1


squashFactorMin

float | Minimum influence on the squash chain. Use 0 if you want the start and end to have to squash stretch from the


visMeasure

bool | Whether to show our measure nodes on our rigBlock.


Post

Settings for post processes.


loftReverseNormal

bool | Reverse the normal on the lofts. Because maya is consistently inconsistent with lofting. Between sessions. It's nutty.


proxyGeoRoot

enum | What kind and whether you want a proxy geo root

  • none | Nothing.
  • loft | Our current default
  • ball | Simple sphere
proxyNone proxyBall proxyLoft

States

The Morpheus Rig System is designed to push rigBlocks through states as we call them.

There are five states:

  • Define | Size, vectors, points in space
  • Form | Shaping the form of our proxy
  • Prerig | Points of articulation, shapes for rigging, more
  • Skeleton | Build our joints
  • Rig | Rig it, rig it!

Define

The define state is the barest of information for the block. What you will see will depend on the block type but you usually at least have a handle for the block root. You might see a number of visualizers:

  • Bounding Box | An open cube shape driven size wize by the baseSize attr on the rigBlock
  • Vector helpers | global up for the block module
  • Plane | visual plane for the block to see the center line

Main call

This is by far the easiest one. At most the define state should be a dag node and is the core node of our rigBlock.

Examples of things you might do here:

  • Reset transform data if desirable (like a master block)
  • Verify attribute alias, min/max, lock and hide

Results

  • A rigBlock node
  • Define handles
  • State nulls where necessary

Form

The form state is about shaping our proxy to give the rest of our processes the best picture of what it is we're working with and be able to generate appropriate shapes and proxy meshes later on.

Requirements

  • d_wiring_template | dictionary of data the state check calls look for to see if the state requirements are met
  • msgLinks | Message attributes to check for data
  • msgLists | cgm msgList attrs to check
  • form | The blockType's setup caller

Optional * templateDelete | There is a general shared call that works for most purposes but that call checks the rigBlocks module for this call for special case needs.

Main call

The form call pushes a block from define to form state

  • ""formNull** | A null to go under our rigBlock under which most of our form state items are parented for easy cleanup
  • noFormNull | For those things that can't be transformed. Lofts for example
  • Form handles | These are our proxy shaping handles and they are loosely connected to the subsequent prerig handles.
  • prerigLoftMesh | This is the result of lofting our shapers and is important to the rest of our calls

Results

  • Template null
  • noTransform null(sometimes)
  • Template handles
  • Template proxy mesh (usually)

Prerig

The prerig state is about joints, controls and prep for moving on to rig creation..

Requirements

  • d_wiring_prerig | dictionary of data the state check calls look for to see if the state requirements are met
  • msgLinks | Message attributes to check for data
  • msgLists | cgm msgList attrs to check
  • prerig | The blockType's setup caller

Optional

  • prerigDelete | There is a general shared call that works for most purposes but that call checks the rigBlocks module for this call for special case needs.

For example, turning back on overrides for the form state

Main call

The prerig call pushes a block from form to prerig state

  • Prerig Null | A null to go under our rigBlock under which most of our prerig state items are parented for easy cleanup
  • Prerig handles | These are our control handles which then have...
  • Joint Handles | These are the handles which will layout the joint chains for the given module
  • Joint loft mesh | This is the result of lofting our joint handles. It is for visualizing the joint chain position relative to the proxy without regard to the form handles

Results

  • Prerig null
  • Prerig handles
  • Joint loft mesh (usually)

Skeleton

The skeleton state is simply the joint creation state where our bind joints are created, oriented, named and connected.

Requirements

  • skeleton_build call | It needs to use the BLOCKUTILS.skeleton_connectToParent

Main call

The skeleton call pushes a block from prerig to skeleton state

  • Bind skeleton | Oriented, named and wired bind skeleton

Results

  • Joint chain

Rig

This is where we take all the information and bits we've laid out and make an actual rig. It's a multi call process.

Requirements

  • __l_rigBuildOrder__ - List of string calls for the rigFactory calls in the module for a successful rig build.

Main calls

The rig call pushes a block from skeleton to rig state. It's bit more complicated than what we've looked at before. First of all self for our calls is not our rig block but a rigFactory instance .

Instead of one call we break up or steps into separate calls as it makes troubleshooting much more easy than one behemoth call.

In general we still go through a series of specific actions regardless of the block type.

Things to remember

In order for a block to go to a given state, it's parent blocks must be at least that state. For example if you want to take an arm to rig, the spine must be rigged


Updating Blocks

See the post on the site


Terminology

Context

We use the term context in several places in our tools. Simply but it is those things which will be affected by any given action.

With mrsAnimate based on a given control selection you could be working in a context of control,part,puppet, with our without siblings/children/mirror.

  • self | selected - Only that selected block will be affected by contextual actions
  • self | active - Only the active block ...
  • self | below - Selected and children blocks
  • root | below - Gets root from selected, then root below

nameList

A string datList we use for having connectable and indexable string attributes to plug into multiple things - wrist being pushed to joints, dags, controls etc for naming.


Name Tags

We use a naming system in our tools and setups that allows an object to know what it should be named. It does this by getting it's name dictionary. Then that name dictionary is compiled to a given name based on core setting that can be changed.

We'll flesh this more out later.


msgList/datList

This was our answer to having index managed message lists. It is a managed system for handling message connections and other data lists (strings,floats,etc) in connectable indexed lists. It does this as a series of single message attributes sharing a base name and treated as a single list by our system. You'll see these calls all over our code base.

Why was it necessary to do msgLists?

Maya has a bug that comes up not infrequently in versions where multimessage connected objects duplicate their wiring even when you have index matters or other options set. When you need very specific data lists - say a joint chain and you don't want that list if joints getting messed up you need a solution. This was ours.

It seemed a better answer than accounting for the bug creeping up in different iterations of maya.

Last year we added the datList support mainly for name work but it's expanded some. For our MRS joint naming we use something called name tagging so that a given node is tagged in a way that when you mNode.doName() for example it is able to detect it's appropriate name by how it's tagged. Name's are inherited hierarchically and via connections.

This may be unwieldy at times but it's served it's purposes over the years. We'll go into more detail on these concepts when we get to a Workshop on making your own rigBlocks.


Mirroring

Our rigs utilize red9's mirroring paradigm for their setup which involves a series of attribute and mirror index values to determine how and in what order things are mirrored.

We use some language in our tools that would be helpful to understand:

  • Push | Push my values to whatever would be in my mirrorable context
  • Pull | Pull values from my mirror to me
  • Symmetry Left/Right | Make me symmetrical with the given side being the prime axis to make that symmetry happen.

Proxy Meshprioximus animaximus

The mesh that is generated from our rigblock lofts to create approximated versions of a given asset. Check the post for more info.


Rotate Plane

_images/prerig_snapHandlesToRotatePlane2.png

RP Plane

A plane as defined by the rotate plane handle to the rigblock root, then aimed at the end handle.

Used for snapping the prerig/joint handles to a consistent plane so that they might rotate over themselves in a chain rather than crookedly.