Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3984 was 3984, checked in by patrick, 20 years ago

orxonox/trunk: implemented the sinus function for shifCoor method

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