Friday, 26 October 2012

nCloth instances

I have been working on a confetti shot and wanted to use nCloth. I decided to use a particle emitter and to instance the nCloth object onto the particles - but how? If I were to simply assign the nCloth object to the instance, then each instance would be identical. I wanted to have a different starting point in the nCloth cache for each instance. Unfortunately Maya's instancer doesn't support this kind of connection. I tried to use an userScalarPP attribute along with a particle sampler to access the cacheStart attribute on the nCloth cache, but that didn't work.

Here's how I did it:

First cache the nCloth object

Export the nCloth as a sequence of OBJs. I used a python script called objsExporter_v2 from Christos Parliaros

Re-import the OBJ sequence using Dave Girard's objSequenceImporter

Use the imported OBJs to create an instancer with cycling set to On

On the particle object I setup a per-particle attribute; cyclePP and used this to select the correct OBJ in the sequence. For example, if there are 30 OBJs in your sequence, in the creation expression:


and in the Runtime before dynamics:

cyclePP=(cyclePP+1) % 30;

so the nCloth object will loop through the cache and start from the beginning at the end of the loop.

Tuesday, 3 January 2012

Maya Strands*

*OK, not exactly the same as Softimage ICE strands (which are great, by the way), but here is a way to get a very basic approximation.

I am basically taking Sigillarium's particle expression for making a uniform trail of particles and adding a line to take the seed particle's colour attribute and passing it to the emit command. This way, the trails have the same colour as the emitter particle, which is very handy if you are emitting from a surface and inheriting particle colour from that surface.

Here is the expression:

//runtime before dynamics

seed_particleShape.beforePosition = seed_particleShape.position;

//runtime after dynamics

string $trail_pt = "smoke_nParticle";

float $separ = seed_particleShape.separation;

vector $lastPos = seed_particleShape.beforePosition;

vector $pos = seed_particleShape.position;

vector $move = <<(($pos.x)-($lastPos.x)), (($pos.y)-($lastPos.y)), (($pos.z)-($lastPos.z))>>;

//get colour info

vector $rgb=seed_particleShape.rgbPP;

float $r=$rgb.r;

float $g=$rgb.g;

float $b=$rgb.b;

//get number of particles to emit per frame

int $num = ceil( mag( $move ) / $separ );

//loop !

if( $num != 0 ) {

vector $step = $move / $num;

for( $i = 1; $i <= $num; $i++ ) {

vector $newPos = $lastPos + $step*$i;

float $life = time - (1.0/25/$num * ($num-$i));

emit -o $trail_pt -pos ($newPos.x) ($newPos.y) ($newPos.z) -at rgbPP -vv ($r) ($g) ($b) -at "birthTime" -fv $life;



There are a couple of things to note:

The seed particle shape node has an extra attribute added - separation. This is a float value that determines the distance between each particle in the trail. The number you use depends on the scale of the scene and velocity of the seed particle. It's handy to have this variable on the shape node rather than in the expression.

There is a per-particle vector attribute called beforePosition, which stores a particle's position from the previous frame. This attribute needs to be created using the Add Attribute dialogue:

Also, note the variable $trail_pt in the expression. This is just the name of the trail particle object. Create this object before running the expression either by a 'particle' or 'nParticle' MEL command or by creating an emitter via the menus and deleting the emitter and leaving the particle object behind. Set the $trail_pt variable to the name of your trail particle object.

So, you can hopefully see that I have an image on a plane from which I am emitting some particles which are taking the colour from the plane. Those particles are then emitting more particles in a trail and inheriting the colour from the first particles.

Thanks to Sigillarium for the excellent expression. Please check the Sigillarium blog as it is outstanding and very clearly explains some difficult concepts.