//////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// source setExps; global int $g_popSize; $g_popSize = 16; // size of population generated global float $g_xstep = 2; global float $g_ystep = 2.5; global string $g_shifterName; // current name of "lorezHull" shape shifter global float $g_mutationRate = .1; global float $g_mutationChance = .2; global float $g_crossoverChance = .5; global int $g_selection[]; // indices of selected genotypes global float $g_chooseOtherChance = .1; // mates bodies other than chosen ones global string $g_meshName = "polySurface9"; // was "lorezHull" //////////////////////////////////////// global string $g_genotypes[]; // "part:attrs:defVal,+/-Range" global string $g_genotypeAttrs[]; $g_genotypeAttrs = { "humanoidRoot:size,sizeT,sizeW,sizeD,sizeL:0.5,0.1", "sacroiliac:size,sizeT,sizeW,sizeD,sizeL:0.5,0.1", "vl5:size,sizeT,sizeW,sizeD,sizeL:0.5,0.1", "skullbase:size,sizeT,sizeW,sizeD,sizeL:0.5,0.1", "feet:Size,SizeT,SizeW,SizeD,SizeL:0.5,0.1", "calves:Size,SizeT,SizeL:0.5,0.1", "thighs:Size,SizeT,SizeL:0.5,0.1", "hands:Size,SizeT,SizeW,SizeD,SizeL:0.5,0.1", "forearms:Size,SizeT,SizeL:0.5,0.1", "upperarms:Size,SizeT,SizeL:0.5,0.1", "trunk:Size,SizeT,SizeW,SizeD,SizeL:0.5,0.1", "legs:Size,SizeT,SizeL:0.5,0.1", "arms:Size,SizeT,SizeL:0.5,0.1", "limbs:Size,SizeT,SizeL:0.5,0.1", "humanoid:weight,height,muscle,age,gender:0.5,0.3", "humanoid:pelvicTilt,backArch:0.5,0.1", "humanoid:chestSize,hairTop,hairBack,hairSides,hairLength:0.5,0.5" }; //////////////////////////////////////// // randomly fill in the attributes for humanoid number $idnum global proc string generateGenotype(int $idnum) { //print("Generating new genotype...\n"); global string $g_genotypeAttrs[]; string $geneStr; string $genotype = ""; string $tokens[]; for($geneStr in $g_genotypeAttrs) { tokenize($geneStr,":",$tokens); string $partName = $tokens[0]; // body part to tweak attributes of if(strcmp($partName, "humanoid")==0) { $partName += "_"+$idnum; } string $atStr = $tokens[1]; // list of tweakable attributes string $rangeStr = $tokens[2]; // default, +/- random range for attribute tokenize($rangeStr,",",$tokens); float $defVal = $tokens[0]; // default attribute value float $spread = $tokens[1]; // +/- random range for attribute string $atList[]; tokenize($atStr,",",$atList); string $atName; for($atName in $atList) { float $atValue = clamp(0,1,rand($defVal - $spread, $defVal + $spread)); string $cmd; string $fullAtName; if(isaJoint($partName) || gmatch($partName,"humanoid*")) { $fullAtName = $partName+"."+$atName; } else { $fullAtName = "humanoid_"+$idnum+"."+$partName+$atName; } //print("$fullAtName="+$fullAtName+"\n"); if(strcmp($genotype, "")!=0) { $genotype += ":"; } $genotype += $fullAtName + "=" + $atValue; } } //print("genotype="+$genotype+"\n"); return $genotype; } global proc gg(int $idnum) { generateGenotype($idnum); } // alias //////////////////////////////////////// // set all genotype attributes back to 1 // what if not default? i.e. gender? have to look up default // idnum is which humanoid's attributes to reset global proc resetGenotypeAttributes(int $idnum) { global string $g_genotypeAttrs[]; string $geneStr; string $tokens[]; for($geneStr in $g_genotypeAttrs) { tokenize($geneStr,":",$tokens); string $partName = $tokens[0]; // body part to tweak attributes of if(strcmp($partName, "humanoid")==0) { $partName += "_"+$idnum; } string $atStr = $tokens[1]; // list of tweakable attributes string $rangeStr = $tokens[2]; // default, +/- random range for attribute tokenize($rangeStr,",",$tokens); string $defVal = $tokens[0]; // default attribute value float $spread = $tokens[1]; // +/- random range for attribute string $atList[]; tokenize($atStr,",",$atList); string $atName; for($atName in $atList) { float $atValue = $defVal; string $cmd; if(isaJoint($partName) || gmatch($partName,"humanoid*")) { $cmd = "setAttr \""+$partName+"."+$atName+"\" "+$atValue+";\n"; } else { $cmd = "setAttr \"humanoid_"+$idnum+"."+$partName+$atName+ "\" "+$atValue+";\n"; } //print($cmd); eval($cmd); } } } global proc rga(int $idnum) { resetGenotypeAttributes($idnum); } // alias //////////////////////////////////////// // delete all old bodies, except last one if exist global proc deleteBodies() { //print("killing everyone...\n"); global string $g_meshName; global string $g_shifterName; rename $g_shifterName $g_meshName; // spare the shape-shifter $g_shifterName = $g_meshName; string $bodies[] = `ls "body_*"`; // take names string $body; for($body in $bodies) { // delete them all, ignore "Shape" nodes if(!gmatch($body,"*Shape*")) { delete $body; } } } //////////////////////////////////////// // apply genotype $i to the shapeShifter global proc applyGenotype(int $i) { global string $g_genotypes[]; string $genotype = $g_genotypes[$i]; //print("genotype="+$genotype+"\n"); string $pairs[]; tokenize($genotype, ":", $pairs); string $pair; for($pair in $pairs) { //print("pair="+$pair+"\n"); string $tokens[]; tokenize($pair, "=", $tokens); string $attribute = $tokens[0]; if(strcmp($tokens[1],"")!=0) { float $value = $tokens[1]; if($value == 0) { print("genotype="+$genotype+"\n"); print("pair="+$pair+"\n"); print("attribute="+$attribute+"\n"); print("value="+$value+"\n"); } setAttr $attribute $value; } } } //////////////////////////////////////// global proc createPhenotypes() { //print("creating individuals...\n"); global int $g_popSize; global float $g_xstep; global float $g_ystep; global string $g_genotypes[]; global string $g_meshName; int $i; float $sqrez = sqrt($g_popSize); float $xrez = ($sqrez-1) * $g_xstep; float $yrez = ($sqrez-1) * $g_ystep; float $x = -$xrez; float $y = $yrez; string $newHullName = "body_"+($g_popSize-1); if(size(`ls $g_meshName`)) { rename $g_meshName $newHullName; } global string $g_shifterName; $g_shifterName = $newHullName; for($i = 0; $i < $g_popSize; $i++) { applyGenotype($i); string $bodyName = "body_"+$i; if($i < ($g_popSize - 1)) { select -r $newHullName; // so can duplicate its geometry duplicate -n $bodyName; // create and name a duplicate of deformed body // parent -w $bodyName; // parent new body under world } if($i < ($g_popSize - 1)) { float $bbny = getAttr($bodyName+".bbny"); float $ytweak = (-$bbny) - $g_ystep/2.0; //print($bodyName + ", $ytweak=" + $ytweak + "\n"); move -r $x ($y + $ytweak) 0; // position geometry in grid } else { select -r humanoidRoot; setAttr "humanoidRoot.translateY" 0; float $bbny = getAttr($bodyName+".bbny"); float $ytweak = (-$bbny) - $g_ystep/2.0; move -a 0 $ytweak 0; // position geometry in grid //print($bodyName + ": bbny="+$bbny+" ytweak=" + $ytweak + "\n"); } $x += $g_xstep; // increment next X position if($x > 0) { $x = -$xrez; $y -= $g_ystep; } // inc y and reset x } select -cl; } //////////////////////////////////////// global proc initPopulation() { global int $g_popSize; global string $g_genotypes[]; global string $g_meshName; // rename shapeShifter's geometry as body_(n-1) string $newHullName = "body_"+($g_popSize-1); rename $g_meshName $newHullName; global string $g_shifterName; $g_shifterName = $newHullName; // randomly fill in genotypes //print("creating random genotypes...\n"); for($i = 0; $i < $g_popSize; $i++) { $g_genotypes[$i] = generateGenotype(1); // tweak proto, store geno //print($g_genotypes[$i]+"\n"); } createPhenotypes(); } //////////////////////////////////////// global proc string mutateGene(string $gene) { global float $g_mutationRate; string $tokens[]; tokenize($gene, "=", $tokens); string $at = $tokens[0]; if(strcmp($tokens[1], "")!=0) { float $val = $tokens[1]; $val += rand(-$g_mutationRate, $g_mutationRate); $val = clamp(0, 1, $val); string $newGene = $at + "=" + $val; return $newGene; } else { return $gene; } } //////////////////////////////////////// // combine genotypes g1 & g2 into a new genotype using crossover and mutation global proc string mateGenotypes(string $g1, string $g2) { global float $g_crossoverChance; global float $g_mutationChance; global float $g_mutationRate; string $genes1[], $genes2[], $newGenes[]; tokenize($g1,":",$genes1); tokenize($g2,":",$genes2); int $toggle = 0; int $i; for($i=0; $i