Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: TrackManager now uses tList instead of Arrays (). this is slower, but more compatible, and should have less errors

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