Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/util/animation/animation3d.cc @ 3982

Last change on this file since 3982 was 3982, checked in by bensch, 19 years ago

orxonox/trunk: now there is a posibility to play only parts of the animation:
use anim→playNextKeyframes(count_of_keyframes_to_play); to make it work

File size: 13.2 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Patrick Boenzli
13   co-programmer: Benjamin Grauer
14
15   2005-04-17: Benjamin Grauer
16          Rewritte all functions, so it will fit into the Animation-class
17   2005-04-25: Patrick Boenzli
18          Extended the framework to support quatSlerp rotations. Each frame now supports diff mov/rot types. Implemented mov/rot functions
19*/
20
21#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_ANIM
22
23#include "animation3d.h"
24
25#include "p_node.h"
26
27using namespace std;
28
29/**
30   \brief standard constructor
31*/
32Animation3D::Animation3D(PNode* object)
33{
34  this->object = object;
35
36  // create a new List
37  this->keyFrameList = new tList<KeyFrame3D>();
38  KeyFrame3D* tmpKeyFrame = new KeyFrame3D;
39  tmpKeyFrame->position = Vector();
40  tmpKeyFrame->direction = Quaternion();
41  keyFrameList->add(tmpKeyFrame);
42
43  this->currentKeyFrame = tmpKeyFrame;
44  this->nextKeyFrame = tmpKeyFrame;
45
46  this->animFuncMov = &Animation3D::mLinear;
47  this->animFuncRot = &Animation3D::rLinear;
48}
49
50/**
51   \brief standard deconstructor
52   
53   deletes all the Keyframes
54*/
55Animation3D::~Animation3D(void)
56{
57  // delete all the KeyFrames
58  tIterator<KeyFrame3D>* itKF = keyFrameList->getIterator();
59  KeyFrame3D*  enumKF = itKF->nextElement();
60  while (enumKF)
61    {
62      delete enumKF;
63      enumKF = itKF->nextElement();
64    }
65  delete itKF;
66  delete this->keyFrameList;
67}
68
69/**
70   \brief rewinds the Animation to the beginning (first KeyFrame and time == 0)
71*/
72void Animation3D::rewind(void)
73{
74  this->currentKeyFrame = keyFrameList->firstElement();
75  this->nextKeyFrame = keyFrameList->nextElement(keyFrameList->firstElement());
76  this->localTime = 0.0;
77  this->setAnimFuncMov(this->currentKeyFrame->animFuncMov);
78  this->setAnimFuncRot(this->currentKeyFrame->animFuncRot);
79}
80
81/**
82   \brief Appends a new Keyframe
83   \param position The position of the new Keyframe
84   \param direction The direction of the new Keyframe.
85   \param duration The duration from the new KeyFrame to the next one
86   \param animFuncMov The function to animate position between this keyFrame and the next one
87   \param animFuncMov The function to animate rotation between this keyFrame and the next one
88*/
89void Animation3D::addKeyFrame(Vector position, Quaternion direction, float duration, ANIM_FUNCTION animFuncMov, ANIM_FUNCTION animFuncRot)
90{
91  // some small check
92  if (duration <= 0.0)
93    duration = 1.0;
94  // if the Rotation-Animation-function is set ANIM_NULL, animFuncRot will match animFuncRot
95  if (animFuncMov == ANIM_NULL)
96    animFuncMov = ANIM_DEFAULT_FUNCTION;
97  if (animFuncRot == ANIM_NULL)
98    animFuncRot = animFuncMov;
99
100  KeyFrame3D* tmpKeyFrame;
101   
102  // when adding the first frame
103  if (this->keyFrameCount == 0)
104    {
105      tmpKeyFrame = this->keyFrameList->firstElement();
106      this->setAnimFuncMov(animFuncMov);
107      this->setAnimFuncRot(animFuncRot);
108    }
109  else
110    {
111      tmpKeyFrame = new KeyFrame3D;
112      // when adding the second frame
113      if (this->currentKeyFrame == this->nextKeyFrame)
114        this->nextKeyFrame = tmpKeyFrame;
115      this->keyFrameList->add(tmpKeyFrame);
116    }
117
118  tmpKeyFrame->position = position;
119  //tmpKeyFrame->lastPosition = position;
120  tmpKeyFrame->direction = direction;
121  tmpKeyFrame->duration = duration;
122  tmpKeyFrame->animFuncMov = animFuncMov;
123  tmpKeyFrame->animFuncRot = animFuncRot;
124  this->keyFrameCount++;
125}
126
127
128
129/**
130   \brief ticks the Animation
131   \param dt how much time to tick
132*/
133void Animation3D::tick(float dt)
134{
135  if (this->bRunning)
136    { 
137      this->localTime += dt;
138      if (localTime >= this->currentKeyFrame->duration)
139        {
140          if (likely(this->keyFramesToPlay != 0))
141            {
142              if (unlikely(this->keyFramesToPlay > 0))
143                --this->keyFramesToPlay;
144              // switching to the next Key-Frame
145              this->localTime -= this->currentKeyFrame->duration;
146              this->currentKeyFrame = this->nextKeyFrame;
147              // checking, if we should still Play the animation
148              if (this->currentKeyFrame == this->keyFrameList->lastElement())
149                this->handleInfinity();
150              this->nextKeyFrame = this->keyFrameList->nextElement(this->currentKeyFrame);
151              this->setAnimFuncMov(this->currentKeyFrame->animFuncMov);
152              this->setAnimFuncRot(this->currentKeyFrame->animFuncRot);
153            }
154          else
155            this->pause();
156        }     
157      /* now animate it */
158      (this->*animFuncMov)(this->localTime);
159      (this->*animFuncRot)(this->localTime);
160    }
161}
162
163
164/*==Movement Section==========================================================*/
165
166/**
167   \brief Sets The kind of movment Animation between this keyframe and the next one
168   \param animFunc The Type of Animation to set
169*/
170void Animation3D::setAnimFuncMov(ANIM_FUNCTION animFuncMov)
171{
172  switch (animFuncMov)
173    {
174    default:
175    case ANIM_CONSTANT:
176      this->animFuncMov = &Animation3D::mConstant;
177      break;
178    case ANIM_LINEAR:
179      this->animFuncMov = &Animation3D::mLinear;
180      this->object->setRelCoor(this->currentKeyFrame->position);
181      this->currentKeyFrame->lastPosition = Vector();
182      break;
183    case ANIM_SINE:
184      this->animFuncMov = &Animation3D::mSine;
185      break;
186    case ANIM_COSINE:
187      this->animFuncMov = &Animation3D::mCosine;
188      break;
189    case ANIM_EXP:
190      this->animFuncMov = &Animation3D::mExp;
191      break;
192    case ANIM_NEG_EXP:
193      this->animFuncMov = &Animation3D::mNegExp;
194      this->expFactorMov = -1.0 / this->currentKeyFrame->duration * logf(DELTA_X_3D);
195      break;
196    case ANIM_QUADRATIC:
197      this->animFuncMov = &Animation3D::mQuadratic;
198      break;
199    case ANIM_RANDOM:
200      this->animFuncMov = &Animation3D::mRandom;
201      break;
202    }
203}
204
205
206
207/**
208   \brief stays at the value of the currentKeyFrame
209   \param timePassed The time passed since this Keyframe began
210*/
211void Animation3D::mConstant(float timePassed) const
212{
213  this->object->setRelCoor(this->currentKeyFrame->position);
214
215  /*
216    this->tmpVect = this->nextKeyFrame->position - this->currentKeyFrame->position;
217    this->tmpVect = this->tmpVect * this->localTime / this->currentKeyFrame->duration;
218    this->currentFrame->object->setRelCoor(*this->lastFrame->position + *this->tmpVect);
219    this->lastPosition = this->tmpVect;
220  */
221}
222
223/**
224   \brief linear interpolation between this keyframe and the next one
225   \param timePassed The time passed since this Keyframe began
226
227   \todo implement also do this for direction
228*/
229void Animation3D::mLinear(float timePassed) const
230{
231  Vector v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (timePassed/this->currentKeyFrame->duration);
232  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
233  this->currentKeyFrame->lastPosition = v;
234}
235
236/**
237   \brief a Sinusodial Interpolation between this keyframe and the next one
238   \param timePassed The time passed since this Keyframe began
239
240   \todo implement
241*/
242void Animation3D::mSine(float timePassed) const
243{
244  if( timePassed  < this->currentKeyFrame->duration/2.0)
245    this->object->setRelCoor( this->currentKeyFrame->position + (this->nextKeyFrame->position - this->currentKeyFrame->position) *
246                              sin( M_PI * timePassed /this->currentKeyFrame->duration) / 2.0);
247  else
248    this->object->setRelCoor( this->nextKeyFrame->position - (this->nextKeyFrame->position - this->currentKeyFrame->position) *
249                              sin( M_PI * (1.0 - timePassed /this->currentKeyFrame->duration) )/2.0);
250}
251
252
253/**
254   \brief a cosine interpolation between this keyframe and the next one
255   \param timePassed The time passed since this Keyframe began
256
257   \todo implement
258*/
259void Animation3D::mCosine(float timePassed) const
260{
261  this->object->setRelCoor( this->nextKeyFrame->position -
262                            (this->nextKeyFrame->position - this->currentKeyFrame->position) *
263                            (1.0 + cos( M_PI * timePassed / this->currentKeyFrame->duration))/2.0);
264}
265
266
267
268/**
269   \brief an exponential interpolation between this keyframe and the next one
270   \param timePassed The time passed since this Keyframe began
271*/
272void Animation3D::mExp(float timePassed) const
273{
274  PRINTF(0)("no exp animation3d defined\n");
275  this->mLinear(timePassed);
276}
277
278/**
279   \brief a negative exponential interpolation between this keyframe and the next one
280   \param timePassed The time passed since this Keyframe began
281*/
282void Animation3D::mNegExp(float timePassed) const
283{
284  this->object->setRelCoor( this->currentKeyFrame->position +
285                            (this->nextKeyFrame->position - this->currentKeyFrame->position) * 
286                            (1.0 - expf(- timePassed * expFactorMov)) );
287}
288
289
290/**
291   \brief a quadratic interpolation between this keyframe and the next one
292   \param timePassed The time passed since this Keyframe began
293
294   \todo implement
295*/
296void Animation3D::mQuadratic(float timePassed) const
297{
298  PRINTF(0)("no quadratic animation3d defined\n");
299  this->mLinear(timePassed);
300}
301
302/**
303   \brief some random animation (fluctuating)
304   \param timePassed The time passed since this Keyframe began
305*/
306void Animation3D::mRandom(float timePassed) const
307{
308  this->object->setRelCoor(this->currentKeyFrame->position + 
309                           (this->nextKeyFrame->position - this->currentKeyFrame->position) * (float)rand()/(float)RAND_MAX);
310  this->object->setRelDir(this->currentKeyFrame->direction +
311                          (this->nextKeyFrame->direction - this->currentKeyFrame->direction)* (float)rand()/(float)RAND_MAX);
312}
313
314
315/*==Rotation Section==========================================================*/
316
317
318/**
319   \brief Sets The kind of rotation Animation between this keyframe and the next one
320   \param animFunc The Type of Animation to set
321*/
322void Animation3D::setAnimFuncRot(ANIM_FUNCTION animFuncRot)
323{
324  switch (animFuncRot)
325    {
326   default:
327    case ANIM_CONSTANT:
328      this->animFuncRot = &Animation3D::rConstant;
329      break;
330    case ANIM_LINEAR:
331      this->animFuncRot = &Animation3D::rLinear;
332      break;
333    case ANIM_SINE:
334      this->animFuncRot = &Animation3D::rSine;
335      break;
336    case ANIM_COSINE:
337      this->animFuncRot = &Animation3D::rCosine;
338      break;
339    case ANIM_EXP:
340      this->animFuncRot = &Animation3D::rExp;
341      break;
342    case ANIM_NEG_EXP:
343      this->animFuncRot = &Animation3D::rNegExp;
344      this->expFactorRot = -1.0 / this->currentKeyFrame->duration * logf(DELTA_X_3D);
345      break;
346    case ANIM_QUADRATIC:
347      this->animFuncRot = &Animation3D::rQuadratic;
348      break;
349    case ANIM_RANDOM:
350      this->animFuncRot = &Animation3D::rRandom;
351      break;
352    }
353}
354
355
356/**
357   \brief stays at the value of the currentKeyFrame
358   \param timePassed The time passed since this Keyframe began
359*/
360void Animation3D::rConstant(float timePassed) const
361{
362  this->object->setRelDir(this->currentKeyFrame->direction);
363}
364
365/**
366   \brief linear interpolation between this keyframe and the next one
367   \param timePassed The time passed since this Keyframe began
368
369   \todo implement also do this for direction
370*/
371void Animation3D::rLinear(float timePassed) const
372{
373  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
374                                     this->currentKeyFrame->direction, 
375                                     timePassed/this->currentKeyFrame->duration) );
376}
377
378/**
379   \brief a Sinusodial Interpolation between this keyframe and the next one
380   \param timePassed The time passed since this Keyframe began
381
382   \todo implement
383*/
384void Animation3D::rSine(float timePassed) const
385{
386  float scale;
387  if( timePassed < this->currentKeyFrame->duration / 2.0)
388    scale = sin( M_PI * timePassed / this->currentKeyFrame->duration);
389  else
390    scale = 1.0 - sin( M_PI * timePassed / this->currentKeyFrame->duration);
391
392  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
393                                     this->currentKeyFrame->direction, 
394                                     scale) );
395}
396
397
398/**
399   \brief a cosine interpolation between this keyframe and the next one
400   \param timePassed The time passed since this Keyframe began
401
402   \todo implement
403*/
404void Animation3D::rCosine(float timePassed) const
405{
406  float scale = cos(M_PI * timePassed / this->currentKeyFrame->duration);
407  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
408                                     this->currentKeyFrame->direction, 
409                                     scale) );
410}
411
412
413
414/**
415   \brief an exponential interpolation between this keyframe and the next one
416   \param timePassed The time passed since this Keyframe began
417*/
418void Animation3D::rExp(float timePassed) const
419{
420  PRINTF(0)("exp rotation function not implemented\n");
421}
422
423/**
424   \brief a negative exponential interpolation between this keyframe and the next one
425   \param timePassed The time passed since this Keyframe began
426*/
427void Animation3D::rNegExp(float timePassed) const
428{
429  float scale = (1.0 - expf(- timePassed * expFactorRot));
430  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
431                                     this->currentKeyFrame->direction, 
432                                     scale) );
433}
434
435
436/**
437   \brief a quadratic interpolation between this keyframe and the next one
438   \param timePassed The time passed since this Keyframe began
439
440   \todo implement
441*/
442void Animation3D::rQuadratic(float timePassed) const
443{
444  PRINTF(0)("quadratic rotation alg not implemented\n");
445}
446
447/**
448   \brief some random animation (fluctuating)
449   \param timePassed The time passed since this Keyframe began
450*/
451void Animation3D::rRandom(float timePassed) const
452{
453  PRINTF(0)("random rotation alg not implemented\n");
454}
Note: See TracBrowser for help on using the repository browser.