Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3729 was 3710, checked in by patrick, 20 years ago

orxonox/trunk: added the TestBullet to framework, made some doxygen, works

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