Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: fixed two major bugs in the animation3d framework (addKeyFrame, tick issues), added shoot animation again. one of both animation is still placed at the wrong place, since the weapons are not symmetrical

File size: 14.1 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/**
30   \brief standard constructor
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
49  this->bRunning = false;
[3851]50}
51
[3855]52/**
53   \brief standard deconstructor
54   
55   deletes all the Keyframes
56*/
[3851]57Animation3D::~Animation3D(void)
58{
59  // delete all the KeyFrames
60  tIterator<KeyFrame3D>* itKF = keyFrameList->getIterator();
61  KeyFrame3D*  enumKF = itKF->nextElement();
62  while (enumKF)
63    {
64      delete enumKF;
65      enumKF = itKF->nextElement();
66    }
67  delete itKF;
68  delete this->keyFrameList;
69}
70
[3855]71/**
72   \brief rewinds the Animation to the beginning (first KeyFrame and time == 0)
73*/
[3851]74void Animation3D::rewind(void)
75{
76  this->currentKeyFrame = keyFrameList->firstElement();
77  this->nextKeyFrame = keyFrameList->nextElement(keyFrameList->firstElement());
78  this->localTime = 0.0;
[3973]79  this->setAnimFuncMov(this->currentKeyFrame->animFuncMov);
80  this->setAnimFuncRot(this->currentKeyFrame->animFuncRot);
[3851]81}
82
[3855]83/**
84   \brief Appends a new Keyframe
85   \param position The position of the new Keyframe
86   \param direction The direction of the new Keyframe.
87   \param duration The duration from the new KeyFrame to the next one
[3978]88   \param animFuncMov The function to animate position between this keyFrame and the next one
89   \param animFuncMov The function to animate rotation between this keyFrame and the next one
[3855]90*/
[3973]91void Animation3D::addKeyFrame(Vector position, Quaternion direction, float duration, 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;
103   
[3876]104  // when adding the first frame
105  if (this->keyFrameCount == 0)
[3851]106    {
[3876]107      tmpKeyFrame = this->keyFrameList->firstElement();
[3973]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)
116        this->nextKeyFrame = tmpKeyFrame;
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/**
132   \brief ticks the Animation
133   \param dt how much time to tick
134*/
[3852]135void Animation3D::tick(float dt)
[3851]136{
137  if (this->bRunning)
138    { 
[3852]139      this->localTime += dt;
[3851]140      if (localTime >= this->currentKeyFrame->duration)
141        {
[3982]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/**
[3973]169   \brief Sets The kind of movment Animation between this keyframe and the next one
[3855]170   \param animFunc The Type of Animation to set
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;
[3985]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;
[3985]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;
[3985]191      //this->object->setRelCoor(this->currentKeyFrame->position);
192      this->currentKeyFrame->lastPosition = Vector();
[3851]193      break;
194    case ANIM_EXP:
[3973]195      this->animFuncMov = &Animation3D::mExp;
[3851]196      break;
197    case ANIM_NEG_EXP:
[3973]198      this->animFuncMov = &Animation3D::mNegExp;
[3977]199      this->expFactorMov = -1.0 / this->currentKeyFrame->duration * logf(DELTA_X_3D);
[3986]200      this->currentKeyFrame->lastPosition = Vector();
[3851]201      break;
202    case ANIM_QUADRATIC:
[3973]203      this->animFuncMov = &Animation3D::mQuadratic;
[3851]204      break;
205    case ANIM_RANDOM:
[3973]206      this->animFuncMov = &Animation3D::mRandom;
[3851]207      break;
[3986]208    default:
209      break;
[3851]210    }
211}
212
[3973]213
214
[3855]215/**
216   \brief stays at the value of the currentKeyFrame
217   \param timePassed The time passed since this Keyframe began
218*/
[3973]219void Animation3D::mConstant(float timePassed) const
[3851]220{
[3986]221  //this->object->setRelCoor(this->currentKeyFrame->position);
[3851]222
[3852]223  /*
224    this->tmpVect = this->nextKeyFrame->position - this->currentKeyFrame->position;
225    this->tmpVect = this->tmpVect * this->localTime / this->currentKeyFrame->duration;
226    this->currentFrame->object->setRelCoor(*this->lastFrame->position + *this->tmpVect);
227    this->lastPosition = this->tmpVect;
228  */
[3851]229}
230
[3855]231/**
232   \brief linear interpolation between this keyframe and the next one
233   \param timePassed The time passed since this Keyframe began
[3856]234
235   \todo implement also do this for direction
[3855]236*/
[3973]237void Animation3D::mLinear(float timePassed) const
[3851]238{
[3981]239  Vector v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (timePassed/this->currentKeyFrame->duration);
240  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
241  this->currentKeyFrame->lastPosition = v;
[3851]242}
243
[3855]244/**
245   \brief a Sinusodial Interpolation between this keyframe and the next one
246   \param timePassed The time passed since this Keyframe began
[3856]247
248   \todo implement
[3855]249*/
[3973]250void Animation3D::mSine(float timePassed) const
[3851]251{
[3984]252  Vector v;
253  if( timePassed  < this->currentKeyFrame->duration/2.0)
254    v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * sin( M_PI * timePassed /this->currentKeyFrame->duration) / 2.0;
255  else
256    v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (2.0 + sin( M_PI * (- timePassed /this->currentKeyFrame->duration)) )/ 2.0;
257 
258  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
259  this->currentKeyFrame->lastPosition = v;
[3851]260}
261
[3965]262
[3855]263/**
264   \brief a cosine interpolation between this keyframe and the next one
265   \param timePassed The time passed since this Keyframe began
[3856]266
267   \todo implement
[3855]268*/
[3973]269void Animation3D::mCosine(float timePassed) const
[3851]270{
[3985]271  Vector v;
272  v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (1.0 + cos( M_PI * timePassed / this->currentKeyFrame->duration))/2.0;
273  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
274  this->currentKeyFrame->lastPosition = v;
275
276
277  /*
[3967]278  this->object->setRelCoor( this->nextKeyFrame->position -
279                            (this->nextKeyFrame->position - this->currentKeyFrame->position) *
280                            (1.0 + cos( M_PI * timePassed / this->currentKeyFrame->duration))/2.0);
[3985]281  */
[3851]282}
283
[3967]284
285
[3855]286/**
287   \brief an exponential interpolation between this keyframe and the next one
288   \param timePassed The time passed since this Keyframe began
289*/
[3973]290void Animation3D::mExp(float timePassed) const
[3851]291{
[3968]292  PRINTF(0)("no exp animation3d defined\n");
[3973]293  this->mLinear(timePassed);
[3851]294}
295
[3855]296/**
297   \brief a negative exponential interpolation between this keyframe and the next one
298   \param timePassed The time passed since this Keyframe began
299*/
[3973]300void Animation3D::mNegExp(float timePassed) const
[3851]301{
[3986]302  Vector v;
303  v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (1.0 - expf(- timePassed * expFactorMov));
304  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
305  this->currentKeyFrame->lastPosition = v;
306
307  /*
[3964]308  this->object->setRelCoor( this->currentKeyFrame->position +
309                            (this->nextKeyFrame->position - this->currentKeyFrame->position) *
[3977]310                            (1.0 - expf(- timePassed * expFactorMov)) );
[3986]311  */
[3851]312}
313
[3964]314
[3855]315/**
316   \brief a quadratic interpolation between this keyframe and the next one
317   \param timePassed The time passed since this Keyframe began
[3856]318
319   \todo implement
[3855]320*/
[3973]321void Animation3D::mQuadratic(float timePassed) const
[3851]322{
[3968]323  PRINTF(0)("no quadratic animation3d defined\n");
[3973]324  this->mLinear(timePassed);
[3851]325}
326
[3855]327/**
328   \brief some random animation (fluctuating)
329   \param timePassed The time passed since this Keyframe began
330*/
[3973]331void Animation3D::mRandom(float timePassed) const
[3851]332{
[3986]333  /*
[3874]334  this->object->setRelCoor(this->currentKeyFrame->position +
335                           (this->nextKeyFrame->position - this->currentKeyFrame->position) * (float)rand()/(float)RAND_MAX);
336  this->object->setRelDir(this->currentKeyFrame->direction +
337                          (this->nextKeyFrame->direction - this->currentKeyFrame->direction)* (float)rand()/(float)RAND_MAX);
[3986]338  */
[3851]339}
[3973]340
341
342/*==Rotation Section==========================================================*/
343
344
345/**
346   \brief Sets The kind of rotation Animation between this keyframe and the next one
347   \param animFunc The Type of Animation to set
348*/
349void Animation3D::setAnimFuncRot(ANIM_FUNCTION animFuncRot)
350{
351  switch (animFuncRot)
352    {
[3986]353    default:
[3973]354    case ANIM_CONSTANT:
355      this->animFuncRot = &Animation3D::rConstant;
[3986]356      printf("a;sdlfkja;lskdjf;alskjdf;lasjdf;lasjdf;lasjdf;lajsdf\n");
[3973]357      break;
358    case ANIM_LINEAR:
359      this->animFuncRot = &Animation3D::rLinear;
360      break;
361    case ANIM_SINE:
362      this->animFuncRot = &Animation3D::rSine;
363      break;
364    case ANIM_COSINE:
365      this->animFuncRot = &Animation3D::rCosine;
366      break;
367    case ANIM_EXP:
368      this->animFuncRot = &Animation3D::rExp;
369      break;
370    case ANIM_NEG_EXP:
371      this->animFuncRot = &Animation3D::rNegExp;
[3977]372      this->expFactorRot = -1.0 / this->currentKeyFrame->duration * logf(DELTA_X_3D);
[3973]373      break;
374    case ANIM_QUADRATIC:
375      this->animFuncRot = &Animation3D::rQuadratic;
376      break;
377    case ANIM_RANDOM:
378      this->animFuncRot = &Animation3D::rRandom;
379      break;
[3986]380
[3973]381    }
382}
383
384
385/**
386   \brief stays at the value of the currentKeyFrame
387   \param timePassed The time passed since this Keyframe began
388*/
389void Animation3D::rConstant(float timePassed) const
390{
[3977]391  this->object->setRelDir(this->currentKeyFrame->direction);
[3973]392}
393
394/**
395   \brief linear interpolation between this keyframe and the next one
396   \param timePassed The time passed since this Keyframe began
397
398   \todo implement also do this for direction
399*/
400void Animation3D::rLinear(float timePassed) const
401{
402  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
403                                     this->currentKeyFrame->direction, 
404                                     timePassed/this->currentKeyFrame->duration) );
405}
406
407/**
408   \brief a Sinusodial Interpolation between this keyframe and the next one
409   \param timePassed The time passed since this Keyframe began
410
411   \todo implement
412*/
413void Animation3D::rSine(float timePassed) const
414{
[3975]415  float scale;
416  if( timePassed < this->currentKeyFrame->duration / 2.0)
417    scale = sin( M_PI * timePassed / this->currentKeyFrame->duration);
418  else
419    scale = 1.0 - sin( M_PI * timePassed / this->currentKeyFrame->duration);
420
421  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
422                                     this->currentKeyFrame->direction, 
423                                     scale) );
[3973]424}
425
426
427/**
428   \brief a cosine interpolation between this keyframe and the next one
429   \param timePassed The time passed since this Keyframe began
430
431   \todo implement
432*/
433void Animation3D::rCosine(float timePassed) const
434{
[3976]435  float scale = cos(M_PI * timePassed / this->currentKeyFrame->duration);
436  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
437                                     this->currentKeyFrame->direction, 
438                                     scale) );
[3973]439}
440
441
442
443/**
444   \brief an exponential interpolation between this keyframe and the next one
445   \param timePassed The time passed since this Keyframe began
446*/
447void Animation3D::rExp(float timePassed) const
448{
[3980]449  PRINTF(0)("exp rotation function not implemented\n");
[3973]450}
451
452/**
453   \brief a negative exponential interpolation between this keyframe and the next one
454   \param timePassed The time passed since this Keyframe began
455*/
456void Animation3D::rNegExp(float timePassed) const
457{
[3977]458  float scale = (1.0 - expf(- timePassed * expFactorRot));
459  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
460                                     this->currentKeyFrame->direction, 
461                                     scale) );
[3973]462}
463
464
465/**
466   \brief a quadratic interpolation between this keyframe and the next one
467   \param timePassed The time passed since this Keyframe began
468
469   \todo implement
470*/
471void Animation3D::rQuadratic(float timePassed) const
472{
[3980]473  PRINTF(0)("quadratic rotation alg not implemented\n");
[3973]474}
475
476/**
477   \brief some random animation (fluctuating)
478   \param timePassed The time passed since this Keyframe began
479*/
480void Animation3D::rRandom(float timePassed) const
481{
[3980]482  PRINTF(0)("random rotation alg not implemented\n");
[3973]483}
Note: See TracBrowser for help on using the repository browser.