SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLAnimation.cpp
Go to the documentation of this file.
1 /**
2  * \file SLAnimation.cpp
3  * \date Autumn 2014
4  * \remarks Please use clangformat to format the code. See more code style on
5  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
6  * \authors Marc Wacker, Marcus Hudritsch
7  * \copyright http://opensource.org/licenses/GPL-3.0
8 */
9 
10 #include <math/SLCurveBezier.h>
11 #include <SLScene.h>
12 
13 //-----------------------------------------------------------------------------
14 /*! Constructor
15  */
17  : _name(name), _lengthSec(duration)
18 {
19 }
20 //-----------------------------------------------------------------------------
21 /*! Destructor
22  */
24 {
25  for (auto it : _nodeAnimTracks)
26  delete it.second;
27 }
28 //-----------------------------------------------------------------------------
29 /*! Setter for the animation length
30  */
32 {
34 }
35 //-----------------------------------------------------------------------------
36 /*! Returns the timestamp for the next keyframe in all of the tracks.
37  */
39 {
40  // find the closest keyframe time to the right
41  SLfloat result = _lengthSec;
42  SLAnimKeyframe* kf1;
43  SLAnimKeyframe* kf2;
44 
45  for (auto it : _nodeAnimTracks)
46  {
47  it.second->getKeyframesAtTime(time, &kf1, &kf2);
48  if (kf2->time() < result && kf2->time() >= time)
49  result = kf2->time();
50  }
51 
52  return result;
53 }
54 //-----------------------------------------------------------------------------
55 /*! Returns the timestamp for the previous keyframe in all of the tracks.
56  */
58 {
59  // find the closest keyframe time to the right
60  SLfloat result = 0.0;
61  SLAnimKeyframe* kf1;
62  SLAnimKeyframe* kf2;
63 
64  // shift the time a little bit to the left or else the getKeyframesAtTime function
65  // would return the same keyframe over and over again
66  time -= 0.01f;
67  if (time <= 0.0f)
68  return 0.0f;
69 
70  for (auto it : _nodeAnimTracks)
71  {
72  it.second->getKeyframesAtTime(time, &kf1, &kf2);
73  if (kf1->time() > result && kf1->time() <= time)
74  result = kf1->time();
75  }
76 
77  return result;
78 }
79 //-----------------------------------------------------------------------------
80 /*! Returns true if node is the animationTarget of any of the SLNodeAnimationTracks
81 in this animation.
82 */
84 {
85  for (auto it : _nodeAnimTracks)
86  if (it.second->animatedNode() == node)
87  return true;
88 
89  return false;
90 }
91 //-----------------------------------------------------------------------------
92 /*! Creates a new SLNodeAnimationTrack with the next free handle.
93  */
95 {
96  SLuint freeIndex = 0;
97 
98  auto it = _nodeAnimTracks.begin();
99  for (; it != _nodeAnimTracks.end() && freeIndex == it->first; ++it, ++freeIndex)
100  {
101  }
102 
103  return createNodeAnimTrack(freeIndex);
104 }
105 //-----------------------------------------------------------------------------
106 /*! Creates a new SLNodeAnimationTrack with the passed in track id.
107  */
109 {
110  // track with same handle already exists
111  if (_nodeAnimTracks.find(trackID) != _nodeAnimTracks.end())
112  return nullptr;
113 
114  _nodeAnimTracks[trackID] = new SLNodeAnimTrack(this);
115 
116  return _nodeAnimTracks[trackID];
117 }
118 //-----------------------------------------------------------------------------
119 /*! Applies all animation tracks for the passed in timestamp, weight and scale.
120  */
121 void SLAnimation::apply(SLfloat time, SLfloat weight, SLfloat scale)
122 {
123  for (auto it : _nodeAnimTracks)
124  it.second->apply(time, weight, scale);
125 }
126 //-----------------------------------------------------------------------------
127 /*! Applies all node tracks of this animation on a single node
128  */
130  SLfloat time,
131  SLfloat weight,
132  SLfloat scale)
133 {
134  for (auto it : _nodeAnimTracks)
135  it.second->applyToNode(node, time, weight, scale);
136 }
137 //-----------------------------------------------------------------------------
138 /*! Applies all the tracks to their respective joints in the passed in skeleton.
139  */
141  SLfloat time,
142  SLfloat weight,
143  SLfloat scale)
144 {
145  for (auto it : _nodeAnimTracks)
146  {
147  SLJoint* joint = skel->getJoint(it.first);
148  it.second->applyToNode(joint, time, weight, scale);
149  }
150 }
151 //-----------------------------------------------------------------------------
152 /*! Draws the visualizations of all node tracks
153  */
155 {
156  for (auto it : _nodeAnimTracks)
157  it.second->drawVisuals(sv);
158 }
159 //-----------------------------------------------------------------------------
160 /*! Resets all default animation targets to their initial state.
161  */
163 {
164  for (auto it : _nodeAnimTracks)
165  it.second->animatedNode()->resetToInitialState();
166 }
167 //-----------------------------------------------------------------------------
168 /*! Specialized SLNodeAnimationTrack creator for a two keyframe translation animation
169  */
171  const SLVec3f& endPos)
172 {
174  target->setInitialState();
175  track->animatedNode(target);
176  track->createNodeKeyframe(0.0f);
177  track->createNodeKeyframe(lengthSec())->translation(endPos);
178  return track;
179 }
180 //-----------------------------------------------------------------------------
181 /*! Specialized SLNodeAnimationTrack creator for a two keyframe rotation
182  * animation from 0° to angleDeg.
183  */
185  SLfloat angleDeg,
186  const SLVec3f& axis)
187 {
189  target->setInitialState();
190  track->animatedNode(target);
191  track->createNodeKeyframe(0.0f);
192  track->createNodeKeyframe(lengthSec())->rotation(SLQuat4f(angleDeg, axis));
193  return track;
194 }
195 //-----------------------------------------------------------------------------
196 /*! Specialized SLNodeAnimationTrack creator for 2 keyframes at angleDeg0 and
197  * angleDeg1.
198  */
200  SLfloat angleDeg0,
201  SLfloat angleDeg1,
202  const SLVec3f& axis)
203 {
205  target->setInitialState();
206  track->animatedNode(target);
207 
208  SLTransformKeyframe* frame0 = track->createNodeKeyframe(0.0f);
209  frame0->rotation(SLQuat4f(angleDeg0, axis));
210 
212  frame1->rotation(SLQuat4f(angleDeg1, axis));
213 
214  return track;
215 }
216 //-----------------------------------------------------------------------------
217 /*! Specialized SLNodeAnimationTrack creator for 3 keyframes at angleDeg0,
218  * angleDeg1 and angleDeg2.
219  */
221  SLfloat angleDeg0,
222  SLfloat angleDeg1,
223  SLfloat angleDeg2,
224  const SLVec3f& axis)
225 {
227  target->setInitialState();
228  track->animatedNode(target);
229 
230  SLTransformKeyframe* frame0 = track->createNodeKeyframe(0.0f);
231  frame0->rotation(SLQuat4f(angleDeg0, axis));
232 
233  SLTransformKeyframe* frame1 = track->createNodeKeyframe(lengthSec() * 0.5f);
234  frame1->rotation(SLQuat4f(angleDeg1, axis));
235 
237  frame2->rotation(SLQuat4f(angleDeg2, axis));
238 
239  return track;
240 }
241 //-----------------------------------------------------------------------------
242 /*! Specialized SLNodeAnimationTrack creator for 4 keyframes at angleDeg0,
243  * angleDeg1, angleDeg2 and angleDeg3.
244  */
246  SLfloat angleDeg0,
247  SLfloat angleDeg1,
248  SLfloat angleDeg2,
249  SLfloat angleDeg3,
250  const SLVec3f& axis)
251 {
253  target->setInitialState();
254  track->animatedNode(target);
255 
256  SLTransformKeyframe* frame0 = track->createNodeKeyframe(0.0f);
257  frame0->rotation(SLQuat4f(angleDeg0, axis));
258 
259  SLTransformKeyframe* frame1 = track->createNodeKeyframe(lengthSec() * 0.3333f);
260  frame1->rotation(SLQuat4f(angleDeg1, axis));
261 
262  SLTransformKeyframe* frame2 = track->createNodeKeyframe(lengthSec() * 0.6666f);
263  frame2->rotation(SLQuat4f(angleDeg2, axis));
264 
266  frame3->rotation(SLQuat4f(angleDeg3, axis));
267 
268  return track;
269 }
270 //-----------------------------------------------------------------------------
271 /*! Specialized SLNodeAnimationTrack creator for a 360 deg. node rotation track
272  * with 3 keyframes from 0° to 180° to 360°.
273  */
275  const SLVec3f& axis)
276 {
278  target->setInitialState();
279  track->animatedNode(target);
280 
281  SLTransformKeyframe* frame0 = track->createNodeKeyframe(0.0f);
282  frame0->rotation(SLQuat4f(0.0f, axis));
283 
284  SLTransformKeyframe* frame1 = track->createNodeKeyframe(lengthSec() * 0.5f);
285  frame1->rotation(SLQuat4f(180.0f, axis));
286 
288  frame2->rotation(SLQuat4f(360.0f, axis));
289 
290  return track;
291 }
292 //-----------------------------------------------------------------------------
293 /*! Specialized SLNodeAnimationTrack creator for a two keyframe scaling animation
294  */
296  const SLVec3f& endScale)
297 {
299  target->setInitialState();
300  track->animatedNode(target);
301  track->createNodeKeyframe(0.0f);
302  track->createNodeKeyframe(lengthSec())->scale(endScale);
303  return track;
304 }
305 
306 //-----------------------------------------------------------------------------
307 /*! Specialized SLNodeAnimationTrack creator for an elliptic node animation
308  */
310  SLfloat radiusA,
311  SLAxis axisA,
312  SLfloat radiusB,
313  SLAxis axisB)
314 {
315  assert(axisA != axisB && radiusA > 0 && radiusB > 0);
317  target->setInitialState();
318  track->animatedNode(target);
319 
320  /* The ellipse is defined by 5 keyframes: A,B,C,D and again A
321 
322  c2----B----c1
323  c3 c0
324  | |
325  | | |
326  C --0-- A
327  | | |
328  | |
329  c4 c7
330  c5----D----c6
331  */
332 
333  SLVec3f A(0, 0, 0);
334  A.comp[axisA] = radiusA;
335  SLVec3f B(0, 0, 0);
336  B.comp[axisB] = radiusB;
337  SLVec3f C(0, 0, 0);
338  C.comp[axisA] = -radiusA;
339  SLVec3f D(0, 0, 0);
340  D.comp[axisB] = -radiusB;
341 
342  // Control points with the magic factor kappa for control points
343  SLfloat k = 0.5522847498f;
344 
345  SLVVec3f controls;
346  controls.resize(8);
347  for (SLuint i = 0; i < controls.size(); ++i)
348  controls[i].set(0, 0, 0);
349  controls[0].comp[axisA] = radiusA;
350  controls[0].comp[axisB] = k * radiusB;
351  controls[1].comp[axisB] = radiusB;
352  controls[1].comp[axisA] = k * radiusA;
353  controls[2].comp[axisB] = radiusB;
354  controls[2].comp[axisA] = k * -radiusA;
355  controls[3].comp[axisA] = -radiusA;
356  controls[3].comp[axisB] = k * radiusB;
357  controls[4].comp[axisA] = -radiusA;
358  controls[4].comp[axisB] = k * -radiusB;
359  controls[5].comp[axisB] = -radiusB;
360  controls[5].comp[axisA] = k * -radiusA;
361  controls[6].comp[axisB] = -radiusB;
362  controls[6].comp[axisA] = k * radiusA;
363  controls[7].comp[axisA] = radiusA;
364  controls[7].comp[axisB] = k * -radiusB;
365 
366  // Add keyframes
367  SLfloat t4 = lengthSec() / 4.0f;
368  track->createNodeKeyframe(0.0f * t4)->translation(A);
369  track->createNodeKeyframe(1.0f * t4)->translation(B);
370  track->createNodeKeyframe(2.0f * t4)->translation(C);
371  track->createNodeKeyframe(3.0f * t4)->translation(D);
372  track->createNodeKeyframe(4.0f * t4)->translation(A);
373 
374  // Build curve data w. cumulated times
375  SLVVec4f points;
376  points.resize((SLulong)track->numKeyframes());
377  for (SLuint i = 0; i < (SLuint)track->numKeyframes(); ++i)
378  {
380  points[i].set(kf->translation().x,
381  kf->translation().y,
382  kf->translation().z,
383  kf->time());
384  }
385 
386  // create curve and delete temp arrays again
387  track->interpolationCurve(new SLCurveBezier(points, controls));
389 
390  return track;
391 }
392 //-----------------------------------------------------------------------------
float SLfloat
Definition: SL.h:173
unsigned long SLulong
Definition: SL.h:165
unsigned int SLuint
Definition: SL.h:171
bool SLbool
Definition: SL.h:175
string SLstring
Definition: SL.h:158
int SLint
Definition: SL.h:170
SLAxis
Coordinate axis enumeration.
Definition: SLEnums.h:79
@ AI_bezier
Definition: SLEnums.h:162
SLQuat4< SLfloat > SLQuat4f
Definition: SLQuat4.h:846
vector< SLVec3f > SLVVec3f
Definition: SLVec3.h:325
vector< SLVec4f > SLVVec4f
Definition: SLVec4.h:239
Base class for all animation keyframes.
void time(SLfloat t)
SLAnimSkeleton keeps track of a skeletons joints and animations.
SLJoint * getJoint(SLuint id)
SLAnimKeyframe * keyframe(SLint index)
Definition: SLAnimTrack.cpp:48
SLint numKeyframes() const
Definition: SLAnimTrack.h:47
SLNodeAnimTrack * createNodeAnimTrackForRotation(SLNode *target, SLfloat angleDeg1, const SLVec3f &axis)
void drawNodeVisuals(SLSceneView *sv)
SLAnimation(const SLstring &name, SLfloat duration)
Definition: SLAnimation.cpp:16
SLNodeAnimTrack * createNodeAnimTrackForRotation360(SLNode *target, const SLVec3f &axis)
SLMNodeAnimTrack _nodeAnimTracks
map of all the node tracks in this animation
Definition: SLAnimation.h:81
SLNodeAnimTrack * createNodeAnimTrack()
Definition: SLAnimation.cpp:94
SLfloat _lengthSec
duration of the animation in seconds
Definition: SLAnimation.h:80
SLfloat lengthSec() const
Definition: SLAnimation.h:72
SLfloat prevKeyframeTime(SLfloat time)
Definition: SLAnimation.cpp:57
SLNodeAnimTrack * createNodeAnimTrackForRotation3(SLNode *target, SLfloat angleDeg0, SLfloat angleDeg1, SLfloat angleDeg2, const SLVec3f &axis)
SLbool affectsNode(SLNode *node)
Definition: SLAnimation.cpp:83
SLNodeAnimTrack * createNodeAnimTrackForTranslation(SLNode *target, const SLVec3f &endPos)
SLNodeAnimTrack * createNodeAnimTrackForRotation4(SLNode *target, SLfloat angleDeg0, SLfloat angleDeg1, SLfloat angleDeg2, SLfloat angleDeg3, const SLVec3f &axis)
void resetNodes()
SLNodeAnimTrack * createNodeAnimTrackForScaling(SLNode *target, const SLVec3f &endScale)
void apply(SLfloat time, SLfloat weight=1.0f, SLfloat scale=1.0f)
SLfloat nextKeyframeTime(SLfloat time)
Definition: SLAnimation.cpp:38
void applyToNode(SLNode *node, SLfloat time, SLfloat weight=1.0f, SLfloat scale=1.0f)
SLNodeAnimTrack * createNodeAnimTrackForEllipse(SLNode *target, SLfloat radiusA, SLAxis axisA, SLfloat radiusB, SLAxis axisB)
SLNodeAnimTrack * createNodeAnimTrackForRotation2(SLNode *target, SLfloat angleDeg0, SLfloat angleDeg1, const SLVec3f &axis)
The SLCurveBezier class implements a Bezier curve interpolation.
Definition: SLCurveBezier.h:25
Specialized SLNode that represents a single joint (or bone) in a skeleton.
Definition: SLJoint.h:27
Specialized animation track for node animations.
Definition: SLAnimTrack.h:66
void animatedNode(SLNode *target)
Definition: SLAnimTrack.h:73
void interpolationCurve(SLCurve *curve)
SLTransformKeyframe * createNodeKeyframe(SLfloat time)
void translationInterpolation(SLAnimInterpolation interp)
Definition: SLAnimTrack.h:82
SLNode represents a node in a hierarchical scene graph.
Definition: SLNode.h:147
void setInitialState()
Definition: SLNode.cpp:1084
SceneView class represents a dynamic real time 3D view onto the scene.
Definition: SLSceneView.h:69
SLTransformKeyframe is a specialized SLKeyframe for node transformations.
void translation(const SLVec3f &t)
void scale(const SLVec3f &s)
void rotation(const SLQuat4f &r)
T comp[3]
Definition: SLVec3.h:46
void set(std::string path, const std::vector< char > &data)
Definition: SLIOMemory.cpp:29