Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: now implemented the shiftCoor functions correctly

File size: 13.7 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      //this->object->setRelCoor(this->currentKeyFrame->position);
191      this->currentKeyFrame->lastPosition = Vector();
192      break;
193    case ANIM_EXP:
194      this->animFuncMov = &Animation3D::mExp;
195      break;
196    case ANIM_NEG_EXP:
197      this->animFuncMov = &Animation3D::mNegExp;
198      this->expFactorMov = -1.0 / this->currentKeyFrame->duration * logf(DELTA_X_3D);
199      break;
200    case ANIM_QUADRATIC:
201      this->animFuncMov = &Animation3D::mQuadratic;
202      break;
203    case ANIM_RANDOM:
204      this->animFuncMov = &Animation3D::mRandom;
205      break;
206    }
207}
208
209
210
211/**
212   \brief stays at the value of the currentKeyFrame
213   \param timePassed The time passed since this Keyframe began
214*/
215void Animation3D::mConstant(float timePassed) const
216{
217  this->object->setRelCoor(this->currentKeyFrame->position);
218
219  /*
220    this->tmpVect = this->nextKeyFrame->position - this->currentKeyFrame->position;
221    this->tmpVect = this->tmpVect * this->localTime / this->currentKeyFrame->duration;
222    this->currentFrame->object->setRelCoor(*this->lastFrame->position + *this->tmpVect);
223    this->lastPosition = this->tmpVect;
224  */
225}
226
227/**
228   \brief linear interpolation between this keyframe and the next one
229   \param timePassed The time passed since this Keyframe began
230
231   \todo implement also do this for direction
232*/
233void Animation3D::mLinear(float timePassed) const
234{
235  Vector v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (timePassed/this->currentKeyFrame->duration);
236  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
237  this->currentKeyFrame->lastPosition = v;
238}
239
240/**
241   \brief a Sinusodial Interpolation between this keyframe and the next one
242   \param timePassed The time passed since this Keyframe began
243
244   \todo implement
245*/
246void Animation3D::mSine(float timePassed) const
247{
248  Vector v;
249  if( timePassed  < this->currentKeyFrame->duration/2.0)
250    v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * sin( M_PI * timePassed /this->currentKeyFrame->duration) / 2.0;
251  else
252    v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (2.0 + sin( M_PI * (- timePassed /this->currentKeyFrame->duration)) )/ 2.0;
253 
254  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
255  this->currentKeyFrame->lastPosition = v;
256}
257
258
259/**
260   \brief a cosine interpolation between this keyframe and the next one
261   \param timePassed The time passed since this Keyframe began
262
263   \todo implement
264*/
265void Animation3D::mCosine(float timePassed) const
266{
267  Vector v;
268  v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (1.0 + cos( M_PI * timePassed / this->currentKeyFrame->duration))/2.0;
269  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
270  this->currentKeyFrame->lastPosition = v;
271
272
273  /*
274  this->object->setRelCoor( this->nextKeyFrame->position -
275                            (this->nextKeyFrame->position - this->currentKeyFrame->position) *
276                            (1.0 + cos( M_PI * timePassed / this->currentKeyFrame->duration))/2.0);
277  */
278}
279
280
281
282/**
283   \brief an exponential interpolation between this keyframe and the next one
284   \param timePassed The time passed since this Keyframe began
285*/
286void Animation3D::mExp(float timePassed) const
287{
288  PRINTF(0)("no exp animation3d defined\n");
289  this->mLinear(timePassed);
290}
291
292/**
293   \brief a negative exponential interpolation between this keyframe and the next one
294   \param timePassed The time passed since this Keyframe began
295*/
296void Animation3D::mNegExp(float timePassed) const
297{
298  this->object->setRelCoor( this->currentKeyFrame->position +
299                            (this->nextKeyFrame->position - this->currentKeyFrame->position) * 
300                            (1.0 - expf(- timePassed * expFactorMov)) );
301}
302
303
304/**
305   \brief a quadratic interpolation between this keyframe and the next one
306   \param timePassed The time passed since this Keyframe began
307
308   \todo implement
309*/
310void Animation3D::mQuadratic(float timePassed) const
311{
312  PRINTF(0)("no quadratic animation3d defined\n");
313  this->mLinear(timePassed);
314}
315
316/**
317   \brief some random animation (fluctuating)
318   \param timePassed The time passed since this Keyframe began
319*/
320void Animation3D::mRandom(float timePassed) const
321{
322  this->object->setRelCoor(this->currentKeyFrame->position + 
323                           (this->nextKeyFrame->position - this->currentKeyFrame->position) * (float)rand()/(float)RAND_MAX);
324  this->object->setRelDir(this->currentKeyFrame->direction +
325                          (this->nextKeyFrame->direction - this->currentKeyFrame->direction)* (float)rand()/(float)RAND_MAX);
326}
327
328
329/*==Rotation Section==========================================================*/
330
331
332/**
333   \brief Sets The kind of rotation Animation between this keyframe and the next one
334   \param animFunc The Type of Animation to set
335*/
336void Animation3D::setAnimFuncRot(ANIM_FUNCTION animFuncRot)
337{
338  switch (animFuncRot)
339    {
340   default:
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;
358      this->expFactorRot = -1.0 / this->currentKeyFrame->duration * logf(DELTA_X_3D);
359      break;
360    case ANIM_QUADRATIC:
361      this->animFuncRot = &Animation3D::rQuadratic;
362      break;
363    case ANIM_RANDOM:
364      this->animFuncRot = &Animation3D::rRandom;
365      break;
366    }
367}
368
369
370/**
371   \brief stays at the value of the currentKeyFrame
372   \param timePassed The time passed since this Keyframe began
373*/
374void Animation3D::rConstant(float timePassed) const
375{
376  this->object->setRelDir(this->currentKeyFrame->direction);
377}
378
379/**
380   \brief linear interpolation between this keyframe and the next one
381   \param timePassed The time passed since this Keyframe began
382
383   \todo implement also do this for direction
384*/
385void Animation3D::rLinear(float timePassed) const
386{
387  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
388                                     this->currentKeyFrame->direction, 
389                                     timePassed/this->currentKeyFrame->duration) );
390}
391
392/**
393   \brief a Sinusodial Interpolation between this keyframe and the next one
394   \param timePassed The time passed since this Keyframe began
395
396   \todo implement
397*/
398void Animation3D::rSine(float timePassed) const
399{
400  float scale;
401  if( timePassed < this->currentKeyFrame->duration / 2.0)
402    scale = sin( M_PI * timePassed / this->currentKeyFrame->duration);
403  else
404    scale = 1.0 - sin( M_PI * timePassed / this->currentKeyFrame->duration);
405
406  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
407                                     this->currentKeyFrame->direction, 
408                                     scale) );
409}
410
411
412/**
413   \brief a cosine interpolation between this keyframe and the next one
414   \param timePassed The time passed since this Keyframe began
415
416   \todo implement
417*/
418void Animation3D::rCosine(float timePassed) const
419{
420  float scale = cos(M_PI * timePassed / this->currentKeyFrame->duration);
421  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
422                                     this->currentKeyFrame->direction, 
423                                     scale) );
424}
425
426
427
428/**
429   \brief an exponential interpolation between this keyframe and the next one
430   \param timePassed The time passed since this Keyframe began
431*/
432void Animation3D::rExp(float timePassed) const
433{
434  PRINTF(0)("exp rotation function not implemented\n");
435}
436
437/**
438   \brief a negative exponential interpolation between this keyframe and the next one
439   \param timePassed The time passed since this Keyframe began
440*/
441void Animation3D::rNegExp(float timePassed) const
442{
443  float scale = (1.0 - expf(- timePassed * expFactorRot));
444  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
445                                     this->currentKeyFrame->direction, 
446                                     scale) );
447}
448
449
450/**
451   \brief a quadratic interpolation between this keyframe and the next one
452   \param timePassed The time passed since this Keyframe began
453
454   \todo implement
455*/
456void Animation3D::rQuadratic(float timePassed) const
457{
458  PRINTF(0)("quadratic rotation alg not implemented\n");
459}
460
461/**
462   \brief some random animation (fluctuating)
463   \param timePassed The time passed since this Keyframe began
464*/
465void Animation3D::rRandom(float timePassed) const
466{
467  PRINTF(0)("random rotation alg not implemented\n");
468}
Note: See TracBrowser for help on using the repository browser.