Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3993 was 3993, checked in by patrick, 19 years ago

orxonox/trunk: patch to use relative coordinates again, some smaller changes in the preLoading/loading mechanisms

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