if(! $spaced) { spaceGen 1000; expression -n "Physics" -s "for( $obName in $Phys_Obs){ if( $obName == \"\") { break;} Do_Gravity $obName;Do_Physics $obName;} Border;" ; $spaced ++; } /* expression -n "Physics" -s "for( $obName in $Phys_Obs){ if( $obName == "") { break;} Do_Gravity $obName;Do_Physics $obName; }" ; for( $obName in $Phys_Obs) { if( $obName == "") { break;} Do_Gravity $obName; Do_Physics $obName; Border; } */ global string $Phys_Obs[]; global int $Obs_Count; global int $spaced; /* This is a CRUCIAL section of the code it must be called for every object that will have my newtonian physics applied to it when it is called the syntax MUST be as follows " $Phys_Obs[ unique number ] = `Set_Physics "Object Name"`; " this is crucial to the expressions evaluating properly otherwise nothing will happen */ proc string Set_Physics(string $obName) { select -r $obName; addAttr -at "float" -ln "Mass" -sn "ms" -dv 1 -min 0.001 -k 1; addAttr -at "float" -ln "VelocityX" -sn "vx" -k 1; addAttr -at "float" -ln "VelocityY" -sn "vy" -k 1; addAttr -at "float" -ln "VelocityZ" -sn "vz" -k 1; addAttr -at "float" -ln "ForceX" -sn "fx" -k 1; addAttr -at "float" -ln "ForceY" -sn "fy" -k 1; addAttr -at "float" -ln "ForceZ" -sn "fz" -k 1; return $obName; } /* Here we are entering my procedural toolkit, This is where I have put all of my simple procedures so I can call them as needed by the other procedures, These are also very useful in relation to Mel coding in general becuse they supply very useful information from 'DAG' objects */ /* Get_Pos seems obvious, but serves a very useful function that I had difficulty dragging out of maya. It returns the center position of an object in WORLD SPACE cordinates, it is indepedant of objects being parented, or having there transformations frozen. I find this VERY USEFULL */ proc float[] Get_Pos(string $obName) { float $hold[] = `xform -q -ws -bb $obName`; float $carrier[]; $carrier[0] = (($hold[0] + $hold[3])/2); $carrier[1] = (($hold[1] + $hold[4])/2); $carrier[2] = (($hold[2] + $hold[5])/2); return $carrier; } /* Get_Dir returns a positive or negative for the direction that a pt is from an object I used this to decide what direction to add force when dealing with gravity and massive objects. */ proc string[] Get_Dir(float $ob[], float $pt[]) { string $dir[]; int $c; for($c = 0; $c < 4;) { if( $ob[$c] > $pt[$c]) { $dir[$c] = ("-"); } if( $ob[$c] < $pt[$c]) { $dir[$c] = ("+"); } $c ++; } return $dir; } /* Get_Dis returns the distance between two points, it is nessecary to acomplish newton's law of gravity I also intend to use this to test for collisions. */ proc float Get_Dis( float $obPos[], float $ptPos[]) { float $disHold; float $distance; // print ( ($obPos[0] * $ptPos[0]) + "\n"); $disHold = ( (($obPos[0] - $ptPos[0])*($obPos[0] - $ptPos[0])) + (($obPos[1] - $ptPos[1])*($obPos[1] - $ptPos[1])) + (($obPos[2] - $ptPos[2])*($obPos[2] - $ptPos[2]))); // print ($disHold + "\n"); if($disHold > 0) { $distance = sqrt($disHold); } else { $disHold = 0 - $disHold; $distance = sqrt($disHold); } // print ("Distance is " + $distance + "\n"); return $distance; } /* This is used to get the correct information for initializing semi-stable orbits It seems to work quite well and makes use of the Vis Viva Equation original of which is: v² = G×(m+M)×[(2÷r)-(1÷a)] However this one gave me problems so I parsed it down to: v² = G×(m+M)÷r */ proc float Get_Orbit(string $satName, string $wellName, string $wellAxi) { float $aHandler; float $oBoost; float $satPos[]; float $wellPos[]; float $dis; float $num; float $var; float $satMass = getAttr ($satName + ".ms"); float $wellMass = getAttr ($wellName + ".ms") * 280 ; float $G = 0.000000672; float $Gforce ; float $holdF; $aHandler = (getAttr ($satName + ".f" + $wellAxi))/( getAttr ($satName + ".ms") * 30); $satPos = `Get_Pos $satName`; $wellPos = `Get_Pos $wellName`; $dis = `Get_Dis $satPos $wellPos`; $Gforce = ( ($G * (($satMass * $wellMass)/($dis))) ); $var = $G * ($satMass + $wellMass) / ($dis + $dis ); $num = ( sqrt($var) ); $oBoost = $num ; return $oBoost; } /* This is really usefull I made it to help adjust the location of elements in the $Phys_Obs array This way I can remove things from it on the fly and then add stuff back to it */ proc removeElement(int $removed) { print ($removed + "\n"); int $count = 0; string $store[]; global string $Phys_Obs[]; global int $Obs_Count; $store = $Phys_Obs; for($count = $removed; $count < $Obs_Count; $count ++) { $Phys_Obs[$count] = ($store[$count + 1] ); } $Phys_Obs[$Obs_Count] = ""; if($Obs_Count != 0) { $Obs_Count --; } } /* This is where the CORE of my physics simulation exists, These two procedures are called by the expression constantly, they also call within them several procedures from the tool kit for easier coding. I had to spend quite a while getting this right and isolating all the bugs in the toolkit procs and the core physics procs. */ /* This is one of the most important ones it applies Newton Law of gravity to decide forces applied between massive objects. the hardest part was getting all the object information into the procedure and referencing it properly the formula is sublimely simple and I am mildly in awe of newton's insight. f = G×m×M÷d² */ proc Do_Gravity(string $obName) { global string $Phys_Obs[]; string $source; int $chex; float $obPos[]; float $ptPos[]; float $holdF; float $distance; float $G = 0.000000672; float $obMs; float $ptMs; string $Gdir[]; string $charCheck = "+"; for( $source in $Phys_Obs) { if($source == "") { break; } else if (isParentOf( $obName , $source )) { // print "bummer \n"; } else if($source == $obName) { // print "FooBar \n"; } else { print "woot \n"; $obPos = Get_Pos($obName); $ptPos = Get_Pos($source); // print( "I see " + $obPos[0] + " in $obPos 0 \n"); $obMs = getAttr ($obName + ".ms"); $ptMs = (getAttr ($source + ".ms") * 1000 ); // print( "I see " + $obPos[0] + " in $obPos 0 \n"); $Gdir = `Get_Dir $obPos $ptPos`; $distance = `Get_Dis $obPos $ptPos`; // print ( $obName + " Distance is " + $distance + "\n"); if ( $distance == 0) { $distance = 0.00000000001;} if($Gdir[0] == $charCheck) { $holdF = (getAttr ($obName + ".fx") / ($distance * $distance) ); setAttr ($obName + ".fx") ( $holdF + ($G * (($obMs * $ptMs)/($distance * $distance))) ); } else { $holdF = (getAttr ($obName + ".fx") / ($distance * $distance) ); setAttr ($obName + ".fx") ( $holdF - ($G * (($obMs * $ptMs)/($distance * $distance))) ); } if($Gdir[1] == $charCheck) { $holdF = (getAttr ($obName + ".fy") / ($distance * $distance) ); setAttr ($obName + ".fy") ( $holdF + ($G * (($obMs * $ptMs)/($distance * $distance))) ); } else { $holdF = (getAttr ($obName + ".fy")/ ($distance * $distance) ); setAttr ($obName + ".fy") ( $holdF - ($G * (($obMs * $ptMs)/($distance * $distance))) ); } if($Gdir[2] == $charCheck) { $holdF = (getAttr ($obName + ".fz") / ($distance * $distance) ); setAttr ($obName + ".fz") ( $holdF + ($G * (($obMs * $ptMs)/($distance * $distance))) ); } else { $holdF = (getAttr ($obName + ".fz") / ($distance * $distance) ); setAttr ($obName + ".fz") ( $holdF - ($G * (($obMs * $ptMs)/($distance * $distance))) ); } } } } /* This is where the law of inertia is applied as well as acceleration, forces and velocity. Without this code the entire thing will do NOTHING. This was a bit tricky to develope as the newtonian laws of intertia are not as easily interpreted as that of gravity. They have very few variables and I had to tweak and fiddle a bit to get this behaving right. */ proc Do_Physics(string $obName) { float $aHandler = 0; float $vHandler = 0; float $tHandler = 0; string $axi[3] = {"x", "y" , "z"}; string $let; for( $let in $axi) { if(($obName + ".f" + $let) != 0) { $aHandler = (getAttr ($obName + ".f" + $let))/( getAttr ($obName + ".ms") * 30); } $vHandler = getAttr ($obName + ".v" + $let); setAttr ($obName + ".v" + $let) ($aHandler + $vHandler); $tHandler = getAttr ($obName + ".t" + $let); setAttr ($obName + ".t" + $let) ($tHandler + $vHandler); } // print ("Physics Done For " + $obName + "\n"); };