Support for keyframe based animation

Agreed, this is critical for usability.

To add support for interpolation and associated UI for key frame edition, here is what I was thinking (based on what we discussed during the last project week).

The Key Frame editor

from a high level, I suggest we keep things simple and support the following:

(1) a master timeline to drive the animation. (at first we would only have “Real-time” mode where we set the the duration in seconds).

We could reuse the Drishti widget (MIT License) or the one from Paraview, or an improved version getting the best of both.

  • Drishti timeline (I was able to compile it … and it was not straightforward)

  • Paraview timeline

(2) three pre-defined tracks:

  • camera path

  • ROINode (the one allowing to crop volume rendering)

  • transfer function

where keyframe can explicitly be added/removed only for ROINode and transfer function

The “camera path” would be defined using an improved version of the endoscopy module (as describe here).

Suggested approach

This section describe a possible way to more forward by updating the sequences modules to be user in Key Frame editor.

See https://www.slicer.org/wiki/Documentation/Nightly/Extensions/Sequences

Features already available in sequences extension

Given the current sequences implementation where:

  • A given vtkMRMLSequenceNode is associated with a collection of data nodes.

  • A vtkMRMLSequenceBrowserNode is associated with a collection of vtkMRMLSequenceNode

  • The entrypoint for updating all proxy nodes is the function vtkSlicerSequenceBrowserLogic::UpdateProxyNodesFromSequences

  • The “time steps” available in a given sequence browser corresponds to the number of “items” associated with a browser node, itself corresponding to the number data nodes in the associated master node.

  • if a synchronized sequence node (different from the master sequence) doesn’t have a data node corresponding to the requested “step” (call “indexValue” in the code), the closest data node is used to update the proxy node. This is implemented in

    • vtkMRMLSequenceNode::GetItemNumberFromIndexValue(const std::string& indexValue, bool exactMatchRequired /* =true */)

    • vtkMRMLSequenceNode::GetDataNodeAtValue(const std::string& indexValue, bool exactMatchRequired /* =true */)

We need a way to map:

  • the concept of track and key frame with vtkMRMLSequenceNode, vtkMRMLSequenceBrowserNode and data node

  • have a container to store time for a key frame, and interpolation function used between two frames

Good news, key frames are data node within a vtkMRMLSequenceNode

Support for interpolation

To support interpolation , I was then thinking of the following:

  • update the parameter exactMatchRequired from “GetDataNodeAtValue” function to be something like “interpolationMode” accepting the following values:

    • ExactMatch

    • ClosestMatch

    • ExactMatchOrInterpolated Interpolated

  • In case of ExactMatchOrInterpolated mode, if not an exact match GetDataNodeAtValue would have to perform the interpolation (or retrieved a cached value of the interpolated data node)

  • the interpolation function would have the following paramerters: fromDataNode, toDataNode, nodeInterpolator, fromTime, toTime and currentTime (or fromStep, toStep and currentStep)

  • within each sequence node we would store a vector of “node interpolators”. This would corresponds to the function applies when performing an interpolation between two data nodes.

  • update the vtkMRMLNodeSequencer::NodeSequencer base class adding interpolation method : GetInterplatedNode(vtkMRMLNode* from, vtkMRMLNode* to, vtkMRMLNodeSequencer::NodeInterpolator* interpolator, double fromTime, double toTime, double currentTime)

Reusing Paraview code

I was initially thinking to extract some of the code of Paraview and add it to VTK so that we can reuse some in both Slicer and Paraview:

  vtkPVKeyFrame
  vtkPVCompositeKeyFrame
  vtkPVBooleanKeyFrame
  vtkPVSinusoidKeyFrame
  vtkPVExponentialKeyFrame
  vtkPVRampKeyFrame
  vtkPVKeyFrameCueManipulator (and base class vtkPVCueManipulator)
  vtkRealtimeAnimationPlayer
  vtkSequenceAnimationPlayer
  vtkTimestepsAnimationPlayer
  vtkCompositeAnimationPlayer
  vtkSMAnimationScene (investigate if changes can be integrated with vtkAnimationScene)
  Note that vtkAnimationCue and vtkAnimationScene are already part of VTK.

But it seems the API available in the sequences module doesn’t really overlap with what was done in Paraview.