VTK/Examples/Cxx/Animation/AnimateActors

From KitwarePublic
< VTK‎ | Examples‎ | Cxx
Jump to: navigation, search
VTK Examples Baseline Animation TestAnimateActors.png

This example uses vtkAnimationScene and vtkAnimationCue to animate actors. The vtk Scene and Cue classes provide a powerful mechanism for animating vtk classes. However, the setup can be complicated. This example provides an ActorAnimator class that can serve as a prototype for actor animation. It tries to hide some of the complexity of scene and cue animation.

AnimateActors.cxx

#include "AnimateActors.h"
#include <vtkSmartPointer.h>
#include <vtkAnimationCue.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>
#include <vtkConeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkCommand.h>
#include <vtkAnimationScene.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkCamera.h>
 
int main(int argc, char *argv[])
{
  // Create the graphics structure. The renderer renders into the
  // render window.
  vtkSmartPointer<vtkRenderWindowInteractor> iren =
    vtkSmartPointer<vtkRenderWindowInteractor>::New();
  vtkSmartPointer<vtkRenderer> ren1 =
    vtkSmartPointer<vtkRenderer>::New();
  vtkSmartPointer<vtkRenderWindow> renWin = 
    vtkSmartPointer<vtkRenderWindow>::New();
  renWin->SetMultiSamples(0);
  iren->SetRenderWindow(renWin);
  renWin->AddRenderer(ren1);
 
  // Generate a sphere
  vtkSmartPointer<vtkSphereSource> sphereSource =
    vtkSmartPointer<vtkSphereSource>::New();
  vtkSmartPointer<vtkPolyDataMapper> sphereMapper =
    vtkSmartPointer<vtkPolyDataMapper>::New();
  sphereMapper->SetInputConnection( sphereSource->GetOutputPort());
  vtkSmartPointer<vtkActor> sphere =
    vtkSmartPointer<vtkActor>::New();
  sphere->SetMapper(sphereMapper);
  ren1->AddActor(sphere);
 
  // Generate a cone
  vtkSmartPointer<vtkConeSource> coneSource =
    vtkSmartPointer<vtkConeSource>::New();
  vtkSmartPointer<vtkPolyDataMapper> coneMapper =
    vtkSmartPointer<vtkPolyDataMapper>::New();
  coneMapper->SetInputConnection( coneSource->GetOutputPort());
  vtkSmartPointer<vtkActor> cone =
    vtkSmartPointer<vtkActor>::New();
  cone->SetMapper(coneMapper);
  ren1->AddActor(cone);
 
  // Create an Animation Scene
  vtkSmartPointer<vtkAnimationScene> scene =
    vtkSmartPointer<vtkAnimationScene>::New();
  if(argc>=2 && strcmp(argv[1],"-real")==0)
    {
    cout << "real-time mode" << endl;
    scene->SetModeToRealTime();
    }
  else
    {
    cout << "sequence mode" << endl;
    scene->SetModeToSequence();
    }
  scene->SetLoop(0);
  scene->SetFrameRate(5);
  scene->SetStartTime(0);
  scene->SetEndTime(20);
 
  vtkSmartPointer<AnimationSceneObserver> sceneObserver =
    vtkSmartPointer<AnimationSceneObserver>::New();
  sceneObserver->SetRenderWindow(renWin);
  scene->AddObserver(vtkCommand::AnimationCueTickEvent,sceneObserver);
 
  // Create an Animation Cue for each actor
  vtkSmartPointer<vtkAnimationCue> cue1 =
    vtkSmartPointer<vtkAnimationCue>::New();
  cue1->SetStartTime(5);
  cue1->SetEndTime(23);
  scene->AddCue(cue1);
 
  vtkSmartPointer<vtkAnimationCue> cue2 =
    vtkSmartPointer<vtkAnimationCue>::New();
  cue2->SetStartTime(1);
  cue2->SetEndTime(10);
  scene->AddCue(cue2);
 
  // Create an ActorAnimator for each actor;
  ActorAnimator animateSphere;
  animateSphere.SetActor(sphere);
  animateSphere.AddObserversToCue(cue1);
 
  ActorAnimator animateCone;
  std::vector<double> endCone(3);
    endCone[0] = -1;
    endCone[1] = -1;
    endCone[2] = -1;
  animateCone.SetEndPosition(endCone);
  animateCone.SetActor(cone);
  animateCone.AddObserversToCue(cue2);
 
  renWin->Render();
  ren1->ResetCamera();
  ren1->GetActiveCamera()->Dolly(.5);
  ren1->ResetCameraClippingRange();
 
  // Create Cue observer.
  scene->Play();
  scene->Stop();
 
  iren->Start();
  return EXIT_SUCCESS;
}

AnimateActors.h

#ifndef __AnimateActors_h
#include <vtkActor.h>
#include <vtkAnimationCue.h>
#include <vtkCommand.h>
#include <vtkRenderWindow.h>
#include <vector>
 
class ActorAnimator
{
public:
  ActorAnimator()
    {
    this->Actor=0;
    this->Observer = AnimationCueObserver::New();
    this->Observer->Animator = this;
    this->StartPosition.resize(3);
    this->StartPosition.insert(this->StartPosition.begin(), 3, 0.0);
    this->EndPosition.resize(3);
    this->EndPosition.insert(this->EndPosition.begin(), 3, .5);
    }
 
  ~ActorAnimator()
    {
    if(this->Actor)
      {
      this->Actor->UnRegister(0);
      this->Actor=0;
      }
    this->Observer->UnRegister(0);
    }
  void SetActor(vtkActor *actor)
    {
    if (this->Actor)
      {
      this->Actor->UnRegister(0);
      }
    this->Actor = actor;
    this->Actor->Register(0);
    }
  void SetStartPosition(std::vector<double> position)
    {
    this->StartPosition = position;
    }
  void SetEndPosition(std::vector<double> position)
    {
    this->EndPosition = position;
    }
  void AddObserversToCue(vtkAnimationCue *cue)
    {
    cue->AddObserver(vtkCommand::StartAnimationCueEvent,this->Observer);
    cue->AddObserver(vtkCommand::EndAnimationCueEvent,this->Observer);
    cue->AddObserver(vtkCommand::AnimationCueTickEvent,this->Observer);
    }
 
  void Start(vtkAnimationCue::AnimationCueInfo *vtkNotUsed(info))
    {
    this->Actor->SetPosition(this->StartPosition[0],
                             this->StartPosition[1], 
                             this->StartPosition[2]);
    }
 
  void Tick(vtkAnimationCue::AnimationCueInfo *info)
    {
    double t = (info->AnimationTime - info->StartTime) / (info->EndTime - info->StartTime);
    double position[3];
    for (int i = 0; i < 3; i++)
      {
      position[i] = this->StartPosition[i] + (this->EndPosition[i] - this->StartPosition[i]) * t;
      }
    this->Actor->SetPosition(position);
 
    }
 
  void End(vtkAnimationCue::AnimationCueInfo *vtkNotUsed(info))
    {
    this->Actor->SetPosition(this->EndPosition[0],
                             this->EndPosition[1], 
                             this->EndPosition[2]);
    }
 
protected:
  class AnimationCueObserver : public vtkCommand
  {
  public:
    static AnimationCueObserver *New()
      {
      return new AnimationCueObserver;
      }
 
    virtual void Execute(vtkObject *vtkNotUsed(caller),
                         unsigned long event,
                         void *calldata)
      {
      if(this->Animator != 0)
        {
        vtkAnimationCue::AnimationCueInfo *info=
          static_cast<vtkAnimationCue::AnimationCueInfo *>(calldata);
        switch(event)
          {
          case vtkCommand::StartAnimationCueEvent:
            this->Animator->Start(info);
            break;
          case vtkCommand::EndAnimationCueEvent:
            this->Animator->End(info);
            break;
          case vtkCommand::AnimationCueTickEvent:
            this->Animator->Tick(info);
            break;
          }
        }
      }
 
    AnimationCueObserver()
      {
      this->Animator = 0;
      }
    ActorAnimator *Animator;
  };
 
  vtkActor *             Actor;
  AnimationCueObserver * Observer;
  std::vector<double>    StartPosition;
  std::vector<double>    EndPosition;
};
 
class AnimationSceneObserver : public vtkCommand
{
public:
  static AnimationSceneObserver *New()
    {
    return new AnimationSceneObserver;
    }
 
  void SetRenderWindow( vtkRenderWindow *renWin)
    {
    if (this->RenderWindow)
      {
      this->RenderWindow->UnRegister(this);
      }
    this->RenderWindow = renWin;
    this->RenderWindow->Register(this);
 
    }
  virtual void Execute(vtkObject *vtkNotUsed(caller),
                       unsigned long event,
                       void *vtkNotUsed(calldata))
    {
    if(this->RenderWindow != 0)
      {
      switch(event)
        {
        case vtkCommand::AnimationCueTickEvent:
          this->RenderWindow->Render();
          break;
        }
      }
    }
 
protected:
  AnimationSceneObserver()
    {
    this->RenderWindow = 0;
    }
  ~AnimationSceneObserver()
    {
    if(this->RenderWindow)
      {
      this->RenderWindow->UnRegister(this);
      this->RenderWindow = 0;
      }
    }
  vtkRenderWindow *RenderWindow;
};
 
#endif

CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
 
PROJECT(AnimateActors)
 
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
 
add_executable(AnimateActors MACOSX_BUNDLE AnimateActors.cxx)
 
if(VTK_LIBRARIES)
  target_link_libraries(AnimateActors ${VTK_LIBRARIES})
else()
  target_link_libraries(AnimateActors vtkHybrid vtkWidgets)
endif()

Download and Build AnimateActors

Click here to download AnimateActors. and its CMakeLists.txt file.

Once the tarball AnimateActors.tar has been downloaded and extracted,

cd AnimateActors/build 
  • If VTK is installed:
cmake ..
  • If VTK is not installed but compiled on your system, you will need to specify the path to your VTK build:
cmake -DVTK_DIR:PATH=/home/me/vtk_build ..

Build the project:

make

and run it:

./AnimateActors

WINDOWS USERS PLEASE NOTE: Be sure to add the VTK bin directory to your path. This will resolve the VTK dll's at run time.