[vtkusers] Help - Setting multiple views after a user interaction.

Andrew Maclean a.maclean at acfr.usyd.edu.au
Thu Apr 24 22:53:06 EDT 2003


Can anyone help me with this?
 
Imagine that you are looking at a cow through several different windows from 
the side of a building. Then you use the camera in the master window to change 
the view of the cow.

The problem is that the views are all correct when first displayed. However 
when I interact with the image using the mouse the views (except for the 
central one) are incorrect.
 
Essentially I have several views of the same object and I want to rotate and 
zoom and update the views in all the windows that they are correct. So at the 
beginning of the mouse interaction I transform each actor back to being the 
same as the master one. Then at the end of the event I transform them back. 
However they all look the same as the master - so something is clearly 
incorrect.

Any help or comments are appreciated.

Here is the sample code:

//////////////////////////////////////////////////////////////////////////////
#
# Purpose:
# Display a cow in a rectangular array of viewports. The central vieport
# is perpendicular to the z-axis of the cow and lies on the z-axis. The
# other viewports are perpendicular to the z-axis of the cow but are
# offset in the x- and y- directions from the central one. Thus these off-axis
# viewports show an image of the cow that is translated and rotated.

# First we include the VTK Tcl packages which will make available
# all of the VTK commands to Tcl.
#
package require vtk
package require vtkinteraction

# Get the corrct position of the cow relative to the view window.
proc TransformObj { i j cmx sclX xrng cmy sclY yrng cols rows r } {

global dx
global dy
global theta
global psi
global scale
# The coordinates for the viewport
global xmin
global xmax
global ymin
global ymax

  set xmin [expr $j * {1.0 / $cols}]
  set ymin [expr $i * {1.0 / $rows}]
  set xmax [expr [expr $j * {1.0 / $cols}] + [expr 1.0 / $cols]]
  set ymax [expr [expr $i * {1.0 / $rows}] + [expr 1.0 / $rows]]

  # We need to move the cow backwards along the line of
  # sight and rotate it so that the correct part is in view.
  # Firstly find the centre of the viewport.
  # We can move the centres by scaling them.
  set cx [expr (($xmax - $xmin) / 2.0 + $xmin)]
  set cy [expr (($ymax - $ymin) / 2.0 + $ymin)]
  # Calculate the angle theta corresponding to the angular distance
  # from the master window in the x-direction and the corresponding
  # angle psi in the y-direction. (dx,dy) is the position of the centre
  # of the window relative to the master window
  # Remember to scale it using xrng, yrng snd sclX, sclY
  # sclX, sclY move the windows away from the central one by the factor
  # corresponding to their value.
  set dx [expr ($cx-$cmx)*$sclX*$xrng]
  set dy [expr ($cy-$cmy)*$sclY*$yrng]
  set d [expr sqrt($dx*$dx+$dy*$dy)]
  set psi [expr atan2($dx,$r)*45/atan(1)]
  set theta [expr atan2($dy,$r)*45/atan(1)]
  # Because the viewpoint is a plane perpendicular to the z-axis
  # the off-centre cows will be slightly further away by an amount dr.
  set dr [expr $r*(-1+sqrt(1+$d/$r*$d/$r))]
  # So the scale factor is:
  set scale [expr $r/($r+$dr)]

 }

# Rendering stuff
vtkRenderWindow renWin

vtkRenderWindowInteractor iren
   iren SetRenderWindow renWin
   iren AddObserver LeftButtonPressEvent BeginCameraEvnt
   iren AddObserver LeftButtonReleaseEvent EndCameraEvnt
   iren AddObserver MiddleButtonPressEvent BeginCameraEvnt
   iren AddObserver MiddleButtonReleaseEvent EndCameraEvnt
   iren AddObserver RightButtonPressEvent BeginCameraEvnt
   iren AddObserver RightButtonReleaseEvent EndCameraEvnt
   iren Initialize
   # This adds the "u" keypress event...it pops up a Tcl interpreter.
   #
   iren AddObserver UserEvent {wm deiconify .vtkInteract}

# First start by reading a cow model. We also generate surface normals for
# prettier rendering.
vtkBYUReader cow
  cow SetGeometryFileName "$VTK_DATA_ROOT/Data/Viewpoint/cow.g"

