Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: more optimizations of the Quaternion Class.
Now the 3D-rotation is much faster through this code:

Vector tmpRot = this→getAbsDir().getSpacialAxis();
glRotatef (this→getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );

instead of the old Matrix-approach. furthermore glRotate is optimized much better in openGL as is clearly stated in the red book

also implemented some other really useless functions for Quaternion

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