Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: fixed two major bugs in the animation3d framework (addKeyFrame, tick issues), added shoot animation again. one of both animation is still placed at the wrong place, since the weapons are not symmetrical

File size: 14.1 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  this->bRunning = false;
50}
51
52/**
53   \brief standard deconstructor
54   
55   deletes all the Keyframes
56*/
57Animation3D::~Animation3D(void)
58{
59  // delete all the KeyFrames
60  tIterator<KeyFrame3D>* itKF = keyFrameList->getIterator();
61  KeyFrame3D*  enumKF = itKF->nextElement();
62  while (enumKF)
63    {
64      delete enumKF;
65      enumKF = itKF->nextElement();
66    }
67  delete itKF;
68  delete this->keyFrameList;
69}
70
71/**
72   \brief rewinds the Animation to the beginning (first KeyFrame and time == 0)
73*/
74void Animation3D::rewind(void)
75{
76  this->currentKeyFrame = keyFrameList->firstElement();
77  this->nextKeyFrame = keyFrameList->nextElement(keyFrameList->firstElement());
78  this->localTime = 0.0;
79  this->setAnimFuncMov(this->currentKeyFrame->animFuncMov);
80  this->setAnimFuncRot(this->currentKeyFrame->animFuncRot);
81}
82
83/**
84   \brief Appends a new Keyframe
85   \param position The position of the new Keyframe
86   \param direction The direction of the new Keyframe.
87   \param duration The duration from the new KeyFrame to the next one
88   \param animFuncMov The function to animate position between this keyFrame and the next one
89   \param animFuncMov The function to animate rotation between this keyFrame and the next one
90*/
91void Animation3D::addKeyFrame(Vector position, Quaternion direction, float duration, 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   \brief 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   \brief Sets The kind of movment Animation between this keyframe and the next one
170   \param animFunc 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->animFuncMov = &Animation3D::mExp;
196      break;
197    case ANIM_NEG_EXP:
198      this->animFuncMov = &Animation3D::mNegExp;
199      this->expFactorMov = -1.0 / this->currentKeyFrame->duration * logf(DELTA_X_3D);
200      this->currentKeyFrame->lastPosition = Vector();
201      break;
202    case ANIM_QUADRATIC:
203      this->animFuncMov = &Animation3D::mQuadratic;
204      break;
205    case ANIM_RANDOM:
206      this->animFuncMov = &Animation3D::mRandom;
207      break;
208    default:
209      break;
210    }
211}
212
213
214
215/**
216   \brief stays at the value of the currentKeyFrame
217   \param timePassed The time passed since this Keyframe began
218*/
219void Animation3D::mConstant(float timePassed) const
220{
221  //this->object->setRelCoor(this->currentKeyFrame->position);
222
223  /*
224    this->tmpVect = this->nextKeyFrame->position - this->currentKeyFrame->position;
225    this->tmpVect = this->tmpVect * this->localTime / this->currentKeyFrame->duration;
226    this->currentFrame->object->setRelCoor(*this->lastFrame->position + *this->tmpVect);
227    this->lastPosition = this->tmpVect;
228  */
229}
230
231/**
232   \brief linear interpolation between this keyframe and the next one
233   \param timePassed The time passed since this Keyframe began
234
235   \todo implement also do this for direction
236*/
237void Animation3D::mLinear(float timePassed) const
238{
239  Vector v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (timePassed/this->currentKeyFrame->duration);
240  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
241  this->currentKeyFrame->lastPosition = v;
242}
243
244/**
245   \brief a Sinusodial Interpolation between this keyframe and the next one
246   \param timePassed The time passed since this Keyframe began
247
248   \todo implement
249*/
250void Animation3D::mSine(float timePassed) const
251{
252  Vector v;
253  if( timePassed  < this->currentKeyFrame->duration/2.0)
254    v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * sin( M_PI * timePassed /this->currentKeyFrame->duration) / 2.0;
255  else
256    v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (2.0 + sin( M_PI * (- timePassed /this->currentKeyFrame->duration)) )/ 2.0;
257 
258  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
259  this->currentKeyFrame->lastPosition = v;
260}
261
262
263/**
264   \brief a cosine interpolation between this keyframe and the next one
265   \param timePassed The time passed since this Keyframe began
266
267   \todo implement
268*/
269void Animation3D::mCosine(float timePassed) const
270{
271  Vector v;
272  v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (1.0 + cos( M_PI * timePassed / this->currentKeyFrame->duration))/2.0;
273  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
274  this->currentKeyFrame->lastPosition = v;
275
276
277  /*
278  this->object->setRelCoor( this->nextKeyFrame->position -
279                            (this->nextKeyFrame->position - this->currentKeyFrame->position) *
280                            (1.0 + cos( M_PI * timePassed / this->currentKeyFrame->duration))/2.0);
281  */
282}
283
284
285
286/**
287   \brief an exponential interpolation between this keyframe and the next one
288   \param timePassed The time passed since this Keyframe began
289*/
290void Animation3D::mExp(float timePassed) const
291{
292  PRINTF(0)("no exp animation3d defined\n");
293  this->mLinear(timePassed);
294}
295
296/**
297   \brief a negative exponential interpolation between this keyframe and the next one
298   \param timePassed The time passed since this Keyframe began
299*/
300void Animation3D::mNegExp(float timePassed) const
301{
302  Vector v;
303  v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (1.0 - expf(- timePassed * expFactorMov));
304  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
305  this->currentKeyFrame->lastPosition = v;
306
307  /*
308  this->object->setRelCoor( this->currentKeyFrame->position +
309                            (this->nextKeyFrame->position - this->currentKeyFrame->position) *
310                            (1.0 - expf(- timePassed * expFactorMov)) );
311  */
312}
313
314
315/**
316   \brief a quadratic interpolation between this keyframe and the next one
317   \param timePassed The time passed since this Keyframe began
318
319   \todo implement
320*/
321void Animation3D::mQuadratic(float timePassed) const
322{
323  PRINTF(0)("no quadratic animation3d defined\n");
324  this->mLinear(timePassed);
325}
326
327/**
328   \brief some random animation (fluctuating)
329   \param timePassed The time passed since this Keyframe began
330*/
331void Animation3D::mRandom(float timePassed) const
332{
333  /*
334  this->object->setRelCoor(this->currentKeyFrame->position +
335                           (this->nextKeyFrame->position - this->currentKeyFrame->position) * (float)rand()/(float)RAND_MAX);
336  this->object->setRelDir(this->currentKeyFrame->direction +
337                          (this->nextKeyFrame->direction - this->currentKeyFrame->direction)* (float)rand()/(float)RAND_MAX);
338  */
339}
340
341
342/*==Rotation Section==========================================================*/
343
344
345/**
346   \brief Sets The kind of rotation Animation between this keyframe and the next one
347   \param animFunc The Type of Animation to set
348*/
349void Animation3D::setAnimFuncRot(ANIM_FUNCTION animFuncRot)
350{
351  switch (animFuncRot)
352    {
353    default:
354    case ANIM_CONSTANT:
355      this->animFuncRot = &Animation3D::rConstant;
356      printf("a;sdlfkja;lskdjf;alskjdf;lasjdf;lasjdf;lasjdf;lajsdf\n");
357      break;
358    case ANIM_LINEAR:
359      this->animFuncRot = &Animation3D::rLinear;
360      break;
361    case ANIM_SINE:
362      this->animFuncRot = &Animation3D::rSine;
363      break;
364    case ANIM_COSINE:
365      this->animFuncRot = &Animation3D::rCosine;
366      break;
367    case ANIM_EXP:
368      this->animFuncRot = &Animation3D::rExp;
369      break;
370    case ANIM_NEG_EXP:
371      this->animFuncRot = &Animation3D::rNegExp;
372      this->expFactorRot = -1.0 / this->currentKeyFrame->duration * logf(DELTA_X_3D);
373      break;
374    case ANIM_QUADRATIC:
375      this->animFuncRot = &Animation3D::rQuadratic;
376      break;
377    case ANIM_RANDOM:
378      this->animFuncRot = &Animation3D::rRandom;
379      break;
380
381    }
382}
383
384
385/**
386   \brief stays at the value of the currentKeyFrame
387   \param timePassed The time passed since this Keyframe began
388*/
389void Animation3D::rConstant(float timePassed) const
390{
391  this->object->setRelDir(this->currentKeyFrame->direction);
392}
393
394/**
395   \brief linear interpolation between this keyframe and the next one
396   \param timePassed The time passed since this Keyframe began
397
398   \todo implement also do this for direction
399*/
400void Animation3D::rLinear(float timePassed) const
401{
402  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
403                                     this->currentKeyFrame->direction, 
404                                     timePassed/this->currentKeyFrame->duration) );
405}
406
407/**
408   \brief a Sinusodial Interpolation between this keyframe and the next one
409   \param timePassed The time passed since this Keyframe began
410
411   \todo implement
412*/
413void Animation3D::rSine(float timePassed) const
414{
415  float scale;
416  if( timePassed < this->currentKeyFrame->duration / 2.0)
417    scale = sin( M_PI * timePassed / this->currentKeyFrame->duration);
418  else
419    scale = 1.0 - sin( M_PI * timePassed / this->currentKeyFrame->duration);
420
421  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
422                                     this->currentKeyFrame->direction, 
423                                     scale) );
424}
425
426
427/**
428   \brief a cosine interpolation between this keyframe and the next one
429   \param timePassed The time passed since this Keyframe began
430
431   \todo implement
432*/
433void Animation3D::rCosine(float timePassed) const
434{
435  float scale = cos(M_PI * timePassed / this->currentKeyFrame->duration);
436  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
437                                     this->currentKeyFrame->direction, 
438                                     scale) );
439}
440
441
442
443/**
444   \brief an exponential interpolation between this keyframe and the next one
445   \param timePassed The time passed since this Keyframe began
446*/
447void Animation3D::rExp(float timePassed) const
448{
449  PRINTF(0)("exp rotation function not implemented\n");
450}
451
452/**
453   \brief a negative exponential interpolation between this keyframe and the next one
454   \param timePassed The time passed since this Keyframe began
455*/
456void Animation3D::rNegExp(float timePassed) const
457{
458  float scale = (1.0 - expf(- timePassed * expFactorRot));
459  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
460                                     this->currentKeyFrame->direction, 
461                                     scale) );
462}
463
464
465/**
466   \brief a quadratic interpolation between this keyframe and the next one
467   \param timePassed The time passed since this Keyframe began
468
469   \todo implement
470*/
471void Animation3D::rQuadratic(float timePassed) const
472{
473  PRINTF(0)("quadratic rotation alg not implemented\n");
474}
475
476/**
477   \brief some random animation (fluctuating)
478   \param timePassed The time passed since this Keyframe began
479*/
480void Animation3D::rRandom(float timePassed) const
481{
482  PRINTF(0)("random rotation alg not implemented\n");
483}
Note: See TracBrowser for help on using the repository browser.