[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