MRS Dev Branch Update – 04.02.2019

Current Sprint: MK Base

  • GitHub
    • Finaling
  • mrsAnimate
    • Time Context
    • Bugs/workflow
  • Workflow
    • Continuing to iterate


Important Changes

MRS DEV Branch Update –

  • This will stay on the MRSDev branch till we get a bit more testing. I’ll merge it when class prep is done.
  • Major rework to allow scale baking to the setup process. Old blocks will need a rebuild.

If you’re currently using MRS you’ll wanna look at these until I get a chance to update the docs.

  • Builder
    • Scroll list stretches rather than right side now
    • Added iter name to nameList editing/verifying
    • Contextual>Names>nameList | edit | added ability to work with nameLists along with the prerig validation in LIMB
    • To ScriptEditor | Right click menu on block to initialize the selected block to the script editor as mBlock
    • Connected build
    • bakeScale | Blocks should now generally have their scale baked down before mirroring. It really only has to happen for that to ensure proper mirror.
  • General
    • Block mirroring | reworked this call to allow for partial loading and sectioned loads so that if the source has more state controls than the mirror target, only up to the target mirror will load.
    • Loft Setup Polish | Tweaks to base loft setup to make them adhere to the loft curves more
    • Reverse normal detection | Added system to the geo generation to avoid messed up normals because Maya is oddly inconsistent in how these are calculated.
  • LIMB
    • Decent amount of iteration on the setups. Testging digitgrade and ungulate with 3,1,0 roll setups
    • new/renamed profiles
      • leg digitgrade front/rear
      • leg plantigrade
      • leg ungulate front/rear
      • leg unigrade – like  peg/stilt leg
  • Optimization
    • Proxy mesh creation has been sped up. From 9.6 sec to ~4 sec on a finger
      • New shapeParent_in_place method
      • Factored out rigFactory necessity
      • General optimizing
  • Core calls
    • GEO
      • is_reversed | check to see if geo is normal flipped. Still in testing
      • normalCheck | if reversed, flip the normals
    •  CURVES
      • connect | rework from join_shapes to not use components but the much better length along curve split
      • create_fromName| Updates
        • Added bakeScale to bake a scale value into a curve
        • Added baseSize to allow a custom baseSize to be set. So for example if you have a 5.5 unit obj you can have a library create at 1.0 and scale up


l = 'circle:wideUp:wideDown:widePos:wideNeg:diamond:square:squareRoundUp:squareRoundDown:squareUp:squareDown:squarePos:squareNeg:squircle:squircleDiamond:squircleUp:squircleDown:squirclePos:squircleNeg:triUp:triDown:triPos:triNeg:digit'
l = l.split(':')

for s in l:




Lofts inadvertently reversing normals on mesh creation is something I’ve struggled with a long time. I added a toggle on the blocks to handle it and it kinda worked but still would get lofts reversed at times.

Before pushing MRS to being beta-ish I wanted to resolve this better.

Solution #1

My solution was to create a is_reversed call to check geo and then a call to reverse the normals if it finds this to be True.

With a bit of trial and error it’s holding up.

