TCL File Referencing

This excercise serves as an introduction to the TCL (Tool Command Language or "Tickle") Programming Language. We are starting out by creating a TCL script that can read in a list of files from a certain directory and randomly choose one, in order to eventually create a system that uses geometry replacement inside a RIB file.

   


set listA {dog cat {MAN WOMAN CHILD} mouse}

foreach item $listA {
puts "$item"
}



A *very* basic script we started with just to practice creating lists and learning about various substitution characters, {} [ ], /, $



proc myrand { input } {
set out [expr [expr rand()]*$input]
set out [expr int($out)]
return $out
}

 

proc itemrand {inlist} {

set count [llength $inlist]
set index [myrand $count]
set item [lindex $inlist $index]

return $item
}



A first crack at creating procedures, myrand creates a random integer between zero and $input. Itemrand takes this random integer and returns the corresponding element in the list it is provided with. These are the first steps at selecting a random file from a list of file names.

 

source "H:/vsfx705/TCL/Lister.tcl"
proc getfilelist {dir ext} {
#make and empty list
set outlist [list]
set contents [glob -nocomplain -directory $dir "*.$ext"]

foreach item $contents {
if {[file isfile $item] == 1} {
lappend outlist $item
#puts "Found File Called $item"
#or puts "[file tail $item]" for just ending of filename
}

}

return $outlist
}

set files [getfilelist "H:/vsfx705/MEL" "mel"]
puts [itemrand $files]


This script sources the script above and uses it with its own procedure, getfilelist. This script allows the user to specify a directory and the file extension they are looking for. It then returns a list all of these files. The script then uses itemrand to select a random file and prints its path to the console. The goal is to be able to have a set of varying rib files that match a certain part of a character (say a head or arm) and pick one them randomly to generate different versions of a character model when the scene is rendered.



  To implement this in Maya, we began by testing a simple ribbox substitution. First we created seven boxes. Then we each made a very simple model and used SLIM's archiver to create a pre-baked rib for them.  

 

 




			


#RIBBOX CODE:
Surface \"plastic\" \"Kd\" 1
ReadArchive \"//Vsfx/vsfx705_tr12p/shared_ribs/(name of each rib).rib\"
Opacity .5 .5 .5
  Using a separate ribbox (code at right) attached to each cube allowed the geomtry of our models to be substituted in place of the boxes in the renderer.    

 

The next stage was to merge our work with TCL and Maya together in order to have our script randomly substitute the actual geometry into the renderer. We modified the script to return a random rib file within a specified directory. Then we created a TCLbox inside SLIM in order to source in our TCL script and use it to create a variable called "archive" that has a path to the prebaked rib file to be used. Then using this stored path in the Ribbox with the readArchive command allows the geometry to be randomly subitituted each time the render is done. This creates a problem in a animation context, however, since the objects substituted for a given cube will be completely different each time the scene is rendered. We addressed this problem later.

#TCL SCRIPT

proc myrand { input } {
set out [expr [expr rand()]*$input]
set out [expr int($out)]
return $out
}

 

proc getRandomItem {inlist} {

set count [llength $inlist]
set index [myrand $count]
set item [lindex $inlist $index]

return $item
}

proc getRandomRib { dir } {
#1. get the paths to all the rib files in the source directory
set ribs [glob -nocomplain -directory $dir "*.rib"]
#2. Return a random file from the list of found files
return [getRandomItem $ribs]
}

#3.test line to observe random selection of ribs, commented out for use in Maya
#puts [getRandomRib "//Vsfx/vsfx705_tr12p/shared_ribs"]

 

#TCL BOX inside MAYA

