Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7682 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: 14.7 KB
RevLine 
[3851]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
[3980]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
[3851]19*/
20
[3863]21#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_ANIM
[3851]22
23#include "animation3d.h"
24
25#include "p_node.h"
26
27using namespace std;
28
[3855]29/**
[4836]30 *  standard constructor
[3855]31*/
[3852]32Animation3D::Animation3D(PNode* object)
[3851]33{
[3852]34  this->object = object;
35
[3851]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
[5062]46  this->animFuncMov = NULL;//&Animation3D::mLinear;
47  this->animFuncRot = NULL;//&Animation3D::rLinear;
[3986]48
[3851]49}
50
[3855]51/**
[4836]52 *  standard deconstructor
[4597]53
[3855]54   deletes all the Keyframes
55*/
[4746]56Animation3D::~Animation3D()
[3851]57{
58  // delete all the KeyFrames
59  tIterator<KeyFrame3D>* itKF = keyFrameList->getIterator();
[5115]60  KeyFrame3D*  enumKF = itKF->firstElement();
[3851]61  while (enumKF)
62    {
63      delete enumKF;
64      enumKF = itKF->nextElement();
65    }
66  delete itKF;
67  delete this->keyFrameList;
68}
69
[3855]70/**
[4836]71 *  rewinds the Animation to the beginning (first KeyFrame and time == 0)
[3855]72*/
[4746]73void Animation3D::rewind()
[3851]74{
75  this->currentKeyFrame = keyFrameList->firstElement();
76  this->nextKeyFrame = keyFrameList->nextElement(keyFrameList->firstElement());
77  this->localTime = 0.0;
[3973]78  this->setAnimFuncMov(this->currentKeyFrame->animFuncMov);
79  this->setAnimFuncRot(this->currentKeyFrame->animFuncRot);
[3851]80}
81
[3855]82/**
[4836]83 *  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
[3855]89*/
[4485]90void Animation3D::addKeyFrame(Vector position, Quaternion direction, float duration,
[4597]91                              ANIM_FUNCTION animFuncMov, ANIM_FUNCTION animFuncRot)
[3851]92{
93  // some small check
94  if (duration <= 0.0)
95    duration = 1.0;
[3978]96  // if the Rotation-Animation-function is set ANIM_NULL, animFuncRot will match animFuncRot
[5062]97//  if (animFuncMov == ANIM_NULL)
98//    animFuncMov = ANIM_DEFAULT_FUNCTION;
99//  if (animFuncRot == ANIM_NULL)
100//    animFuncRot = animFuncMov;
[3851]101
102  KeyFrame3D* tmpKeyFrame;
[4597]103
[3876]104  // when adding the first frame
105  if (this->keyFrameCount == 0)
[3851]106    {
[3876]107      tmpKeyFrame = this->keyFrameList->firstElement();
[4000]108      //this->setAnimFuncMov(animFuncMov);
109      //this->setAnimFuncRot(animFuncRot);
[3876]110    }
111  else
112    {
[3851]113      tmpKeyFrame = new KeyFrame3D;
[3876]114      // when adding the second frame
[3851]115      if (this->currentKeyFrame == this->nextKeyFrame)
[4597]116        this->nextKeyFrame = tmpKeyFrame;
[3851]117      this->keyFrameList->add(tmpKeyFrame);
118    }
119
120  tmpKeyFrame->position = position;
[3981]121  //tmpKeyFrame->lastPosition = position;
[3851]122  tmpKeyFrame->direction = direction;
123  tmpKeyFrame->duration = duration;
[3973]124  tmpKeyFrame->animFuncMov = animFuncMov;
125  tmpKeyFrame->animFuncRot = animFuncRot;
[3876]126  this->keyFrameCount++;
[3851]127}
128
[3855]129/**
[4836]130 *  ticks the Animation
131 * @param dt how much time to tick
[3855]132*/
[3852]133void Animation3D::tick(float dt)
[3851]134{
135  if (this->bRunning)
[4597]136    {
[3852]137      this->localTime += dt;
[3851]138      if (localTime >= this->currentKeyFrame->duration)
[4597]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        }
[3851]157      /* now animate it */
[5062]158      if (likely(this->animFuncMov != NULL))
159        (this->*animFuncMov)(this->localTime);
160      if (likely(this->animFuncRot != NULL))
161        (this->*animFuncRot)(this->localTime);
[3851]162    }
163}
164
165
[3973]166/*==Movement Section==========================================================*/
167
[3855]168/**
[4836]169 *  Sets The kind of movment Animation between this keyframe and the next one
170 * @param animFuncMov: The Type of Animation to set
[3855]171*/
[3973]172void Animation3D::setAnimFuncMov(ANIM_FUNCTION animFuncMov)
[3851]173{
[3973]174  switch (animFuncMov)
[3851]175    {
176    case ANIM_CONSTANT:
[3973]177      this->animFuncMov = &Animation3D::mConstant;
[3851]178      break;
179    case ANIM_LINEAR:
[3973]180      this->animFuncMov = &Animation3D::mLinear;
[3993]181      this->object->setRelCoor(this->currentKeyFrame->position);
[3981]182      this->currentKeyFrame->lastPosition = Vector();
[3851]183      break;
184    case ANIM_SINE:
[3973]185      this->animFuncMov = &Animation3D::mSine;
[3993]186      this->object->setRelCoor(this->currentKeyFrame->position);
[3984]187      this->currentKeyFrame->lastPosition = Vector();
[3851]188      break;
189    case ANIM_COSINE:
[3973]190      this->animFuncMov = &Animation3D::mCosine;
[3993]191      this->object->setRelCoor(this->currentKeyFrame->position);
[3985]192      this->currentKeyFrame->lastPosition = Vector();
[3851]193      break;
194    case ANIM_EXP:
[3993]195      this->object->setRelCoor(this->currentKeyFrame->position);
[3973]196      this->animFuncMov = &Animation3D::mExp;
[3851]197      break;
198    case ANIM_NEG_EXP:
[3973]199      this->animFuncMov = &Animation3D::mNegExp;
[3993]200      this->object->setRelCoor(this->currentKeyFrame->position);
[3977]201      this->expFactorMov = -1.0 / this->currentKeyFrame->duration * logf(DELTA_X_3D);
[3986]202      this->currentKeyFrame->lastPosition = Vector();
[3851]203      break;
204    case ANIM_QUADRATIC:
[3993]205      this->object->setRelCoor(this->currentKeyFrame->position);
[3973]206      this->animFuncMov = &Animation3D::mQuadratic;
[3851]207      break;
208    case ANIM_RANDOM:
[3993]209      this->object->setRelCoor(this->currentKeyFrame->position);
[3973]210      this->animFuncMov = &Animation3D::mRandom;
[3851]211      break;
[3986]212    default:
[5062]213      this->animFuncMov = NULL;
[3986]214      break;
[3851]215    }
216}
217
[3855]218/**
[4836]219 *  stays at the value of the currentKeyFrame
220 * @param timePassed The time passed since this Keyframe began
[3855]221*/
[3973]222void Animation3D::mConstant(float timePassed) const
[3851]223{
[3986]224  //this->object->setRelCoor(this->currentKeyFrame->position);
[3851]225
[3852]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  */
[3851]232}
233
[3855]234/**
[4836]235 *  linear interpolation between this keyframe and the next one
236 * @param timePassed The time passed since this Keyframe began
[3856]237
[4836]238   @todo implement also do this for direction
[3855]239*/
[3973]240void Animation3D::mLinear(float timePassed) const
[3851]241{
[3981]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;
[3851]245}
246
[3855]247/**
[4836]248 *  a Sinusodial Interpolation between this keyframe and the next one
249 * @param timePassed The time passed since this Keyframe began
[3856]250
[4836]251   @todo implement
[3855]252*/
[3973]253void Animation3D::mSine(float timePassed) const
[3851]254{
[3984]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;
[4597]260
[3984]261  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
262  this->currentKeyFrame->lastPosition = v;
[3851]263}
264
[3965]265
[3855]266/**
[4836]267 *  a cosine interpolation between this keyframe and the next one
268 * @param timePassed The time passed since this Keyframe began
[3856]269
[4836]270   @todo implement
[3855]271*/
[3973]272void Animation3D::mCosine(float timePassed) const
[3851]273{
[3985]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  /*
[3967]281  this->object->setRelCoor( this->nextKeyFrame->position -
[4597]282                            (this->nextKeyFrame->position - this->currentKeyFrame->position) *
283                            (1.0 + cos( M_PI * timePassed / this->currentKeyFrame->duration))/2.0);
[3985]284  */
[3851]285}
286
[3967]287
288
[3855]289/**
[4836]290 *  an exponential interpolation between this keyframe and the next one
291 * @param timePassed The time passed since this Keyframe began
[3855]292*/
[3973]293void Animation3D::mExp(float timePassed) const
[3851]294{
[3968]295  PRINTF(0)("no exp animation3d defined\n");
[3973]296  this->mLinear(timePassed);
[3851]297}
298
[3855]299/**
[4836]300 *  a negative exponential interpolation between this keyframe and the next one
301 * @param timePassed The time passed since this Keyframe began
[3855]302*/
[3973]303void Animation3D::mNegExp(float timePassed) const
[3851]304{
[3986]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  /*
[3964]311  this->object->setRelCoor( this->currentKeyFrame->position +
[4597]312                            (this->nextKeyFrame->position - this->currentKeyFrame->position) *
313                            (1.0 - expf(- timePassed * expFactorMov)) );
[3986]314  */
[3851]315}
316
[3964]317
[3855]318/**
[4836]319 *  a quadratic interpolation between this keyframe and the next one
320 * @param timePassed The time passed since this Keyframe began
[3856]321
[4836]322   @todo implement
[3855]323*/
[3973]324void Animation3D::mQuadratic(float timePassed) const
[3851]325{
[3968]326  PRINTF(0)("no quadratic animation3d defined\n");
[3973]327  this->mLinear(timePassed);
[3851]328}
329
[3855]330/**
[4836]331 *  some random animation (fluctuating)
332 * @param timePassed The time passed since this Keyframe began
[3855]333*/
[3973]334void Animation3D::mRandom(float timePassed) const
[3851]335{
[3986]336  /*
[4597]337  this->object->setRelCoor(this->currentKeyFrame->position +
338                           (this->nextKeyFrame->position - this->currentKeyFrame->position) * (float)rand()/(float)RAND_MAX);
[3874]339  this->object->setRelDir(this->currentKeyFrame->direction +
[4597]340                          (this->nextKeyFrame->direction - this->currentKeyFrame->direction)* (float)rand()/(float)RAND_MAX);
[3986]341  */
[3851]342}
[3973]343
344
345/*==Rotation Section==========================================================*/
346
347
348/**
[4836]349 *  Sets The kind of rotation Animation between this keyframe and the next one
350 * @param animFuncRot: The Type of Animation to set
[3973]351*/
352void Animation3D::setAnimFuncRot(ANIM_FUNCTION animFuncRot)
353{
354  switch (animFuncRot)
355    {
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;
[3977]373      this->expFactorRot = -1.0 / this->currentKeyFrame->duration * logf(DELTA_X_3D);
[3973]374      break;
375    case ANIM_QUADRATIC:
376      this->animFuncRot = &Animation3D::rQuadratic;
377      break;
378    case ANIM_RANDOM:
379      this->animFuncRot = &Animation3D::rRandom;
380      break;
[3986]381
[5062]382    default:
383      this->animFuncRot = NULL;
[3973]384    }
385}
386
387
388/**
[4836]389 *  stays at the value of the currentKeyFrame
390 * @param timePassed The time passed since this Keyframe began
[3973]391*/
392void Animation3D::rConstant(float timePassed) const
393{
[3977]394  this->object->setRelDir(this->currentKeyFrame->direction);
[3973]395}
396
397/**
[4836]398 *  linear interpolation between this keyframe and the next one
399 * @param timePassed The time passed since this Keyframe began
[3973]400
[4836]401   @todo implement also do this for direction
[3973]402*/
403void Animation3D::rLinear(float timePassed) const
404{
[4998]405  this->object->setRelDir(Quaternion::quatSlerp( this->nextKeyFrame->direction,
406                          this->currentKeyFrame->direction,
407                          timePassed/this->currentKeyFrame->duration) );
[3973]408}
409
410/**
[4836]411 *  a Sinusodial Interpolation between this keyframe and the next one
412 * @param timePassed The time passed since this Keyframe began
[3973]413
[4836]414   @todo implement
[3973]415*/
416void Animation3D::rSine(float timePassed) const
417{
[3975]418  float scale;
419  if( timePassed < this->currentKeyFrame->duration / 2.0)
420    scale = sin( M_PI * timePassed / this->currentKeyFrame->duration);
421  else
422    scale = 1.0 - sin( M_PI * timePassed / this->currentKeyFrame->duration);
423
[4998]424  this->object->setRelDir(Quaternion::quatSlerp( this->nextKeyFrame->direction,
425                          this->currentKeyFrame->direction,
426                          scale) );
[3973]427}
428
429
430/**
[4836]431 *  a cosine interpolation between this keyframe and the next one
432 * @param timePassed The time passed since this Keyframe began
[3973]433
[4836]434   @todo implement
[3973]435*/
436void Animation3D::rCosine(float timePassed) const
437{
[3976]438  float scale = cos(M_PI * timePassed / this->currentKeyFrame->duration);
[4998]439  this->object->setRelDir(Quaternion::quatSlerp( this->nextKeyFrame->direction,
440                          this->currentKeyFrame->direction,
441                          scale) );
[3973]442}
443
444
445
446/**
[4836]447 *  an exponential interpolation between this keyframe and the next one
448 * @param timePassed The time passed since this Keyframe began
[3973]449*/
450void Animation3D::rExp(float timePassed) const
451{
[5062]452  PRINTF(2)("exp rotation function not implemented\n");
[3973]453}
454
455/**
[4836]456 *  a negative exponential interpolation between this keyframe and the next one
457 * @param timePassed The time passed since this Keyframe began
[3973]458*/
459void Animation3D::rNegExp(float timePassed) const
460{
[3977]461  float scale = (1.0 - expf(- timePassed * expFactorRot));
[4998]462  this->object->setRelDir(Quaternion::quatSlerp( this->nextKeyFrame->direction,
463                          this->currentKeyFrame->direction,
464                          scale) );
[3973]465}
466
467
468/**
[4836]469 *  a quadratic interpolation between this keyframe and the next one
470 * @param timePassed The time passed since this Keyframe began
[3973]471
[4836]472   @todo implement
[3973]473*/
474void Animation3D::rQuadratic(float timePassed) const
475{
[3980]476  PRINTF(0)("quadratic rotation alg not implemented\n");
[3973]477}
478
479/**
[4836]480 *  some random animation (fluctuating)
481 * @param timePassed The time passed since this Keyframe began
[3973]482*/
483void Animation3D::rRandom(float timePassed) const
484{
[3980]485  PRINTF(0)("random rotation alg not implemented\n");
[3973]486}
Note: See TracBrowser for help on using the repository browser.