vcanim.gif (8357 bytes)Venetian Blinds Tutorial
Home ] Sales ] Products ] Services ] Support ] Downloads ]

 

 


Making a Venetian blind.

  • First we need to make a single slat of a Venetian blind, so make a grid using Model->Get->Primitive->Grid, and scale it so that it is 12 units long and 1 unit wide.
  • Now make the rest of the slats by Model->Duplicate->Repetition of grid1, specifying 30 or 40 duplicates. Rename null1 which is the parent of all these new slats control.
  • Rename the original slat from grid1 to blind1.
  • Next move the slats into their proper positions, Use Model->Display->SoftWishConsole to generate an expression on each of these slats, by typing:
    	SWN_do i grid* {
    		regexp {([a-z]+)([0-9]+)} $i junk alphaJunk num
    		SW_expression "$i.etrny = blind1.etrny + [expr $num - 1 + 0.75]"
    	}
    

    where 0.75 is the space we will leave between slats when they are in the open position. (Remember that you need to type:
        package require SWN
        SWN_init
    before you can use any of the SWN procedures, and
        package require SW
    before you can use any SW procedures.)     

    SWN_do takes 3 arguments: a variable name, a pattern, and some code. For every element in the scene which matches the pattern, it evaluates the code, substituting each specific element name which matches the pattern. For example, grid2 matches the pattern grid*, so SW_do will substitute grid2 into the code, producing:

    regexp {([a-z]+)([0-9]+)} grid2 junk alphaJunk num
    SW_expression "grid2.etrny = blind1.etrny + [expr $num - 1 + 0.75]"

    When evaluated, this generates an expression on grid2. Let's take a closer look at the regexp line. Regexp takes a regular expression as its first argument and uses it to split its second argument into parts. In this case the ([a-z]+) part matches grid and gets put into alphaJunk, the ([0-9]+) matches the number 2 from grid2 and puts it into num.

    Tcl uses expr to evaluate arithmetic expressions, so [expr $num - 1 + 0.75] returns the number of the grid minus 1 plus 0.75, so in this case it would return 1.75.

    Figure 1
    Click for hi-res image.

  • Now that the slats are in the right place, delete blind1 (Model->Delete->Selection). This will delete all the expressions we used to move the slats, which we don't need anymore.
  • We should also name all the slats correctly, which we can do easily using SWC_rename, like this:
    	SWN_rename /control/* grid* blind*

    This renames all the descendants of the control null whose names begin with grid to begin with blind instead.

    Figure 2
    Click for hi-res image.

  • Now select the control null and Motion->Savekey->Object->Rotation->All.
  • In order to be able to rotate all of the slats by rotating only the control null, we generate expressions on each of the slats, like this:
    	SWN_do i blind* { SW_expression "$i.rotx = control.rotx" }
    

    Figure 3
    Click for hi-res image.

  • Construction of the Venetian blind is now complete. Now that we know what to do, let's make a Venetian-blind generating procedure so that we never have to figure this out again. Such a procedure would look like this:

    proc makeVenetianBlind { numSlats } {
    package require SWN
    package require SW
    global SAA_Constants
    global SWN

    SWN_init
    SWN_pre

    # make the parent null
    set nullElem [ SAA_AllocElem ]
    SAA_nullCreate $SWN(scene) $nullElem
    set name control
    SAA_elementSetName $SWN(scene) $nullElem name

    # build all the slats, name them blindn, for n=0,1,2... numSlats, and
    # parent to control null
    for { set i 0 } { $i  < $numSlats } { incr i } {
    set gridElem [ SAA_AllocElem $numSlats ]
    SAA_meshCreateGrid $SWN(scene) 1.0 12.0 1 1 [ access $gridElem $i ]
    set name blind$i
    SAA_elementSetName $SWN(scene) [ access $gridElem $i ] name
    SAA_modelSetParent $SWN(scene) [ access $gridElem $i] $nullElem
    }

    # move all the slats into position, don't use expressions
    SWN_do i blind* {
    regexp {([a-z]+)([0-9]+)} $i j1 j2 num
    set start [SW_exprValue blind1.etrny]
    set position [expr $start + ($num * 0.75)]
    set modelID [ SWN_name2element $i ]
    SAA_modelGetTranslation $SWN(scene) $modelID $SAA_Constants(SAA_COORDSYS_GLOBAL) x y z
    SAA_modelSetTranslation $SWN(scene) $modelID 1 0 $SAA_Constants(SAA_COORDSYS_GLOBAL) $x $position $z
    }

    # slave the rotation of all the slats to the first slat
    SWN_do i blind* {
    regexp {([a-z]+)([0-9]+)} $i j1 j2 num
    if {$num != 0 } {
    set expression [ SW_expression "$i.rotz=blind0.rotz" ]
    SAA_Free $expression
    }
    }

    }
        
  • If we store this code in a file named VenetianBlind.tcl then the next time we need to make a blind with 100 slats, we can use the SoftWish Console to source this file and then type: makeVenetianBlind 100
  • To safeguard against accidentally rotating the entire Venetian blind, when we meant to rotate only the control null we could use SoftWish behavior to attach a select-me-only script to the control null. SoftWish behaviors cause attached scripts to be evaluated whenever the object to which the script is attached is modified. The select-me-only script determines if the object it is attached to is selected, and if it is, then it deselects everything else in that object's branch. Using SoftWish behaviors involves 2 steps:
    1. Attach the script. We do this with Model->Effects->behaviorEdit, which brings up the behaviorEdit control. We choose the control null and then attach the select-me-only.tcl script, via the file browser, to the control null .

      Figure 4
      Click for hi-res image.

    2. Getting the script evaluated. We do this with Model->Effects->behaviorSingleFirst. The status bar prompts us to pick a model with attached tcl code and we pick the control null twice. Now the script attached to the control null gets evaluated before any changes in the scene which affect the null take place.

      Figure 5
      Click for hi-res image.

  • If one wants to be able to select the entire Venetian blind tree and transform it, just Model->Effects->behaviorEdit again and disable the attached select-me-only script. Note that you can also use behaviorEdit to edit scripts. Any changes you make are immediately reflected in the behavior of the object that the script is attached to. Here is what the select-me-only script looks like:
    	set rootID [ SWB_getCurrentElement ]
    
       	SAA_elementGetSelectionType [ SWB_getScene ] $rootID selType
    
    	if { $SAA_unConstants(SAA_SelectionType,$selType) == "SAA_SEL_BRANCH_SELECTED" } {
    		SAA_selectlistSetModelBranch [ SWB_getScene ] 0 1 $rootID
    		SAA_selectlistSetElements [ SWB_getScene ] 1 1 $rootID
    	}
    

Whitepaper ] Terms and Conventions ] Release Notes 2.2 ] Problems You May Encounter ] Installation overview ] Installing on Irix ] Installing on Nt ] Licensing ] Scripting ] Utilities and Libraries ] Tools ] Tutorials ]

copyright Video-Collage Inc.