Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: started to implement the weapon change animation

File size: 12.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->direction = direction;
120  tmpKeyFrame->duration = duration;
121  tmpKeyFrame->animFuncMov = animFuncMov;
122  tmpKeyFrame->animFuncRot = animFuncRot;
123  this->keyFrameCount++;
124}
125
126
127
128/**
129   \brief ticks the Animation
130   \param dt how much time to tick
131*/
132void Animation3D::tick(float dt)
133{
134  if (this->bRunning)
135    { 
136      this->localTime += dt;
137      if (localTime >= this->currentKeyFrame->duration)
138        {
139          // switching to the next Key-Frame
140          this->localTime -= this->currentKeyFrame->duration;
141          this->currentKeyFrame = this->nextKeyFrame;
142          // checking, if we should still Play the animation
143          if (this->currentKeyFrame == this->keyFrameList->lastElement())
144            this->handleInfinity();
145          this->nextKeyFrame = this->keyFrameList->nextElement(this->currentKeyFrame);
146          this->setAnimFuncMov(this->currentKeyFrame->animFuncMov);
147          this->setAnimFuncRot(this->currentKeyFrame->animFuncRot);
148        }
149      /* now animate it */
150      (this->*animFuncMov)(this->localTime);
151      (this->*animFuncRot)(this->localTime);
152    }
153}
154
155
156/*==Movement Section==========================================================*/
157
158/**
159   \brief Sets The kind of movment Animation between this keyframe and the next one
160   \param animFunc The Type of Animation to set
161*/
162void Animation3D::setAnimFuncMov(ANIM_FUNCTION animFuncMov)
163{
164  switch (animFuncMov)
165    {
166    default:
167    case ANIM_CONSTANT:
168      this->animFuncMov = &Animation3D::mConstant;
169      break;
170    case ANIM_LINEAR:
171      this->animFuncMov = &Animation3D::mLinear;
172      break;
173    case ANIM_SINE:
174      this->animFuncMov = &Animation3D::mSine;
175      break;
176    case ANIM_COSINE:
177      this->animFuncMov = &Animation3D::mCosine;
178      break;
179    case ANIM_EXP:
180      this->animFuncMov = &Animation3D::mExp;
181      break;
182    case ANIM_NEG_EXP:
183      this->animFuncMov = &Animation3D::mNegExp;
184      this->expFactorMov = -1.0 / this->currentKeyFrame->duration * logf(DELTA_X_3D);
185      break;
186    case ANIM_QUADRATIC:
187      this->animFuncMov = &Animation3D::mQuadratic;
188      break;
189    case ANIM_RANDOM:
190      this->animFuncMov = &Animation3D::mRandom;
191      break;
192    }
193}
194
195
196
197/**
198   \brief stays at the value of the currentKeyFrame
199   \param timePassed The time passed since this Keyframe began
200*/
201void Animation3D::mConstant(float timePassed) const
202{
203  this->object->setRelCoor(this->currentKeyFrame->position);
204
205  /*
206    this->tmpVect = this->nextKeyFrame->position - this->currentKeyFrame->position;
207    this->tmpVect = this->tmpVect * this->localTime / this->currentKeyFrame->duration;
208    this->currentFrame->object->setRelCoor(*this->lastFrame->position + *this->tmpVect);
209    this->lastPosition = this->tmpVect;
210  */
211}
212
213/**
214   \brief linear interpolation between this keyframe and the next one
215   \param timePassed The time passed since this Keyframe began
216
217   \todo implement also do this for direction
218*/
219void Animation3D::mLinear(float timePassed) const
220{
221  this->object->setRelCoor(this->currentKeyFrame->position +
222                          (this->nextKeyFrame->position - this->currentKeyFrame->position) * 
223                          (timePassed/this->currentKeyFrame->duration));
224}
225
226/**
227   \brief a Sinusodial Interpolation between this keyframe and the next one
228   \param timePassed The time passed since this Keyframe began
229
230   \todo implement
231*/
232void Animation3D::mSine(float timePassed) const
233{
234  if( timePassed  < this->currentKeyFrame->duration/2.0)
235    this->object->setRelCoor( this->currentKeyFrame->position + (this->nextKeyFrame->position - this->currentKeyFrame->position) *
236                              sin( M_PI * timePassed /this->currentKeyFrame->duration) / 2.0);
237  else
238    this->object->setRelCoor( this->nextKeyFrame->position - (this->nextKeyFrame->position - this->currentKeyFrame->position) *
239                              sin( M_PI * (1.0 - timePassed /this->currentKeyFrame->duration) )/2.0);
240}
241
242
243/**
244   \brief a cosine interpolation between this keyframe and the next one
245   \param timePassed The time passed since this Keyframe began
246
247   \todo implement
248*/
249void Animation3D::mCosine(float timePassed) const
250{
251  this->object->setRelCoor( this->nextKeyFrame->position -
252                            (this->nextKeyFrame->position - this->currentKeyFrame->position) *
253                            (1.0 + cos( M_PI * timePassed / this->currentKeyFrame->duration))/2.0);
254}
255
256
257
258/**
259   \brief an exponential interpolation between this keyframe and the next one
260   \param timePassed The time passed since this Keyframe began
261*/
262void Animation3D::mExp(float timePassed) const
263{
264  PRINTF(0)("no exp animation3d defined\n");
265  this->mLinear(timePassed);
266}
267
268/**
269   \brief a negative exponential interpolation between this keyframe and the next one
270   \param timePassed The time passed since this Keyframe began
271*/
272void Animation3D::mNegExp(float timePassed) const
273{
274  this->object->setRelCoor( this->currentKeyFrame->position +
275                            (this->nextKeyFrame->position - this->currentKeyFrame->position) * 
276                            (1.0 - expf(- timePassed * expFactorMov)) );
277}
278
279
280/**
281   \brief a quadratic interpolation between this keyframe and the next one
282   \param timePassed The time passed since this Keyframe began
283
284   \todo implement
285*/
286void Animation3D::mQuadratic(float timePassed) const
287{
288  PRINTF(0)("no quadratic animation3d defined\n");
289  this->mLinear(timePassed);
290}
291
292/**
293   \brief some random animation (fluctuating)
294   \param timePassed The time passed since this Keyframe began
295*/
296void Animation3D::mRandom(float timePassed) const
297{
298  this->object->setRelCoor(this->currentKeyFrame->position + 
299                           (this->nextKeyFrame->position - this->currentKeyFrame->position) * (float)rand()/(float)RAND_MAX);
300  this->object->setRelDir(this->currentKeyFrame->direction +
301                          (this->nextKeyFrame->direction - this->currentKeyFrame->direction)* (float)rand()/(float)RAND_MAX);
302}
303
304
305/*==Rotation Section==========================================================*/
306
307
308/**
309   \brief Sets The kind of rotation Animation between this keyframe and the next one
310   \param animFunc The Type of Animation to set
311*/
312void Animation3D::setAnimFuncRot(ANIM_FUNCTION animFuncRot)
313{
314  switch (animFuncRot)
315    {
316   default:
317    case ANIM_CONSTANT:
318      this->animFuncRot = &Animation3D::rConstant;
319      break;
320    case ANIM_LINEAR:
321      this->animFuncRot = &Animation3D::rLinear;
322      break;
323    case ANIM_SINE:
324      this->animFuncRot = &Animation3D::rSine;
325      break;
326    case ANIM_COSINE:
327      this->animFuncRot = &Animation3D::rCosine;
328      break;
329    case ANIM_EXP:
330      this->animFuncRot = &Animation3D::rExp;
331      break;
332    case ANIM_NEG_EXP:
333      this->animFuncRot = &Animation3D::rNegExp;
334      this->expFactorRot = -1.0 / this->currentKeyFrame->duration * logf(DELTA_X_3D);
335      break;
336    case ANIM_QUADRATIC:
337      this->animFuncRot = &Animation3D::rQuadratic;
338      break;
339    case ANIM_RANDOM:
340      this->animFuncRot = &Animation3D::rRandom;
341      break;
342    }
343}
344
345
346/**
347   \brief stays at the value of the currentKeyFrame
348   \param timePassed The time passed since this Keyframe began
349*/
350void Animation3D::rConstant(float timePassed) const
351{
352  this->object->setRelDir(this->currentKeyFrame->direction);
353}
354
355/**
356   \brief linear interpolation between this keyframe and the next one
357   \param timePassed The time passed since this Keyframe began
358
359   \todo implement also do this for direction
360*/
361void Animation3D::rLinear(float timePassed) const
362{
363  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
364                                     this->currentKeyFrame->direction, 
365                                     timePassed/this->currentKeyFrame->duration) );
366}
367
368/**
369   \brief a Sinusodial Interpolation between this keyframe and the next one
370   \param timePassed The time passed since this Keyframe began
371
372   \todo implement
373*/
374void Animation3D::rSine(float timePassed) const
375{
376  float scale;
377  if( timePassed < this->currentKeyFrame->duration / 2.0)
378    scale = sin( M_PI * timePassed / this->currentKeyFrame->duration);
379  else
380    scale = 1.0 - sin( M_PI * timePassed / this->currentKeyFrame->duration);
381
382  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
383                                     this->currentKeyFrame->direction, 
384                                     scale) );
385}
386
387
388/**
389   \brief a cosine interpolation between this keyframe and the next one
390   \param timePassed The time passed since this Keyframe began
391
392   \todo implement
393*/
394void Animation3D::rCosine(float timePassed) const
395{
396  float scale = cos(M_PI * timePassed / this->currentKeyFrame->duration);
397  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
398                                     this->currentKeyFrame->direction, 
399                                     scale) );
400}
401
402
403
404/**
405   \brief an exponential interpolation between this keyframe and the next one
406   \param timePassed The time passed since this Keyframe began
407*/
408void Animation3D::rExp(float timePassed) const
409{
410  PRINTF(0)("exp rotation function not implemented\n");
411}
412
413/**
414   \brief a negative exponential interpolation between this keyframe and the next one
415   \param timePassed The time passed since this Keyframe began
416*/
417void Animation3D::rNegExp(float timePassed) const
418{
419  float scale = (1.0 - expf(- timePassed * expFactorRot));
420  this->object->setRelDir(quatSlerp( this->nextKeyFrame->direction, 
421                                     this->currentKeyFrame->direction, 
422                                     scale) );
423}
424
425
426/**
427   \brief a quadratic interpolation between this keyframe and the next one
428   \param timePassed The time passed since this Keyframe began
429
430   \todo implement
431*/
432void Animation3D::rQuadratic(float timePassed) const
433{
434  PRINTF(0)("quadratic rotation alg not implemented\n");
435}
436
437/**
438   \brief some random animation (fluctuating)
439   \param timePassed The time passed since this Keyframe began
440*/
441void Animation3D::rRandom(float timePassed) const
442{
443  PRINTF(0)("random rotation alg not implemented\n");
444}
Note: See TracBrowser for help on using the repository browser.