/* ------------------------------------------------------------------------------------- \\\\\\\\____________________2.5D Cellular Automaton v1.0_____________________//////// //////// \\\\\\\\ ------------------------------------------------------------------------------------- > Written by dimitris gourdoukis. > object-e architecture 2009. ------------------------------------------------------------------------------------- > http://object-e.blogspot.com/ > object.e.architecture@gmail.com ------------------------------------------------------------------------------------- > released under the creative commons license "share alike unported 3.0" > http://creativecommons.org/licenses/by-sa/3.0/ ------------------------------------------------------------------------------------- > v1.0 Last Modified 05/11/09. Tested on Maya 2008. > Use and modify at your own risk. ------------------------------------------------------------------------------------- > Description: This script is a two-dimensional cellular automaton algorithm. It creates a grid of cells, generates a random initial state and simulates the ca for a user defi- ned number of generations. Each new generation is not replacing the old one, but is placed on top of it. It also animates the ca growth. ------------------------------------------------------------------------------------- */ proc cellAutom (){ int $xmax = `intSliderGrp -q -v numofCellsx`; int $ymax = `intSliderGrp -q -v numofCellsy`; int $generations = `intSliderGrp -q -v numofGenerations`; int $duration = `intSliderGrp -q -v duration`; float $h = `floatSliderGrp -q -v cellHeight`; float $d = `floatSliderGrp -q -v distbwGens`; //create the lattice of cells. for($x=0; $x<$xmax; $x++){ for($y=0; $y<$ymax; $y++){ polyCube -ax 0 0 1 -w 1 -h $h -sx 1 -sy 1 -name ("Cell0_" + $y + "x" +$x); move $x $y 0; } } //set the current time to 0 currentTime 0; //create a random initial state. for($x=0; $x<$xmax; $x++){ for($y=0; $y<$ymax; $y++){ $name = ("Cell0_"+$y+"x"+$x); select -cl ; select -r $name ; if(rand(2) >1){ scale 0 0 0; } } } for ($i=1; $i<$generations; $i++){ //create an array that will contain the state of each cell. int $cell_state[]; //specify the distance to move the cells in the z direction. $m = $i*($h+$d); //get the state of each cell and add it to the array. for($y=0; $y<$ymax; $y++){ for($x=0; $x<$xmax; $x++){ $name = ("Cell"+($i-1)+"_"+$y+"x"+$x); string $attribholder = "getAttr \"" + $name + ".scaleX\""; $cell_state [$x + $y*$xmax] = `eval ($attribholder)`; } } //create an array that will contain the sum of the states (0 or 1) of the neighbors of each cell. int $cell_neighborhood[]; //get the sum of the states (0s or 1s) of the neighbors of each cell and add it to the array. //exclude the borders of the matrix. for($y=1; $y<($ymax-1); $y++){ for($x=1; $x<($xmax-1); $x++){ $cell_neighborhood [$y*$xmax +$x] = $cell_state [($y-1)*$xmax+$x-1] + $cell_state [($y-1)*$xmax+$x] + $cell_state [($y-1)*$xmax+$x+1] + $cell_state [$y*$xmax +$x-1] + $cell_state [$y*$xmax +$x+1] + $cell_state [($y+1)*$xmax+$x-1] + $cell_state [($y+1)*$xmax+$x] + $cell_state [($y+1)*$xmax+$x+1]; } } //get the sum of the states (0s or 1s) of the neighbors of the border cells. for($x=1; $x<($xmax-1); $x++){ $cell_neighborhood [$x] = $cell_state [$x-1] + $cell_state [$x+1] + $cell_state [$xmax+($x-1)] + $cell_state [$xmax+$x] + $cell_state [$xmax+($x+1)]; $cell_neighborhood [($ymax-1)*$xmax+$x] = $cell_state [($ymax-2)*$xmax+($x-1)] + $cell_state [($ymax-2)*$xmax+$x] + $cell_state [($ymax-2)*$xmax+($x+1)] + $cell_state [($ymax-1)*$xmax+($x-1)] + $cell_state [($ymax-1)*$xmax+($x+1)]; } for($y=1; $y<($ymax-1); $y++){ $cell_neighborhood [$y*$xmax] = $cell_state [($y-1)*$xmax] + $cell_state [($y-1)*$xmax+1] + $cell_state [$y*$xmax+1] + $cell_state [($y+1)*$xmax] + $cell_state [($y+1)*$xmax+1]; $cell_neighborhood [($y+1)*$xmax-1] = $cell_state [$y*$xmax-2] + $cell_state [$y*$xmax-1] + $cell_state [($y+1)*$xmax-2] + $cell_state [($y+2)*$xmax-2] + $cell_state [($y+2)*$xmax-1]; } //get the sum of the states (0s or 1s) of the corner cells. $cell_neighborhood [0] = $cell_state [1] + $cell_state [$xmax] + $cell_state [$xmax+1]; $cell_neighborhood [$xmax-1] = $cell_state [$xmax-2] + $cell_state [2*$xmax-1] + $cell_state [2*$xmax-2]; $cell_neighborhood [($ymax-1)*$xmax] = $cell_state [($ymax-2)*$xmax] + $cell_state [($ymax-2)*$xmax+1] + $cell_state [($ymax-1)*$xmax+1]; $cell_neighborhood [$xmax*$ymax-1] = $cell_state [$xmax*($ymax-1)-2] + $cell_state [$xmax*($ymax-1)-1] + $cell_state [$xmax*$ymax-2]; //loop for each cell and apply the ca rules. for($y=0; $y<$ymax; $y++){ for($x=0; $x<$xmax; $x++){ $name = ("Cell"+$i+"_"+$y+"x"+$x); $m1 = $cell_state [$x + $y*$xmax]; $m2 = $cell_neighborhood [$x + $y*$xmax]; //here are the ca rules (game of life). if ($m2 < 2 || $m2 > 3){ polyCube -ax 0 0 1 -w 1 -h 1 -sx 1 -sy 1 -name ("Cell"+$i+"_" + $y + "x" +$x); move $x $y $m; eval ("setAttr \"" + $name + ".scaleX\" 0"); eval ("setAttr \"" + $name + ".scaleY\" 0"); eval ("setAttr \"" + $name + ".scaleZ\" 0"); }else if ($m2 == 3){ polyCube -ax 0 0 1 -w 1 -h 1 -sx 1 -sy 1 -name ("Cell"+$i+"_" + $y + "x" +$x); move $x $y $m; currentTime (($i-1)*$duration); eval ("setAttr \"" + $name + ".scaleX\" 0"); eval ("setAttr \"" + $name + ".scaleY\" 0"); eval ("setAttr \"" + $name + ".scaleZ\" 0"); eval ("setKeyframe \"" + $name + ".sx\""); eval ("setKeyframe \"" + $name + ".sy\""); eval ("setKeyframe \"" + $name + ".sz\""); currentTime ($i*$duration); eval ("setAttr \"" + $name + ".scaleX\" 1"); eval ("setAttr \"" + $name + ".scaleY\" 1"); eval ("setAttr \"" + $name + ".scaleZ\" 1"); }else if ($m2 == 2 && $m1 == 0){ if ($m1==0){ polyCube -ax 0 0 1 -w 1 -h 1 -sx 1 -sy 1 -name ("Cell"+$i+"_" + $y + "x" +$x); move $x $y $m; eval ("setAttr \"" + $name + ".scaleX\" 0"); eval ("setAttr \"" + $name + ".scaleY\" 0"); eval ("setAttr \"" + $name + ".scaleZ\" 0"); }else { polyCube -ax 0 0 1 -w 1 -h 1 -sx 1 -sy 1 -name ("Cell"+$i+"_" + $y + "x" +$x); move $x $y $m; currentTime (($i-1)*$duration); eval ("setAttr \"" + $name + ".scaleX\" 0"); eval ("setAttr \"" + $name + ".scaleY\" 0"); eval ("setAttr \"" + $name + ".scaleZ\" 0"); eval ("setKeyframe \"" + $name + ".sx\""); eval ("setKeyframe \"" + $name + ".sy\""); eval ("setKeyframe \"" + $name + ".sz\""); currentTime ($i*$duration); eval ("setAttr \"" + $name + ".scaleX\" 1"); eval ("setAttr \"" + $name + ".scaleY\" 1"); eval ("setAttr \"" + $name + ".scaleZ\" 1"); } }else { polyCube -ax 0 0 1 -w 1 -h 1 -sx 1 -sy 1 -name ("Cell"+$i+"_" + $y + "x" +$x); move $x $y $m; currentTime (($i-1)*$duration); eval ("setAttr \"" + $name + ".scaleX\" 0"); eval ("setAttr \"" + $name + ".scaleY\" 0"); eval ("setAttr \"" + $name + ".scaleZ\" 0"); eval ("setKeyframe \"" + $name + ".sx\""); eval ("setKeyframe \"" + $name + ".sy\""); eval ("setKeyframe \"" + $name + ".sz\""); currentTime ($i*$duration); eval ("setAttr \"" + $name + ".scaleX\" 1"); eval ("setAttr \"" + $name + ".scaleY\" 1"); eval ("setAttr \"" + $name + ".scaleZ\" 1"); } //set a keyframe for the new scale of each cell. eval ("setKeyframe \"" + $name + ".sx\""); eval ("setKeyframe \"" + $name + ".sy\""); eval ("setKeyframe \"" + $name + ".sz\""); } } } } proc deleteDead(){ //delete the dead cells int $xmax = `intSliderGrp -q -v numofCellsx`; int $ymax = `intSliderGrp -q -v numofCellsy`; int $generations = `intSliderGrp -q -v numofGenerations`; int $duration = `intSliderGrp -q -v duration`; for ($i=0; $i<$generations; $i++){ $time = $generations*$duration + 5; currentTime ($time); for($y=0; $y<$ymax; $y++){ for($x=0; $x<$xmax; $x++){ $name = ("Cell"+$i+"_"+$y+"x"+$x); select -cl ; select -r $name ; $act = `eval("getAttr \"" + $name + ".scaleX\"")`; if ($act < 1){ doDelete; } } } } } /*----------------------------------------------- //print the array of the state of the cells. //(note that it is upside down). for ($y=0; $y<$ymax; $y++){ string $cl = "\n"; print $cl; for ($x=0; $x<$xmax; $x++){ print $cell_state[$x + $y*$xmax]; print " "; } } ------------------------------------------------*/ //UI global proc constructCellAutWin () { if (`window -exists CellAutWindow`) { deleteUI CellAutWindow; } window -width 400 -height 380 -title "2.5D Cellular Automaton v1.0" -sizeable true CellAutWindow; columnLayout; text -l ""; intSliderGrp -label "x: number of cells " -field true -fieldStep 1 -sliderStep 1 -value 10 -fieldMinValue 0 -fieldMaxValue 100 numofCellsx; intSliderGrp -label "y: number of cells " -field true -fieldStep 1 -sliderStep 1 -value 10 -fieldMinValue 0 -fieldMaxValue 100 numofCellsy; intSliderGrp -label "number of gens" -field true -fieldStep 1 -sliderStep 1 -value 5 -fieldMinValue 0 -fieldMaxValue 100 numofGenerations; intSliderGrp -label "duration" -field true -fieldStep 1 -sliderStep 1 -value 10 -fieldMinValue 0 -fieldMaxValue 100 duration; floatSliderGrp -label "cell height" -field true -fieldStep 0.1 -sliderStep 0.1 -value 1 -fieldMinValue 0 -fieldMaxValue 10 cellHeight; floatSliderGrp -label "dist bw gens" -field true -fieldStep 0.1 -sliderStep 0.1 -value 0 -fieldMinValue 0 -fieldMaxValue 10 distbwGens; //create button button -label "Generate CA" -command "cellAutom" buildIt; //create button2 button -label "Delete Dead" -command "deleteDead" buildU; setParent ..; //break columnLayout; text -l ""; separator -w 800 -h 4 -backgroundColor 1 0.663 1; text -l "object-e / dimitris gourdoukis. 2009."; text -l "http://object-e.blogspot.com/"; showWindow; } constructCellAutWin;