Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/vs-enhencements/src/util/animation/animation3d.cc @ 10627

Last change on this file since 10627 was 10618, checked in by bknecht, 18 years ago

merged cleanup into trunk (only improvements)

File size: 14.2 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
27
28
29/**
30 *  standard constructor
31*/
32Animation3D::Animation3D(PNode* object)
33{
34  this->object = object;
35
36  // create a new List
37  KeyFrame3D tmpKeyFrame;
38  keyFrameList.push_back(tmpKeyFrame);
39
40  this->currentKeyFrame = keyFrameList.begin();
41  this->nextKeyFrame = keyFrameList.begin();
42
43  this->animFuncMov = NULL;//&Animation3D::mLinear;
44  this->animFuncRot = NULL;//&Animation3D::rLinear;
45}
46
47/**
48 *  standard deconstructor
49
50   deletes all the Keyframes
51*/
52Animation3D::~Animation3D()
53{
54}
55
56/**
57 *  rewinds the Animation to the beginning (first KeyFrame and time == 0)
58*/
59void Animation3D::rewind()
60{
61  this->currentKeyFrame = keyFrameList.begin();
62  this->nextKeyFrame = keyFrameList.begin()++;
63  this->localTime = 0.0;
64  this->setAnimFuncMov((*this->currentKeyFrame).animFuncMov);
65  this->setAnimFuncRot((*this->currentKeyFrame).animFuncRot);
66}
67
68/**
69 *  Appends a new Keyframe
70 * @param position The position of the new Keyframe
71 * @param direction The direction of the new Keyframe.
72 * @param duration The duration from the new KeyFrame to the next one
73 * @param animFuncMov The function to animate position between this keyFrame and the next one
74 * @param animFuncRot The function to animate rotation between this keyFrame and the next one
75*/
76void Animation3D::addKeyFrame(Vector position, Quaternion direction, float duration,
77                              ANIM_FUNCTION animFuncMov, ANIM_FUNCTION animFuncRot)
78{
79  // some small check
80  if (duration <= 0.0)
81    duration = 1.0;
82  // if the Rotation-Animation-function is set ANIM_NULL, animFuncRot will match animFuncRot
83//  if (animFuncMov == ANIM_NULL)
84//    animFuncMov = ANIM_DEFAULT_FUNCTION;
85//  if (animFuncRot == ANIM_NULL)
86//    animFuncRot = animFuncMov;
87
88  KeyFrame3D& tmpKeyFrame = keyFrameList.front();
89
90  // when adding the first frame
91  if (this->keyFrameCount == 0)
92    {
93      //this->setAnimFuncMov(animFuncMov);
94      //this->setAnimFuncRot(animFuncRot);
95    }
96  else
97    {
98      // when adding the second frame
99      this->keyFrameList.push_back(KeyFrame3D());
100      if (this->currentKeyFrame == this->nextKeyFrame)
101        this->nextKeyFrame = --keyFrameList.end();
102    }
103
104  tmpKeyFrame.position = position;
105  //tmpKeyFrame->lastPosition = position;
106  tmpKeyFrame.direction = direction;
107  tmpKeyFrame.duration = duration;
108  tmpKeyFrame.animFuncMov = animFuncMov;
109  tmpKeyFrame.animFuncRot = animFuncRot;
110  this->keyFrameCount++;
111}
112
113/**
114 *  ticks the Animation
115 * @param dt how much time to tick
116*/
117void Animation3D::tick(float dt)
118{
119  if (this->bRunning)
120    {
121      this->localTime += dt;
122      if (localTime >= this->currentKeyFrame->duration)
123        {
124          if (likely(this->keyFramesToPlay != 0))
125            {
126              if (unlikely(this->keyFramesToPlay > 0))
127                --this->keyFramesToPlay;
128              // switching to the next Key-Frame
129              this->localTime -= this->currentKeyFrame->duration;
130              this->currentKeyFrame = this->nextKeyFrame;
131              // checking, if we should still Play the animation
132              if (this->currentKeyFrame == --this->keyFrameList.end())
133                this->handleInfinity();
134              this->nextKeyFrame = this->currentKeyFrame;
135              this->nextKeyFrame++;
136              this->setAnimFuncMov(this->currentKeyFrame->animFuncMov);
137              this->setAnimFuncRot(this->currentKeyFrame->animFuncRot);
138            }
139          else
140            this->pause();
141        }
142      /* now animate it */
143      if (likely(this->animFuncMov != NULL))
144        (this->*animFuncMov)(this->localTime);
145      if (likely(this->animFuncRot != NULL))
146        (this->*animFuncRot)(this->localTime);
147    }
148}
149
150
151/*==Movement Section==========================================================*/
152
153/**
154 *  Sets The kind of movment Animation between this keyframe and the next one
155 * @param animFuncMov: The Type of Animation to set
156*/
157void Animation3D::setAnimFuncMov(ANIM_FUNCTION animFuncMov)
158{
159  switch (animFuncMov)
160    {
161    case ANIM_CONSTANT:
162      this->animFuncMov = &Animation3D::mConstant;
163      break;
164    case ANIM_LINEAR:
165      this->animFuncMov = &Animation3D::mLinear;
166      this->object->setRelCoor(this->currentKeyFrame->position);
167      this->currentKeyFrame->lastPosition = Vector();
168      break;
169    case ANIM_SINE:
170      this->animFuncMov = &Animation3D::mSine;
171      this->object->setRelCoor(this->currentKeyFrame->position);
172      this->currentKeyFrame->lastPosition = Vector();
173      break;
174    case ANIM_COSINE:
175      this->animFuncMov = &Animation3D::mCosine;
176      this->object->setRelCoor(this->currentKeyFrame->position);
177      this->currentKeyFrame->lastPosition = Vector();
178      break;
179    case ANIM_EXP:
180      this->object->setRelCoor(this->currentKeyFrame->position);
181      this->animFuncMov = &Animation3D::mExp;
182      break;
183    case ANIM_NEG_EXP:
184      this->animFuncMov = &Animation3D::mNegExp;
185      this->object->setRelCoor(this->currentKeyFrame->position);
186      this->expFactorMov = -1.0 / this->currentKeyFrame->duration * logf(DELTA_X_3D);
187      this->currentKeyFrame->lastPosition = Vector();
188      break;
189    case ANIM_QUADRATIC:
190      this->object->setRelCoor(this->currentKeyFrame->position);
191      this->animFuncMov = &Animation3D::mQuadratic;
192      break;
193    case ANIM_RANDOM:
194      this->object->setRelCoor(this->currentKeyFrame->position);
195      this->animFuncMov = &Animation3D::mRandom;
196      break;
197    default:
198      this->animFuncMov = NULL;
199      break;
200    }
201}
202
203/**
204 *  stays at the value of the currentKeyFrame
205 * @param timePassed The time passed since this Keyframe began
206*/
207void Animation3D::mConstant(float timePassed) const
208{
209  //this->object->setRelCoor(this->currentKeyFrame->position);
210
211  /*
212    this->tmpVect = this->nextKeyFrame->position - this->currentKeyFrame->position;
213    this->tmpVect = this->tmpVect * this->localTime / this->currentKeyFrame->duration;
214    this->currentFrame->object->setRelCoor(*this->lastFrame->position + *this->tmpVect);
215    this->lastPosition = this->tmpVect;
216  */
217}
218
219/**
220 *  linear interpolation between this keyframe and the next one
221 * @param timePassed The time passed since this Keyframe began
222
223   @todo implement also do this for direction
224*/
225void Animation3D::mLinear(float timePassed) const
226{
227  Vector v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (timePassed/this->currentKeyFrame->duration);
228  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
229  this->currentKeyFrame->lastPosition = v;
230}
231
232/**
233 *  a Sinusodial Interpolation between this keyframe and the next one
234 * @param timePassed The time passed since this Keyframe began
235
236   @todo implement
237*/
238void Animation3D::mSine(float timePassed) const
239{
240  Vector v;
241  if( timePassed  < this->currentKeyFrame->duration/2.0)
242    v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * sin( M_PI * timePassed /this->currentKeyFrame->duration) / 2.0;
243  else
244    v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (2.0 + sin( M_PI * (- timePassed /this->currentKeyFrame->duration)) )/ 2.0;
245
246  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
247  this->currentKeyFrame->lastPosition = v;
248}
249
250
251/**
252 *  a cosine interpolation between this keyframe and the next one
253 * @param timePassed The time passed since this Keyframe began
254
255   @todo implement
256*/
257void Animation3D::mCosine(float timePassed) const
258{
259  Vector v;
260  v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (1.0 + cos( M_PI * timePassed / this->currentKeyFrame->duration))/2.0;
261  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
262  this->currentKeyFrame->lastPosition = v;
263
264
265  /*
266  this->object->setRelCoor( this->nextKeyFrame->position -
267                            (this->nextKeyFrame->position - this->currentKeyFrame->position) *
268                            (1.0 + cos( M_PI * timePassed / this->currentKeyFrame->duration))/2.0);
269  */
270}
271
272
273
274/**
275 *  an exponential interpolation between this keyframe and the next one
276 * @param timePassed The time passed since this Keyframe began
277*/
278void Animation3D::mExp(float timePassed) const
279{
280  PRINTF(0)("no exp animation3d defined\n");
281  this->mLinear(timePassed);
282}
283
284/**
285 *  a negative exponential interpolation between this keyframe and the next one
286 * @param timePassed The time passed since this Keyframe began
287*/
288void Animation3D::mNegExp(float timePassed) const
289{
290  Vector v;
291  v = (this->nextKeyFrame->position - this->currentKeyFrame->position) * (1.0 - expf(- timePassed * expFactorMov));
292  this->object->shiftCoor(v - this->currentKeyFrame->lastPosition);
293  this->currentKeyFrame->lastPosition = v;
294
295  /*
296  this->object->setRelCoor( this->currentKeyFrame->position +
297                            (this->nextKeyFrame->position - this->currentKeyFrame->position) *
298                            (1.0 - expf(- timePassed * expFactorMov)) );
299  */
300}
301
302
303/**
304 *  a quadratic interpolation between this keyframe and the next one
305 * @param timePassed The time passed since this Keyframe began
306
307   @todo implement
308*/
309void Animation3D::mQuadratic(float timePassed) const
310{
311  PRINTF(0)("no quadratic animation3d defined\n");
312  this->mLinear(timePassed);
313}
314
315/**
316 *  some random animation (fluctuating)
317 * @param timePassed The time passed since this Keyframe began
318*/
319void Animation3D::mRandom(float timePassed) const
320{
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
330/*==Rotation Section==========================================================*/
331
332
333/**
334 *  Sets The kind of rotation Animation between this keyframe and the next one
335 * @param animFuncRot: The Type of Animation to set
336*/
337void Animation3D::setAnimFuncRot(ANIM_FUNCTION animFuncRot)
338{
339  switch (animFuncRot)
340    {
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    default:
368      this->animFuncRot = NULL;
369    }
370}
371
372
373/**
374 *  stays at the value of the currentKeyFrame
375 * @param timePassed The time passed since this Keyframe began
376*/
377void Animation3D::rConstant(float timePassed) const
378{
379  this->object->setRelDir(this->currentKeyFrame->direction);
380}
381
382/**
383 *  linear interpolation between this keyframe and the next one
384 * @param timePassed The time passed since this Keyframe began
385
386   @todo implement also do this for direction
387*/
388void Animation3D::rLinear(float timePassed) const
389{
390  this->object->setRelDir(Quaternion::quatSlerp( this->nextKeyFrame->direction,
391                          this->currentKeyFrame->direction,
392                          timePassed/this->currentKeyFrame->duration) );
393}
394
395/**
396 *  a Sinusodial Interpolation between this keyframe and the next one
397 * @param timePassed The time passed since this Keyframe began
398
399   @todo implement
400*/
401void Animation3D::rSine(float timePassed) const
402{
403  float scale;
404  if( timePassed < this->currentKeyFrame->duration / 2.0)
405    scale = sin( M_PI * timePassed / this->currentKeyFrame->duration);
406  else
407    scale = 1.0 - sin( M_PI * timePassed / this->currentKeyFrame->duration);
408
409  this->object->setRelDir(Quaternion::quatSlerp( this->nextKeyFrame->direction,
410                          this->currentKeyFrame->direction,
411                          scale) );
412}
413
414
415/**
416 *  a cosine interpolation between this keyframe and the next one
417 * @param timePassed The time passed since this Keyframe began
418
419   @todo implement
420*/
421void Animation3D::rCosine(float timePassed) const
422{
423  float scale = cos(M_PI * timePassed / this->currentKeyFrame->duration);
424  this->object->setRelDir(Quaternion::quatSlerp( this->nextKeyFrame->direction,
425                          this->currentKeyFrame->direction,
426                          scale) );
427}
428
429
430
431/**
432 *  an exponential interpolation between this keyframe and the next one
433 * @param timePassed The time passed since this Keyframe began
434*/
435void Animation3D::rExp(float timePassed) const
436{
437  PRINTF(2)("exp rotation function not implemented\n");
438}
439
440/**
441 *  a negative exponential interpolation between this keyframe and the next one
442 * @param timePassed The time passed since this Keyframe began
443*/
444void Animation3D::rNegExp(float timePassed) const
445{
446  float scale = (1.0 - expf(- timePassed * expFactorRot));
447  this->object->setRelDir(Quaternion::quatSlerp( this->nextKeyFrame->direction,
448                          this->currentKeyFrame->direction,
449                          scale) );
450}
451
452
453/**
454 *  a quadratic interpolation between this keyframe and the next one
455 * @param timePassed The time passed since this Keyframe began
456
457   @todo implement
458*/
459void Animation3D::rQuadratic(float timePassed) const
460{
461  PRINTF(0)("quadratic rotation alg not implemented\n");
462}
463
464/**
465 *  some random animation (fluctuating)
466 * @param timePassed The time passed since this Keyframe began
467*/
468void Animation3D::rRandom(float timePassed) const
469{
470  PRINTF(0)("random rotation alg not implemented\n");
471}
Note: See TracBrowser for help on using the repository browser.