Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/util/animation/t_animation.h @ 7227

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

orxonox/trunk: reimplemented the list functions, as i did before in revision 5110.
This time, i looked out for the bugs, and i think i found one

@patrick: i know, that you do not want to code at the moment… :/ → see mail

File size: 9.9 KB
RevLine 
[3851]1/*
2   orxonox - the future of 3D-vertical-scrollers
[3849]3
[3851]4   Copyright (C) 2004 orx
[3849]5
[3851]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.
[3849]10
[3851]11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14*/
15
[4597]16/*!
[5039]17 * @file t_animation.h
[3851]18*/
19
20#ifndef _T_ANIMATION_H
21#define _T_ANIMATION_H
22
[3849]23#include "animation.h"
24
[3860]25#define DELTA_X 0.05  //!< the percentag of the distance that doesnt have to be done by neg_exp (asymptotical) ~ maschinendelta
26
[3863]27//! A Struct for Keyframes that simply hold a float
28typedef struct KeyFrameF
29{
30  float duration;             //!< duration of this keyframe
31  float value;                //!< value of this keyframe
32  ANIM_FUNCTION animFunc;     //!< with whitch function to iterate to the next KeyFrameF
33};
34
35
[3849]36//! A Class to handle some animation for single floated values.
37template<class T> class tAnimation : public Animation
38{
39 public:
40  tAnimation(T* object = NULL, void (T::*funcToAnim)(float) = NULL);
41  virtual ~tAnimation();
42
[3859]43  void setFuncToAnim(T* object, void (T::*funcToAnim)(float));
[3849]44
[3979]45  void addKeyFrame(float value, float duration, ANIM_FUNCTION animFunc = ANIM_DEFAULT_FUNCTION);
[3849]46
[3859]47  virtual void rewind();
[3852]48  virtual void tick(float dt);
[3849]49
[3859]50 private:
[3849]51  // animation functions
52  void setAnimFunc(ANIM_FUNCTION animFunc);
53  float constant(float timePassed) const;
54  float linear(float timePassed) const;
55  float sine(float timePassed) const;
56  float cosine(float timePassed) const;
57  float exp(float timePassed) const;
58  float negExp(float timePassed) const;
59  float quadratic(float timePassed) const;
60  float random(float timePassed) const;
[3851]61
62
[4837]63  //  ANIM_FUNCTION animFunc
[3854]64  float (tAnimation<T>::*animFunc)(float) const;  //!< A Function for the AnimationType
[3855]65
[3854]66  KeyFrameF* currentKeyFrame;                     //!< The current KeyFrame
67  KeyFrameF* nextKeyFrame;                        //!< The KeyFrame we iterate to
68  tList<KeyFrameF>* keyFrameList;                 //!< The KeyFrameList
[3849]69
[3854]70  T* object;                                      //!< The Object from which to Animate something
71  void (T::*funcToAnim)(float);                   //!< The function to Animate
72
73  float expFactor;                                //!< some factors
[3849]74};
75
76
77
78/**
[4836]79 *  standard constructor
[3849]80*/
81template<class T>
[4597]82tAnimation<T>::tAnimation (T* object, void (T::*funcToAnim)(float))
[3849]83{
84  // create a new List
85  this->keyFrameList = new tList<KeyFrameF>();
86  KeyFrameF* tmpKeyFrame = new KeyFrameF;
87  tmpKeyFrame->value = 0.0;
88  tmpKeyFrame->duration = 1.0;
89  keyFrameList->add(tmpKeyFrame);
90
91  this->currentKeyFrame = tmpKeyFrame;
92  this->nextKeyFrame = tmpKeyFrame;
93
94  this->animFunc = &tAnimation<T>::linear;
95
96  this->setFuncToAnim(object, funcToAnim);
97}
98
99
100/**
[4836]101 *  standard deconstructor
[4597]102
[3854]103   deletes all the Keyframes
[3849]104*/
105template<class T>
[4597]106tAnimation<T>::~tAnimation ()
[3849]107{
108  // delete all the KeyFrames
109  tIterator<KeyFrameF>* itKF = keyFrameList->getIterator();
[5115]110  KeyFrameF*  enumKF = itKF->firstElement();
[3849]111  while (enumKF)
112    {
113      delete enumKF;
114      enumKF = itKF->nextElement();
115    }
116  delete itKF;
117  delete this->keyFrameList;
118}
119
[3854]120/**
[4836]121 *  rewinds the Animation to the beginning (first KeyFrame and time == 0)
[3854]122*/
[3849]123template<class T>
[4746]124void tAnimation<T>::rewind()
[3849]125{
126  this->currentKeyFrame = keyFrameList->firstElement();
127  this->nextKeyFrame = keyFrameList->nextElement(keyFrameList->firstElement());
128  this->localTime = 0.0;
[3872]129  this->setAnimFunc(this->currentKeyFrame->animFunc);
[3849]130}
131
[3854]132/**
[4836]133 *  sets the Function we want to animate
134 * @param object from what object do we want to animate
135 * @param funcToAnim which function
[3854]136*/
[3849]137template<class T>
138void tAnimation<T>::setFuncToAnim(T* object, void (T::*funcToAnim)(float))
139{
140  this->baseObject = this->object = object;
141  this->funcToAnim = funcToAnim;
142}
143
[3854]144/**
[4836]145 *  Appends a new Keyframe
146 * @param value the value of the new KeyFrame
147 * @param duration The duration from the new KeyFrame to the next one
148 * @param animFunc The function to animate between this keyFrame and the next one
[3854]149*/
[3849]150template<class T>
151void tAnimation<T>::addKeyFrame(float value, float duration, ANIM_FUNCTION animFunc)
152{
153  // some small check
154  if (duration <= 0.0)
155    duration = 1.0;
[3979]156  if (animFunc == ANIM_NULL)
157    animFunc = ANIM_DEFAULT_FUNCTION;
[3849]158
159  KeyFrameF* tmpKeyFrame;
[4597]160
[3876]161  // when adding the first frame
162  if (this->keyFrameCount == 0)
[3849]163    {
[3876]164      tmpKeyFrame = this->keyFrameList->firstElement();
165      this->setAnimFunc(animFunc);
166    }
167  else
168    {
[3849]169      tmpKeyFrame = new KeyFrameF;
[3871]170      // when adding the second frame
[3849]171      if (this->currentKeyFrame == this->nextKeyFrame)
[4597]172        this->nextKeyFrame = tmpKeyFrame;
[3849]173      this->keyFrameList->add(tmpKeyFrame);
174    }
[3871]175
[3849]176  tmpKeyFrame->value = value;
177  tmpKeyFrame->duration = duration;
178  tmpKeyFrame->animFunc = animFunc;
[3876]179  this->keyFrameCount++;
[3849]180}
181
[3854]182/**
[4836]183 *  ticks the Animation
184 * @param dt how much time to tick
[3854]185*/
[3849]186template<class T>
[3852]187void tAnimation<T>::tick(float dt)
[3849]188{
189  if (this->bRunning)
190    {
[3852]191      this->localTime += dt;
[3849]192      if (localTime >= this->currentKeyFrame->duration)
[4597]193        {
194          if (likely(this->keyFramesToPlay != 0))
195            {
196              if (unlikely(this->keyFramesToPlay > 0))
197                --this->keyFramesToPlay;
198              // switching to the next Key-Frame
199              this->localTime -= this->currentKeyFrame->duration;
200
201              this->currentKeyFrame = this->nextKeyFrame;
202              // checking, if we should still Play the animation
203              if (this->currentKeyFrame == this->keyFrameList->lastElement())
204                this->handleInfinity();
205              this->nextKeyFrame = this->keyFrameList->nextElement(this->currentKeyFrame);
206
[4885]207              //printf("%p from:%f to:%f\n", this->currentKeyFrame,this->currentKeyFrame->value, this->nextKeyFrame->value);
[4597]208              this->setAnimFunc(this->currentKeyFrame->animFunc);
209            }
210          else
211            this->pause();
212        }
213
[3849]214      (this->object->*(funcToAnim))((this->*animFunc)(this->localTime));
215    }
216}
217
[3854]218/**
[4836]219 *  Sets The kind of Animation between this keyframe and the next one
220 * @param animFunc The Type of Animation to set
[3854]221*/
[3849]222template<class T>
223void tAnimation<T>::setAnimFunc(ANIM_FUNCTION animFunc)
224{
225  switch (animFunc)
226    {
227    default:
228    case ANIM_CONSTANT:
229      this->animFunc = &tAnimation<T>::constant;
230      break;
231    case ANIM_LINEAR:
232      this->animFunc = &tAnimation<T>::linear;
233      break;
234    case ANIM_SINE:
235      this->animFunc = &tAnimation<T>::sine;
236      break;
237    case ANIM_COSINE:
238      this->animFunc = &tAnimation<T>::cosine;
239      break;
240    case ANIM_EXP:
241      this->animFunc = &tAnimation<T>::exp;
242      break;
243    case ANIM_NEG_EXP:
244      {
[4597]245        this->animFunc = &tAnimation<T>::negExp;
246        expFactor =  - 1.0 / this->currentKeyFrame->duration * logf(DELTA_X);
247        break;
[3849]248      }
249    case ANIM_QUADRATIC:
250      this->animFunc = &tAnimation<T>::quadratic;
251      break;
252    case ANIM_RANDOM:
253      this->animFunc = &tAnimation<T>::random;
254      break;
255    }
256}
257
258
259// animation functions
[3854]260/**
[4836]261 *  stays at the value of the currentKeyFrame
262 * @param timePassed The time passed since this Keyframe began
[3854]263*/
[3849]264template<class T>
265float tAnimation<T>::constant(float timePassed) const
266{
267  return this->currentKeyFrame->value;
268}
269
[3854]270/**
[4836]271 *  linear interpolation between this keyframe and the next one
272 * @param timePassed The time passed since this Keyframe began
[3854]273*/
[3849]274template<class T>
[4597]275float tAnimation<T>::linear(float timePassed) const
[3849]276{
[3871]277  return this->currentKeyFrame->value + (this->nextKeyFrame->value - this->currentKeyFrame->value)
[3849]278    * (timePassed / this->currentKeyFrame->duration);
279}
280
[3854]281/**
[4836]282 *  a Sinusodial Interpolation between this keyframe and the next one
283 * @param timePassed The time passed since this Keyframe began
[3854]284*/
[3849]285template<class T>
286float tAnimation<T>::sine(float timePassed) const
287{
[3871]288  if (timePassed * 2.0 < this->currentKeyFrame->duration)
[4597]289    return this->currentKeyFrame->value + (this->nextKeyFrame->value - this->currentKeyFrame->value)
[3871]290      * sin( M_PI * timePassed / this->currentKeyFrame->duration)/2;
[4597]291  else
[3871]292    return this->nextKeyFrame->value - (this->nextKeyFrame->value - this->currentKeyFrame->value)
293      * sin( M_PI * (1.0 - timePassed / this->currentKeyFrame->duration))/2;
[3849]294  /*
[3871]295  printf("::%f::::%f::\n",timePassed/this->currentKeyFrame->duration,retVal);
296  return retVal;
[3849]297  */
298}
299
[3854]300/**
[4836]301 *  a cosine interpolation between this keyframe and the next one
302 * @param timePassed The time passed since this Keyframe began
[3854]303*/
[3849]304template<class T>
305float tAnimation<T>::cosine(float timePassed) const
306{
[3871]307  return ((this->nextKeyFrame->value + this->currentKeyFrame->value) +
308    (this->currentKeyFrame->value - this->nextKeyFrame->value) *
309    cos( M_PI * timePassed / this->currentKeyFrame->duration))/2;
[3849]310}
311
[3854]312/**
[4836]313 *  an exponential interpolation between this keyframe and the next one
314 * @param timePassed The time passed since this Keyframe began
[3854]315*/
[3849]316template<class T>
317float tAnimation<T>::exp(float timePassed) const
318{
[3872]319  return this->linear(timePassed);
320
[3849]321}
322
[3854]323/**
[4836]324 *  a negative exponential interpolation between this keyframe and the next one
325 * @param timePassed The time passed since this Keyframe began
[3854]326*/
[3849]327template<class T>
328float tAnimation<T>::negExp(float timePassed) const
329{
330  float d = this->currentKeyFrame->value - this->nextKeyFrame->value;
331  float e = d * (1.0 - expf(- timePassed * expFactor));
332  return  this->currentKeyFrame->value - e;
333}
334
[3854]335/**
[4836]336 *  a quadratic interpolation between this keyframe and the next one
337 * @param timePassed The time passed since this Keyframe began
[3854]338*/
[3849]339template<class T>
340float tAnimation<T>::quadratic(float timePassed) const
341{
[3856]342  this->linear(timePassed);
[3849]343}
[3851]344
[3855]345/**
[4836]346 *  some random animation (fluctuating)
347 * @param timePassed The time passed since this Keyframe began
[3855]348*/
349template<class T>
350float tAnimation<T>::random(float timePassed) const
351{
[4597]352  return this->currentKeyFrame->value +
[3874]353    (this->nextKeyFrame->value - this->currentKeyFrame->value) *
354    (float)rand()/(float)RAND_MAX;
[3855]355}
[3851]356
357#endif /* _T_ANIMATION_H */
Note: See TracBrowser for help on using the repository browser.