package require vtk
package require vtkinteraction

# Demonstrate how to use vtkCameraWidget to record and playback interpolated
# camera views.  This example also demonstrates the use of vtkSliderWidget, in
# this case to set the number of frames the camera widget will play back.
#
# Start by generating some data: the planet earth.
#
# Define a 2D plane to act as a base to apply a texture to.  The coordinates
# are specified as origin: {1, pi, 0}, point 1: {1, pi, 2*pi},
# point 2: {1, 0, 0} and can be thought of as a rectangle oriented parallel
# to the y-z plane and offset along the x-axis by 1.
#
vtkPlaneSource plane
  plane SetOrigin 1.0 [expr 3.14159265359 - 0.0001] 0.0
  plane SetPoint1 1.0 [expr 3.14159265359 - 0.0001] 6.28318530719
  plane SetPoint2 1.0 0.0001                        0.0
  plane SetXResolution 19
  plane SetYResolution 9

# Warp the plane's spherical coordinates to Cartesian coordinates using
# vtkSphericalTransfrom and vtkTransformPolyDataFilter.  The transform will
# map coordinates into a range suitable for texture mapping: [0,1].
#
vtkSphericalTransform transform

vtkTransformPolyDataFilter tpoly
  tpoly SetInputConnection [plane GetOutputPort]
  tpoly SetTransform transform

# Load an image: a map of the earth.
#
vtkPNMReader earth
  earth SetFileName "$VTK_DATA_ROOT/Data/earth.ppm"

# Apply the image to a vtkTexture so that the earth image can be mapped onto
# our sphere.
#
vtkTexture texture
  texture SetInputConnection [earth GetOutputPort]
  texture InterpolateOn

# Create a mapper to render the sphere.
#
vtkDataSetMapper mapper
  mapper SetInputConnection [tpoly GetOutputPort]

# Create an actor to display and interact with.  The actor will apply the
# texture map to geometry of the sphere.
#
vtkActor world
  world SetMapper mapper
  world SetTexture texture

# Create a renderer and a render window.
#
vtkRenderer ren1
vtkRenderWindow renWin
    renWin AddRenderer ren1

# Create an interactor to respond to mouse events.
#
vtkRenderWindowInteractor iren
    iren SetRenderWindow renWin


# VTK widgets consist of two parts: the widget part that handles event processing;
# and the widget representation that defines how the widget appears in the scene
# (i.e., matters pertaining to geometry).  The camera representation inherits
# from vtkBorderRepresentation, a rectangular region, and is therefore
# essentially a 2D rectangle containing 3 pictograms: a camera that when clicked
# records the current camera position, a triangle to represent a playback button
# and an "X" to represent a reset button that erases all previously recorded
# camera positions.  The representation also sets the number of frames to
# generate during playback.
#
# Create the widget and its representation.
#

vtkCameraRepresentation cameraRep
  cameraRep SetNumberOfFrames 500

# An interpolator is used to fill in camera positions between the positions
# recorded by the widget.  Here we interpolate smoothly with a spline scheme.
#
vtkCameraInterpolator interpolator
  interpolator SetInterpolationTypeToSpline

  cameraRep SetInterpolator interpolator

# Position the rectangle to be in the lower left of the renderer window.
#
  [cameraRep GetPositionCoordinate] SetCoordinateSystemToNormalizedDisplay
  [cameraRep GetPositionCoordinate] SetValue 0.08 0.07
  [cameraRep GetPosition2Coordinate] SetCoordinateSystemToNormalizedDisplay
  [cameraRep GetPosition2Coordinate] SetValue 0.16 0.14

# Create the actual camera widget that will listen and react to events.
#
vtkCameraWidget cameraWidget
  cameraWidget SetInteractor iren
  cameraWidget SetRepresentation cameraRep
  cameraWidget KeyPressActivationOff

# Create a slider widget so that we can interactively set the number of frames
# that are interpolated between recorded camera positions.  First we create
# the widget's representation, in this case it will be a 2D slider.  A slider
# representation consists of 4 parts: a tube along which a slider runs and
# represents the range of values the slider can attain, the slider which has a
# text actor over top to display the current slider value, end caps
# to signify the ends of the slider's range and a text actor to display a
# title about what the slider represents (e.g., temperature, time, number
# of camera frames etc.).  The tube and the end caps can be clicked on and
# the slider will move to that chosen location.  The slider can be dragged along
# the tube.
#
  vtkSliderRepresentation2D sliderRep
  sliderRep SetMinimumValue 10
  sliderRep SetMaximumValue 1000
  sliderRep SetValue 500
  sliderRep SetTitleText "Number of Frames"

# Position the representation to be along the bottom of the render window
# and to the right of the camera widget.
#
  [sliderRep GetPoint1Coordinate] SetCoordinateSystemToNormalizedDisplay
  [sliderRep GetPoint1Coordinate] SetValue 0.3 0.1
  [sliderRep GetPoint2Coordinate] SetCoordinateSystemToNormalizedDisplay
  [sliderRep GetPoint2Coordinate] SetValue 0.9 0.1

# Specifiy the sizes of the slider, the end caps and the slider's tube.
#
  sliderRep SetSliderLength 0.02
  sliderRep SetSliderWidth 0.03
  sliderRep SetEndCapLength 0.01
  sliderRep SetEndCapWidth 0.03
  sliderRep SetTubeWidth 0.005
  sliderRep SetLabelFormat "%4.0lf"

# Create the actual slider widget that will listen and react to events.
#
vtkSliderWidget sliderWidget
  sliderWidget SetInteractor iren
  sliderWidget SetRepresentation sliderRep
  sliderWidget KeyPressActivationOff

# The slider widget can respond to interactions by either immediately updating
# the representation's slider position, or by animating it from its current
# position to a newly chosen one.
#
  sliderWidget SetAnimationModeToAnimate

# Add a callback to the slider widget to set the number of frames desired
# during playback by the camera widget.  More frames results in a longer/slower
# playback.
#
  sliderWidget AddObserver InteractionEvent callback

#  Add the actors to the renderer, set the background color and size.
#
  ren1 AddActor world
  ren1 SetBackground .1 .2 .4
  renWin SetSize 600 400

# Initialize the interactor so we can get the active camera.
#
  iren Initialize
  renWin Render

# Set the camera that the representation will record.
#
  cameraRep SetCamera [ ren1 GetActiveCamera ]

# Turn on both widgets.
#
  cameraWidget On
  sliderWidget On

  iren AddObserver UserEvent {wm deiconify .vtkInteract}

# Prevent the tk window from showing up then start the event loop.
#
  wm withdraw .

# vtkMath is needed to convert double values returned by the slider
# representation into integers.
#
  vtkMath math

# Callback for the interaction
#
proc callback { } {
  cameraRep SetNumberOfFrames [ eval math Round [ sliderRep GetValue ] ]
}

iren Start