Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/track_manager.cc @ 3833

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

orxonox/trunk: animation class functions implemented, list enhanced

File size: 26.0 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: Benjamin Grauer
13   co-programmer: ...
14*/
15
16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_TRACK_MANAGER
17
18#include "track_manager.h"
19
20#include "base_object.h"
21#include "p_node.h"
22#include "track_node.h"
23#include "stdincl.h"
24#include "list.h"
25
26
27
28#include <stdarg.h>
29
30using namespace std;
31
32/**
33   \brief initializes a TrackElement (sets the default values)
34*/
35TrackElement::TrackElement(void)
36{
37  this->isFresh = true;
38  this->isHotPoint = false;
39  this->isSavePoint = false;
40  this->isFork = false;
41  this->isJoined = false;
42  this->mainJoin = false;
43  this->ID = -1;
44  this->startingTime = 0;
45  this->duration = TMAN_DEFAULT_DURATION;
46  this->endTime = 1;
47  this->jumpTime = 0;
48  this->width = TMAN_DEFAULT_WIDTH;
49  this->nodeCount = 0;
50  this->childCount = 0;
51  this->name = NULL;
52  this->curve = NULL;
53  this->children = NULL;
54
55  this->history = NULL;
56
57  this->condFunc = &TrackElement::random;
58}
59
60/**
61    \brief destroys all alocated memory)
62    \todo eventually when deleting a TrackElement you would not like to delete all its preceding TrackElements
63*/
64TrackElement::~TrackElement(void)
65{
66  if (this->name)
67    delete []name;
68  if (this->curve)
69    delete this->curve;
70  if ((!this->isJoined &&this->childCount > 0) || (this->isJoined && this->mainJoin))
71    {
72      tIterator<TrackElement>* iterator = this->children->getIterator();
73      TrackElement* enumElem = iterator->nextElement();
74      while (enumElem)
75        {
76          delete enumElem;
77          enumElem = iterator->nextElement();
78        }
79      delete iterator;
80      delete this->children;
81    }
82}
83
84/**
85   \brief Searches through all the TrackElements for trackID.
86   \param trackID The ID to search for.
87   \returns The TrackElement if Found, NULL otherwise.
88   
89   \todo make this more modular, to search for different things
90*/
91TrackElement* TrackElement::findByID(unsigned int trackID)
92{
93  // return if Found.
94  if (this->ID == trackID)
95    return this;
96  // search on.
97  if (this->childCount > 0)
98    {
99      tIterator<TrackElement>* iterator = this->children->getIterator();
100      TrackElement* enumElem = iterator->nextElement();
101      TrackElement* tmpElem;
102      while (enumElem)
103        {
104          if ((tmpElem = enumElem->findByID(trackID)))
105            return tmpElem;
106          enumElem = iterator->nextElement();
107        }
108      delete iterator;
109    }
110  else 
111    return NULL;
112}
113
114
115/**
116   \brief checks if there are any BackLoops in the Track
117   \param trackElem the trackElement to check about
118   it simply does this by looking if the current trackElem is found again somewhere else in the Track
119*/
120bool TrackElement::backLoopCheck(TrackElement* trackElem)
121{
122  if (this->childCount == 0)
123    return true;
124  else
125    {
126      tIterator<TrackElement>* iterator = this->children->getIterator();
127      TrackElement* enumElem = iterator->nextElement();
128      while (enumElem)
129        {
130          if(!enumElem->backLoopCheck(trackElem))
131            return false;
132          enumElem = iterator->nextElement();
133        }
134      delete iterator;
135     
136      return true;
137    }
138}
139
140/**
141   \param childNumber which child to return
142   \returns the n-the children (starting at 0)
143*/
144TrackElement* TrackElement::getChild(int childCount)
145{
146  if (this->childCount == 0)
147    return NULL;
148  if (childCount > this->childCount)
149    childCount = this->childCount;
150 
151  //  TrackElement* enumElem = this->children->enumerate();
152  tIterator<TrackElement>* iterator = this->children->getIterator();
153  TrackElement* enumElem = iterator->nextElement();
154  for (int i = 0; i < childCount; i++)
155    enumElem = iterator->nextElement();
156  delete iterator;
157  return enumElem;
158}
159
160/**
161   \param name the Name to set.
162*/
163void TrackElement::setName(const char* name)
164{
165  //  delete the old name
166  if (this->name)
167    delete []this->name;
168  // if a name was given already.
169  if (name)
170    {
171      this->name = new char[strlen(name)+1];
172      strcpy(this->name, name);
173    }
174  else 
175    this->name = NULL;
176}
177
178/**
179   \returns The name of this TrackElement
180*/
181char* TrackElement::getName(void) const
182{
183  return this->name;
184}
185
186/**
187   \brief prints out debug information about this TrackElement
188*/
189void TrackElement::debug(void)
190{
191  PRINT(0)("--== TrackElement:%i ==--", this->ID);
192  if(this->getName())
193    PRINT(0)("Name: %s::", this->getName());
194  if(this->isFresh)
195    PRINT(0)("  -- has not jet eddited in any way --\n");
196  PRINT(0)("\n   TimeTable: startingTime=%f; endTime=%f; duration=%f; jumpTime=%f\n", this->startingTime, this->endTime, this->duration, this->jumpTime);
197  PRINT(0)("   consists of %d Points\n", this->nodeCount);
198  if (this->childCount == 0)
199    PRINT(0)("   has no child\n");
200  else if (this->childCount == 1)
201    PRINT(0)("   has 1 child: =%d=\n", this->getChild(0)->ID);
202  else if (this->childCount > 1)
203    {
204      PRINT(0)("   has %d children: ", this->childCount);
205      //TrackElement* enumElem = this->children->enumerate();
206      tIterator<TrackElement>* iterator = this->children->getIterator();
207      TrackElement* enumElem = iterator->nextElement();
208      while (enumElem)
209        {
210          PRINT(0)("=%d= ", enumElem->ID);
211          enumElem = iterator->nextElement();
212        }
213      delete iterator;
214      PRINT(0)("\n");
215    }
216 
217  if(this->isHotPoint)
218    PRINT(0)("   is a special Point:\n");
219  if(this->isSavePoint)
220    PRINT(0)("    is a SavePoint\n");
221  if(this->isFork)
222    {
223      PRINT(0)("    is A Fork with with %d children.\n", this->childCount);
224    }
225  if(this->isJoined)
226    PRINT(0)("   is Joined at the End\n");
227 
228  if(!this->backLoopCheck(this)) /* this should not happen */
229    PRINT(2)(" THERE IS A BACKLOOP TO THIS ELEMENT\n");
230}
231
232/**
233   \brief CONDITION that chooses the first child for the decision (static)
234   \param nothing Nothing in this function
235   \returns the chosen child
236*/
237int TrackElement::lowest(void* nothing)
238{
239  return 0;
240}
241
242/**
243   \brief CONDITION that chooses the last child for the decision (static)
244   \param nothing Nothing in this function
245   \returns the chosen child
246*/
247int TrackElement::highest(void* nothing)
248{ 
249  return this->childCount-1;
250}
251
252/**
253   \brief CONDITION that chooses a random child for the decision (static)
254   \param nothing Nothing in this function
255   \returns the chosen child
256*/
257int TrackElement::random(void* nothing)
258{
259  int i = (int)floor ((float)rand()/(float)RAND_MAX * (float)this->childCount);
260  if (i >= this->childCount)
261    return this->childCount-1;
262  else 
263    return i;
264}
265
266/**
267   \brief CONDITION that chooses child 0, if the node(probably Player)
268   is left of its parent (z<0)) and 1/right otherwise.
269   \param node The node to act upon.
270   \returns the chosen child
271*/
272int TrackElement::leftRight(void* node)
273{
274  PNode* tmpNode = (PNode*)node;
275
276  if (tmpNode->getRelCoor()->z < 0)
277    return 0;
278  else 
279    return 1;
280}
281
282
283/**
284   \brief CONDITION that chooses the child, that has the nearest distance to the node (probably player).
285   \param node The node to act upon.
286   \returns the chosen child
287
288   This is rather dangerous, because one must carefully set the points on the curve.
289   The best Way is to set the nodes as wide away of each other as possible,
290   but take into consideration, that if the nodes are to far from a center node, the center will be chosen.
291   (play with this!!).
292*/
293int TrackElement::nearest(void* node)
294{
295  PNode* tmpNode = (PNode*)node;
296
297  Vector nodeRelCoord = *tmpNode->getRelCoor();
298  float minDist = 100000000;
299  int childNumber = 0;
300  int i = 0;
301
302  //TrackElement* enumElem = this->children->enumerate();
303  tIterator<TrackElement>* iterator = this->children->getIterator();
304  TrackElement* enumElem = iterator->nextElement();
305  while (enumElem)
306    {
307      float dist = (nodeRelCoord - enumElem->curve->getNode(4)).len();
308      if (dist < minDist)
309        {
310          minDist = dist;
311          childNumber = i;
312        }
313      i++;
314      enumElem = iterator->nextElement();
315    }
316  delete iterator;
317
318  PRINTF(4)("PathDecision with nearest algorithm: %d\n", childNumber);
319  return childNumber;
320}
321
322
323////////////////////////
324///// TRACKMANAGER /////
325////////////////////////
326/**
327   \brief standard constructor
328
329*/
330TrackManager::TrackManager(void)
331{
332  this->setClassName("TrackManager");
333 
334  TrackManager::singletonRef = this;
335
336  PRINTF(3)("Initializing the TrackManager\n");
337  this->firstTrackElem = new TrackElement();
338  this->firstTrackElem->ID = 1;
339  this->currentTrackElem = firstTrackElem;
340  this->localTime = 0;
341  this->maxTime = 0;
342  this->trackElemCount = 1;
343  this->setBindSlave(this->trackNode = new TrackNode());
344}
345
346
347/**
348   \brief standard destructor
349*/
350TrackManager::~TrackManager(void)
351{
352  PRINTF(3)("Destruct TrackManager\n");
353
354  PRINTF(4)("Deleting all the TrackElements\n");
355  delete this->firstTrackElem;
356
357  // we do not have a TrackManager anymore
358  TrackManager::singletonRef = NULL;
359}
360
361//! Singleton Reference to TrackManager
362TrackManager* TrackManager::singletonRef = NULL;
363
364/**
365   \returns The reference on the TrackManager.
366
367   If the TrackManager does not exist, it will be created.
368*/
369TrackManager* TrackManager::getInstance(void) 
370{
371  if (!TrackManager::singletonRef)
372    TrackManager::singletonRef = new TrackManager();
373  return TrackManager::singletonRef;
374}
375
376/**
377   \brief reserves Space for childCount children
378   \param childCount The Count of children to make space for.
379*/
380void TrackManager::initChildren(unsigned int childCount)
381{
382  this->currentTrackElem->childCount = childCount;
383  this->currentTrackElem->mainJoin = true;
384  this->currentTrackElem->children =  new tList<TrackElement>();
385  for (int i = 0; i < childCount; i++)
386    {
387      TrackElement* newElem = new TrackElement();
388      this->currentTrackElem->children->add(newElem);
389      newElem->ID = ++trackElemCount;
390      newElem->startingTime = this->currentTrackElem->endTime + this->currentTrackElem->jumpTime;
391      this->addPoint(this->currentTrackElem->curve->getNode(this->currentTrackElem->curve->getNodeCount()), this->currentTrackElem->getChild(i));
392    }
393  if (childCount == 1)
394    this->currentTrackElem->getChild(0)->setName(this->currentTrackElem->getName());
395}
396
397/**
398   \brief Searches for a given trackID.
399   \param trackID the trackID to search for.
400   \returns The TrackElement #trackID if found, NULL otherwise.
401*/
402TrackElement* TrackManager::findTrackElementByID(unsigned int trackID) const
403{
404  return firstTrackElem->findByID(trackID);
405}
406
407// INITIALIZE //
408
409/**
410   \brief Sets the trackID we are working on.
411   \param trackID the trackID we are working on
412*/
413void TrackManager::workOn(unsigned int trackID)
414{
415  TrackElement* tmpElem = findTrackElementByID(trackID);
416  if (tmpElem)
417    this->currentTrackElem = tmpElem;
418  else
419    PRINTF(2)("TrackElement not Found, leaving unchanged\n");
420  PRINTF(4)("now Working on %d\n", this->currentTrackElem->ID);
421
422}
423
424/**
425   \brief Sets the Type of the Curve
426   \param curveType The Type to set
427   \param trackElem the TrackElement that should get a new Curve.
428*/
429void TrackManager::setCurveType(CurveType curveType, TrackElement* trackElem)
430{
431  if (!trackElem->isFresh)
432    {
433      PRINTF(2)("It is not possible to change the type of a Curve after you have have appended some points to it\n");
434      return;
435    }
436  this->curveType = curveType;
437  switch (curveType)
438    {
439    case BEZIERCURVE:
440      trackElem->curve = new BezierCurve();
441      break;
442
443    }
444}
445
446/**
447   \brief Sets the duration of the current path in seconds.
448   \param time The duration in seconds.
449*/
450
451void TrackManager::setDuration(float time)
452{
453  this->currentTrackElem->duration = time;
454  this->currentTrackElem->endTime = this->currentTrackElem->startingTime + time;
455}
456
457/**
458   \brief adds a point to the current TrackElement
459   \param newPoint The point to add.
460*/
461bool TrackManager::addPoint(Vector newPoint)
462{
463  return this->addPoint(newPoint, this->currentTrackElem);
464}
465
466/**
467   \brief adds a point to trackElem
468   \param newPoint The point to add.
469   \param trackElem The TrackElement to add the Point to
470*/
471bool TrackManager::addPoint(Vector newPoint, TrackElement* trackElem)
472{
473  if (trackElem->isFresh)
474    {
475      this->setCurveType(TMAN_DEFAULT_CURVETYPE, trackElem);
476      trackElem->isFresh = false;
477    }
478  trackElem->curve->addNode(newPoint);
479  trackElem->nodeCount++;
480}
481
482/**
483   \brief adds save/splitpoint.
484   \param newPoint The point to add.
485   \returns A Pointer to a newly appended Curve
486*/
487int TrackManager::addHotPoint(Vector newPoint)
488{
489  PRINTF(4)("setting up a HotPoint\n");
490  if (this->currentTrackElem->isFresh)
491    {
492      this->setCurveType(BEZIERCURVE);
493      this->currentTrackElem->isFresh = false;
494    }
495
496  // \todo HotPoint Handling.
497  this->currentTrackElem->curve->addNode(newPoint);
498  this->currentTrackElem->nodeCount++;
499  this->initChildren(1);
500  this->currentTrackElem = this->currentTrackElem->getChild(0);
501}
502
503/**
504   \brief Sets the last HotPoint into a savePoint.
505   \returns A Pointer to a newly appended Curve
506   
507   If no HotPoint was defined the last added Point will be rendered into a savePoint. \n
508   If the HotPoint was defined as a fork the Point will \b not be set into a savePoint.
509*/
510int TrackManager::setSavePoint(void)
511{
512  PRINTF(4)("setting up a SavePoint.\n");
513  if (this->currentTrackElem->isFork || this->currentTrackElem->isSavePoint)
514    {
515      PRINTF(2)("%d is already finished \n", currentTrackElem->ID);
516      return this->currentTrackElem->getChild(0)->ID;
517    }
518  this->currentTrackElem->isSavePoint = true;
519  this->currentTrackElem->isHotPoint = true;
520
521  this->initChildren(1);
522  this->currentTrackElem = this->currentTrackElem->getChild(0);
523}
524
525/**
526   \brief adds some interessting non-linear movments through the level.
527   \param count The Count of childrens the current HotPoint will have.
528
529   If no HotPoint was defined the last added Point will be rendered into a fork. \n
530   If the HotPoint was defined as a savePoint the Point will \b not be set into a fork.
531*/
532void TrackManager::fork(unsigned int count, ...)
533{
534  int* trackIDs = new int[count];
535  this->forkV(count, trackIDs);
536  va_list ID;
537  va_start (ID, count);
538  for(int i = 0; i < count; i++)
539    {
540      *va_arg (ID, int*) = trackIDs[i];
541    }
542  va_end(ID); 
543  delete []trackIDs;
544}
545
546/**
547   \brief adds some interessting non-linear movments through the level.
548   \param count The Count of childrens the current HotPoint will have.
549   \param trackIDs A Pointer to an Array of ints which will hold the trackID's (the user will have to reserve space for this).
550
551   \see void TrackManager::fork(int count, ...)
552
553   \todo initialisation is wrong!! also in setSavePoint.
554*/
555void TrackManager::forkV(unsigned int count, int* trackIDs)
556{
557  PRINTF(4)("Forking with %d children\n", count);
558  if (this->currentTrackElem->isSavePoint)
559    return;
560  this->currentTrackElem->isFork = true;
561  this->currentTrackElem->isHotPoint = true;
562  for(int i = 0; i < count; i++)
563    trackIDs[i]=this->trackElemCount+1+i;
564  this->initChildren(count);
565}
566
567/**
568   \brief decides under what condition a certain Path will be chosen.
569   \param cond the CONDITION of the decision
570   \param subject the Subject that will be decided upon with CONDITION cond.
571*/
572void TrackManager::condition(CONDITION cond, void* subject)
573{
574  this->condition(this->currentTrackElem->ID, cond, subject);
575}
576/**
577   \brief decides under what condition a certain Path will be chosen.
578   \param groupID the ID on which to choose the preceding move
579   \param cond the CONDITION of the decision
580   \param subject the Subject that will be decided upon with CONDITION cond.
581*/
582void TrackManager::condition(unsigned int groupID, CONDITION cond, void* subject)
583{
584  TrackElement* tmpElem = this->findTrackElementByID(groupID);
585  if (!tmpElem->isFork)
586    {
587      PRINTF(2)("%d is not a Fork, and no condition can be set in this case\n", tmpElem->ID);
588      return;
589    }
590  else
591    {
592      switch (cond)
593        {
594        case LOWEST:
595          tmpElem->condFunc = &TrackElement::lowest;
596          break;
597        case HIGHEST:
598          tmpElem->condFunc = &TrackElement::highest;
599          break;
600        case RANDOM: 
601          tmpElem->condFunc = &TrackElement::random;
602          break;
603        case LEFTRIGHT:
604          tmpElem->condFunc = &TrackElement::leftRight;
605          break;
606        case NEAREST:
607          tmpElem->condFunc = &TrackElement::nearest;
608          break;
609        case ENEMYKILLED:
610          break;
611        }
612      tmpElem->subject=subject;
613    }
614}
615
616
617/**
618   \brief joins some tracks together again.
619   \param count The count of Paths to join.
620
621   Join will set the localTime to the longest time a Path has to get to this Point. \n
622   Join will join all curves to the first curve, meaning that all the tangents will be matched.
623*/
624void TrackManager::join(unsigned int count, ...)
625{
626  int* trackIDs = new int [count];
627  va_list ID;
628  va_start (ID, count);
629  for(int i = 0; i < count; i++)
630    {
631      trackIDs[i] = va_arg (ID, int);
632    }
633  va_end(ID);
634  this->joinV(count, trackIDs);
635  delete []trackIDs;
636}
637
638/**
639   \brief joins some tracks together again.
640   \param count The count of Paths to join.
641   \param trackIDs an Array with the trackID's to join
642
643   \see void TrackManager::join(int count, ...)
644*/
645void TrackManager::joinV(unsigned int count, int* trackIDs)
646{
647  PRINTF(3)("Joining %d tracks and merging to Track %d\n", count, trackIDs[0]);
648
649  // checking if there is a back-loop-connection and ERROR if it is.
650  TrackElement* tmpTrackElem = this->findTrackElementByID(trackIDs[0]);
651  if (!tmpTrackElem->backLoopCheck(tmpTrackElem))
652    PRINTF(2)("Backloop connection detected at joining trackElements\n");
653
654  // chanching work-on to temporary value. going back at the end.
655  int tmpCurrentWorkingID = this->currentTrackElem->ID;
656  this->workOn(trackIDs[0]);
657  TrackElement* firstJoint = this->currentTrackElem;
658  float tmpLatestTime = firstJoint->endTime;
659
660  Vector tmpEndPoint = firstJoint->curve->getNode(firstJoint->curve->getNodeCount());
661  Vector tmpTangentPoint = firstJoint->curve->getNode(firstJoint->curve->getNodeCount()-1);
662  Vector tmpc2Point = firstJoint->curve->getNode(firstJoint->curve->getNodeCount()-2);
663  firstJoint->isJoined = true;
664  //  firstJoint->mainJoin = true;
665  if(!firstJoint->isHotPoint)
666    this->setSavePoint();
667  // Timing:
668  for (int i = 0; i < count; i++)
669    {
670      TrackElement* tmpJoinElem = this->findTrackElementByID(trackIDs[i]);
671      if (tmpJoinElem->childCount == 0
672          && tmpJoinElem->endTime > tmpLatestTime)
673        tmpLatestTime = tmpJoinElem->endTime;
674    }
675  // time the main Join.
676  firstJoint->jumpTime = tmpLatestTime - firstJoint->endTime;
677 
678  // Joining:
679  for (int i = 1; i < count; i++)
680    {
681      TrackElement* tmpJoinElem = this->findTrackElementByID(trackIDs[i]);
682      if (tmpJoinElem->childCount > 0)
683        printf("!!This Curve has children, and as such will not be joined!!\n You can try joining other childless TrackElements to this one!");
684      else
685        {
686          this->addPoint(tmpc2Point, tmpJoinElem);
687          this->addPoint(tmpTangentPoint, tmpJoinElem);
688          this->addPoint(tmpEndPoint, tmpJoinElem);
689          // time all other Joins
690          tmpJoinElem->jumpTime = tmpLatestTime - tmpJoinElem->endTime;
691         
692          //Copying Joint-Info
693          tmpJoinElem->children = firstJoint->children;
694          tmpJoinElem->childCount = firstJoint->childCount;
695          tmpJoinElem->isSavePoint = firstJoint->isSavePoint;
696          tmpJoinElem->isFork = firstJoint->isFork;
697
698          tmpJoinElem->isJoined = true;
699        }
700    }
701  if(firstJoint->childCount > 0)
702    {
703      //TrackElement* enumElem = firstJoint->children->enumerate();
704      tIterator<TrackElement>* iterator = firstJoint->children->getIterator();
705      TrackElement* enumElem = iterator->nextElement();
706      while (enumElem)
707        {
708          PRINTF(4)("Setting startingTime of %d to %f.\n", enumElem->ID, tmpLatestTime);
709          enumElem->startingTime = tmpLatestTime;
710          enumElem->endTime = tmpLatestTime + enumElem->duration;
711         
712          enumElem = iterator->nextElement();
713        }
714      delete iterator;
715    }
716  // returning to the TrackElement we were working on.
717  this->workOn(tmpCurrentWorkingID);
718}
719
720/**
721   \brief finalizes the TrackSystem. after this it will not be editable anymore
722
723   \todo check for any inconsistencies, output errors
724*/
725void TrackManager::finalize(void)
726{
727  for (int i = 1; i<= trackElemCount ;i++)
728    {
729      TrackElement* tmpElem = findTrackElementByID(i);
730      if( tmpElem->childCount > 0 && tmpElem->mainJoin)
731        {
732          tIterator<TrackElement>* iterator = tmpElem->children->getIterator();
733          TrackElement* enumElem = iterator->nextElement();
734          //TrackElement* enumElem = tmpElem->children->enumerate();
735          while (enumElem)
736            {
737             
738              // c1-continuity
739              enumElem->curve->addNode(enumElem->curve->getNode(0) +
740                                                   ((enumElem->curve->getNode(0) - 
741                                                    tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-1))
742                                                    ),2);
743              enumElem->nodeCount++;
744              // c2-continuity
745              enumElem->curve->addNode((tmpElem->curve->getNode(tmpElem->curve->getNodeCount())-
746                                                    tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-1)) * 4 +
747                                                   tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-2), 3);
748              enumElem->nodeCount++;                                               
749              PRINTF(5)("accelerations: %d-in: count: %d, %f, %f, %f\n                  %d-out: count: %d %f, %f, %f\n",
750                     tmpElem->ID, tmpElem->nodeCount,
751                     tmpElem->curve->calcAcc(0.999).x, tmpElem->curve->calcAcc(0.999).y, tmpElem->curve->calcAcc(0.999).z,
752                     enumElem->ID, enumElem->nodeCount,
753                     enumElem->curve->calcAcc(0).x, enumElem->curve->calcAcc(0).y, enumElem->curve->calcAcc(0).z);
754             
755              enumElem = iterator->nextElement();
756            }
757          delete iterator;
758        }
759    }
760  for (int i = 1; i <=trackElemCount;i++)
761    if (this->findTrackElementByID(i)->endTime > this->maxTime)
762      this->maxTime = findTrackElementByID(i)->endTime; // very bad implemented :/
763}
764
765
766// RUNTIME //
767
768/**
769   \brief calculates the Position for the localTime of the Track.
770   \returns the calculated Position
771*/
772Vector TrackManager::calcPos() const
773{
774  return this->currentTrackElem->curve->calcPos((this->localTime-this->currentTrackElem->startingTime)/this->currentTrackElem->duration);
775}
776
777/**
778   \brief calculates the Rotation for the localTime of the Track.
779   \returns the calculated Rotation
780*/
781Vector TrackManager::calcDir() const
782{
783  return this->currentTrackElem->curve->calcDir((this->localTime - this->currentTrackElem->startingTime)/this->currentTrackElem->duration);
784}
785
786/**
787   \returns the current Width of the track
788*/
789float TrackManager::getWidth(void) const
790{
791  return this->currentTrackElem->width;
792}
793
794/**
795   \brief Advances the local-time of the Track around dt
796   \param dt The time about which to advance.
797
798   This function also checks, if the TrackElement has to be changed.
799*/
800void TrackManager::tick(float dt)
801{
802  dt /= 1000;
803  PRINTF(4)("CurrentTrackID: %d, LocalTime is: %f, timestep is: %f\n", this->currentTrackElem->ID, this->localTime, dt);
804  if (this->localTime <= this->firstTrackElem->duration)
805    this->jumpTo(this->localTime);
806  if (this->localTime <= this->maxTime)
807    this->localTime += dt;
808  if (this->localTime > this->currentTrackElem->endTime
809      && this->currentTrackElem->children)
810    {
811      if (this->currentTrackElem->jumpTime != 0.0)
812        this->jumpTo(this->localTime + this->currentTrackElem->jumpTime);
813      // jump to the next TrackElement and also set the history of the new Element to the old one.
814      TrackElement* tmpHistoryElem = this->currentTrackElem;
815      this->currentTrackElem = this->currentTrackElem->getChild(this->choosePath(this->currentTrackElem));
816      this->currentTrackElem->history = tmpHistoryElem;
817    }
818  if (this->bindSlave)
819    {
820      Vector tmp = this->calcPos();
821      Quaternion quat = Quaternion(this->calcDir(), Vector(this->currentTrackElem->curve->calcAcc((localTime-this->currentTrackElem->startingTime)/this->currentTrackElem->duration).x,1,this->currentTrackElem->curve->calcAcc((localTime-this->currentTrackElem->startingTime)/this->currentTrackElem->duration).z)); 
822
823      Vector v(0.0, 1.0, 0.0);
824      Quaternion q(-PI/2, v);
825      quat = quat * q;
826
827      this->bindSlave->setAbsCoor(tmp);
828      this->bindSlave->setAbsDir(quat);
829    }
830}
831
832/**
833   \brief Jumps to a certain point on the Track.
834   \param time The time on the Track to jump to.
835
836   This should be used to Jump backwards on a Track, because moving forward means to change between the Path. (it then tries to choose the default.)
837   Max is trackLengthMax.
838*/
839void TrackManager::jumpTo(float time)
840{
841  if (time == 0)
842    this->currentTrackElem = this->firstTrackElem;
843  this->localTime = time;
844}
845
846/**
847   \brief a Function that decides which Path we should follow.
848   \param trackElem The Path to choose.
849   
850*/
851int TrackManager::choosePath(TrackElement* trackElem)
852{
853  return (trackElem->*(trackElem->condFunc))(trackElem->subject);
854}
855
856/**
857   \brief Sets the PNode, that should be moved along the Tack
858   \param bindSlave the PNode to set
859*/
860void TrackManager::setBindSlave(PNode* bindSlave)
861{
862  this->bindSlave = bindSlave;
863}
864
865/**
866   \returns the main TrackNode
867*/
868PNode* TrackManager::getTrackNode(void)
869{
870  return this->trackNode;
871}
872
873// DEBUG //
874
875/**
876   \brief Imports a model of the Graph into the OpenGL-environment.
877   \param dt The Iterator used in seconds for Painting the Graph.
878
879   This is for testing facility only. Do this if you want to see the Path inside the Level.
880   eventually this will all be packed into a gl-list.
881*/
882void TrackManager::drawGraph(float dt) const
883{
884  for (int i = 1; i <= trackElemCount; i++)
885    {
886      glBegin(GL_LINE_STRIP);
887      TrackElement* tmpElem = this->findTrackElementByID(i);
888      if (tmpElem->curve)
889        for(float f = 0.0; f < 1.0; f+=dt)
890          {
891            //      printf("%f, %f, %f\n",trackManager->calcPos().x, trackManager->calcPos().y, trackManager->calcPos().z);
892            Vector tmpVector = tmpElem->curve->calcPos(f);
893            glVertex3f(tmpVector.x, tmpVector.y, tmpVector.z);
894          }
895      glEnd();
896    }
897}
898
899/**
900   \brief outputs debug information about the trackManager
901   \param level how much debug
902*/
903void TrackManager::debug(unsigned int level) const
904{
905  PRINT(0)("=========================================\n");
906  PRINT(0)("= CLASS TRACKMANAGER::debug information =\n");
907  PRINT(0)("=========================================\n");
908  //  PRINT(0)("Status is: %
909  PRINT(0)(" Consists of %d elements\n", this->trackElemCount);
910  PRINT(0)(" localTime is: %f\n", this->localTime);
911  if (level >= 2)
912    {
913      for (int i = 1; i <= trackElemCount; i++)
914        {
915          TrackElement* tmpElem = this->findTrackElementByID(i);
916          tmpElem->debug();
917        }
918    }
919  PRINT(0)("-----------------------------------------\n");
920}
Note: See TracBrowser for help on using the repository browser.