source "G:/sepalmer/TCL/randomRib.tcl"
set archive [getRandomRib "G:/sepalmer/shared_ribs/armour"]
#RIBBOX inside MAYA
Surface \"plastic\" \"kd\" 1
ReadArchive \"$archive\"
Opacity 0 0 0
       

 


  Some reference for a more sophistocated model. We were each to do a model of a helmet, sword, armour, boots, and a shield for the next part of the assignment, which was to create a full soldier's armour and randomly substitute each part. This time we created a set of reference boxes for each student to use when creating the models so they would all conform to the same scale when rendered in MTOR. As before, each piece was made into a prebaked rib file and put in shared folders by category.  

 


  My final model (completion time 7 hours) to be used in our excercise, rendered using Maya's default renderer.  

 


  The Reference Boxes can now be used with five separate TCL boxes, one for each piece of armour, to bring in the prebaked ribs. Using the TCL script, this can be done randomly.  

 



  A test of the reference boxes using my own rib files in preparation for generating the army.  

 

Shot of an organized group of soldiers. One has been keyframe animated, then duplicated (including the input graph) to replicate the same motion. A final problem that needed to be addressed is the need to randomly assign the geometry to a given box, but then maintain that over time so that the soldiers can be animated moving and won't continue substituting out their components. The solution (shown at right) was to seed the random number generator based off of the geometry number using a regular expression. (For example PolyCube87 would become just 87, an integer which can be used with expr [srand ()]. The TCL boxes were modified to pass in the additional variable $OBJNAME, the name of the object the TCLbox is assigned to.

#randomRibSeed.tcl

proc getseed {geoname} {
regsub -all {[^0-9]} $geoname "" out
return $out
}

proc myrand {inputLength seed} {
expr srand($seed)
set out [expr [expr rand()] * $inputLength]
set out [expr int($out)]
return $out
}

 

proc getRandomItem {inlist seed} {

set count [llength $inlist]
set index [myrand $count $seed]
set item [lindex $inlist $index]

return $item
}

proc getRandomRib {dir geoname} {
#1. get the paths to all the rib files in the source directory
set ribs [glob -nocomplain -directory $dir "*.rib"]
#2. determine a seed value for the random number generator based off the geometry name
set geonum [getseed $geoname]
#3. Return a random file from the list of found files
return [getRandomItem $ribs $geonum]

}

#3.test line to observe random selection of ribs, commented out for use in Maya

#puts [getRandomRib "//Vsfx/vsfx705_tr12p/shared_ribs/armour" "polyCube94"]

#TCL BOX inside MAYA

source "G:/sepalmer/TCL/randomRibSeed.tcl"
set archive [getRandomRib "G:/sepalmer/shared_ribs/(name of object)" $OBJNAME]
 

 

   


 

(Double Click to Play/Pause)

 

An initial animation showing the random substitution over the same animated behavior. It's not very interesting, and we all realized we should have had separate boxes for each boot, so the soldiers would not have to "hop".

 

 

I thought I'd try to one up the cheesiness of the first animation by creating a short battle sequence between two soldiers. This is the scene as it appears in Maya....

     


  And this is the rendered image.  

 


 

(Double Click to Play/Pause)

A Maya playblast for the proposed fighting animation

 


 

(Double Click to Play/Pause)

 

The first render of the same Battle Sequence

 

 


 

(Double Click to Play/Pause)

 

The Second render showing the same actions, but with different geometry substituted in.

 

 

 

The next logical step was to take this action and duplicate it for an entire battle scene. Here is the playblast.

     

A rendered shot of the randomly substituted warriors about to clash.

     

 


  The fully rendered battle scene.  

 

 


  Finally a third playblast of an overall army marching shot. It's worth noting that for the hundred or more soldiers shown, the rib files were only 1.5mb each, versus the 500 or more mb they would be had the actual geometry been present in the scene.  

 


  A still of the test render.  


 

The final marching army animation. Yeah it's cheesy, but I think it demonstrates the concept and the potential for this system.

 

 

 

Overall, I think we have tapped into something that has a great deal of potential. I'm especially interested in how this could be used with randomized behaviors or particle systems. The system we developed certainly lacks in sophistication, some rudimentary level of detail work or at the very least using delayedReadArchive to test the bounding box certainly could have helped with render times. We also really had to work as a group to keep the scales of the objects working together, but problems still arose. I would like to use this concept to eventually fuel a more sophisticated solution, but I think we did a great job realizing the vast potential of this process.