# Apply a preliminary rotation and/or other transforms to the cow.
# We will then use this transformed cow as the basis for the views
# of the cow in all the windows. This transformed cow is further
# transformed to reflect the different geometry being seen in each
# viewport.
# Use the variable r (below) to control the distance of the observer
# from the cow. This will affect the non-master window views.

# The windows
set rows 3
set cols 3

# The master window - this controls the rotaton/scaling performed by the 
camera.
set masterWindow [expr int(floor([expr {$rows * $cols} / 2.0]))]
# Find the centre of the master window viewport.
set i [expr int(floor([expr $rows / 2.0]))]
set j [expr int(floor([expr $cols / 2.0]))]
set xmin [expr $j * {1.0 / $cols}]
set ymin [expr $i * {1.0 / $rows}]
set xmax [expr [expr $j * {1.0 / $cols}] + [expr 1.0 / $cols]]
set ymax [expr [expr $i * {1.0 / $rows}] + [expr 1.0 / $rows]]
# Find the centre of the viewport.
set cmx [expr ($xmax - $xmin) / 2.0 + $xmin]
set cmy [expr ($ymax - $ymin) / 2.0 + $ymin]

# Initial orientations
set rotY 0
set rotX 0

# Scaling - if you want it.
set scaleX 0.3
set scaleY 0.5
set scaleZ 0.8

vtkTransform transForCow
  transForCow RotateY $rotY
  transForCow RotateX $rotX
#  transForCow Scale $scaleX $scaleY $scaleZ

vtkTransformPolyDataFilter pdTransCow
   pdTransCow SetInput [cow GetOutput]
   pdTransCow SetTransform transForCow

vtkPolyDataMapper cowMapper
   cowMapper SetInput [pdTransCow GetOutput]

set bounds [cowMapper GetBounds]
scan $bounds "%f %f %f %f %f %f" minx maxx miny maxy minz maxz
set xrng [expr ($maxx-$minx)/2]
set yrng [expr ($maxy-$miny)/2]
set zrng [expr ($maxz-$minz)/2]
# Find the maximum dimension.
set mdim [expr ($xrng > $yrng)?$xrng:$yrng ]
set mdim [expr ($zrng > $mdim)?$zrng:$mdim ]

# The distance of the observer from the central cow.
set r [expr $mdim*2 ]
# The scale used to set the x-, y-coordinate of the window centre.
set sclX 5
set sclY 5

# Build all the objects first.
set count 0
while {$count < [expr $rows * $cols]} {
   if {$count != $masterWindow} {
      vtkTransform trans($count)
      vtkTransformPolyDataFilter pdTrans($count)
   }
   vtkPolyDataNormals cowNormals($count)
   vtkPolyDataMapper cowMapper($count)
   vtkActor cowActor($count)
   vtkRenderer ren($count)
   incr count
}

set i 0
set j 0
set k 0
set count 0

while {$i < $rows} {
   while {$j < $cols} {
     TransformObj $i $j $cmx $sclX $xrng $cmy $sclY $yrng $cols $rows $r
      if {$count != $masterWindow} {

         cowNormals($count) SetInput [pdTransCow GetOutput]

         cowMapper($count) SetInput [cowNormals($count) GetOutput]

         cowActor($count) SetMapper cowMapper($count)
         # Set the transform directly in the actor.
         cowActor($count) AddOrientation [expr $theta] [expr -$psi] 0
         cowActor($count) AddPosition [expr -$dx] [expr -$dy] 0
         cowActor($count) SetScale $scale $scale $scale
         # A goldenrod cow
         [cowActor($count) GetProperty] SetColor 0.8549 0.6471 0.1255
         # A renderer renders into a viewport within the vtkRenderWindow.
         # It is part or all of a window on the screen and it is
         #  responsible for drawing the actors it has.  We also set
         # the background color here.

         ren($count) AddActor cowActor($count)
         ren($count) SetViewport $xmin $ymin $xmax $ymax
 
         renWin AddRenderer ren($count)
      } else {
         cowNormals($count) SetInput [pdTransCow GetOutput]; # Comment out for 
a thin lens.

         cowMapper($count) SetInput [cowNormals($count) GetOutput]

         cowActor($count) SetMapper cowMapper($count)
         # A navajo white 2 cow
         [cowActor($count) GetProperty] SetColor 0.9333 0.8118 0.6314

         ren($count) AddActor cowActor($count)
         ren($count) SetViewport $xmin $ymin $xmax $ymax
      
         renWin AddRenderer ren($count)

    }

    incr j
    incr count
  }
set j 0
incr i
}

