TCL (tool command language)

 

 

set listA {dog cat {MAN {earth mars venus} WOMAN CHILD} mule}

 

# implement a procedure _______________
proc printlist { inlist } {
foreach item $inlist {
if { [llength $item] > 1 } {
printlist $item
} else {
puts $item
}
}
}

 

# use a procedure _____________________
printlist $listA

 

 

This is a basic script is written to show the use of list substitution. By executing this script we get a simple list that states in order the items within the set list.

Script Returns

 

 

 

 

 

# generate a random number based on how many items in the list
proc myrand { input } {
set out [expr [expr rand()] * $input]
set out [expr int($out)]
return $out
}

proc getitem { inlist } {
# 1 count the items within the list
set count [llength $inlist]
# 2 get a random number from the count
set rnum [myrand $count]
# 3 return the item to the process
return [lindex $inlist $rnum]
}

# create the list for testing out list procedure
set mylist [list A B C D E]
# for loop to give random numbers based on the #increment
for {set n 0} {$n <= 10} {incr n 1} {
puts "Random letter is : [getitem $mylist]"

 

 

This is the start of creating a procedure that will call to a list and randomly select an item from the list. Shown here is an example of how this script works. By using "expr rand()", we are able to create a purely random generated number based on the number of items within the list. This number is then used to return a random letter from the list that is set in "mylist". The" for loop" generates a random number for each increment within the loop. This short routine will allow us to generate random files from within a directory.

Script Returns

 

 

 

 

 

#sources the TCL file that has the procedures needed #to run the random number generator

 

source "H:/vsfx705/TCL/list.tcl"

proc getfilelist { dir ext } {
# makes an empty list
set outlist [list]

set contents [glob -nocomplain -directory $dir "*.$ext"]
foreach item $contents {
if { [file isfile $item] == 1 } {
lappend outlist $item
}
}
return $outlist
}


#sets the specific path to the directory

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

puts [getitem $files]

 

This brings us to the use of "source" within a script to call to another script to run a procedure. This script above is calling to our previous script to generate a random number based on the number of files within a specified directory. Setting "glob" to "-nocomplain" tells TCL not to return any errors when a directory does not have files within it. We set the getfileslist procedure to a directory and tell it to only return back a random file with an extension of .mel. This script will allow us to pull a random .rib file from a specific directory for use in reference box substitution in Maya.

Script Returns

 

 

 

 

 

 

 

 

 

 

 

 

 

 

At this point we moved away from scripting and focused on creating geometric objects in Maya for our substitution script.


These objects were all created using Maya. We decided as a group to use medieval armour and weaponry. Certain problems arose when we were not standardize to a similar reference box for each object. We then came up with these step to make sure the size of our objects matched.

 

 

 

Proxy Object Creation (Reference Boxes)

 

1) Create one polygon box for each object that will need a proxy.

 

2) Set the height, depth, and width to be relative to what you want the size of the models to be.

 

3) Once the proportions of the boxes have been adjusted accordingly, position the boxes relative to the grid, this will establish the origin of its local coordinate system when the next step is applied.

 

4) Apply a "Freeze Transformation" to each box.

 

5) Once all of the boxes have been prepared, then, and only then, move them into their relative locations for the final proxy model scene.

 

6) export this out as a Maya .mb file and allow access to it for all within the project.

 

 

 

Archiving the Model

 

1) Model the object.

 

2) import in the proxy objects created above.

 

3) Position the object relative to the center of the Maya grid (i.e. the origin of the "Maya World")

 

4) If need be, create duplicates of the proxy object and move them also to the center of the Maya world.

 

5) Translate the model to fit within the proxy object, making sure that the center pivot points match up.

 

6) Delete the duplicated proxy object.

 

7) Once these steps are done, apply a "Freeze Transformation" to each model.

 

8) Export out the model's geometry by creating an Archiver in a SLIM palette then rendering out the scene with PRMan.

 

 

 

Back to scripting.....

 

 

# generate a random number based on how many items in the #list
proc myrand { input } {
set out [expr [expr rand()] * $input]
set out [expr int($out)]
return $out
}

proc getRandomItem { inlist } {
# 1 count the items within the list
set count [llength $inlist]
# 2 get a random number from the count
set rnum [myrand $count]
# 3 return the item to the process
return [lindex $inlist $rnum]
}

proc getRandomRib { dir } {
# 1: get the paths to all of the .rib files in the source
# directory

set ribs [glob -nocomplain -directory $dir "*.rib"]
return [getRandomItem $ribs]
}


This script consolidated within one script all that has been done in the previous works. This generates the random number based on the number of specified files within the directory and return one at random. This works as is needed to, but for every frame you get a different set of random objects. A random seed is needed to be able to reproduce the same randomness over multiple frames. We will then link to this in Maya using MtoR (Maya to Renderman) and SLIM.

 

 

 

 

 

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]

}


This script seeds the random generator with a number based on the unique object name for each proxy object that is created. Using a regular expression, we parse out the characters and only leave the integers for the seed. This is then used in the subsequent procedures to generate the exact same random file over multiple frames. We will then link to this in Maya using MtoR (Maya to Renderman) and SLIM.

 

 

 

 

 

 

With the creation of the proxy objects (reference boxes) we are able to link to the model geometry that was rendered out to a .rib file using a archiver in SLIM.

 

 

 

Above show the completed layout of the proxy objects within the Maya scene. To the right is the SLIM palette that is used to "attach" the model geometry to the proxy objects.

 

 

TCLbox

 

source "H:/vsfx705/TCL/randomRibSeed.tcl"
set archive [getRandomRib "//Vsfx/vsfx705_tr12p/shared_ribs/armour" $OBJNAME]

RIBbox

 

Surface \"plastic\" \"Kd\" 1.0
ReadArchive \"$archive\"
Opacity 0 0 0

 

These are the actual code that is within the TCL and RIB boxes. The first one, TCLbox, is sourcing to the TCL script above that generates the random file. It is also setting a variable "archive" that will allow the RIBbox to "attach" the correct geometry to the proxy object during rendering. We are also specifying the explicit path to the .rib files and also able to easily get the proxy object's name using the $OBJNAME function in Maya. Each one of the TCLboxes corresponds to a specific part of the armour (i.e. helm, armour, boots..). These are then attached to the correct proxy object and a common RIBbox is used that has a default plastic shader and with the Opacity set at 0 0 0, it "turns off" the proxy object so that it does not render.

 

 

All of this allows us to create random scenes within Maya using proxy objects. So we get something that looks like this:

 


 

The left image is the proxy objects rendered with Maya and the right image is the proxy objects rendered with PRMan via MtoR. You can see that the proxy objects have been replaced be the actual geometry in a random fashion.

 

 

And Finally...

 

By creating a scene file with multiple proxy objects duplicated off of the original ones, we are able to create scenes that allow the ease of moving around large number of troops without having to deal with the heavy geometry. I have created a simple dynamics simulation using this idea. By applying ridgid body solvers to specific proxy objects and allowing a gravity force to manipulate them I have come up with this: