Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: return value of quat-slerp was wrong

File size: 8.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*/
18
19#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_ANIM
20
21#include "animation3d.h"
22
23#include "p_node.h"
24
25using namespace std;
26
27/**
28   \brief standard constructor
29*/
30Animation3D::Animation3D(PNode* object)
31{
32  this->object = object;
33
34  // create a new List
35  this->keyFrameList = new tList<KeyFrame3D>();
36  KeyFrame3D* tmpKeyFrame = new KeyFrame3D;
37  tmpKeyFrame->position = Vector();
38  tmpKeyFrame->direction = Quaternion();
39  keyFrameList->add(tmpKeyFrame);
40
41  this->currentKeyFrame = tmpKeyFrame;
42  this->nextKeyFrame = tmpKeyFrame;
43
44  this->animFunc = &Animation3D::linear;
45}
46
47/**
48   \brief standard deconstructor
49   
50   deletes all the Keyframes
51*/
52Animation3D::~Animation3D(void)
53{
54  // delete all the KeyFrames
55  tIterator<KeyFrame3D>* itKF = keyFrameList->getIterator();
56  KeyFrame3D*  enumKF = itKF->nextElement();
57  while (enumKF)
58    {
59      delete enumKF;
60      enumKF = itKF->nextElement();
61    }
62  delete itKF;
63  delete this->keyFrameList;
64}
65
66/**
67   \brief rewinds the Animation to the beginning (first KeyFrame and time == 0)
68*/
69void Animation3D::rewind(void)
70{
71  this->currentKeyFrame = keyFrameList->firstElement();
72  this->nextKeyFrame = keyFrameList->nextElement(keyFrameList->firstElement());
73  this->localTime = 0.0;
74  this->setAnimFunc(this->currentKeyFrame->animFunc);
75}
76
77/**
78   \brief Appends a new Keyframe
79   \param position The position of the new Keyframe
80   \param direction The direction of the new Keyframe.
81   \param duration The duration from the new KeyFrame to the next one
82   \param animFunc The function to animate between this keyFrame and the next one
83*/
84void Animation3D::addKeyFrame(Vector position, Quaternion direction, float duration, ANIM_FUNCTION animFunc)
85{
86  // some small check
87  if (duration <= 0.0)
88    duration = 1.0;
89
90  KeyFrame3D* tmpKeyFrame;
91   
92  // when adding the first frame
93  if (this->keyFrameCount == 0)
94    {
95      tmpKeyFrame = this->keyFrameList->firstElement();
96      this->setAnimFunc(animFunc);
97    }
98  else
99    {
100      tmpKeyFrame = new KeyFrame3D;
101      // when adding the second frame
102      if (this->currentKeyFrame == this->nextKeyFrame)
103        this->nextKeyFrame = tmpKeyFrame;
104      this->keyFrameList->add(tmpKeyFrame);
105    }
106
107  tmpKeyFrame->position = position;
108  tmpKeyFrame->direction = direction;
109  tmpKeyFrame->duration = duration;
110  tmpKeyFrame->animFunc = animFunc;
111  this->keyFrameCount++;
112}
113
114/**
115   \brief ticks the Animation
116   \param dt how much time to tick
117*/
118void Animation3D::tick(float dt)
119{
120  if (this->bRunning)
121    { 
122      this->localTime += dt;
123      if (localTime >= this->currentKeyFrame->duration)
124        {
125          // switching to the next Key-Frame
126          this->localTime -= this->currentKeyFrame->duration;
127          this->currentKeyFrame = this->nextKeyFrame;
128          // checking, if we should still Play the animation
129          if (this->currentKeyFrame == this->keyFrameList->lastElement())
130            this->handleInfinity();
131          this->nextKeyFrame = this->keyFrameList->nextElement(this->currentKeyFrame);
132          this->setAnimFunc(this->currentKeyFrame->animFunc);     
133        }
134      /* now animate it */
135      (this->*animFunc)(this->localTime);
136    }
137}
138
139
140/**
141   \brief Sets The kind of Animation between this keyframe and the next one
142   \param animFunc The Type of Animation to set
143*/
144void Animation3D::setAnimFunc(ANIM_FUNCTION animFunc)
145{
146  switch (animFunc)
147    {
148    default:
149    case ANIM_CONSTANT:
150      this->animFunc = &Animation3D::constant;
151      break;
152    case ANIM_LINEAR:
153      this->animFunc = &Animation3D::linear;
154      break;
155    case ANIM_SINE:
156      this->animFunc = &Animation3D::sine;
157      break;
158    case ANIM_COSINE:
159      this->animFunc = &Animation3D::cosine;
160      break;
161    case ANIM_EXP:
162      this->animFunc = &Animation3D::exp;
163      break;
164    case ANIM_NEG_EXP:
165      this->animFunc = &Animation3D::negExp;
166      this->expFactor = -1.0 / this->currentKeyFrame->duration * logf(DELTA_X_3D);
167      break;
168    case ANIM_QUADRATIC:
169      this->animFunc = &Animation3D::quadratic;
170      break;
171    case ANIM_RANDOM:
172      this->animFunc = &Animation3D::random;
173      break;
174    }
175}
176
177/**
178   \brief stays at the value of the currentKeyFrame
179   \param timePassed The time passed since this Keyframe began
180*/
181void Animation3D::constant(float timePassed) const
182{
183  this->object->setRelCoor(this->currentKeyFrame->position);
184
185  /*
186    this->tmpVect = this->nextKeyFrame->position - this->currentKeyFrame->position;
187    this->tmpVect = this->tmpVect * this->localTime / this->currentKeyFrame->duration;
188    this->currentFrame->object->setRelCoor(*this->lastFrame->position + *this->tmpVect);
189    this->lastPosition = this->tmpVect;
190  */
191}
192
193/**
194   \brief linear interpolation between this keyframe and the next one
195   \param timePassed The time passed since this Keyframe began
196
197   \todo implement also do this for direction
198*/
199void Animation3D::linear(float timePassed) const
200{
201  this->object->setRelCoor(this->currentKeyFrame->position +
202                          (this->nextKeyFrame->position - this->currentKeyFrame->position) * 
203                          (timePassed/this->currentKeyFrame->duration));
204
205  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
206                                     this->currentKeyFrame->direction, 
207                                     timePassed/this->currentKeyFrame->duration) );
208
209}
210
211/**
212   \brief a Sinusodial Interpolation between this keyframe and the next one
213   \param timePassed The time passed since this Keyframe began
214
215   \todo implement
216*/
217void Animation3D::sine(float timePassed) const
218{
219  if( timePassed  < this->currentKeyFrame->duration/2.0)
220    this->object->setRelCoor( this->currentKeyFrame->position + (this->nextKeyFrame->position - this->currentKeyFrame->position) *
221                              sin( M_PI * timePassed /this->currentKeyFrame->duration) / 2.0);
222  else
223    this->object->setRelCoor( this->nextKeyFrame->position - (this->nextKeyFrame->position - this->currentKeyFrame->position) *
224                              sin( M_PI * (1.0 - timePassed /this->currentKeyFrame->duration) )/2.0);
225}
226
227
228/**
229   \brief a cosine interpolation between this keyframe and the next one
230   \param timePassed The time passed since this Keyframe began
231
232   \todo implement
233*/
234void Animation3D::cosine(float timePassed) const
235{
236  this->object->setRelCoor( this->nextKeyFrame->position -
237                            (this->nextKeyFrame->position - this->currentKeyFrame->position) *
238                            (1.0 + cos( M_PI * timePassed / this->currentKeyFrame->duration))/2.0);
239}
240
241
242/*
243 return ((this->nextKeyFrame->value + this->currentKeyFrame->value) +
244    (this->currentKeyFrame->value - this->nextKeyFrame->value) *
245    cos( M_PI * timePassed / this->currentKeyFrame->duration))/2;
246*/
247
248/**
249   \brief an exponential interpolation between this keyframe and the next one
250   \param timePassed The time passed since this Keyframe began
251*/
252void Animation3D::exp(float timePassed) const
253{
254  PRINTF(0)("no exp animation3d defined\n");
255  this->linear(timePassed);
256}
257
258/**
259   \brief a negative exponential interpolation between this keyframe and the next one
260   \param timePassed The time passed since this Keyframe began
261*/
262void Animation3D::negExp(float timePassed) const
263{
264  this->object->setRelCoor( this->currentKeyFrame->position +
265                            (this->nextKeyFrame->position - this->currentKeyFrame->position) * 
266                            (1.0 - expf(- timePassed * expFactor)) );
267}
268
269
270/**
271   \brief a quadratic interpolation between this keyframe and the next one
272   \param timePassed The time passed since this Keyframe began
273
274   \todo implement
275*/
276void Animation3D::quadratic(float timePassed) const
277{
278  PRINTF(0)("no quadratic animation3d defined\n");
279  this->linear(timePassed);
280}
281
282/**
283   \brief some random animation (fluctuating)
284   \param timePassed The time passed since this Keyframe began
285*/
286void Animation3D::random(float timePassed) const
287{
288  this->object->setRelCoor(this->currentKeyFrame->position + 
289                           (this->nextKeyFrame->position - this->currentKeyFrame->position) * (float)rand()/(float)RAND_MAX);
290  this->object->setRelDir(this->currentKeyFrame->direction +
291                          (this->nextKeyFrame->direction - this->currentKeyFrame->direction)* (float)rand()/(float)RAND_MAX);
292}
Note: See TracBrowser for help on using the repository browser.