Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10687 was 10618, checked in by bknecht, 18 years ago

merged cleanup into trunk (only improvements)

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