## 50,000 Tetrahedrons

February 9th, 2009After some tweaking (including getting re-aquainted with the dot product) the generative code is faster and the geo is 25% lighter… in fact they’re not really tetrahedrons anymore. Actually, each of them is as much as it ever was, but more aren’t as many as they used to be.

Using that logic, I can reliably get up to about 50,000 iterations before Maya starts getting cranky. It only takes a couple of minutes, and here’s what I get:

MEL code follows:

//--start-- // find the center of a face proc vector centerOfFace(string $face) { // get locations of all the face's vertices float $pos[] = `xform -q -ws -t ($face)`; // get length of the array: # vertices * 3 int $posSize = size($pos); // put the average of all vectors into 1st vector for ($i = 0; $i < 3; $i++){ for ($j = $i + 3; $j < $posSize; $j += 3){ $pos[$i] += $pos[$j]; } $pos[$i] /= ($posSize / 3); } return <<$pos[0], $pos[1], $pos[2]>>; } //get angle between two vertices with respect to a third point proc float getAngle(string $vertA, string $vertB, vector $origin) { // get location of both vertices vector $aLoc = `xform -q -ws -t $vertA`; vector $bLoc = `xform -q -ws -t $vertB`; // normalize locations to the face center vector $aOrigin = <<$aLoc.x - $origin.x, $aLoc.y - $origin.y, $aLoc.z - $origin.z>>; vector $bOrigin = <<$bLoc.x - $origin.x, $bLoc.y - $origin.y, $bLoc.z - $origin.z>>; // use law of cosines via dot product float $dot = dotProduct( $aOrigin, $bOrigin, 1 ); float $angle = rad_to_deg(acos($dot)); //round answer down to two decimal places return (floor(($angle+.005)*100))/100; } proc doit() { // make a regular tetrahedron and select it select `polyCone -r 1 -h 1.414214 -sx 3`; // move its pivot point to the bottom face xform -rp 0 -0.707107 0; // move to origin and freeze xforms xform -t 0 0.707107 0; makeIdentity -apply true -t 1; //delete the bottom face to lighten the load $old = `ls -sl`; $selectedFace = ( $old[0] + ".f[0]" ); delete $selectedFace; //I'm leaving the safety on, you can add more zeros if you like for ($i=1; $i<500; ++$i) { // copy cone $new = `duplicate $old[0]`; // if ($i != 1) {parent -w $new;} // move to world space // pick a random face on $old that isn't the base int $r = rand(3)+1; $selectedFace = ( $old[0] + ".f[" + $r + "]" ); // move $new to selected face vector $fc = centerOfFace($selectedFace); xform -a -t ($fc.x) ($fc.y) ($fc.z) $new[0]; // aim $new at face with a temporary normal constraint string $tmpConst[] = `normalConstraint -aim 0 1 0 $selectedFace $new`; delete $tmpConst[0]; // pick a vertex on each pyramid $newVertex = $new[0]+".vtx[0]"; // 0 is on the base $oldVertex = $old[0]+".vtx[3]"; // 3 is the tip // get angle between two vertices $angle = getAngle($newVertex, $oldVertex, $fc); if ($angle > 0) { // if not already aligned // rotate $new to align the corners xform -r -os -ro 0 $angle 0 $new[0]; // check the result $angle2 = getAngle($newVertex, $oldVertex, $fc); // if still not aligned, go the other way twice if ($angle2 > 0) { $angle3 = $angle * -2; xform -r -os -ro 0 $angle3 0 $new[0]; } } $old = $new; } } doit(); print("done!"); //--end---« previously: Sloppy twisty worm | Home | next: Sloppy worm knot »