Archive for April, 2016

So, finally wrapped up my work for Morpheus 2 in regards to the wrap setups. As you can see from the last two trips on the rabbit trail(Step 1, Step 2), this wasn’t exactly a simple process.

The point of all of this is to be able to bake blendshapes reliably to nonconforming geo while affecting only the regions we want without having to go in and tweak things by hand. This will prove more and more useful as customization option expand. Why bother with this? Wrap deformers are exceedingly slow. Being able to replace them with skinning data and copying blendshapes between meshes will make your animations play faster and feel more interactive. The final solution was to create proximity geo which is localized to the area I want to affect the nonconforming target mesh. The proximesh is wrapped to the base driver and the target is wrapped to the proximesh.

target –[wraps to]—>> proximesh –[wraps to]–>> base

Here’s a general breakdown of the baking function:

Given a source mesh that has the blendshapes and a nonconforming target mesh we want them on…

Go through all blendshape channels on the source mesh and…

Get their connections/values

Break all connections/zero values so we have clean channels to push our specific shapes to our target mesh

Generate a proximesh of the source with the area we want influencing our nonconforming mesh

Generate a duplicate target mesh so we’re not messing with that mesh

Wrap the proximesh to the source mesh

Wrap the duplicate target mesh to the base mesh

Go through all the blendshape channels on the source mesh and…

Turn a channel on

Duplicate our wrapped target mesh to create a new mesh with the blendshape data on it pushed through by the wrap

If we’re going to cull no change shapes – check each generated shape against the target mesh to figure out when are not moving any verts and delete those offenders

Go through all the original blendshape channels again and rewire them as they were before our function

Delete the wraps and temporary geo

If desired, create a new blendshape node with our final list of baked targets on our nonconforming base mesh

If desired wire the new blendshape node to match the original one we baked from so the channels follow one another.

Easy peasy:)

Functions created while working through it:

cgm.lib.deformers

proximityWrapObject — This was the solution in the end to getting rid of movement in the mesh in areas I didn’t want affected.

influenceWrapObject — See step one above. Dead end but might prove useful in the future

bakeBlendShapeNodesToTargetObject — Greatly expanded this during this little journey

Added cullNoChangeGeo — removes baked targets that don’t move the base mesh within the given tolerance

cgm.core.lib.geo_Utils

is_equivalent — Function comparing points of to pieces of geometry to see if their components match in object space. Useful for culling out empty blendshape targets that have been baked. Supports tolerance in checking as well

get_proximityGeo — In depth function for returning geo within range of a source/target object setup. Search by boundingbox and raycasting to find geo within the source. Can return objects,faces,edges,verts or proximity geo which is new geo from the targets that corresponds to the search return

Lessons Learned for wraps in general

The maya command call to create a node is mc.CreateWrap (in 2011 at least). I hope later versions made it easier as

The object you wrap your target two gets two attributes (dropoff and smoothness) that dicatate how the wrap on your target is affected. No idea why it took me this long in maya to notice that in the docs.

Simply using Maya wrapDeformer to wrap an object to another when the object to be wrapped doesn’t conform to the target geo is a bad idea. You’ll get movement in your wrap geo where you don’t want it.

So the rabbit trail from over the weekend proved to not be the answer to my original problem as hoped. Namely I was still getting geo movement from far off regions when baking blendshapes to non-similar geo (think a sphere placed on a body).

As such, my next plan to resolve this was to create a specific conforming geo piece to wrap to then wrap my nonconforming object to. To do this, I need a way to find the geo closest to my geo I wanted to transfer the blendshapes too and so wrote a new function for this that would:

Search target geo against a source geo piece to find geo from each target within the source by two methods:

boundingBox.contains – by vert

rayCasting – by the compass vectors to make sure it is completely within the sourceObject

Translate that data to verts,edges, faces

Have a method to expand that data:

selection traversing

softSelection radius

Lessons learned:

bounding box checking is much much faster so use that mode unless you just have to have a more precise idea of what verts are inside the mesh.

Not a lot of specific info I could find on some of these concepts and so wanted to share to save someone else time and deadends

Here’s part one of this issue which is housed at cgm.core.lib.geo_Utils.get_contained. There are too many dependencies to include them all but you can get this gist from the code.

On yet another rabbit trail of problem solving on Morpheus 2.0, I came across an issue where wrap deformers weren’t working as needed. Namely transferring blendshapes from one mesh to another when the shape of the target mesh wasn’t like the original. Even geo changes in regions no where near the ‘to bake’ geo were affecting it.

So did some googling and came across a concept I’d not used before – namely using a mesh to deform another with a skinCluster.

Neat, so how do we do it?

Get your target and source mesh ready

Create a joint and skinCluster your target mesh to it

Add the driving mesh to the skinCluster with the useGeometry flag ( sample code for this line below).

polySmoothness flag. This controls the smoothness of the mesh deformation of the target mesh.

A polySmoothness of 0 is the closest to a standard wrap deformer

In my initial testing I found that this flag could only be set consistently on creation. Editing the flag could push the smoothness up but not down (in 2011 at least).

Make sure the useComponents attribute on the skinCluster is set to True. If you don’t see the deformation doing anything this is the likely culprit.

I wrote a script to set this up but it’s still wip. It’s a function found here: cgm.lib.deformers.influenceWrapObject. Because of the issue noted in step 3.2, I added the polySmoothness as a creation flag.

This method of wrapping is much more localized than wrap deformers when the mesh isn’t close AND provides an easy way to paint weights for the deformation.