Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: reimplemented the list functions, as i did before in revision 5110.
This time, i looked out for the bugs, and i think i found one

@patrick: i know, that you do not want to code at the moment… :/ → see mail

File size: 14.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 *  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 = NULL;//&Animation3D::mLinear;
47  this->animFuncRot = NULL;//&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->firstElement();
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 *  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      if (likely(this->animFuncMov != NULL))
159        (this->*animFuncMov)(this->localTime);
160      if (likely(this->animFuncRot != NULL))
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      this->animFuncMov = NULL;
214      break;
215    }
216}
217
218/**
219 *  stays at the value of the currentKeyFrame
220 * @param timePassed The time passed since this Keyframe began
221*/
222void Animation3D::mConstant(float timePassed) const
223{
224  //this->object->setRelCoor(this->currentKeyFrame->position);
225
226  /*
227    this->tmpVect = this->nextKeyFrame->position - this->currentKeyFrame->position;
228    this->tmpVect = this->tmpVect * this->localTime / this->currentKeyFrame->duration;
229    this->currentFrame->object->setRelCoor(*this->lastFrame->position + *this->tmpVect);
230    this->lastPosition = this->tmpVect;
231  */
232}
233
234/**
235 *  linear interpolation between this keyframe and the next one
236 * @param timePassed The time passed since this Keyframe began
237
238   @todo implement also do this for direction
239*/
240void Animation3D::mLinear(float timePassed) const
241{
242  Vector v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (timePassed/this->currentKeyFrame->duration);
243  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
244  this->currentKeyFrame->lastPosition = v;
245}
246
247/**
248 *  a Sinusodial Interpolation between this keyframe and the next one
249 * @param timePassed The time passed since this Keyframe began
250
251   @todo implement
252*/
253void Animation3D::mSine(float timePassed) const
254{
255  Vector v;
256  if( timePassed  < this->currentKeyFrame->duration/2.0)
257    v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * sin( M_PI * timePassed /this->currentKeyFrame->duration) / 2.0;
258  else
259    v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (2.0 + sin( M_PI * (- timePassed /this->currentKeyFrame->duration)) )/ 2.0;
260
261  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
262  this->currentKeyFrame->lastPosition = v;
263}
264
265
266/**
267 *  a cosine interpolation between this keyframe and the next one
268 * @param timePassed The time passed since this Keyframe began
269
270   @todo implement
271*/
272void Animation3D::mCosine(float timePassed) const
273{
274  Vector v;
275  v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (1.0 + cos( M_PI * timePassed / this->currentKeyFrame->duration))/2.0;
276  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
277  this->currentKeyFrame->lastPosition = v;
278
279
280  /*
281  this->object->setRelCoor( this->nextKeyFrame->position -
282                            (this->nextKeyFrame->position - this->currentKeyFrame->position) *
283                            (1.0 + cos( M_PI * timePassed / this->currentKeyFrame->duration))/2.0);
284  */
285}
286
287
288
289/**
290 *  an exponential interpolation between this keyframe and the next one
291 * @param timePassed The time passed since this Keyframe began
292*/
293void Animation3D::mExp(float timePassed) const
294{
295  PRINTF(0)("no exp animation3d defined\n");
296  this->mLinear(timePassed);
297}
298
299/**
300 *  a negative exponential interpolation between this keyframe and the next one
301 * @param timePassed The time passed since this Keyframe began
302*/
303void Animation3D::mNegExp(float timePassed) const
304{
305  Vector v;
306  v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (1.0 - expf(- timePassed * expFactorMov));
307  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
308  this->currentKeyFrame->lastPosition = v;
309
310  /*
311  this->object->setRelCoor( this->currentKeyFrame->position +
312                            (this->nextKeyFrame->position - this->currentKeyFrame->position) *
313                            (1.0 - expf(- timePassed * expFactorMov)) );
314  */
315}
316
317
318/**
319 *  a quadratic interpolation between this keyframe and the next one
320 * @param timePassed The time passed since this Keyframe began
321
322   @todo implement
323*/
324void Animation3D::mQuadratic(float timePassed) const
325{
326  PRINTF(0)("no quadratic animation3d defined\n");
327  this->mLinear(timePassed);
328}
329
330/**
331 *  some random animation (fluctuating)
332 * @param timePassed The time passed since this Keyframe began
333*/
334void Animation3D::mRandom(float timePassed) const
335{
336  /*
337  this->object->setRelCoor(this->currentKeyFrame->position +
338                           (this->nextKeyFrame->position - this->currentKeyFrame->position) * (float)rand()/(float)RAND_MAX);
339  this->object->setRelDir(this->currentKeyFrame->direction +
340                          (this->nextKeyFrame->direction - this->currentKeyFrame->direction)* (float)rand()/(float)RAND_MAX);
341  */
342}
343
344
345/*==Rotation Section==========================================================*/
346
347
348/**
349 *  Sets The kind of rotation Animation between this keyframe and the next one
350 * @param animFuncRot: The Type of Animation to set
351*/
352void Animation3D::setAnimFuncRot(ANIM_FUNCTION animFuncRot)
353{
354  switch (animFuncRot)
355    {
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    default:
383      this->animFuncRot = NULL;
384    }
385}
386
387
388/**
389 *  stays at the value of the currentKeyFrame
390 * @param timePassed The time passed since this Keyframe began
391*/
392void Animation3D::rConstant(float timePassed) const
393{
394  this->object->setRelDir(this->currentKeyFrame->direction);
395}
396
397/**
398 *  linear interpolation between this keyframe and the next one
399 * @param timePassed The time passed since this Keyframe began
400
401   @todo implement also do this for direction
402*/
403void Animation3D::rLinear(float timePassed) const
404{
405  this->object->setRelDir(Quaternion::quatSlerp( this->nextKeyFrame->direction,
406                          this->currentKeyFrame->direction,
407                          timePassed/this->currentKeyFrame->duration) );
408}
409
410/**
411 *  a Sinusodial 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::rSine(float timePassed) const
417{
418  float scale;
419  if( timePassed < this->currentKeyFrame->duration / 2.0)
420    scale = sin( M_PI * timePassed / this->currentKeyFrame->duration);
421  else
422    scale = 1.0 - sin( M_PI * timePassed / this->currentKeyFrame->duration);
423
424  this->object->setRelDir(Quaternion::quatSlerp( this->nextKeyFrame->direction,
425                          this->currentKeyFrame->direction,
426                          scale) );
427}
428
429
430/**
431 *  a cosine interpolation between this keyframe and the next one
432 * @param timePassed The time passed since this Keyframe began
433
434   @todo implement
435*/
436void Animation3D::rCosine(float timePassed) const
437{
438  float scale = cos(M_PI * timePassed / this->currentKeyFrame->duration);
439  this->object->setRelDir(Quaternion::quatSlerp( this->nextKeyFrame->direction,
440                          this->currentKeyFrame->direction,
441                          scale) );
442}
443
444
445
446/**
447 *  an exponential interpolation between this keyframe and the next one
448 * @param timePassed The time passed since this Keyframe began
449*/
450void Animation3D::rExp(float timePassed) const
451{
452  PRINTF(2)("exp rotation function not implemented\n");
453}
454
455/**
456 *  a negative exponential interpolation between this keyframe and the next one
457 * @param timePassed The time passed since this Keyframe began
458*/
459void Animation3D::rNegExp(float timePassed) const
460{
461  float scale = (1.0 - expf(- timePassed * expFactorRot));
462  this->object->setRelDir(Quaternion::quatSlerp( this->nextKeyFrame->direction,
463                          this->currentKeyFrame->direction,
464                          scale) );
465}
466
467
468/**
469 *  a quadratic interpolation between this keyframe and the next one
470 * @param timePassed The time passed since this Keyframe began
471
472   @todo implement
473*/
474void Animation3D::rQuadratic(float timePassed) const
475{
476  PRINTF(0)("quadratic rotation alg not implemented\n");
477}
478
479/**
480 *  some random animation (fluctuating)
481 * @param timePassed The time passed since this Keyframe began
482*/
483void Animation3D::rRandom(float timePassed) const
484{
485  PRINTF(0)("random rotation alg not implemented\n");
486}
Note: See TracBrowser for help on using the repository browser.