SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLAnimTrack Class Referenceabstract

Abstract base class for SLAnimationTracks providing time and keyframe functions. More...

#include <SLAnimTrack.h>

Inheritance diagram for SLAnimTrack:
[legend]

Public Member Functions

 SLAnimTrack (SLAnimation *parent)
 
virtual ~SLAnimTrack ()
 
SLAnimKeyframecreateKeyframe (SLfloat time)
 
SLfloat getKeyframesAtTime (SLfloat time, SLAnimKeyframe **k1, SLAnimKeyframe **k2) const
 
virtual void calcInterpolatedKeyframe (SLfloat time, SLAnimKeyframe *keyframe) const =0
 
virtual void apply (SLfloat time, SLfloat weight=1.0f, SLfloat scale=1.0f)=0
 
virtual void drawVisuals (SLSceneView *sv)=0
 
SLint numKeyframes () const
 
SLAnimKeyframekeyframe (SLint index)
 

Protected Member Functions

virtual SLAnimKeyframecreateKeyframeImpl (SLfloat time)=0
 Keyframe creator function for derived implementations. More...
 

Protected Attributes

SLAnimation_animation
 parent animation that created this track More...
 
SLVKeyframe _keyframes
 keyframe list for this track More...
 

Detailed Description

Abstract base class for SLAnimationTracks providing time and keyframe functions.

An animation track is a specialized track that affects a single SLNode or an SLJoint of an SLAnimSkeleton by interpolating its transform. It holds therefore a list of SLKeyframe. For a smooth motion it can interpolate the transform at a given time between two neighboring SLKeyframe.

Definition at line 31 of file SLAnimTrack.h.

Constructor & Destructor Documentation

◆ SLAnimTrack()

SLAnimTrack::SLAnimTrack ( SLAnimation animation)

Constructor

Definition at line 18 of file SLAnimTrack.cpp.

19  : _animation(animation)
20 {
21 }
SLAnimation * _animation
parent animation that created this track
Definition: SLAnimTrack.h:54

◆ ~SLAnimTrack()

SLAnimTrack::~SLAnimTrack ( )
virtual

Destructor

Definition at line 26 of file SLAnimTrack.cpp.

27 {
28  for (auto kf : _keyframes)
29  delete kf;
30 }
SLVKeyframe _keyframes
keyframe list for this track
Definition: SLAnimTrack.h:55

Member Function Documentation

◆ apply()

virtual void SLAnimTrack::apply ( SLfloat  time,
SLfloat  weight = 1.0f,
SLfloat  scale = 1.0f 
)
pure virtual

Implemented in SLNodeAnimTrack.

◆ calcInterpolatedKeyframe()

virtual void SLAnimTrack::calcInterpolatedKeyframe ( SLfloat  time,
SLAnimKeyframe keyframe 
) const
pure virtual

Implemented in SLNodeAnimTrack.

◆ createKeyframe()

SLAnimKeyframe * SLAnimTrack::createKeyframe ( SLfloat  time)

Creates a new keyframed with the passed in timestamp.

Note
It is required that the keyframes are created in chronological order. since we currently don't sort the keyframe list they have to be sorted before being created.

Definition at line 38 of file SLAnimTrack.cpp.

39 {
41  _keyframes.push_back(kf);
42  return kf;
43 }
Base class for all animation keyframes.
virtual SLAnimKeyframe * createKeyframeImpl(SLfloat time)=0
Keyframe creator function for derived implementations.

◆ createKeyframeImpl()

virtual SLAnimKeyframe* SLAnimTrack::createKeyframeImpl ( SLfloat  time)
protectedpure virtual

Keyframe creator function for derived implementations.

Implemented in SLNodeAnimTrack.

◆ drawVisuals()

virtual void SLAnimTrack::drawVisuals ( SLSceneView sv)
pure virtual

Implemented in SLNodeAnimTrack.

◆ getKeyframesAtTime()

SLfloat SLAnimTrack::getKeyframesAtTime ( SLfloat  time,
SLAnimKeyframe **  k1,
SLAnimKeyframe **  k2 
) const

Get the two keyframes to the left or the right of the passed in timestamp. If keyframes will wrap around, if there is no keyframe after the passed in time then the k2 result will be the first keyframe in the list. If only one keyframe exists the two values will be equivalent.

