<body><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener('load', function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <div id="navbar-iframe-container"></div> <script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script> <script type="text/javascript"> gapi.load("gapi.iframes:gapi.iframes.style.bubble", function() { if (gapi.iframes && gapi.iframes.getContext) { gapi.iframes.getContext().openChild({ url: 'https://www.blogger.com/navbar.g?targetBlogID\x3d13215318\x26blogName\x3dezio@gsapp\x26publishMode\x3dPUBLISH_MODE_BLOGSPOT\x26navbarType\x3dBLACK\x26layoutType\x3dCLASSIC\x26searchRoot\x3dhttp://ezioatcolumbia.blogspot.com/search\x26blogLocale\x3den_US\x26v\x3d2\x26homepageUrl\x3dhttp://ezioatcolumbia.blogspot.com/\x26vt\x3d-9099282204773819064', where: document.getElementById("navbar-iframe-container"), id: "navbar-iframe" }); } }); </script>
ezio@gsapp

This is my blog while at the MSAAD program of the GSAPP of Columbia University. 1st post came with my arrival at NYC. e-mail: eb2283@columbia.edu, ezio@otn.gr, ezioblasetti@gmail.com 

Saturday, November 19, 2005

5:54 PM - slime script in MEL


follow comments for the entire script/....


Blogger ezio said...

/*
***************************************************************************

This script is an experiment on simulating agent behaviour and was produced
within the context of Cory Clarke’s "Algorithmic Morphology" course
(GSAPP Columbia University – Fall 2005). It was inspired by the
biology\slime project in StarLogo produced in MIT in 2004. The basic
idea that I tried to reproduce in 3d space was the one described here by
the authors of the StarLogo version:
”This project is inspired by the aggregation behavior of slime-mold cells.
It shows how creatures can aggregate into clusters using a very
decentralized strategy, without any "leader" involved.”
The script will create “tails” for the starting objects it is introduced
for and it will move them around dependent to several variables; eventually
the emergent behaviour of these objects will lead to a “meta-structure”.
This is also my introduction to scripting so I can see several ways of
re-writing it in terms of optimising or making it shorter. The script
produces a key framed timeline and the final product (hopefully) can be
viewed once the script has finished calculating. The first three global
procedures are directly borrowed form Cory’s scripts.

If you want extraordinary results, CRASH Maya… (maybe that stands for
everything). If you are reading this and you are interested, give me a
feedback.

syntax:

select a population of any starting objects,
type slime and input:

$life, for how many frames you want to run the procedure

$box, for size of constrain box (note that similar to logo, the “turtles”
in this case the starting objects as soon as they get outside the constrain
box will come back inside from the opposite side)

$step, for the step of the “turtles”; movement in space (always in the
local X axis) for each frame

$rotation, for the range of the random rotation after every step (works for
all axis and stands for the range of -$rotation to +$rotation)

$drift, for the range of the random rotation away from aiming the centre
of the population

$sniff, for the max distance within which the turtles check if there are
others so that they would move together towards the centre of the population

$enough, for the space close to the centre within which the turtles lose
their interest in moving towards the centre

$length, of chemical; how many objects every starting object will have in
its tail

$fitness, of chemical; for how fat or thin the tail will be

examples:

slime 100 100 1 10 3 5 3 9 2;(overnight) with 80 spheres

slime 500 50 1 10 0 1 4 9 1;

slime 100 20 1 10 0 4 3 4 2;


Ezio Blasetti otn.gr email: ezioblasetti at gmail.com
my blogs: ezioatcolumbia.blogspot.com / otn-arch.blogspot.com
More information and scripts from Cory are available at http://www.nthd.org
***************************************************************************
*/

// this procedure checks if a point is inside the $object (author: Cory Clarke)

global proc int aa_isInside(string $object,float $x, float $y, float $z){

float $transl[];

$mincmd = "getAttr " + $object + ".boundingBoxMin";
$min = eval($mincmd);
$maxcmd = "getAttr " + $object + ".boundingBoxMax";
$max = eval($maxcmd);

if($x < ($max[0]) && $x > ($min[0]) && $y < ($max[1]) && $y > ($min[1]) && $z < ($max[2]) && $z > ($min[2])){
return 1;
}
return 0;

}

// this procedure calculates the distance between two points (author: Cory Clarke)

global proc float nthd_calcDistance(string $one, string $two){


float $currentpos[] = `xform -ws -q -t ($one)`;
$v1 = <<$currentpos[0],$currentpos[1],$currentpos[2]>>;
float $poscheck[] = `xform -ws -q -t $two`;
$v2 = <<$poscheck[0],$poscheck[1],$poscheck[2]>>;

return abs(mag($v1 - $v2));


}

// this procedure returns the translate of the center of a group (author: Cory Clarke)

global proc float[] nthd_getCentroid(string $obj){

float $minx,$maxx,$miny,$maxy,$minz,$maxz;

$minx = `getAttr ($obj + ".boundingBoxMinX")`;
$maxx = `getAttr ($obj + ".boundingBoxMaxX")`;
$miny = `getAttr ($obj + ".boundingBoxMinY")`;
$maxy = `getAttr ($obj + ".boundingBoxMaxY")`;
$minz = `getAttr ($obj + ".boundingBoxMinZ")`;
$maxz = `getAttr ($obj + ".boundingBoxMaxZ")`;

float $return[];

$return[0] = ($minx + $maxx) / 2.0;
$return[1] = ($miny + $maxy) / 2.0;
$return[2] = ($minz + $maxz) / 2.0;

return $return;

}

// this procedure creates the tails of the starting objects

global proc chemical (int $length, float $fitness){
$objectsforchemical = `ls -sl -tr`;
$countobj = size ($objectsforchemical);
int $q=0;
while ($q<$length){
$duplobj = `duplicate -rr $objectsforchemical`;
$n=0;
while ($n<$countobj){
$newscaleX = `setAttr ($duplobj[$n] + ".scaleX") ($length/($length+($q*$fitness)))`;
$newscaleY = `setAttr ($duplobj[$n] + ".scaleY") ($length/($length+($q*$fitness)))`;
$newscaleZ = `setAttr ($duplobj[$n] + ".scaleZ") ($length/($length+($q*$fitness)))`;
$name = "chemical" + $q + "_" + $n;
select $duplobj[$n];
rename $name;
$n++;
}
$q++;
}

}

// this procedure is used to get back into the constrain box any turtle that moved out of it

global proc newPosition (string $object, float $currentpositionX, float $currentpositionY, float $currentpositionZ, float $box, float $step){

if ($currentpositionX > $box){
$newpositionX = `setAttr ($object + ".translateX") $step`;
}
if ($currentpositionX < 0){
$newpositionX = `setAttr ($object + ".translateX") ($box-$step)`;
}

if ($currentpositionY > $box){
$newpositionY = `setAttr ($object + ".translateY") $step`;
}
if ($currentpositionY < 0){
$newpositionY = `setAttr ($object + ".translateY") ($box-$step)`;
}

if ($currentpositionZ > $box){
$newpositionZ = `setAttr ($object + ".translateZ") $step`;
}
if ($currentpositionZ < 0){
$newpositionZ = `setAttr ($object + ".translateZ") ($box-$step)`;
}
}

//this procedure literally moves things around and keyframes them, is one of the main.

global proc movethings (int $step, int $rotation, int $box, float $sniff, int $enough, float $drift) {
$objects = `ls -sl -tr`;
$countobj = size ($objects);
$j=0;
while ($j<$countobj){
$object = $objects[$j];
$currentpositionX = `getAttr ($object + ".translateX")`;
$currentpositionY = `getAttr ($object + ".translateY")`;
$currentpositionZ = `getAttr ($object + ".translateZ")`;
if(aa_isInside("pCube1",$currentpositionX,$currentpositionY,$currentpositionZ) == 1){
select "chemical*";
string $chem[] = `ls -sl -tr`;
int $i=0;
for($i=0;$i float $distance = nthd_calcDistance($object,$chem[$i]);
if($distance > $enough && $distance < $sniff){
float $center[] = nthd_getCentroid("groupchemical");
setAttr ("center_groupchemical" + ".translateX") $center[0];
setAttr ("center_groupchemical" + ".translateY") $center[1];
setAttr ("center_groupchemical" + ".translateZ") $center[2];
setKeyframe ("center_groupchemical" + ".translateX");
setKeyframe ("center_groupchemical" + ".translateY");
setKeyframe ("center_groupchemical" + ".translateZ");
select -r center_groupchemical;
select -tgl $object;
aimConstraint -offset 0 0 0 -weight 1 -aimVector 1 0 0 -upVector 0 1 0 -worldUpType "vector" -worldUpVector 0 1 0;
select ($object + "_aimConstraint1");
delete;
rotate -r (rand(-$drift,$drift)) (rand(-$drift,$drift)) (rand(-$drift,$drift)) $object;
}else{
rotate -r (rand(-$rotation,$rotation)) (rand(-$rotation,$rotation)) (rand(-$rotation,$rotation)) $object;
}
}
move -r -os -wd $step 0 0 $object;
setKeyframe ($object + ".translateX");
setKeyframe ($object + ".translateY");
setKeyframe ($object + ".translateZ");
setKeyframe ($object + ".rotateX");
setKeyframe ($object + ".rotateY");
setKeyframe ($object + ".rotateZ");

}else{
newPosition $object $currentpositionX $currentpositionY $currentpositionZ $box $step;
select "chemical*";
string $chem[] = `ls -sl -tr`;
int $i=0;
for($i=0;$i float $distance = nthd_calcDistance($object,$chem[$i]);
if($distance > $enough && $distance < $sniff){
float $center[] = nthd_getCentroid("groupchemical");
setAttr ("center_groupchemical" + ".translateX") $center[0];
setAttr ("center_groupchemical" + ".translateY") $center[1];
setAttr ("center_groupchemical" + ".translateZ") $center[2];
setKeyframe ("center_groupchemical" + ".translateX");
setKeyframe ("center_groupchemical" + ".translateY");
setKeyframe ("center_groupchemical" + ".translateZ");
select -r center_groupchemical;
select -tgl $object;
aimConstraint -offset 0 0 0 -weight 1 -aimVector 1 0 0 -upVector 0 1 0 -worldUpType "vector" -worldUpVector 0 1 0;
select ($object + "_aimConstraint1");
delete;
rotate -r (rand(-$drift,$drift)) (rand(-$drift,$drift)) (rand(-$drift,$drift)) $object;
}else{
rotate -r (rand(-$rotation,$rotation)) (rand(-$rotation,$rotation)) (rand(-$rotation,$rotation)) $object;
}
}
move -r -os -wd $step 0 0 $object;
setKeyframe ($object + ".translateX");
setKeyframe ($object + ".translateY");
setKeyframe ($object + ".translateZ");
setKeyframe ($object + ".rotateX");
setKeyframe ($object + ".rotateY");
setKeyframe ($object + ".rotateZ");
}
$j++;
}
}

// this procedure creates the constrain box

global proc constrain (int $box){
CreatePolygonCube;
setAttr "pCube1.scaleX" $box;
setAttr "pCube1.scaleY" $box;
setAttr "pCube1.scaleZ" $box;
setAttr "pCube1.translateX" ($box/2);
setAttr "pCube1.translateY" ($box/2);
setAttr "pCube1.translateZ" ($box/2);
}

// this procedure sets the starting objects to random points withing the constrain box

global proc rearrange (int $box){
$startobj = `ls -sl -tr`;
$population = size ($startobj);
$i=0;
while ($i < $population) {
$object = $startobj[$i];
setAttr ($object + ".translateX") (rand(0,$box));
setAttr ($object + ".translateY") (rand(0,$box));
setAttr ($object + ".translateZ") (rand(0,$box));
$i++;
}
}

// this procedure moves the tail dependant to the head, what it does is that it goes
// back one frame in time, gets the position and gives it to the next fellow and
// then keyframes everything

global proc moveChemical (int $length, int $population, int $i){
$startobj = `ls -sl -tr`;
$t=0;
while ($t<$length){
if ($t>0){
$e=0;
while ($e<$population){
currentTime ($i-1);
$cpX = `getAttr ("groupchemicalchemical" + ($t-1) + "_" + $e + ".translateX")`;
$cpY = `getAttr ("groupchemicalchemical" + ($t-1) + "_" + $e + ".translateY")`;
$cpZ = `getAttr ("groupchemicalchemical" + ($t-1) + "_" + $e + ".translateZ")`;
$rX = `getAttr ("groupchemicalchemical" + ($t-1) + "_" + $e + ".rotateX")`;
$rY = `getAttr ("groupchemicalchemical" + ($t-1) + "_" + $e + ".rotateY")`;
$rZ = `getAttr ("groupchemicalchemical" + ($t-1) + "_" + $e + ".rotateZ")`;
currentTime $i;
setAttr ("groupchemicalchemical" + $t + "_" + $e + ".translateX") $cpX;
setAttr ("groupchemicalchemical" + $t + "_" + $e + ".translateY") $cpY;
setAttr ("groupchemicalchemical" + $t + "_" + $e + ".translateZ") $cpZ;
setAttr ("groupchemicalchemical" + $t + "_" + $e + ".rotateX") $rX;
setAttr ("groupchemicalchemical" + $t + "_" + $e + ".rotateY") $rY;
setAttr ("groupchemicalchemical" + $t + "_" + $e + ".rotateZ") $rZ;
setKeyframe ("groupchemicalchemical" + $t + "_" + $e + ".translateX");
setKeyframe ("groupchemicalchemical" + $t + "_" + $e + ".translateY");
setKeyframe ("groupchemicalchemical" + $t + "_" + $e + ".translateZ");
setKeyframe ("groupchemicalchemical" + $t + "_" + $e + ".rotateX");
setKeyframe ("groupchemicalchemical" + $t + "_" + $e + ".rotateY");
setKeyframe ("groupchemicalchemical" + $t + "_" + $e + ".rotateZ");
$e++;
}
}

$s=0;
while ($s<$population){
$startobject = $startobj[$s];
currentTime ($i-1);
$currentpositionX = `getAttr ($startobject + ".translateX")`;
$currentpositionY = `getAttr ($startobject + ".translateY")`;
$currentpositionZ = `getAttr ($startobject + ".translateZ")`;
$rotateX = `getAttr ($startobject + ".rotateX")`;
$rotateY = `getAttr ($startobject + ".rotateY")`;
$rotateZ = `getAttr ($startobject + ".rotateZ")`;
currentTime $i;
$newpositionX = `setAttr ("groupchemicalchemical0_" + $s + ".translateX") $currentpositionX`;
$newpositionY = `setAttr ("groupchemicalchemical0_" + $s + ".translateY") $currentpositionY`;
$newpositionZ = `setAttr ("groupchemicalchemical0_" + $s + ".translateZ") $currentpositionZ`;
$newrotateX = `setAttr ("groupchemicalchemical0_" + $s + ".rotateX") $rotateX`;
$newrotateY = `setAttr ("groupchemicalchemical0_" + $s + ".rotateY") $rotateY`;
$newrotateZ = `setAttr ("groupchemicalchemical0_" + $s + ".rotateZ") $rotateZ`;
setKeyframe ("groupchemicalchemical0_" + $s + ".translateX");
setKeyframe ("groupchemicalchemical0_" + $s + ".translateY");
setKeyframe ("groupchemicalchemical0_" + $s + ".translateZ");
setKeyframe ("groupchemicalchemical0_" + $s + ".rotateX");
setKeyframe ("groupchemicalchemical0_" + $s + ".rotateY");
setKeyframe ("groupchemicalchemical0_" + $s + ".rotateZ");
$s++;
}

$t++;
}
}

// this is a procedure only for printing the directions when the script is loaded

global proc printDirections(){
print("\n");
print("\n");
print("slime....loaded\n");
print("\n");
print("\n");
print("select starting objects\n");
print("\n");
print("type slime and input\n");
print("\n");
print("life [for how many frames]\n");
print("box [for size of constrain box]\n");
print("step [for the step of the turtles]\n");
print("rotation [after every step]\n");
print("drift [drift away from the center]\n");
print("sniff [for sniff distance]\n");
print("enough [void space close to the center]\n");
print("length [of chemical]\n");
print("fitness [of chemical]\n");


}


// this is the main procedure, where everything lines up

global proc slime (int $life, int $box, int $step, int $rotation, float $drift, float $sniff, int $enough, int $length, float $fitness){
$startobj = `ls -sl -tr`;
$population = size ($startobj);
constrain $box;
select $startobj;
rearrange $box;
chemical $length $fitness;
select "chemical*";
group -n groupchemical;
CreateLocator;
rename center_groupchemical;
$i=0;
while ($i<$life){
select $startobj;
movethings $step $rotation $box $sniff $enough $drift;
select $startobj;
moveChemical $length $population $i;
currentTime $i;

$i++;
}
}





printDirections;  


Anonymous lrw23 said...

this is interesting. Maybe there is something else there. Read your other email Lynn  


Post a Comment