Given a piece of geo we:

  1. Get a length of verts to check
  2. Provide our selves a check count (int(max * factorCheck) where factor check is how much coverage we want in our sampling
  3. Generate a cap (check * threshold) to know when we’ve met our target and can return True and not do them all when it’s obvious things are flipped
  4. Generate a seed of our verts to check | random.sample(xrange(max-1),check)
  5. Get a OM MFNMesh of that to be able to easily pull the vert normals

Then we start processing per vert:

  1. If we meet our hit cap, we bail and return True
  2. Get our normal and position
  3. Ray cast at only our current shape from that point along that normal and get any hits
  4. If we have hits
    1. If we have more than one hit and the second hit is not equivalent to our start position we add to our hit count
    2. Or if we have one hit and that hit isn’t equivalent to our start, we add to our count

During testing I was creating linear curves along the normals from the start points to see what was happening from some our our other normal vector stuff on this push. It was helpful.

Solution #2

After talking to Locke I tried a slight variant of this. We cut the cast number way down and instead used an odd/even count with the idea that if a ray is cast from inside a mesh you’ll an different count than outside.

It’s a good bit faster so we’re gonna try this for a bit and see if it holds up.


Don’t know who this might help but if it aids you, I’m glad.

  • cgm.core.lib.geo_Utils.is_reversed
  • cgm.core.lib.geo_Utils.normalCheck

Major Scale rework

There was an ongoing issue where if you scaled a block down and then tried to mirror it the mirror would be slightly off in ways that weren’t always apparent.

So, went back to the core and made some major changes to address this and improve overall setup.


New functionality to take the current blockScale value on a block and bake it down into the block.

In general what happens is this:

  • All the control have:
    • Their positions buffered
    • The scale values buffered
  • The scale on the rigBlock is set to 1
  • All the controls
    • Are snapped back to their expected position
    • they are scaled to match the previous
  • The rootShape is updated

Had to make a lot of changes to support this.

  • Control curve building now has the ability to not bake the scale values down do the control curve.
  • baseSize is no longer connecting to the handles at define state
  • New rootShape update call that nondestructively updates the rootShape size off of the baseSize
  • Most rigBlock curves now create from a base size of 1.0 and scaled rather than created at size and ‘baked’


Zero scale = bad

Had a curve that wasn’t snapping right. It was a flat curve so I didn’t see straight away that the scale was off. I was using some bounding box differential math to size it and in the end noticed that zero scale affects the orientation of a given dag.

More than 15 years doing this and never noticed before.

New Code Update Method

Some users were getting confused with the update tool so we’re offering a much simpler version.

  • Pull – specify a location and pull
  • Report – see a breakdown of the last 10 pushes on a branch

Lofts are annoying

Kept running into inconsistency with how maya was treating the loft u/v settings. Sometimes it u would be along the loft, sometimes across. My buddy Charles Wardlaw suggested checking the surface direction by looking at the surface itself to see if we need to reverse the direction.

  • Take the initial loft surface
  • Get the min/max u to find the mid value
  • Generate that curve from the surface
  • Get the first and second cvs from that and get a vector from them
  • Take the start loft curve and do the same for that
  • Take the cross product of those two vectors
  • If it is equivalent to 0, we reverse. If not, we let it go.

For now it’s holding up.

Implemented to cgm.core.mrs.lib.builder_utils.create_loftMesh

Puppet Mesh – getting a better loft options

Since we have the core data to make more use of the puppet mesh concept I wanted to try to expose that better for the end user.

There’s now a ability to build the cubic setup with history active to mess with. Changed the default puppet mesh to be the new methods.

New puppet mesh of the wolf

Puppet Mesh Better Caps

I’ve tried a few ways closing off the caps that don’t feel as good as they might.

  • polyCloseBorder which makes no extra geo for the foot to actually bend on a regular foot
  • Planarsrf is slightly better but doesn’t conform as well to the rest of the geo.

A few weeks ago when I was trying to keep rays from shoot through holes in my lofts I tried taking the start and end curve and collapsing them and the adding those in as the start and end lofts. This allows to fully wrap and have better form.

Another big perk to this is that by merging those collapsed verts at the start and end I can now use heatmap skinning which is giving much better base skinning data.

Some naming was duplicating cgm name tags and other wonkiness

  • Edited nameTools call to filter out more.
  • Retooled how blocks name. They now use their blockProfile in their naming
  • Added camelCase processing for the block profiles in the name

Down legs with rp setups

When we have lever setups with animal like legs going down, the base rotation on the lever handle feels off.

  • For the load base define dat
  • Get a pos aim from the lever pos along the up vector
  • Aim at that point with an up vector other the lever pos to the block root

Straight Limbs

When there is no bend in a limb you need a way to get preferred angles for them.

  • Initially tried with simple base value on the main rot axis channels
  • This works in some cases but not all
  • Need to circle back later and figure out a better way to do knowing the rp vector and the chain



It had the option to use aimAttrs on by default. This was causing some issues with control mirroring. It was a bad idea and now is off by default.

Segment fk/ik snapping not working

Snap targets weren’t being added. Fixed.

Proxy geo loft bases off

Noticed that in some extreme configurations the proxy slices were doing funky things. Dug into and and found that the planarSrf call was having trouble because we didn’t have tolerance set. It’s currently set to 10 to account for loft setup variety


Josh Burton

[MRS Project Lead | CG Monks] Josh is an animator turned TD who hails from Oklahoma, pre-undergrad in the Marine Corps, animation basics at Savannah College of Art and Design, cut his teeth in gaming and commercials before co-founding CG Monks and more recently the CG Monastery. The Morpheus Rigging System is a culmination of years of R&D and he is now thrilled to see what users can create, collaborate and expand on with this open source MRS platform.