Wednesday, 7 March 2012

Python: Create Cluster from soft selection

Edit: Source now available on GitHub.

Get the script 
here.
or from creativecrash here.


All thanks to Brian Escribano for his softSelection() code that gathers the id and weights of the current soft selection (basically, all the hard work).
It was simple enough to apply that information to a new cluster.

Usage:
Extract and place script file into a maya script directory (or python path directory) and run with this
import ld_createSoftCluster as sc
sc.ld_createSoftCluster()

and thanks to Valen Wagner for the icon.

Update:
07/03/12 - 0.4.0
    Alters cluster position to match selection rather than influenced average.

Sunday, 4 March 2012

Showreel 2011-12

Latest work from previous project, Ha Ha Hairies, where I worked for Red Wire Media as the Character TD/Animator.



Reel Breakdown:

Overview:
Rigged all shown characters, scripts and GUI's.

Sequence 1 (00:00:10):
Rigged main character 'Kwiff';
- Rig fully scalable and modularly built to provide easy updating of rig if needed.
- Simple Nurbs-based selection GUI for easy interaction.

Sequence 2 (00:00:31):
Hybrid IK/FK spine for extreme posing and toony nature of show;
- Broken hierarchies to separate upper and lower posing and flexibility.
- Traditional FK control during rotation, controllable volume preservation during translation.
- Position and orient switching for full IK control.

Sequence 3 (00:00:39):
Stretchy, bendy, volume-preserving limbs;
- With custom foot-roll, banking and various pivoting attributes.

Sequence 4 (00:01:18):
Various scripts to assist posing and animation;
- Ik/Fk blending, with snapping between the two over a single frame or a range of frames.
- Fk setup to mirror live rotation.
- Script to mirror or flip any part of the rig, including entire poses.

Sequence 5 (00:01:31):
Animator-friendly finger controls;
- Setup to allow quick posing of fingers with 2 attributes, as well as individual control over each finger via attributes and individual controllers.

Sequence 6 (00:01:36):
Insert-blink script;
- Based on animator designs, for a time-saving script.


Sequence 7 (00:01:41):
Selection GUI;
- Interchangeable between full rig and facial controls.
- Varying levels of detail.

Sequence 8 (00:02:19):
Animator friendly facial rig;
- Minimal, joystick inspired controls with multiple functions to provide alot of interactivity with minimal effort.
- Joint and blendshape based, with interactivity between the controls for quicker, stronger posing.
- Tweaking controls for more specific expressions and fine-tuning.

Sequence 9 (00:02:44):
Test facial rig;
- Use of multiple, individually controllable deformers, built into the rig.
- FK beak with tweaking lip controls.
- Various deformers on expressive areas of the face.
- Re-postionable eye sockets.
- Detachable upper/lower head for extreme posing.

Sequence 10 (00:03:12):
Test facial rig - Deform test;
- All deformers work together, rather than prioritising over each other.
- Complete squash, stretching and deformation over the head rig whilst maintaining any pose, blendshape or joint-based.
- Whilst maintaining that important ability to scale.

Thursday, 23 February 2012

Mel: ld_animToCurve - create nurbs curve from moving objects or verts

