## Sloppy pyramid worm

February 7th, 2009A growing pyramid worm, with faces and corners aligned, mostly. It doesn’t line up exactly, and I’m not sure if that’s because of the shape of the pyramid or my dodgy code.

It’s easy to find out how far away something is, but how do you tell left from right? Things I thought I knew, until I tried to explain them. I may have to resort to particle physics.

MEL code follows…

//---start--- //find the center of a face proc vector centerOfFace(string $face) { // get locations of all vertices in an array 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); } vector $averagePos = <<$pos[0], $pos[1], $pos[2]>>; return $averagePos; } //given three distances, get angle - law of cosines proc float getAngle(float $distance) { //cos angle c = a^2+b^2-c^2/2ab $cSquared = `pow $distance 2`; //a and b in this case are both 1 $cosAngleC = (2-$cSquared)/2; //fix more sloppiness if ($cosAngleC < -1) {$cosAngleC = -1;} //solve for angle with arccosine, in degrees $degrees = `acosd $cosAngleC`; //get angle to closest corner $deg2 = $degrees % 120; return $deg2; } //get distance between two vertices proc float getDistance(string $vertA, string $vertB) { //get location of both vertices $aLoc = `xform -q -ws -t $vertA`; $bLoc = `xform -q -ws -t $vertB`; //get distance with a temporary distanceDimension $distObj = `distanceDimension -sp $aLoc[0] $aLoc[1] $aLoc[2] -ep $bLoc[0] $bLoc[1] $bLoc[2]`; float $dist = `getAttr $distObj.distance`; //cleanup $distObj = firstParentOf($distObj); delete $distObj; delete "*cator*"; return $dist; } proc doit() { //make a 3-sided cone and select it select `polyCone -r 1 -h 1.414214 -sx 3 -n "pCone1"`; //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; //turn off constraint warnings cycleCheck -e off; for ($i=0; $i<500; ++$i) { //select cone $old = `ls -sl`; //select a random face that isn't the base int $r = rand(3)+1; $selectedFace = ( $old[0] + ".f[" + $r + "]" ); select $selectedFace; //instance cone and move to face select `instance $old`; $new = `ls -sl`; vector $fc = centerOfFace($selectedFace); xform -a -t ($fc.x) ($fc.y) ($fc.z) $new; //align instance to face with a temporary normal constraint string $tmpConst[] = `normalConstraint -aim 0 1 0 $selectedFace $new`; delete $tmpConst[0]; //pick a vertex on each cone $newVertex = $new[0]+".vtx[0]"; // 0 is on the base $oldVertex = $old[0]+".vtx[3]"; // 3 is the tip //until i can tell left from right, repeat until it works float $angle = 60; // start with a non-zero number while ($angle > 1) { // 1) get distance between two vertices float $dist = getDistance($newVertex, $oldVertex); // 2) get angle between two vertices $angle = getAngle($dist); // 3) rotate the instance to align the corners xform -r -os -ro 0 $angle 0 $new; } //animate visibility setKeyframe -attribute "visibility" -v 0 -t 0 $new; setKeyframe -attribute "visibility" -v 1 -t ($i+1) $new; select $new; } cycleCheck -e on; } doit(); //---end---« previously: Aligned faces pyramid worm | Home | next: Something I Learned Today »