/* NAME: dbSimpleRadial.mel VERSION: 1.0 CATEGORY: Dynamics FUNCTION: Creates initialVelocities and Spin on rigid bodies based on force and an origin point of a locator. USAGE: 1. Copy the dbConditionControl.mel into your Maya Scripts directory (Usually found in "My Documents\maya\\scripts\"). 2. In the Maya Script Editor, type in "dbConditionControl" AUTHOR: David Bokser E-MAIL: me@davidbokser.com WEBSITE: www.davidbokser.com */ global proc dbSimpleRadial() { string $originLoc[] = {"simpleRadialLocator"}; if(!`objExists "simpleRadialLocator"`) { $originLoc = `spaceLocator -p 0 0 0`; $originLoc[0] = `rename $originLoc[0] "simpleRadialLocator"`; } select $originLoc[0]; if(`window -q -exists simRadWin`) deleteUI -window simRadWin; string $window = `window -title "Simple Radial" -iconName "SimRad" -widthHeight 200 100 -menuBar true simRadWin`; menu -label "Help" -helpMenu true; menuItem -label "Help" -command ("srHelp()"); menuItem -divider 1; menuItem -label "About" -command ("srAbout()"); columnLayout -adjustableColumn true; floatSliderGrp -label "Force" -field true -minValue 0 -maxValue 100.0 -fieldMinValue 0 -fieldMaxValue 10000.0 -value 1 -cw 1 40 -cw 2 60 forceField; floatSliderGrp -label "Spin" -field true -minValue 0 -maxValue 100.0 -fieldMinValue 0 -fieldMaxValue 10000.0 -value 100 -cw 1 40 -cw 2 60 spinField; button -label "Ok" -command ("dbSimpleRadialDo()"); setParent ..; showWindow $window; window -edit -widthHeight 270 130 $window; } global proc dbSimpleRadialDo() { string $objs[] = `ls -sl`; string $radialCenter = "simpleRadialLocator"; float $force = `floatSliderGrp -q -v forceField`; float $spin = `floatSliderGrp -q -v spinField`; float $forceOrigin[] = `getAttr ($radialCenter + ".translate")`; float $distance[] = {}; for($obj in $objs) { string $rigidBody[] = `listRelatives -shapes -type rigidBody $obj`; if(`size($rigidBody)` > 0) { float $objCenter[] = dbBoundingBoxCenter($obj); $distance[`size($distance)`] = dbDistanceBetween($forceOrigin, $objCenter); } } $distance[`size($distance)`] = $force; float $normalizedDist[] = dbNormalize($distance, 0.0, 1.0); float $inversedDist[] = {}; // inverse the distance so objects that are closer have more force applied. for($n in $normalizedDist) { $inversedDist[`size($inversedDist)`] = 1 - $n; } int $i = 0; for($obj in $objs) { string $rigidBody[] = `listRelatives -shapes -type rigidBody $obj`; if(`size($rigidBody)` > 0) { float $objCenter[] = dbBoundingBoxCenter($obj); float $v[] = dbGetVector($forceOrigin, $objCenter); // Set Initial Velocities float $tr = rand(.9,1.0); setAttr ($rigidBody[0] + ".initialVelocityX") ($inversedDist[$i] * $v[0] * $force * $tr); $tr = rand(.9,1.0); setAttr ($rigidBody[0] + ".initialVelocityY") ($inversedDist[$i] * $v[1] * $force * $tr); $tr = rand(.9,1.0); setAttr ($rigidBody[0] + ".initialVelocityZ") ($inversedDist[$i] * $v[2] * $force * $tr); // Set Initial Spin $tr = rand(.9,1.0); setAttr ($rigidBody[0] + ".initialSpinX") ($inversedDist[$i] * $v[0] * $force * 20 * $tr * ($spin/100.0)); $tr = rand(.9,1.0); setAttr ($rigidBody[0] + ".initialSpinY") ($inversedDist[$i] * $v[1] * $force * 20 * $tr * ($spin/100.0)); $tr = rand(.9,1.0); setAttr ($rigidBody[0] + ".initialSpinZ") ($inversedDist[$i] * $v[2] * $force * 20 * $tr * ($spin/100.0)); $i++; } } } // How many licks it takes to get to the center of a bounding box? // Let's ask Mr. Owl. global proc float[] dbBoundingBoxCenter(string $obj) { float $bbox[] = `exactWorldBoundingBox -ignoreInvisible 1 $obj`; float $center[] = dbPointBetween({$bbox[0], $bbox[1], $bbox[2]}, {$bbox[3], $bbox[4], $bbox[5]}); return $center; } global proc float[] dbPointBetween(float $v1[], float $v2[]) { return {(($v1[0] + $v2[0])/2), (($v1[1] + $v2[1])/2), (($v1[2] + $v2[2])/2)}; } global proc float dbDistanceBetween(float $v1[], float $v2[]) { float $p = (($v2[0] - $v1[0]) * ($v2[0] - $v1[0])) + (($v2[1] - $v1[1]) * ($v2[1] - $v1[1])) + (($v2[2] - $v1[2]) * ($v2[2] - $v1[2])); float $d = sqrt($p); return $d; } global proc float[] dbNormalize(float $v[], float $normalMin, float $normalMax) { float $hi; float $low; float $normal = $normalMax - $normalMin; // find the highest and lowest numbers for($n in $v) { if($n == $v[0]) { $hi = $n; $low = $n; } if($n > $hi) $hi = $n; if($n < $low) $low = $n; } float $normalized[] = {}; float $translated[] = {}; for($n in $v) { $translated[`size($translated)`] = $n + $low; } if($low < 0) { $low = $low * -1; } if($low > $hi) { $hi = $low; } if($hi != 0) { $multVal = $normal / $hi; for($n in $v) { $normalized[`size($normalized)`] = ($n * $multVal) + $normalMin; } } else { error "Division by zero. You probably only gave a float array of zeroes. Why would you do such a thing?"; } return $normalized; } global proc float[] dbGetVector(float $v1[], float $v2[]) { float $val[] = {$v2[0] - $v1[0], $v2[1] - $v1[1], $v2[2] - $v1[2]}; $val = dbNormalize($val, 0, 1); return $val; } // HELP AND ABOUT WINDOWS global proc srHelp() { if(`window -q -exists srHelpWin`) deleteUI -window srHelpWin; string $window = `window -title "Help" -iconName "Help" -widthHeight 300 200 srHelpWin`; columnLayout -adjustableColumn true; scrollField -wordWrap true -text ("To use dbSimpleRadial:\n" + "1. Adjust the Force slider.\n" + "2. Position the simpleRadialLocator to the origin of the force. \n" + "3. Select all of the rigid bodies that will be affected. \n" + "4. Click OK.") -editable false -height 170; setParent ..; showWindow $window; window -edit -widthHeight 300 200 $window; } global proc srAbout() { if(`window -q -exists srHelpWin`) deleteUI -window srHelpWin; string $window = `window -title "About" -iconName "About" -widthHeight 300 200 srHelpWin`; columnLayout -adjustableColumn true; scrollField -wordWrap true -text ("dbSimpleRadial\n" + "Version 0.1\n\n" + "Written by David Bokser\n" + "dbokser@gmail.com") -editable false -height 170; setParent ..; showWindow $window; window -edit -widthHeight 300 200 $window; }