Download the script directly, here (follow link and place it in maya's script directory)
or from creativecrash here.




Creates a nurbs curve for each selected object and/or vert over a series of frames (like a motionTrail, but without the motionTrail bit).

Works using xforms - so object could be skinned, constrained, driven by expressions etc,
Simple to cleanup - just rebuild the curve,
Simple to use - select the objects and/or verts you want and execute using ld_animToCurve ;

Useful for quickly putting together complex shapes or tracking a vert's/object's position.


Updates:
07/03/12:  0.6.0
    Fixed issue selecting some verts.
                 0.7.0
   Added poly faces - now requires modified version of owen burgess' 2009 script "getfacecenters.py" (included).


Tuesday, 21 February 2012

Mel: Query part of a string, given its index and separator: PART 3

Update from PART 2.
Thanks to Viktoras Makauskas for the suggestions and link.
// get an item from a string given the string, separator and index range // ld_getName "L_test_me_out_bind_jnt" "_" 2 -2 ; global proc string ld_getName(string $obj,string $separator,int $start,int $end) { string $buffer[],$name ; int $numTokens=`tokenize $obj $separator $buffer` ; if($start<0) $start=$numTokens+$start ; if($end<0) $end=$numTokens+$end ; if($start<0 || $start>=$numTokens || $end<0 || $end>=$numTokens || $start>$end) return "" ; $name=$buffer[$start] ; for($n=($start+1);$n<=$end;$n++) $name+=$separator+$buffer[$n] ; return $name ; }
Changes include:
  1.  Separating the indexing to individual ints instead of a string that needs to get split.
  2.  Using the indexes to specify the token, not the separator.
  3.  More error checking.
Main difference is 0 -1 will now return the entire string rather than all but the last token (as it does in Python), mainly for functionality due to the removal of the colon. Can still return one item using the same int (ie the last token would be -1 -1).

Monday, 20 February 2012

Mel: Query part of a string, given its index and separator: PART 2

Update to previous post (here), needed to grab a range of items from a string given a separator and index/range (supports reverse and extended indexing).
I do have a horribly sneaky suspicion there is already a built in command for this...
Will work with ranges given as "0", "-1", "0:","-2:", ":2", ":-2", "1:3" and "-3:-1" etc.
// get an item from a string given the string, separator and index number/range as string (supports reverse indexing) //ld_getName "L_test_me_out_bind_jnt" "_" "2:-1" ; global proc string ld_getName(string $obj,string $separator,string $index) { string $mulBuffer[],$indBuffer[],$name ; int $range[],$start,$end ; tokenize $index ":" $mulBuffer ; $range[0]=int($mulBuffer[0]) ; if(startsWith($index,":")) { $mulBuffer[1]=$range[0] ; $range[0]=0 ; } else if(endsWith($index,":")) $mulBuffer[1]=-1 ; tokenize $obj $separator $indBuffer ; $start=$range[0] ; if($range[0]<0) $start=size($indBuffer)-(abs($range[0])) ; if(size($mulBuffer)>1) { $range[1]=int($mulBuffer[1]) ; $end=$range[1] ; if($range[1]<0) $end=size($indBuffer)-abs($range[1]) ; if($end>(size($indBuffer)-1)) return "" ; $name=$indBuffer[$start] ; for($n=($start+1);$n<$end;$n++) $name+=$separator+$indBuffer[$n] ; } else { if($start<0) $name=$indBuffer[size($indBuffer)-int(abs($start))] ; else $name=$indBuffer[$start] ; } return $name ; } Would appreciate any feedback (I know how much simpler this is in python, was curious how simple it was to do in mel).
Python, i think, would handle like this:
"L_test_me_out_bind_jnt".split("_")[2:-1]

Thursday, 16 February 2012

Mel: Query part of a string, given its index and separator

UPDATE: Updated version with better functioning here.
I realised how often I was using a mix of the tokenize, startString and endString to get sections of a string, whether the start or end (various ways) or the middle (ie getting the side "L_*" or "R_*" or type of object "*_ctrl" "*_bind_jnt") etc, and I loved the way python handles this instead (especially the reverse indexing) so I come up with this.
global proc string ld_getName(string $obj,string $separator,int $index) { string $buffer[],$name ; tokenize $obj $separator $buffer ; if($index<0) $name=$buffer[size($buffer)-int(abs($index))] ; else $name=$buffer[$index] ; return $name ; } //ld_getName "L_test_me_out_ctrl" "_" -1 ;
EDIT: Changed positive indexing to match 0 = start, -1 = end

Saturday, 4 February 2012

Correctional blendshapes

I always had nightmares creating correctional blendshapes for rigs, having to work on the duplicated default mesh whilst watching the result mesh update (still trying to get over how I ever did this on a single 15" monitor...),
and then I found out how blendshape weights aren't limited from 0 to 1... and less than 0.

Now creating correctional blendshapes is far more enjoyable and takes up much less time, using a very simple setup.

Its actually very basic math (the way I see it anyways)
a + b = c
which therefore means...
b = c - a
so if "a" was a pose, "b" was its correction, and "c" the result of both. Now if you take the pose away from the result, your left with... the correction!

Corrective blendshape wise, you need to put your character into its pose you want to correct,

duplicate the mesh and create the correction ("b"),

duplicate the mesh orginal mesh off again (to get "a")

Then you duplicate the mesh with no deformations on it (as you would creating a normal blendshape), and assign the pose mesh and the corrective mesh ("a" + "b"). You finally want to turn on the correction blend weight to 1, and the pose blend weight to -1.

Your then left with just the correction, which you duplicate off and apply as a corrective blendshape target for you character.

This can be taken so much further to do live pose updates (above is all automated), but I wont go into that yet.

I hope this helps!