Todo:
do we want to consider the edge case below or do we want imported animations to have to have a keyframe at 0.0 time? Is there a better solution for this problem? e.x: the astroboy animation looks wrong when doing this (but thats because it is **** and kf0 and kfn dont match up...

Definition at line 62 of file SLAnimTrack.cpp.

65 {
66  SLfloat t1, t2;
67  SLuint numKf = (SLuint)_keyframes.size();
68  float animationLength = _animation->lengthSec();
69 
70  assert(animationLength > 0.0f && "Animation length is invalid.");
71 
72  *k1 = *k2 = nullptr;
73 
74  // no keyframes or only one keyframe in animation, early out
75  if (numKf == 0)
76  return 0.0f;
77 
78  if (numKf < 2)
79  {
80  *k1 = *k2 = _keyframes[0];
81  return 0.0f;
82  }
83 
84  // wrap time
85  if (time > animationLength)
86  time = fmod(time, animationLength);
87 
88  // @todo is it really required of us to check if time is < 0.0f here? Or should this be done higher up?
89  while (time < 0.0f)
90  time += animationLength;
91 
92  // search lower bound kf for given time
93  // kf list must be sorted by time at this point
94  // @todo we could use std::lower_bounds here
95  // @todo this could be implemented much nicer
96  // use the following algorithm:
97  // 1. find the keyframe that comes after the 'time' parameter
98  // 2. if there is no keyframe after 'time' then set keframe 2 to the first keyframe in the list
99  // set t2 to animationLength + the time of the keyframe
100  // 3. if there is a keyframe after 'time' then set keyframe 2 to that keyframe
101  // set t2 to the time of the keyframe
102  // 4. now find the keyframe before keyframe 2 (if we use iterators here this is trivial!)
103  // set keyframe 1 to the keyframe found before keyframe 2
104  SLuint kfIndex = 0;
105  for (SLuint i = 0; i < numKf; ++i)
106  {
107  SLAnimKeyframe* cur = _keyframes[i];
108 
109  if (cur->time() <= time)
110  {
111  *k1 = cur;
112  kfIndex = i;
113  }
114  }
115 
116  // time is than first kf
117  if (*k1 == nullptr)
118  {
119  *k1 = _keyframes.back();
120  // as long as k1 is in the back
121  }
122 
123  t1 = (*k1)->time();
124 
125  if (*k1 == _keyframes.back())
126  {
127  *k2 = _keyframes.front();
128  t2 = animationLength + (*k2)->time();
129  }
130  else
131  {
132  *k2 = _keyframes[kfIndex + 1];
133  t2 = (*k2)->time();
134  }
135 
136  if (Utils::abs(t1 - t2) < 0.0001f)
137  return 0.0f;
138 
139  /// @todo do we want to consider the edge case below or do we want
140  /// imported animations to have to have a keyframe at 0.0 time?
141  /// Is there a better solution for this problem?
142  /// e.x: the astroboy animation looks wrong when doing this
143  /// (but thats because it is **** and kf0 and kfn dont match up...
144  //
145  // if an animation doesn't have a keyframe at 0.0 and
146  // k1 is the last keyframe and k2 is the first keyframe
147  // and the current timestamp is just above zero in the timeline
148  //
149  // like this:
150  // 0.0 animationLenth
151  // |-.--*----------*----*------*------|~~~~*
152  // ^ ^ ^ ^
153  // | t2 t1 t2'
154  //
155  // t2' is where we put the t2 value if its a wrap around!
156  // time
157  // then the calculation below wont work because time < t1.
158  //
159  //
160  if (time < t1)
161  time += animationLength;
162 
163  return (time - t1) / (t2 - t1);
164 }
float SLfloat
Definition: SL.h:173
unsigned int SLuint
Definition: SL.h:171
void time(SLfloat t)
SLfloat lengthSec() const
Definition: SLAnimation.h:72
T abs(T a)
Definition: Utils.h:249

◆ keyframe()

SLAnimKeyframe * SLAnimTrack::keyframe ( SLint  index)

Getter for keyframes by index.

Definition at line 48 of file SLAnimTrack.cpp.

49 {
50  if (index < 0 || index >= numKeyframes())
51  return nullptr;
52 
53  return _keyframes[(SLuint)index];
54 }
SLint numKeyframes() const
Definition: SLAnimTrack.h:47

◆ numKeyframes()

SLint SLAnimTrack::numKeyframes ( ) const
inline

Definition at line 47 of file SLAnimTrack.h.

47 { return (SLint)_keyframes.size(); }
int SLint
Definition: SL.h:170

Member Data Documentation

◆ _animation

SLAnimation* SLAnimTrack::_animation
protected

parent animation that created this track

Definition at line 54 of file SLAnimTrack.h.

◆ _keyframes

SLVKeyframe SLAnimTrack::_keyframes
protected

keyframe list for this track

Definition at line 55 of file SLAnimTrack.h.


The documentation for this class was generated from the following files: