AnimateActors

VTKExamples/Cxx/Animation/AnimateActors


Question

If you have a simple question about this example contact us at VTKExamplesProject If your question is more complex and may require extended discussion, please use the VTK Discourse Forum

Code

AnimateActors.cxx

#include "AnimateActors.h"

#include <vtkAnimationCue.h>
#include <vtkAnimationScene.h>
#include <vtkCamera.h>
#include <vtkColor.h>
#include <vtkCommand.h>
#include <vtkConeSource.h>
#include <vtkNamedColors.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>

int main(int argc, char* argv[])
{
  // Colors
  auto colors = vtkSmartPointer<vtkNamedColors>::New();
  vtkColor3d coneColor = colors->GetColor3d("Tomato");
  vtkColor3d sphereColor = colors->GetColor3d("Banana");
  vtkColor3d backgroundColor = colors->GetColor3d("Peacock");

  // Create the graphics structure. The renderer renders into the
  // render window.
  auto iren = vtkSmartPointer<vtkRenderWindowInteractor>::New();
  auto ren1 = vtkSmartPointer<vtkRenderer>::New();
  ren1->SetBackground(backgroundColor.GetData());

  auto renWin = vtkSmartPointer<vtkRenderWindow>::New();
  renWin->SetMultiSamples(0);
  iren->SetRenderWindow(renWin);
  renWin->AddRenderer(ren1);

  // Generate a sphere
  auto sphereSource = vtkSmartPointer<vtkSphereSource>::New();
  sphereSource->SetPhiResolution(31);
  sphereSource->SetThetaResolution(31);

  auto sphereMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  sphereMapper->SetInputConnection(sphereSource->GetOutputPort());
  auto sphere = vtkSmartPointer<vtkActor>::New();
  sphere->SetMapper(sphereMapper);
  sphere->GetProperty()->SetDiffuseColor(sphereColor.GetData());
  sphere->GetProperty()->SetDiffuse(.7);
  sphere->GetProperty()->SetSpecular(.3);
  sphere->GetProperty()->SetSpecularPower(30.0);

  ren1->AddActor(sphere);

  // Generate a cone
  auto coneSource = vtkSmartPointer<vtkConeSource>::New();
  coneSource->SetResolution(31);

  auto coneMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  coneMapper->SetInputConnection(coneSource->GetOutputPort());
  auto cone = vtkSmartPointer<vtkActor>::New();
  cone->SetMapper(coneMapper);
  cone->GetProperty()->SetDiffuseColor(coneColor.GetData());

  ren1->AddActor(cone);

  // Create an Animation Scene
  auto 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
  auto cue1 = vtkSmartPointer<vtkAnimationCue>::New();
  cue1->SetStartTime(5);
  cue1->SetEndTime(23);
  scene->AddCue(cue1);

  auto 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 <vector>
#include <vtkActor.h>
#include <vtkAnimationCue.h>
#include <vtkCommand.h>
#include <vtkRenderWindow.h>

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> const& position)
  {
    this->StartPosition = position;
  }
  void SetEndPosition(std::vector<double> const& 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 3.3 FATAL_ERROR)

project(AnimateActors)

find_package(VTK COMPONENTS 
  vtkCommonColor
  vtkCommonCore
  vtkCommonDataModel
  vtkFiltersSources
  vtkInteractionStyle
  vtkRenderingContextOpenGL2
  vtkRenderingCore
  vtkRenderingFreeType
  vtkRenderingGL2PSOpenGL2
  vtkRenderingOpenGL2 QUIET)
if (NOT VTK_FOUND)
  message("Skipping AnimateActors: ${VTK_NOT_FOUND_MESSAGE}")
  return ()
endif()
message (STATUS "VTK_VERSION: ${VTK_VERSION}")
if (VTK_VERSION VERSION_LESS "8.90.0")
  # old system
  include(${VTK_USE_FILE})
  add_executable(AnimateActors MACOSX_BUNDLE AnimateActors.cxx )
  target_link_libraries(AnimateActors PRIVATE ${VTK_LIBRARIES})
else ()
  # include all components
  add_executable(AnimateActors MACOSX_BUNDLE AnimateActors.cxx )
  target_link_libraries(AnimateActors PRIVATE ${VTK_LIBRARIES})
  # vtk_module_autoinit is needed
  vtk_module_autoinit(
    TARGETS AnimateActors
    MODULES ${VTK_LIBRARIES}
    )
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

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