Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: more documentation in util

File size: 14.3 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/**
52   \brief standard deconstructor
53   
54   deletes all the Keyframes
55*/
56Animation3D::~Animation3D(void)
57{
58  // delete all the KeyFrames
59  tIterator<KeyFrame3D>* itKF = keyFrameList->getIterator();
60  KeyFrame3D*  enumKF = itKF->nextElement();
61  while (enumKF)
62    {
63      delete enumKF;
64      enumKF = itKF->nextElement();
65    }
66  delete itKF;
67  delete this->keyFrameList;
68}
69
70/**
71   \brief rewinds the Animation to the beginning (first KeyFrame and time == 0)
72*/
73void Animation3D::rewind(void)
74{
75  this->currentKeyFrame = keyFrameList->firstElement();
76  this->nextKeyFrame = keyFrameList->nextElement(keyFrameList->firstElement());
77  this->localTime = 0.0;
78  this->setAnimFuncMov(this->currentKeyFrame->animFuncMov);
79  this->setAnimFuncRot(this->currentKeyFrame->animFuncRot);
80}
81
82/**
83   \brief Appends a new Keyframe
84   \param position The position of the new Keyframe
85   \param direction The direction of the new Keyframe.
86   \param duration The duration from the new KeyFrame to the next one
87   \param animFuncMov The function to animate position between this keyFrame and the next one
88   \param animFuncRot The function to animate rotation between this keyFrame and the next one
89*/
90void Animation3D::addKeyFrame(Vector position, Quaternion direction, float duration,
91                              ANIM_FUNCTION animFuncMov, ANIM_FUNCTION animFuncRot)
92{
93  // some small check
94  if (duration <= 0.0)
95    duration = 1.0;
96  // if the Rotation-Animation-function is set ANIM_NULL, animFuncRot will match animFuncRot
97  if (animFuncMov == ANIM_NULL)
98    animFuncMov = ANIM_DEFAULT_FUNCTION;
99  if (animFuncRot == ANIM_NULL)
100    animFuncRot = animFuncMov;
101
102  KeyFrame3D* tmpKeyFrame;
103   
104  // when adding the first frame
105  if (this->keyFrameCount == 0)
106    {
107      tmpKeyFrame = this->keyFrameList->firstElement();
108      //this->setAnimFuncMov(animFuncMov);
109      //this->setAnimFuncRot(animFuncRot);
110    }
111  else
112    {
113      tmpKeyFrame = new KeyFrame3D;
114      // when adding the second frame
115      if (this->currentKeyFrame == this->nextKeyFrame)
116        this->nextKeyFrame = tmpKeyFrame;
117      this->keyFrameList->add(tmpKeyFrame);
118    }
119
120  tmpKeyFrame->position = position;
121  //tmpKeyFrame->lastPosition = position;
122  tmpKeyFrame->direction = direction;
123  tmpKeyFrame->duration = duration;
124  tmpKeyFrame->animFuncMov = animFuncMov;
125  tmpKeyFrame->animFuncRot = animFuncRot;
126  this->keyFrameCount++;
127}
128
129
130
131/**
132   \brief ticks the Animation
133   \param dt how much time to tick
134*/
135void Animation3D::tick(float dt)
136{
137  if (this->bRunning)
138    { 
139      this->localTime += dt;
140      if (localTime >= this->currentKeyFrame->duration)
141        {
142          if (likely(this->keyFramesToPlay != 0))
143            {
144              if (unlikely(this->keyFramesToPlay > 0))
145                --this->keyFramesToPlay;
146              // switching to the next Key-Frame
147              this->localTime -= this->currentKeyFrame->duration;
148              this->currentKeyFrame = this->nextKeyFrame;
149              // checking, if we should still Play the animation
150              if (this->currentKeyFrame == this->keyFrameList->lastElement())
151                this->handleInfinity();
152              this->nextKeyFrame = this->keyFrameList->nextElement(this->currentKeyFrame);
153              this->setAnimFuncMov(this->currentKeyFrame->animFuncMov);
154              this->setAnimFuncRot(this->currentKeyFrame->animFuncRot);
155            }
156          else
157            this->pause();
158        }     
159      /* now animate it */
160      (this->*animFuncMov)(this->localTime);
161      (this->*animFuncRot)(this->localTime);
162    }
163}
164
165
166/*==Movement Section==========================================================*/
167
168/**
169   \brief Sets The kind of movment Animation between this keyframe and the next one
170   \param animFuncMov: The Type of Animation to set
171*/
172void Animation3D::setAnimFuncMov(ANIM_FUNCTION animFuncMov)
173{
174  switch (animFuncMov)
175    {
176    case ANIM_CONSTANT:
177      this->animFuncMov = &Animation3D::mConstant;
178      break;
179    case ANIM_LINEAR:
180      this->animFuncMov = &Animation3D::mLinear;
181      this->object->setRelCoor(this->currentKeyFrame->position);
182      this->currentKeyFrame->lastPosition = Vector();
183      break;
184    case ANIM_SINE:
185      this->animFuncMov = &Animation3D::mSine;
186      this->object->setRelCoor(this->currentKeyFrame->position);
187      this->currentKeyFrame->lastPosition = Vector();
188      break;
189    case ANIM_COSINE:
190      this->animFuncMov = &Animation3D::mCosine;
191      this->object->setRelCoor(this->currentKeyFrame->position);
192      this->currentKeyFrame->lastPosition = Vector();
193      break;
194    case ANIM_EXP:
195      this->object->setRelCoor(this->currentKeyFrame->position);
196      this->animFuncMov = &Animation3D::mExp;
197      break;
198    case ANIM_NEG_EXP:
199      this->animFuncMov = &Animation3D::mNegExp;
200      this->object->setRelCoor(this->currentKeyFrame->position);
201      this->expFactorMov = -1.0 / this->currentKeyFrame->duration * logf(DELTA_X_3D);
202      this->currentKeyFrame->lastPosition = Vector();
203      break;
204    case ANIM_QUADRATIC:
205      this->object->setRelCoor(this->currentKeyFrame->position);
206      this->animFuncMov = &Animation3D::mQuadratic;
207      break;
208    case ANIM_RANDOM:
209      this->object->setRelCoor(this->currentKeyFrame->position);
210      this->animFuncMov = &Animation3D::mRandom;
211      break;
212    default:
213      break;
214    }
215}
216
217/**
218   \brief stays at the value of the currentKeyFrame
219   \param timePassed The time passed since this Keyframe began
220*/
221void Animation3D::mConstant(float timePassed) const
222{
223  //this->object->setRelCoor(this->currentKeyFrame->position);
224
225  /*
226    this->tmpVect = this->nextKeyFrame->position - this->currentKeyFrame->position;
227    this->tmpVect = this->tmpVect * this->localTime / this->currentKeyFrame->duration;
228    this->currentFrame->object->setRelCoor(*this->lastFrame->position + *this->tmpVect);
229    this->lastPosition = this->tmpVect;
230  */
231}
232
233/**
234   \brief linear interpolation between this keyframe and the next one
235   \param timePassed The time passed since this Keyframe began
236
237   \todo implement also do this for direction
238*/
239void Animation3D::mLinear(float timePassed) const
240{
241  Vector v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (timePassed/this->currentKeyFrame->duration);
242  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
243  this->currentKeyFrame->lastPosition = v;
244}
245
246/**
247   \brief a Sinusodial Interpolation between this keyframe and the next one
248   \param timePassed The time passed since this Keyframe began
249
250   \todo implement
251*/
252void Animation3D::mSine(float timePassed) const
253{
254  Vector v;
255  if( timePassed  < this->currentKeyFrame->duration/2.0)
256    v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * sin( M_PI * timePassed /this->currentKeyFrame->duration) / 2.0;
257  else
258    v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (2.0 + sin( M_PI * (- timePassed /this->currentKeyFrame->duration)) )/ 2.0;
259 
260  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
261  this->currentKeyFrame->lastPosition = v;
262}
263
264
265/**
266   \brief a cosine interpolation between this keyframe and the next one
267   \param timePassed The time passed since this Keyframe began
268
269   \todo implement
270*/
271void Animation3D::mCosine(float timePassed) const
272{
273  Vector v;
274  v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (1.0 + cos( M_PI * timePassed / this->currentKeyFrame->duration))/2.0;
275  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
276  this->currentKeyFrame->lastPosition = v;
277
278
279  /*
280  this->object->setRelCoor( this->nextKeyFrame->position -
281                            (this->nextKeyFrame->position - this->currentKeyFrame->position) *
282                            (1.0 + cos( M_PI * timePassed / this->currentKeyFrame->duration))/2.0);
283  */
284}
285
286
287
288/**
289   \brief an exponential interpolation between this keyframe and the next one
290   \param timePassed The time passed since this Keyframe began
291*/
292void Animation3D::mExp(float timePassed) const
293{
294  PRINTF(0)("no exp animation3d defined\n");
295  this->mLinear(timePassed);
296}
297
298/**
299   \brief a negative exponential interpolation between this keyframe and the next one
300   \param timePassed The time passed since this Keyframe began
301*/
302void Animation3D::mNegExp(float timePassed) const
303{
304  Vector v;
305  v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (1.0 - expf(- timePassed * expFactorMov));
306  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
307  this->currentKeyFrame->lastPosition = v;
308
309  /*
310  this->object->setRelCoor( this->currentKeyFrame->position +
311                            (this->nextKeyFrame->position - this->currentKeyFrame->position) *
312                            (1.0 - expf(- timePassed * expFactorMov)) );
313  */
314}
315
316
317/**
318   \brief a quadratic interpolation between this keyframe and the next one
319   \param timePassed The time passed since this Keyframe began
320
321   \todo implement
322*/
323void Animation3D::mQuadratic(float timePassed) const
324{
325  PRINTF(0)("no quadratic animation3d defined\n");
326  this->mLinear(timePassed);
327}
328
329/**
330   \brief some random animation (fluctuating)
331   \param timePassed The time passed since this Keyframe began
332*/
333void Animation3D::mRandom(float timePassed) const
334{
335  /*
336  this->object->setRelCoor(this->currentKeyFrame->position +
337                           (this->nextKeyFrame->position - this->currentKeyFrame->position) * (float)rand()/(float)RAND_MAX);
338  this->object->setRelDir(this->currentKeyFrame->direction +
339                          (this->nextKeyFrame->direction - this->currentKeyFrame->direction)* (float)rand()/(float)RAND_MAX);
340  */
341}
342
343
344/*==Rotation Section==========================================================*/
345
346
347/**
348   \brief Sets The kind of rotation Animation between this keyframe and the next one
349   \param animFuncRot: The Type of Animation to set
350*/
351void Animation3D::setAnimFuncRot(ANIM_FUNCTION animFuncRot)
352{
353  switch (animFuncRot)
354    {
355    default:
356    case ANIM_CONSTANT:
357      this->animFuncRot = &Animation3D::rConstant;
358      break;
359    case ANIM_LINEAR:
360      this->animFuncRot = &Animation3D::rLinear;
361      break;
362    case ANIM_SINE:
363      this->animFuncRot = &Animation3D::rSine;
364      break;
365    case ANIM_COSINE:
366      this->animFuncRot = &Animation3D::rCosine;
367      break;
368    case ANIM_EXP:
369      this->animFuncRot = &Animation3D::rExp;
370      break;
371    case ANIM_NEG_EXP:
372      this->animFuncRot = &Animation3D::rNegExp;
373      this->expFactorRot = -1.0 / this->currentKeyFrame->duration * logf(DELTA_X_3D);
374      break;
375    case ANIM_QUADRATIC:
376      this->animFuncRot = &Animation3D::rQuadratic;
377      break;
378    case ANIM_RANDOM:
379      this->animFuncRot = &Animation3D::rRandom;
380      break;
381
382    }
383}
384
385
386/**
387   \brief stays at the value of the currentKeyFrame
388   \param timePassed The time passed since this Keyframe began
389*/
390void Animation3D::rConstant(float timePassed) const
391{
392  this->object->setRelDir(this->currentKeyFrame->direction);
393}
394
395/**
396   \brief linear interpolation between this keyframe and the next one
397   \param timePassed The time passed since this Keyframe began
398
399   \todo implement also do this for direction
400*/
401void Animation3D::rLinear(float timePassed) const
402{
403  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
404                                     this->currentKeyFrame->direction, 
405                                     timePassed/this->currentKeyFrame->duration) );
406}
407
408/**
409   \brief a Sinusodial Interpolation between this keyframe and the next one
410   \param timePassed The time passed since this Keyframe began
411
412   \todo implement
413*/
414void Animation3D::rSine(float timePassed) const
415{
416  float scale;
417  if( timePassed < this->currentKeyFrame->duration / 2.0)
418    scale = sin( M_PI * timePassed / this->currentKeyFrame->duration);
419  else
420    scale = 1.0 - sin( M_PI * timePassed / this->currentKeyFrame->duration);
421
422  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
423                                     this->currentKeyFrame->direction, 
424                                     scale) );
425}
426
427
428/**
429   \brief a cosine interpolation between this keyframe and the next one
430   \param timePassed The time passed since this Keyframe began
431
432   \todo implement
433*/
434void Animation3D::rCosine(float timePassed) const
435{
436  float scale = cos(M_PI * timePassed / this->currentKeyFrame->duration);
437  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
438                                     this->currentKeyFrame->direction, 
439                                     scale) );
440}
441
442
443
444/**
445   \brief an exponential interpolation between this keyframe and the next one
446   \param timePassed The time passed since this Keyframe began
447*/
448void Animation3D::rExp(float timePassed) const
449{
450  PRINTF(0)("exp rotation function not implemented\n");
451}
452
453/**
454   \brief a negative exponential interpolation between this keyframe and the next one
455   \param timePassed The time passed since this Keyframe began
456*/
457void Animation3D::rNegExp(float timePassed) const
458{
459  float scale = (1.0 - expf(- timePassed * expFactorRot));
460  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
461                                     this->currentKeyFrame->direction, 
462                                     scale) );
463}
464
465
466/**
467   \brief a quadratic interpolation between this keyframe and the next one
468   \param timePassed The time passed since this Keyframe began
469
470   \todo implement
471*/
472void Animation3D::rQuadratic(float timePassed) const
473{
474  PRINTF(0)("quadratic rotation alg not implemented\n");
475}
476
477/**
478   \brief some random animation (fluctuating)
479   \param timePassed The time passed since this Keyframe began
480*/
481void Animation3D::rRandom(float timePassed) const
482{
483  PRINTF(0)("random rotation alg not implemented\n");
484}
Note: See TracBrowser for help on using the repository browser.