// // vmvInstanceObjects [name_of_the_particle_object] // // Prebaked simple solution for creating shatter/explosion type of effects with particle instancer - ie. script // replaces every selected object with a particle controlled instance what can be animated by using fields // or expressions or whatever. // // Workflow: // // Source the script. // // Select all the objects you want to instance and type vmvInstanceObjects explodeMe (for example). // // Script will create particle object with custom attributes feeded into instancer, and hide original // object geometry (which new home is in origin now). // // Simple runtime expression is controlling the rotation of instanced objects based on particles velocity. // Scalar attributes rotMult & massMult are used to tune animation. // // Fake creation expression is used, so animation should start around frame 0 (which of course can be changed). // If there seems to be a problem with the playback, adjust particle start frame accordingly // and/or edit the expressions... // // V-M Vasama 2007 / vm_vasama@hotmail.com // global proc vmvInstanceObjects( string $part ) { string $partName = $part; //pass argument string $object, $objects[]; int $i, $numObjects; float $objectIndex, $partPos[4]; //get number of selected objects $objects = `ls -sl`; $numObjects = size($objects); //create initial particle object particle -n $partName; //and add custom attributes //indexPP (float) addAttr -ln indexPP0 -dt doubleArray ( $partName + "Shape" ); addAttr -ln indexPP -dt doubleArray ( $partName + "Shape" ); setAttr -e -keyable true ( $partName + "Shape" + ".indexPP" ); //rotatePP (vector) addAttr -ln rotatePP0 -dt vectorArray ( $partName + "Shape" ); addAttr -ln rotatePP -dt vectorArray ( $partName + "Shape" ); setAttr -e -keyable true ( $partName + "Shape" + ".rotatePP" ); //rotateInitPP (vector) addAttr -ln rotateInitPP0 -dt vectorArray ( $partName + "Shape" ); addAttr -ln rotateInitPP -dt vectorArray ( $partName + "Shape" ); setAttr -e -keyable true ( $partName + "Shape" + ".rotateInitPP" ); //rotMultMin (scalar) addAttr -ln rotMultMin -at double ( $partName + "Shape" ); setAttr -e -keyable true ( $partName + "Shape" + ".rotMultMin" ); //rotMultMax (scalar) addAttr -ln rotMultMax -at double ( $partName + "Shape" ); setAttr -e -keyable true ( $partName + "Shape" + ".rotMultMax" ); //massMultMin (scalar) addAttr -ln massMultMin -at double ( $partName + "Shape" ); setAttr -e -keyable true ( $partName + "Shape" + ".massMultMin" ); //massMultMax (scalar) addAttr -ln massMultMax -at double ( $partName + "Shape" ); setAttr -e -keyable true ( $partName + "Shape" + ".massMultMax" ); //main loop: loop through selected objects and //assign particle at the center of each object //then move objects to origin and zero transforms for ( $i=0; $i < $numObjects; $i++ ) { //select current object $object = $objects[$i]; select $object; //freeze transformations makeIdentity -apply true -t 1 -r 1 -s 1 -n 0; //center pivot xform -cp; //get current particle wrld pos $partPos = `xform -q -rp ($object)`; //update index $objectIndex = $i; //calculate volume of the current object geometry float $bb[] = `xform -q -ws -bb $object`; float $x = abs( $bb[3] - $bb[0] ); float $y = abs( $bb[4] - $bb[1] ); float $z = abs( $bb[5] - $bb[2] ); vector $vv = <<$x, $y, $z>>; //get length of total vector, use this as the particle's mass float $vol = mag( $vv ) + 0.1; //emit particle to object position with attrs emit -object ($partName) -position $partPos[0] $partPos[1] $partPos[2] -attribute mass -floatValue $vol -attribute indexPP -floatValue $objectIndex; //move object to center because of the instancer createPrimitive nullObject; $loc = `ls -sl`; //snap align selected objects to locator (0 0 0) select $object; select -add $loc; align -atl -x Mid -y Mid -z Mid; //delete locator select $loc; delete; //freeze transformations of object select $object; makeIdentity -apply true -t 1 -r 1 -s 1 -n 0; //hide object HideSelectedObjects; } //save initial state of particles saveInitialState ($partName); //create instancer select $objects; select -add $partName; string $objectList; //build string with objects for ( $i = 0; $i < $numObjects ; $i++ ) { $objectList += " -object " + $objects[$i]; } //final launch pre-emptive strike command eval ( "particleInstancer -addObject" + $objectList + " -cycle None -cycleStep 1 -cycleStepUnits Frames -levelOfDetail Geometry -rotationUnits Degrees -rotationOrder XYZ -position worldPosition -age age -objectIndex indexPP -rotation rotatePP " + $partName ); //modify particle runtime expression //and create a fake creation expression just to be sure everything works string $runTime = "if ( frame <= 2.0 ) { \n" + " rotateInitPP = << rand( rotMultMin, rotMultMax ), rand( rotMultMin, rotMultMax ), rand( rotMultMin, rotMultMax ) >>; \n" + " mass *= rand( massMultMin, massMultMax ); \n" + "} else { \n" + " vector $vel = velocity; \n" + " vector $rot = rotateInitPP; \n " + " rotatePP += << $vel.x * $rot.x, $vel.y * $rot.y, $vel.z * $rot.z >>; \n" + "} \n" ; dynExpression -rbd -s $runTime ($partName + "Shape"); //set particle start frame to 0 to accommodate fake creation expression setAttr ( $partName + "Shape" + ".stf" ) 0.0; //set initial attributes setAttr ( $partName + "Shape" + ".rotMultMin" ) -1.0; setAttr ( $partName + "Shape" + ".rotMultMax" ) 1.0; setAttr ( $partName + "Shape" + ".massMultMin" ) 1.0; setAttr ( $partName + "Shape" + ".massMultMax" ) 1.0; //cheers print("\nDone.\n"); }