// crowdSystem.mel // from Chapter 18, Example 4 of MEL Scripting for Maya Animators // by Mark R. Wilkins and Chris Kazmier // Copyright 2003, Morgan Kaufmann Publishers // createCrowd // ___________ global proc createCrowd(int $vNumber, int $gforces, int $obst) // Bring in ints and string from interface. { // Vehicle creation for crowd system. // Create a master crowdSolver for all Vehicles. rigidSolver -create -current -name crowdSolver -velocityVectorScale 0.5 -displayVelocity on; setAttr crowdSolver.allowDisconnection 1; // Get total number of Vehicles from interface options. int $FvNumber; int $LvNumber; switch ($vNumber) { case 10: $FvNumber = 8; // Followers $LvNumber = 2; // Leaders break; case 20: $FvNumber = 18; // Followers $LvNumber = 2; // Leaders break; } if ($gforces == 1) makeGforces; // Check Global Forces option. // Basic Vehicle model type: follower //____________________________ for ($i = 0; $i < $FvNumber; $i++) { polyCube -name ("vehicleF_" + $i) -width 2 -height 2.5 -depth 2; //Add a Vehicle force field for follower. radial -position 0 0 0 -name ("vehicleFForce_" + $i) -magnitude 50 -attenuation 0.3 -maxDistance 8.0; parent ("vehicleFForce_" + $i) ("vehicleF_" + $i); hide ("vehicleFForce_" + $i); // Make the Vehicle a Rigid Body with random placement. rigidBody -name ("rigidVehicleF_" + $i) -active -mass 1 -bounciness 0 -damping 1.5 -position (rand(-70,70)) 0 (rand(-70,70)) -impulse 0 0 0 -standInObject cube -solver crowdSolver ("vehicleF_" + $i); disconnectAttr ("rigidVehicleF_" + $i + "ry.output") ("vehicleF_" + $i + ".rotateY"); disconnectAttr ("rigidVehicleF_" + $i + "rx.output") ("vehicleF_" + $i + ".rotateX"); disconnectAttr ("rigidVehicleF_" + $i + "rz.output") ("vehicleF_" + $i + ".rotateZ"); // Create expression for VehicleF with a random multiplier added to the expression. float $randX = rand(-3,3); float $randZ = rand(3,-3); $expString = "// Set wander motion of vehicle and add random multipliers.\n"; $expString += ("rigidVehicleF_" + $i + ".impulseX"); $expString += " = sin(time * "; $expString += ($randX); $expString += ");\n"; $expString += ("rigidVehicleF_" + $i + ".impulseZ"); $expString += " = (noise(time) * "; $expString += ($randZ); $expString += ");\n\n"; $expString += "// Set orientation of Vehicle according to the velocity direction.\n"; $expString += "float $fVel" + $i + "[];\n"; $expString += "$fVel" + $i +" = `getAttr rigidVehicleF_" + $i + ".velocity`;\n\n"; $expString += "vehicleF_" + $i + ".rotateX = 0;\n"; $expString += "vehicleF_" + $i + ".rotateY = atan2d( $fVel" + $i + "[0], $fVel" + $i + "[2] );\n"; $expString += "vehicleF_" + $i + ".rotateZ = 0;\n"; expression -s $expString -name ("wanderF_exp" + $i) -alwaysEvaluate true -unitConversion all; } // End of Follower creation. // Basic Vehicle model type: Leader //_________________________________ for ($i = 0; $i < $LvNumber; $i++) { polyCube -name ("vehicleL_" + $i) -width 5 -height 3.5 -depth 5; //Add a Vehicle force field for leader. radial -position 0 0 0 -name ("vehicleLForce_" + $i) -magnitude 50 -attenuation 0.3 -maxDistance 8.0; parent ("vehicleLForce_" + $i) ("vehicleL_" + $i); hide ("vehicleLForce_" + $i); // Add leader field radial -position 0 0 0 -name ("vehicleGlobalLeadForce_" + $i ) -magnitude -1 -attenuation 0.2 -maxDistance 50; parent ("vehicleGlobalLeadForce_"+ $i) ("vehicleL_" + $i); hide ("vehicleGlobalLeadForce_"+ $i); // Make the Vehicle a Rigid Body with random placement. rigidBody -name ("rigidVehicleL_" + $i) -active -mass 1 -bounciness 0 -damping 1.5 -position (rand(-70,70)) 0 (rand(-70,70)) -impulse 0 0 0 -standInObject cube -solver crowdSolver ("vehicleL_" + $i); disconnectAttr ("rigidVehicleL_" + $i + "ry.output") ("vehicleL_" + $i + ".rotateY"); disconnectAttr ("rigidVehicleL_" + $i + "rx.output") ("vehicleL_" + $i + ".rotateX"); disconnectAttr ("rigidVehicleL_" + $i + "rz.output") ("vehicleL_" + $i + ".rotateZ"); // Create expression for VehicleL with a random multiplier added to the expression. float $randX = rand(-3,3); float $randZ = rand(3,-3); // Changed $fVel[ ] to $fVelL[ ] in the expression. $expString = "// Set wander motion of vehicle and add multipliers.\n"; $expString += ("rigidVehicleL_" + $i + ".impulseX"); $expString += " = sin(time * "; $expString += ($randX); $expString += ");\n"; $expString += ("rigidVehicleL_" + $i + ".impulseZ"); $expString += " = (noise(time) * "; $expString += ($randZ); $expString += ");\n\n"; $expString += "// Set orientation of Vehicle according to the velocity direction.\n"; $expString += "float $fVelL" + $i + "[];\n"; $expString += "$fVelL" + $i +" = `getAttr rigidVehicleL_" + $i + ".velocity`;\n\n"; $expString += "vehicleL_" + $i + ".rotateX = 0;\n"; $expString += "vehicleL_" + $i + ".rotateY = atan2d( $fVelL" + $i + "[0], $fVelL" + $i + "[2] );\n"; $expString += "vehicleL_" + $i + ".rotateZ = 0;\n"; expression -s $expString -name ("wanderL_exp" + $i) -alwaysEvaluate true -unitConversion all; } // End of Leader creation. // Connect the fields nested loops. // ________________________________ for ($i = 0; $i < $LvNumber; $i++ ) { // Connect Leaders to Followers both fields. for ( $j = 0; $j < $FvNumber; $j++) { connectDynamic -fields ("vehicleLForce_" + $i) ("rigidVehicleF_" + $j); connectDynamic -fields ("vehicleGlobalLeadForce_" + $i) ("rigidVehicleF_" + $j); } } for ($i = 0; $i < $FvNumber; $i++) { // Connect Followers to Leaders for ($j = 0; $j < $LvNumber; $j++) { connectDynamic -fields ("vehicleFForce_" + $i) ("rigidVehicleL_" + $j) ; } } // Connect same type Vehicles to each other. Disconnect Vehicle from itself. for ($i = 0; $i < $LvNumber; $i++) { // Connect Leaders to Leaders for ($j = 0; $j < $LvNumber; $j++) { connectDynamic -fields ("vehicleLForce_" + $i) ("rigidVehicleL_" + $j) ; } connectDynamic -delete -fields ("vehicleLForce_" + $i) ("rigidVehicleL_" + $i); } for ($i = 0; $i < $FvNumber; $i++) { // Connect Follower to Followers for ($j = 0; $j < $FvNumber; $j++) { connectDynamic -fields ("vehicleFForce_" + $i) ("rigidVehicleF_" + $j) ; } connectDynamic -delete -fields ("vehicleFForce_" + $i) ("rigidVehicleF_" + $i); } // Connect the Global Forces to both types of Vehicles if option is on. if ($gforces == 1) { string $compass[4] = { "N", "S", "E", "W" }; for ($i = 0; $i < $LvNumber; $i++) { for ($c = 0; $c < size($compass); $c++) { connectDynamic -fields ("Gforce" + $compass[$c]) ("rigidVehicleL_" + $i); } } for ($i = 0; $i < $FvNumber; $i++) { for ($c = 0; $c < size($compass); $c++) { connectDynamic -fields ("Gforce" + $compass[$c]) ("rigidVehicleF_" + $i); } } } // Build Obstacles if option is selected. if ($obst == 1) collectObstacles; // Disable warning. cycleCheck -e off; } // End of createCrowd proc // Build Obstacles //__________________ global proc collectObstacles() { global string $collectObjects[]; // Declare global array for Obstacles. if (size($collectObjects) == 0) { warning "No obstacle objects were selected."; } else { for ( $i = 0; $i < size($collectObjects); $i++) { rigidBody -passive -name ($collectObjects[$i] + "RigidB" + $i) -bounciness 2.0 ($collectObjects[$i]); } } } // End of collectObstacles proc // Make Global Forces with an interface. //______________________________________ global proc makeGforces() { // Edit the matrix for position changes. matrix $gFp[4][3] = << 0, 0, -150; 0, 0, 150; 150, 0, 0; -150, 0, 0 >>; string $compassForce[] = {"N", "S", "E", "W"}; for ($i = 0; $i < 4; $i++) { radial -name ("Gforce" + $compassForce[$i]) -position $gFp[$i][0] $gFp[$i][1] $gFp[$i][2] -m 0 -att 0; hide ("Gforce" + $compassForce[$i]); } // Set flag in createCrowd for the dynamic hookups. // Launch window control if (`window -exists GforceWin`) // If the window is there, delete and create new. deleteUI -window GforceWin; string $window = `window -t "Global forces control" -w 450 -h 150 GforceWin`; columnLayout; floatSliderGrp -label "Force north" -field false -minValue 0.0 -maxValue 0.3 -value 0.0 magForceN; floatSliderGrp -label "Force south" -field false -minValue 0.0 -maxValue 0.3 -value 0.0 magForceS; floatSliderGrp -label "Force east" -field false -minValue 0.0 -maxValue 0.3 -value 0.0 magForceE; floatSliderGrp -label "Force west" -field false -minValue 0.0 -maxValue 0.3 -value 0.0 magForceW; // Connect the sliders to the fields magnitude. // Swap control sliders with fields. connectControl magForceN GforceS.magnitude; connectControl magForceS GforceN.magnitude; connectControl magForceE GforceW.magnitude; connectControl magForceW GforceE.magnitude; showWindow $window; } // End of makeGforces proc // Main // ____ global proc crowdMain() { global string $collectObjects[]; if (`window -exists crowdWin`) { confirmDialog -t "Already running!" -m "Please close Crowd System window and create a New Scene"; } else { $collectObjects = `ls -sl`; crowdSystem; } } //Window launch //________________ global proc crowdSystem() { window -title "Crowd System" -widthHeight 300 200 crowdWin; string $form = `formLayout`; string $txt = `text -label "Number of Vehicles"`; string $collection = `radioCollection`; string $radiob1, $radiob2; $radiob1 = `radioButton -label "10" -onCommand "$vNumber = 10"`; $radiob2 = `radioButton -label "20" -onCommand "$vNumber = 20"`; setParent ..; setParent ..; string $txtOB = `text -label "Obstacles"`; string $collection2 = `radioCollection`; string $radiob3, $radiob4; $radiob3 = `radioButton -label "On" -onCommand "$obst = 1"`; $radiob4 = `radioButton -label "Off" -onCommand "$obst = 0"`; setParent ..;setParent ..; string $txtGF = `text -label "Global Forces"`; string $collection3 = `radioCollection`; string $radiob5, $radiob6; $radiob5 = `radioButton -label "On" -onCommand "$gforces = 1"`; $radiob6 = `radioButton -label "Off" -onCommand "$gforces = 0"`; setParent ..; setParent ..; radioCollection -edit -select $radiob1 $collection; radioCollection -edit -select $radiob4 $collection2; radioCollection -edit -select $radiob6 $collection3; // Place Vehicle options formLayout -edit -attachForm $txt "top" 20 -attachForm $txt "left" 70 $form; formLayout -edit -attachForm $radiob1 "top" 10 -attachForm $radiob1 "left" 20 -attachForm $radiob2 "top" 30 -attachForm $radiob2 "left" 20 $form; // Place environment options formLayout -edit -attachForm $txtOB "top" 80 -attachForm $txtOB "left" 80 $form; formLayout -edit -attachForm $radiob3 "top" 80 -attachForm $radiob3 "left" 150 -attachForm $radiob4 "top" 80 -attachForm $radiob4 "left" 190 $form; formLayout -edit -attachForm $txtGF "top" 110 -attachForm $txtGF "left" 63 $form; formLayout -edit -attachForm $radiob5 "top" 110 -attachForm $radiob5 "left" 150 -attachForm $radiob6 "top" 110 -attachForm $radiob6 "left" 190 $form; // Create buttons string $button1 = `button -label "Create"`; string $button2 = `button -label "Cancel"`; // Place buttons in the window formLayout -edit -attachForm $button1 "bottom" 10 -attachForm $button1 "left" 185 $form; formLayout -edit -attachForm $button2 "bottom" 10 -attachForm $button2 "right" 10 $form; // Add the commands to the buttons. button -edit -command ("createCrowd $vNumber $gforces $obst; deleteUI crowdWin;") $button1; button -edit -command ("deleteUI crowdWin;") $button2; showWindow crowdWin; } // End of crowdSystem proc