# Amira-Script-Object V3.0 # NO DEPRECATION WARNING ################################################################################ # CreateVRConfig.scro # # Utility script module for creating configuration files for Avizo XScreen. # # This module supports flat screens matrices with optional overlaping and # optional edge blending, which can be set independently on vertical or # horizontal periods. The display be can configured either as tiles or # using coordinates for immersive viewing and interaction - however all # screens lay on plane z=0, arbitrary position is not handled by this script. # For clusters, multiple screens can be distributed 'equally' on each # slave nodes. # This may not cover all configuration possibilities supported by Avizo: # you can reapeat slave nodes in the list, or tune specifically the configuration # for your need by combining different output files using different screen layouts. # You can also list for each screen its cluster nodes and X display id. # See Avizo XScreen user's guide for more information. # # # Usage: # - Choose output configuration filename. It is a good idea to put it in # Avizo XScreen configurations path. # # - Choose the number of screens vertically and horizontally, # # - Choose resolution of each screen # # - Choose overlap in pixels (0 means no overlap), for instance for # projection with edge blending # # - Choose overlap period, i.e. overlaping may occur every 'n' screens # horizontally and/or vertically. # For instance a high resolution wide display system might include 3 # projectors overlaping for edge blending, each projector gathering # 4 channels/screens inputs that do not overlap. # Overlap period is meaningless if overlap value is 0 pixels. # # - Set optional soft edge overlap, for instance if edge blending is not # supported by projection hardware or graphics driver. # Usually the values correspond (in percentage) to the screen overlaps. # # - Choose soft edge gamma, to control fading of intensity towards screen # edge. # # - A toggle is available to force computation from overlap and # resolution values. It may be disabled for tuning edge # blending area independently from overlaping. # # - If 'interactive' toggle option is set, a TCL command is used to # adjust update edge blending ("XScreen Settings" setSoftEdge). However this # is only designed for single row of screens currently. Also it alters # the tile geometry. Y is possible toou should then use first a 0 overlap, then # reset possibly the overlap, once edge blending extent and gamma are choosed. # # - Choose stereo mode. 'Passive' creates 2 screens sets for left/right eye # Note that passive stereo may be managed in some case by the graphics # board while the application actually uses active stereo mode # - You may choose immersive display for use with tracking system. # You can then choose world coordinates for the corners of full display. # Depth/z coordinate is set to 0. A SoTracker node is added to # config file with a centered default position for object and camera # # - Testing options allow to: # - display the whole screens set scaled down on a single display; # # - offset channels with 1 pixel border to distringuish separate screens; # # - shift channels to compensate overlap and check display consistency # # - Parallel mode set to 'cluster' will force output of hostnames fields # # - Optionaly a master screen can be added. # # - If ScaleViz option is selected, a ScaleViz syntax configuration file # is output instead of 'standard' XScreen VR configuration file. # Note than changing ScaleViz configuration at runtime is not exposed # by Avizo as of version 6.1, therefore Avizo must be restarted for test. # # - The list of cluster slave nodes hostnames is assumed to be given by # screen rows (left then right eye). # # - You can specify the number of screen per cluster node. Screen layout is # identical for each node. # # - You can list X display ids corresponding to the nodes. You just need # to repeat a node in "node hostnames" port for setting more than 1 display # per node. # # Tips: # - negative overlap can be useful for displays separated by solid frames # # - use test options for testing localy a configuration # # - you can use auto-refresh for config update upon any change # # author: daniel.lichau@fei.com # ################################################################################ # $this proc constructor {} { $this script hide $this data hide $this newPortFilename filename $this filename setLabel "Output filename" # A default place where to output config file: $this filename setValue "C:/Program Files/Avizo-6.2/share/config/vr" $this newPortIntTextN numScreens 2 $this numScreens setLabel "Number of screens" $this numScreens setLabel 0 columns $this numScreens setValue 0 3 $this numScreens setLabel 1 rows $this numScreens setValue 1 3 $this newPortIntTextN resolution 2 $this resolution setLabel "Screen resolution" $this resolution setValue 0 1280 $this resolution setValue 1 1024 $this resolution setLabel 0 width $this resolution setLabel 1 heigth $this newPortRadioBox stereoOption 3 $this stereoOption setLabel "Stereo mode" $this stereoOption setLabel 0 "monoscopic" $this stereoOption setLabel 1 "active" $this stereoOption setLabel 2 "passive" $this stereoOption setValue 0 $this newPortRadioBox displayMode 2 $this displayMode setLabel "Display mode" $this displayMode setLabel 0 "tiled" $this displayMode setLabel 1 "immersive" $this newPortFloatTextN screensCoords 4 $this screensCoords setLabel "Screen set coords" $this screensCoords setValue 0 0.0 $this screensCoords setLabel 0 "left" $this screensCoords setValue 1 0.0 $this screensCoords setLabel 1 "bottom" $this screensCoords setValue 2 100.0 $this screensCoords setLabel 2 "right" $this screensCoords setValue 3 100.0 $this screensCoords setLabel 3 "top" $this newPortToggleList testingOption 2 $this testingOption setLabel "Testing options" $this testingOption setValue 0 0 $this testingOption setLabel 0 "channel border" $this testingOption setValue 1 0 $this testingOption setLabel 1 "overlap shift" $this newPortSeparator sep1 $this newPortRadioBox parallelOption 3 $this parallelOption setLabel "Parallel mode" $this parallelOption setLabel 0 "single display (test)" $this parallelOption setLabel 1 "local (multi-pipe)" $this parallelOption setLabel 2 "cluster" $this newPortFloatTextN screensScale 1 $this screensScale setValue 0.1 $this newPortToggleList options 3 $this options setLabel "Options" $this options setLabel 0 "master screen (recommended on cluster)" $this options setValue 0 0 $this options setLabel 1 "display ids" $this options setValue 1 0 $this options setLabel 2 "ScaleViz (advanced)" # not used so hidden $this options setToggleVisible 2 0 $this options setValue 2 0 $this newPortText nodeNames $this nodeNames setLabel "Node hostnames" $this nodeNames setNumColumns 60 $this nodeNames setValue "Node1 Node1 Node4 Node2 Node2 Node4 Node3 Node3 Node5" $this newPortText displayNames $this displayNames setNumColumns 60 $this displayNames setValue ":0.0 :1.0 :0.0 :0.0 :1.0 :1.0 :0.0 :1.0 :0.0" $this displayNames setSensitivity 0 $this newPortIntTextN screenPerNode 2 $this screenPerNode setLabel "Screens per cluster node" $this screenPerNode setValue 0 1 $this screenPerNode setValue 1 1 $this screenPerNode setLabel 0 "horizontal" $this screenPerNode setLabel 1 " x vertical" $this newPortSeparator sep2 $this newPortIntTextN overlap 2 $this overlap setLabel "Overlap (pixels)" $this overlap setValue 0 0 $this overlap setValue 1 0 $this overlap setLabel 0 horizontal $this overlap setLabel 1 vertical $this newPortIntTextN overlapPeriod 2 $this overlapPeriod setValue 0 1 $this overlapPeriod setValue 1 1 $this overlapPeriod setLabel 0 horizontal $this overlapPeriod setLabel 1 vertical $this newPortSeparator sep3 $this newPortFloatTextN softEdgeOverlap 2 $this softEdgeOverlap setLabel "Soft edge overlap (%)" $this softEdgeOverlap setValue 0 0 $this softEdgeOverlap setValue 1 0 $this softEdgeOverlap setLabel 0 horizontal $this softEdgeOverlap setLabel 1 vertical # Soft edge overlap can be computed from resolution and overlap in pixels (it may be useful to override it) $this newPortToggleList softEdgeOption 2 $this softEdgeOption setLabel "Soft edge options" $this softEdgeOption setLabel 0 "comp. % from overlap" $this softEdgeOption setValue 0 1 $this softEdgeOption setLabel 1 "interactive soft edge" $this softEdgeOption setValue 0 1 # Default value for gamma is 1.2, 1.0 is linear. $this newPortFloatTextN softEdgeGamma 2 $this softEdgeGamma setValue 0 1.2 $this softEdgeGamma setValue 1 1.2 $this softEdgeGamma setLabel 0 horizontal $this softEdgeGamma setLabel 1 vertical $this newPortSeparator sep4 $this newPortRadioBox onApply 2 $this onApply setLabel "On Apply:" $this onApply setLabel 0 "save only" $this onApply setLabel 1 "save and load" $this newPortDoIt action } # destructor is called when DemoMaker is destroyed $this proc destructor {} { } $this proc setConfigPath {configPath} { $this filename setValue $configPath } # the "compute" method is called whenever a port has changed $this proc compute {} { if {[app cluster] == "slave"} { # Does nothing on slaves return } # Some convenience variables set resolutionX [$this resolution getValue 0] set resolutionY [$this resolution getValue 1] set tilesX [$this numScreens getValue 0] set tilesY [$this numScreens getValue 1] set overlapPeriodX [$this overlapPeriod getValue 0] set overlapPeriodY [$this overlapPeriod getValue 1] set overlapX [$this overlap getValue 0] set overlapY [$this overlap getValue 1] set screenPerNodeX [$this screenPerNode getValue 0] set screenPerNodeY [$this screenPerNode getValue 1] set screensLeft [$this screensCoords getValue 0] set screensBottom [$this screensCoords getValue 1] set screensRight [$this screensCoords getValue 2] set screensTop [$this screensCoords getValue 3] set screensHeigth [expr $screensTop - $screensBottom] set screensWidth [expr $screensRight - $screensLeft] set totalTiles [expr $tilesX * $tilesY] set screensScale [$this screensScale getValue] set channelOffset 0 if {[$this softEdgeOption getValue 0] == 1 } { # Compute soft edge % from pixel overlap $this softEdgeOverlap setValue 0 [expr 100*double([$this overlap getValue 0])/ [$this resolution getValue 0] ] $this softEdgeOverlap setValue 1 [expr 100*double([$this overlap getValue 1])/ [$this resolution getValue 1] ] } # Handle interactive soft edge tuning if {([$this softEdgeOption getValue 1] == 1) && ([$this softEdgeOverlap isNew] || [$this softEdgeGamma isNew]) } { if {$tilesY > 1} { echo Warning: interactive soft edge ("XScreen Settings" setSoftEdge) properly works only for a single screen row in current version. } if {![exists "XScreen Settings"]} { echo Please load XScreen configuration first for soft edge interactive update. } else { set softEdgeOverlapList "" for {set i 1 } { $i < [$this numScreens getValue] } {incr i} { if { ($i % $overlapPeriodX) == 0 } { lappend softEdgeOverlapList [$this softEdgeOverlap getValue 0] } else { lappend softEdgeOverlapList 0 } } eval "{XScreen Settings} setSoftEdge -g [$this softEdgeGamma getValue 0] $softEdgeOverlapList" } } if {[$this parallelOption isNew] == 1 } { if {[$this parallelOption getValue] == 0 } { $this options hide $this nodeNames hide $this displayNames hide $this screenPerNode hide $this screensScale show $this options setSensitivity 1 0 } else { if {[$this parallelOption getValue] == 1 } { $this options show $this nodeNames hide $this displayNames hide $this screenPerNode hide $this screensScale hide $this options setSensitivity 1 0 } else { $this options show $this nodeNames show $this displayNames show $this screenPerNode show $this screensScale hide $this options setSensitivity 1 1 } } } # With local config (multi-pipe), the number of screen per node is equal to the number of screens if {[$this parallelOption getValue] == 1 } { set screenPerNodeX $tilesX set screenPerNodeY $tilesY } if {[$this parallelOption isNew] == 1 } { if {[$this parallelOption getValue] == 1 } { $this options setValue 0 1 } } if {[$this options isNew] == 1 } { if {[$this options getValue 1] == 1 } { $this displayNames setSensitivity 1 } else { $this displayNames setSensitivity 0 } } # Override some values for local test if { [$this parallelOption getValue] == 0 } { set resolutionX [expr int($resolutionX * $screensScale)] set resolutionY [expr int($resolutionY * $screensScale)] set overlapX [expr int($overlapX * $screensScale)] set overlapY [expr int($overlapY * $screensScale)] set screenPerNodeX $tilesX set screenPerNodeY [expr $tilesY * 2] } if { [$this testingOption getValue 0] == 1 } { set channelOffset 1 } set fullSizeX [expr $resolutionX * $tilesX - ($tilesX/$overlapPeriodX - 1)*$overlapX]; set fullSizeY [expr $resolutionY * $tilesY - ($tilesY/$overlapPeriodY - 1)*$overlapY]; if {[$this displayMode getValue] == 1} { # immersive screens $this screensCoords show $this screensCoords setValue 3 [ expr 100 * $fullSizeY/$fullSizeX ] } else { $this screensCoords hide } if {[$this action wasHit] } { set outfile "" if [catch {set outfile [open [$this filename getValue] w] } "Can't open output file" ] { echo "Change output filename" } else { # Output header: if { [$this options getValue 2] == 0} { puts $outfile "#Inventor V2.1 ascii\n" } else { puts $outfile "#ScaleViz V6.0 ascii\n" } puts $outfile "Separator \{" # For information: puts $outfile "\# Full size: $fullSizeX x $fullSizeY\n" # ScaleViz MasterConfig, or VRProperty node and master Screen node if { [$this options getValue 2] == 1 } { # ScaleViz config puts $outfile " MasterConfig \{" puts $outfile " hostname \"change-with-your-master-hostname\" port 3456 " echo "Change master hostname in configuration" puts $outfile " \}" } elseif { [$this options getValue 0] == 1 } { # standard XScreen config puts $outfile " SoVRProperty \{" puts $outfile " keepMasterViewerInsideGUI 1" puts $outfile " \}" puts $outfile " SoScreen \{" puts $outfile " name \"Master\" " puts $outfile " \}" } puts $outfile "\# Screens are numbered bellow from left to right and top to bottom\n" set cameraModeList {MONOSCOPIC ACTIVE_STEREO LEFT_VIEW RIGHT_VIEW} set passiveScreenSets [expr ([$this stereoOption getValue] == 2) + 1] # ... equals 1 if mono or active stereo, 2 if passive stereo for {set s 0} {$s < $passiveScreenSets} {incr s} { # for each left/righ screen set if passive stereo set cameraMode [lindex $cameraModeList [expr [$this stereoOption getValue] + $s ] ] puts $outfile "\# $cameraMode screens" for {set j 0 } { $j < $tilesY} {incr j} { # for each screen row for {set i 0 } { $i < $tilesX} {incr i} { # for each screen column if { [$this options getValue 2] == 1} { # ScaleViz config if { [$this displayMode getValue] == 0 } { # Tile screen puts $outfile " FlatScreen \{" } else { puts $outfile " Screen \{" } } else { puts $outfile " SoScreen \{" } puts $outfile " name \"Screen-$i-$j\" " # For cluster, output hostname: if { [$this parallelOption getValue] == 2} { # We assume hostnames are given per row, then per eye if passive stereo is used. set nodesPerRow [ expr $tilesX / $screenPerNodeX ] set nodesPerEye [ expr $nodesPerRow * ($tilesY / $screenPerNodeY) ] set nodeIndex [ expr $i/$screenPerNodeX + ($j/$screenPerNodeY)*$nodesPerRow + $s*$nodesPerEye ] puts $outfile " hostname \"[lindex [$this nodeNames getValue] $nodeIndex]\" " if {[$this options getValue 1] == 1} { puts $outfile " display \"[lindex [$this displayNames getValue] $nodeIndex]\" " } } # Output channel origin and size (optional offset for local test) set channelOriginX [expr ($resolutionX+$channelOffset)*($i % $screenPerNodeX)] set channelOriginY [expr ($resolutionY+$channelOffset)*(($j+$s*$tilesY) % $screenPerNodeY)] if { [$this testingOption getValue 1] == 1 } { # for test mode, checking overlap set channelOriginX [expr $channelOriginX - $overlapX*int($i/$overlapPeriodX)] set channelOriginY [expr $channelOriginY - $overlapY*int($j/$overlapPeriodY)] } puts $outfile " channelOrigin $channelOriginX $channelOriginY" puts $outfile " channelSize $resolutionX $resolutionY" set tileOriginXPixels [expr $i * $resolutionX - $overlapX*int($i/$overlapPeriodX)] set tileOriginYPixels [expr ($j+1) * $resolutionY - $overlapY*int($j/$overlapPeriodY)] set tileOriginX [expr double($tileOriginXPixels)/$fullSizeX] set tileOriginY [expr 1.0 - double($tileOriginYPixels)/$fullSizeY] set tileSizeX [expr double($resolutionX)/$fullSizeX] set tileSizeY [expr double($resolutionY)/$fullSizeY] if { [$this displayMode getValue] == 0 } { # tiled screens # Tile origin and size puts $outfile " tileOrigin $tileOriginX $tileOriginY" puts $outfile " \# ...in pixels: $tileOriginXPixels $tileOriginYPixels" puts $outfile " tileSize $tileSizeX $tileSizeY" } else { # immersive screens set left [expr $screensLeft + $tileOriginX * $screensWidth] set bottom [expr $screensBottom + $tileOriginY * $screensHeigth] set right [expr $screensLeft + ($tileOriginX + $tileSizeX)*$screensWidth] set top [expr $screensBottom + ($tileOriginY + $tileSizeY) * $screensHeigth] puts $outfile " lowerLeft $left $bottom 0" puts $outfile " lowerRight $right $bottom 0" puts $outfile " upperRight $right $top 0" puts $outfile " upperLeft $left $top 0" } puts $outfile " cameraMode $cameraMode" # Soft edge blending set overX [expr double([$this softEdgeOverlap getValue 0])/100.0] set overY [expr double([$this softEdgeOverlap getValue 1])/100.0] if { $overX != 0 || $overY !=0} { set gammaX [$this softEdgeGamma getValue 0] set gammaY [$this softEdgeGamma getValue 1] set left [expr (($i % $overlapPeriodX)==0) && ($i > 0)] set right [expr ((($i + 1) % $overlapPeriodX)==0) && ($i < ($tilesX - 1))] set top [expr (($j % $overlapPeriodY)==0) && ($j > 0)] set bottom [expr ((($j + 1) % $overlapPeriodY)==0) && ($j < ($tilesY - 1))] puts $outfile " softEdgeOverlap \[[expr $left * $overX ], [expr $right * $overX ], [expr $bottom * $overY ], [expr $top * $overY ]\]" puts $outfile " softEdgeGamma \[[expr $left * $gammaX ], [expr $right * $gammaX ], [expr $bottom * $gammaY ], [expr $top * $gammaY ]\]" } # Set proper background for immersive displays if {[$this displayMode getValue] == 1} { # immersive screens puts $outfile " backgroundMode BG_LOWER" } puts $outfile " \}" } } } # For immersive displays (enabling use of 3D tracker), define some reasonable default object and camera positions if { [$this displayMode getValue] == 1} { # immersive screens if { [$this options getValue 2] == 1} { # ScaleViz config puts $outfile " SoTracker \{" } else { puts $outfile " Tracker \{" } puts $outfile " server \"test\" " puts $outfile " defaultObjectPosition [expr ($screensLeft + $screensRight)/2.] [expr ($screensBottom + $screensTop)/2.] 0" puts $outfile " defaultCameraPosition [expr ($screensLeft + $screensRight)/2.] [expr ($screensBottom + $screensTop)/2.] $screensWidth" puts $outfile " \}" } puts $outfile "\}" close $outfile echo saved configuration file [$this filename getValue] if { [$this options getValue 2] == 1} { # ScaleViz config echo "Restart [theAppSkin getProductName] to use updated ScaleViz configuration" } elseif { [$this onApply getValue] == 1 } { if {![exists "XScreen Settings"]} { create HxTracking } "XScreen Settings" loadConfig [$this filename getValue] } } } }