Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: TrackManager: nicer fuctionality… more to come

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