# Make the master window the only one with the active camera.
set count 0
while {$count < [expr $rows * $cols]} {

   if {$count != $masterWindow} {
      ren($count) SetActiveCamera \
               [ren($masterWindow) GetActiveCamera]
     ren($count) InteractiveOff
   }
   incr count
}

# render the image
#
renWin Render
#  renWin SetSize 1000 1000
# prevent the tk window from showing up then start the event loop
wm withdraw .

# Set all cows to look line the master one.
# and then let the camera operate.
# To do this you can either invert each user matrix and apply it
# or just apply the master cow matrix.
proc BeginCameraEvnt { } {

global masterWindow
global rows
global cols
#
global cmx
global cmy
global sclX
global sclY
global xrng
global yrng
global r
# Values obtained from the transform
global dx
global dy
global theta
global psi
global scale

set i 0
set j 0
set count 0
while {$i < $rows} {
   while {$j < $cols} {
     TransformObj $i $j $cmx $sclX $xrng $cmy $sclY $yrng $cols $rows $r
     if {$count != $masterWindow} {
        #tk_messageBox -message "count: $count\n \
        #(dx,dy): ($dx,$dy)\n \
        #(theta,psi): ($theta,$psi)\n \
        #scale: $scale
        #" -type ok
       # Set the transform directly in the actor.
#        set scale [ expr 1.0 / $scale]
        set scale 1
        cowActor($count) AddOrientation [expr -$theta] [expr $psi] 0
        cowActor($count) AddPosition [expr $dx] [expr $dy] 0
        cowActor($count) SetScale $scale $scale $scale
        cowActor($count) Render ren($count) cowMapper($count)
        }
     incr j
     incr count
   }
set j 0
incr i
}
set i 0

}

# Now that the mouse event has ended, re-apply the transforms to each cow
# to move them back into position
proc EndCameraEvnt { } {

global masterWindow
global rows
global cols
#
global cmx
global cmy
global sclX
global sclY
global xrng
global yrng
global r
# Values obtained from the transform
global dx
global dy
global theta
global psi
global scale

vtkMatrix4x4 objMatrix

set i 0
set j 0
set count 0
while {$i < $rows} {
   while {$j < $cols} {
     # Calculate the transform for the object.
     TransformObj $i $j $cmx $sclX $xrng $cmy $sclY $yrng $cols $rows $r
     if {$count != $masterWindow} {
        #tk_messageBox -message "count: $count\n \
        #(dx,dy): ($dx,$dy)\n \
        #(theta,psi): ($theta,$psi)\n \
        #scale: $scale
        #" -type ok
        # Set the transform directly in the actor.
        cowActor($count) AddOrientation [expr $theta] [expr -$psi] 0
        cowActor($count) AddPosition [expr -$dx] [expr -$dy] 0
        cowActor($count) SetScale $scale $scale $scale
        cowActor($count) Render ren($count) cowMapper($count)
        set objectMatrix [trans($count) GetMatrix]
     }
     incr j
     incr count
   }
set j 0
incr i
}
set i 0

   objMatrix Delete

}

# Display the elements of a 4x4 mtrix.
proc DisplayMatrix { matrix } {
set i 0
set j 0
while {$i < 4} {
  while {$j < 4} {
    set m($i$j) [$matrix GetElement $i $j]
     incr j
  }
  set j 0
  incr i
}
set i 0
set lst [array get m]
tk_messageBox -message "m: $lst" -type ok
}
//////////////////////////////////////////////////////////////////////////////


___________________________________________

   Andrew J. P. Maclean
   Centre for Autonomous Systems
   The Rose Street Building J04
   The University of Sydney  2006  NSW
   AUSTRALIA
   Ph: +61 2 9351 3283	Fax: +61 2 9351 7474
   URL: http://www.cas.edu.au/

___________________________________________






-------------------------------------------------
This mail sent through IMP: www-mail.usyd.edu.au



More information about the vtkusers mailing list