Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: more optimizations of the Quaternion Class.
Now the 3D-rotation is much faster through this code:

Vector tmpRot = this→getAbsDir().getSpacialAxis();
glRotatef (this→getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );

instead of the old Matrix-approach. furthermore glRotate is optimized much better in openGL as is clearly stated in the red book

also implemented some other really useless functions for Quaternion

File size: 14.6 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
[3973]46  this->animFuncMov = &Animation3D::mLinear;
47  this->animFuncRot = &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();
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
[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
[3979]97  if (animFuncMov == ANIM_NULL)
98    animFuncMov = ANIM_DEFAULT_FUNCTION;
[3978]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
[3973]129
130
[3855]131/**
[4836]132 *  ticks the Animation
133 * @param dt how much time to tick
[3855]134*/
[3852]135void Animation3D::tick(float dt)
[3851]136{
137  if (this->bRunning)
[4597]138    {
[3852]139      this->localTime += dt;
[3851]140      if (localTime >= this->currentKeyFrame->duration)
[4597]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        }
[3851]159      /* now animate it */
[3973]160      (this->*animFuncMov)(this->localTime);
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:
213      break;
[3851]214    }
215}
216
[3855]217/**
[4836]218 *  stays at the value of the currentKeyFrame
219 * @param timePassed The time passed since this Keyframe began
[3855]220*/
[3973]221void Animation3D::mConstant(float timePassed) const
[3851]222{
[3986]223  //this->object->setRelCoor(this->currentKeyFrame->position);
[3851]224
[3852]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  */
[3851]231}
232
[3855]233/**
[4836]234 *  linear interpolation between this keyframe and the next one
235 * @param timePassed The time passed since this Keyframe began
[3856]236
[4836]237   @todo implement also do this for direction
[3855]238*/
[3973]239void Animation3D::mLinear(float timePassed) const
[3851]240{
[3981]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;
[3851]244}
245
[3855]246/**
[4836]247 *  a Sinusodial Interpolation between this keyframe and the next one
248 * @param timePassed The time passed since this Keyframe began
[3856]249
[4836]250   @todo implement
[3855]251*/
[3973]252void Animation3D::mSine(float timePassed) const
[3851]253{
[3984]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;
[4597]259
[3984]260  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
261  this->currentKeyFrame->lastPosition = v;
[3851]262}
263
[3965]264
[3855]265/**
[4836]266 *  a cosine interpolation between this keyframe and the next one
267 * @param timePassed The time passed since this Keyframe began
[3856]268
[4836]269   @todo implement
[3855]270*/
[3973]271void Animation3D::mCosine(float timePassed) const
[3851]272{
[3985]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  /*
[3967]280  this->object->setRelCoor( this->nextKeyFrame->position -
[4597]281                            (this->nextKeyFrame->position - this->currentKeyFrame->position) *
282                            (1.0 + cos( M_PI * timePassed / this->currentKeyFrame->duration))/2.0);
[3985]283  */
[3851]284}
285
[3967]286
287
[3855]288/**
[4836]289 *  an exponential interpolation between this keyframe and the next one
290 * @param timePassed The time passed since this Keyframe began
[3855]291*/
[3973]292void Animation3D::mExp(float timePassed) const
[3851]293{
[3968]294  PRINTF(0)("no exp animation3d defined\n");
[3973]295  this->mLinear(timePassed);
[3851]296}
297
[3855]298/**
[4836]299 *  a negative exponential interpolation between this keyframe and the next one
300 * @param timePassed The time passed since this Keyframe began
[3855]301*/
[3973]302void Animation3D::mNegExp(float timePassed) const
[3851]303{
[3986]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  /*
[3964]310  this->object->setRelCoor( this->currentKeyFrame->position +
[4597]311                            (this->nextKeyFrame->position - this->currentKeyFrame->position) *
312                            (1.0 - expf(- timePassed * expFactorMov)) );
[3986]313  */
[3851]314}
315
[3964]316
[3855]317/**
[4836]318 *  a quadratic interpolation between this keyframe and the next one
319 * @param timePassed The time passed since this Keyframe began
[3856]320
[4836]321   @todo implement
[3855]322*/
[3973]323void Animation3D::mQuadratic(float timePassed) const
[3851]324{
[3968]325  PRINTF(0)("no quadratic animation3d defined\n");
[3973]326  this->mLinear(timePassed);
[3851]327}
328
[3855]329/**
[4836]330 *  some random animation (fluctuating)
331 * @param timePassed The time passed since this Keyframe began
[3855]332*/
[3973]333void Animation3D::mRandom(float timePassed) const
[3851]334{
[3986]335  /*
[4597]336  this->object->setRelCoor(this->currentKeyFrame->position +
337                           (this->nextKeyFrame->position - this->currentKeyFrame->position) * (float)rand()/(float)RAND_MAX);
[3874]338  this->object->setRelDir(this->currentKeyFrame->direction +
[4597]339                          (this->nextKeyFrame->direction - this->currentKeyFrame->direction)* (float)rand()/(float)RAND_MAX);
[3986]340  */
[3851]341}
[3973]342
343
344/*==Rotation Section==========================================================*/
345
346
347/**
[4836]348 *  Sets The kind of rotation Animation between this keyframe and the next one
349 * @param animFuncRot: The Type of Animation to set
[3973]350*/
351void Animation3D::setAnimFuncRot(ANIM_FUNCTION animFuncRot)
352{
353  switch (animFuncRot)
354    {
[3986]355    default:
[3973]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
[3973]382    }
383}
384
385
386/**
[4836]387 *  stays at the value of the currentKeyFrame
388 * @param timePassed The time passed since this Keyframe began
[3973]389*/
390void Animation3D::rConstant(float timePassed) const
391{
[3977]392  this->object->setRelDir(this->currentKeyFrame->direction);
[3973]393}
394
395/**
[4836]396 *  linear interpolation between this keyframe and the next one
397 * @param timePassed The time passed since this Keyframe began
[3973]398
[4836]399   @todo implement also do this for direction
[3973]400*/
401void Animation3D::rLinear(float timePassed) const
402{
[4998]403  this->object->setRelDir(Quaternion::quatSlerp( this->nextKeyFrame->direction,
404                          this->currentKeyFrame->direction,
405                          timePassed/this->currentKeyFrame->duration) );
[3973]406}
407
408/**
[4836]409 *  a Sinusodial Interpolation between this keyframe and the next one
410 * @param timePassed The time passed since this Keyframe began
[3973]411
[4836]412   @todo implement
[3973]413*/
414void Animation3D::rSine(float timePassed) const
415{
[3975]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
[4998]422  this->object->setRelDir(Quaternion::quatSlerp( this->nextKeyFrame->direction,
423                          this->currentKeyFrame->direction,
424                          scale) );
[3973]425}
426
427
428/**
[4836]429 *  a cosine interpolation between this keyframe and the next one
430 * @param timePassed The time passed since this Keyframe began
[3973]431
[4836]432   @todo implement
[3973]433*/
434void Animation3D::rCosine(float timePassed) const
435{
[3976]436  float scale = cos(M_PI * timePassed / this->currentKeyFrame->duration);
[4998]437  this->object->setRelDir(Quaternion::quatSlerp( this->nextKeyFrame->direction,
438                          this->currentKeyFrame->direction,
439                          scale) );
[3973]440}
441
442
443
444/**
[4836]445 *  an exponential interpolation between this keyframe and the next one
446 * @param timePassed The time passed since this Keyframe began
[3973]447*/
448void Animation3D::rExp(float timePassed) const
449{
[3980]450  PRINTF(0)("exp rotation function not implemented\n");
[3973]451}
452
453/**
[4836]454 *  a negative exponential interpolation between this keyframe and the next one
455 * @param timePassed The time passed since this Keyframe began
[3973]456*/
457void Animation3D::rNegExp(float timePassed) const
458{
[3977]459  float scale = (1.0 - expf(- timePassed * expFactorRot));
[4998]460  this->object->setRelDir(Quaternion::quatSlerp( this->nextKeyFrame->direction,
461                          this->currentKeyFrame->direction,
462                          scale) );
[3973]463}
464
465
466/**
[4836]467 *  a quadratic interpolation between this keyframe and the next one
468 * @param timePassed The time passed since this Keyframe began
[3973]469
[4836]470   @todo implement
[3973]471*/
472void Animation3D::rQuadratic(float timePassed) const
473{
[3980]474  PRINTF(0)("quadratic rotation alg not implemented\n");
[3973]475}
476
477/**
[4836]478 *  some random animation (fluctuating)
479 * @param timePassed The time passed since this Keyframe began
[3973]480*/
481void Animation3D::rRandom(float timePassed) const
482{
[3980]483  PRINTF(0)("random rotation alg not implemented\n");
[3973]484}
Note: See TracBrowser for help on using the repository browser.