Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: now the TrackManager has a name for each trackElement

File size: 29.6 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->firstTrackElem->setName("root");
381
382  this->currentTrackElem = firstTrackElem;
383
384  this->curveType = CURVE_BEZIER;
385  this->localTime = 0;
386  this->maxTime = 0;
387  this->trackElemCount = 1;
388  this->trackNode = new TrackNode();
389  this->setBindSlave(this->trackNode);
390}
391
392/**
393   \brief standard destructor
394*/
395TrackManager::~TrackManager(void)
396{
397  PRINTF(3)("Destruct TrackManager\n");
398
399  PRINTF(4)("Deleting all the TrackElements\n");
400  delete this->firstTrackElem;
401
402  // the tracknode should be deleted here, but is deleted by pNode: -> null_parent
403
404  // we do not have a TrackManager anymore
405  TrackManager::singletonRef = NULL;
406}
407
408//! Singleton Reference to TrackManager
409TrackManager* TrackManager::singletonRef = NULL;
410
411/**
412   \returns The reference on the TrackManager.
413
414   If the TrackManager does not exist, it will be created.
415*/
416TrackManager* TrackManager::getInstance(void) 
417{
418  if (!TrackManager::singletonRef)
419    TrackManager::singletonRef = new TrackManager();
420  return TrackManager::singletonRef;
421}
422
423
424// INITIALIZE //
425/**
426   \brief reserves Space for childCount children
427   \param childCount The Count of children to make space for.
428   \param trackElem The TrackElement to appy this to. (if NULL chose this->currentTrackElement)
429*/
430void TrackManager::initChildren(unsigned int childCount, TrackElement* trackElem)
431{
432  if (!trackElem)
433    trackElem = this->currentTrackElem;
434
435  trackElem->childCount = childCount;
436  trackElem->mainJoin = true;  // this tells join, that this one is the Main Join, if it tries to join multiple Tracks
437  trackElem->children =  new tList<TrackElement>();
438  for (int i = 0; i < childCount; i++)
439    {
440      // create a new Element
441      TrackElement* newElem = new TrackElement();
442      // setting up the new ID
443      newElem->ID = ++trackElemCount;
444      // setting up the Time
445      newElem->startingTime = trackElem->endTime + trackElem->jumpTime;
446      // adds the conection Point
447      this->addPoint(trackElem->curve->getNode(trackElem->curve->getNodeCount()),
448                     newElem);
449      // add the new child to the childList.
450      trackElem->children->add(newElem);
451    }
452
453  // setting the Name of the new TrackElement to the name of the last one + _childI
454
455  if (trackElem->getName())
456    {
457      for (int i = 0; i < trackElem->childCount; i++)
458      {
459        char* childName = new char[strlen(trackElem->getName())+10];
460        sprintf(childName, "%s_child%d", trackElem->getName(), i);
461        trackElem->getChild(i)->setName(childName);
462      }
463    }
464  // select the first Child to work on.
465  this->currentTrackElem = trackElem->getChild(0);
466}
467
468
469/**
470   \brief Sets the trackID we are working on.
471   \param trackID the trackID we are working on
472*/
473void TrackManager::workOn(unsigned int trackID)
474{
475  TrackElement* tmpElem = this->firstTrackElem->findByID(trackID);
476  if (tmpElem)
477    this->currentTrackElem = tmpElem;
478  else
479    PRINTF(2)("TrackElement %d not Found, leaving unchanged\n", trackID);
480  PRINTF(4)("now Working on %d\n", this->currentTrackElem->ID);
481}
482
483/**
484   \brief Sets the TrackElement to work on
485   \param trackName the Name of the Track to work on
486*/
487void TrackManager::workOn(const char* trackName)
488{
489  TrackElement* tmpElem = this->firstTrackElem->findByName(trackName);
490  if (tmpElem)
491    this->currentTrackElem = tmpElem;
492  else
493    PRINTF(2)("TrackElement %s not Found, leaving unchanged\n", trackName);
494  PRINTF(4)("now Working on %d\n", this->currentTrackElem->ID);
495}
496
497/**
498   \brief Sets the Type of the Curve
499   \param curveType The Type to set
500   \param trackElem the TrackElement that should get a new Curve.
501
502   \brief this will possibly get obsolete during the process.
503*/
504void TrackManager::setCurveType(CurveType curveType, TrackElement* trackElem)
505{
506  if (!trackElem->isFresh)
507    {
508      PRINTF(2)("It is not possible to change the type of a Curve after you have have appended some points to it\n");
509      return;
510    }
511  this->curveType = curveType;
512  switch (curveType)
513    {
514    case CURVE_BEZIER:
515      trackElem->curve = new BezierCurve();
516      break;
517    }
518}
519
520/**
521   \brief Sets the duration of the current path in seconds.
522   \param duration The duration in seconds.
523   \param trackElem The TrackElement to apply this to.
524*/
525void TrackManager::setDuration(float duration, TrackElement* trackElem)
526{
527  if (!trackElem)
528    trackElem = this->currentTrackElem;
529
530  trackElem->duration = duration;
531  trackElem->endTime = trackElem->startingTime + duration;
532}
533
534/**
535   \brief adds a point to trackElem
536   \param newPoint The point to add.
537   \param trackElem The TrackElement to add the Point to
538*/
539bool TrackManager::addPoint(Vector newPoint, TrackElement* trackElem)
540{
541  if (!trackElem)
542    trackElem = this->currentTrackElem;
543
544  if (trackElem->isFresh)
545    {
546      this->setCurveType(TMAN_DEFAULT_CURVETYPE, trackElem);
547      trackElem->isFresh = false;
548    }
549  trackElem->curve->addNode(newPoint);
550  trackElem->nodeCount++;
551}
552
553/**
554   \brief adds save/splitpoint.
555   \param newPoint The point to add.
556   \returns A Pointer to a newly appended Curve
557*/
558int TrackManager::addHotPoint(Vector newPoint, TrackElement* trackElem)
559{
560  if (!trackElem)
561    trackElem = this->currentTrackElem;
562
563  PRINTF(4)("setting up a HotPoint\n");
564  if (trackElem->isFresh)
565    {
566      trackElem->isFresh = false;
567    }
568
569  // \todo HotPoint Handling.
570  trackElem->curve->addNode(newPoint);
571  trackElem->nodeCount++;
572  this->initChildren(1, trackElem);
573}
574
575/**
576   \brief Sets the last HotPoint into a savePoint.
577   \param trackElem The TrackElement to appy this to. (if NULL chose this->currentTrackElement)
578   \returns A Pointer to a newly appended Curve
579
580   If no HotPoint was defined the last added Point will be rendered into a savePoint. \n
581   If the HotPoint was defined as a fork the Point will \b not be set into a savePoint.
582*/
583int TrackManager::setSavePoint(TrackElement* trackElem)
584{
585  if (!trackElem)
586    trackElem = this->currentTrackElem;
587
588  PRINTF(4)("setting up a SavePoint.\n");
589  if (trackElem->isFork || trackElem->isSavePoint)
590    {
591      PRINTF(2)("%d is already finished \n", trackElem->ID);
592      return trackElem->getChild(0)->ID;
593    }
594  trackElem->isSavePoint = true;
595  trackElem->isHotPoint = true;
596
597  this->initChildren(1, trackElem);
598}
599
600/**
601   \brief adds some interessting non-linear movments through the level.
602   \param count The Count of childrens the current HotPoint will have.
603
604   If no HotPoint was defined the last added Point will be rendered into a fork. \n
605   If the HotPoint was defined as a savePoint the Point will \b not be set into a fork.
606*/
607void TrackManager::fork(unsigned int count, ...)
608{
609  int* trackIDs = new int[count];
610  this->forkV(count, trackIDs);
611  va_list ID;
612  va_start (ID, count);
613  for(int i = 0; i < count; i++)
614    {
615      *va_arg (ID, int*) = trackIDs[i];
616    }
617  va_end(ID); 
618  delete []trackIDs;
619}
620
621/**
622   \brief adds some interessting non-linear movments through the level.
623   \param count The Count of childrens the current HotPoint will have.
624   \param trackIDs A Pointer to an Array of ints which will hold the trackID's (the user will have to reserve space for this).
625   \param trackElem The TrackElement to appy this to. (if NULL chose this->currentTrackElement)
626   \see TrackManager::fork(unsigned int count, ...)
627*/
628void TrackManager::forkV(unsigned int count, int* trackIDs, TrackElement* trackElem)
629{
630  if (!trackElem)
631    trackElem = this->currentTrackElem;
632
633  PRINTF(4)("Forking with %d children\n", count);
634  if (trackElem->isSavePoint)
635    return;
636  trackElem->isFork = true;
637  trackElem->isHotPoint = true;
638  for(int i = 0; i < count; i++)
639    trackIDs[i]=this->trackElemCount+1+i;
640  this->initChildren(count, trackElem);
641}
642
643/**
644   \brief decides under what condition a certain Path will be chosen.
645   \param trackID the trackID to apply this to.
646   \param cond the CONDITION of the decision
647   \param subject the Subject that will be decided upon with CONDITION cond.
648*/
649void TrackManager::condition(unsigned int trackID, CONDITION cond, void* subject)
650{
651  this->condition(cond, subject, this->firstTrackElem->findByID(trackID));
652}
653
654/**
655   \brief decides under what condition a certain Path will be chosen.
656   \param cond the CONDITION of the decision
657   \param subject the Subject that will be decided upon with CONDITION cond.
658   \param trackElem The TrackElement to appy this to. (if NULL chose this->currentTrackElement)
659*/
660void TrackManager::condition(CONDITION cond, void* subject, TrackElement* trackElem)
661{
662  if (!trackElem)
663    trackElem = this->currentTrackElem;
664
665  if (!trackElem->isFork)
666    {
667      PRINTF(2)("%d is not a Fork, and no condition can be set in this case\n", trackElem->ID);
668      return;
669    }
670  else
671    {
672      switch (cond)
673        {
674        case LOWEST:
675          trackElem->condFunc = &TrackElement::lowest;
676          break;
677        case HIGHEST:
678          trackElem->condFunc = &TrackElement::highest;
679          break;
680        case RANDOM: 
681          trackElem->condFunc = &TrackElement::random;
682          break;
683        case LEFTRIGHT:
684          trackElem->condFunc = &TrackElement::leftRight;
685          break;
686        case NEAREST:
687          trackElem->condFunc = &TrackElement::nearest;
688          break;
689        case ENEMYKILLED:
690          break;
691        }
692      trackElem->subject=subject;
693    }
694}
695
696/**
697   \brief joins some tracks together again.
698   \param count The count of Paths to join.
699
700   Join will set the localTime to the longest time a Path has to get to this Point. \n
701   Join will join all curves to the first curve, meaning that all the tangents will be matched.
702*/
703void TrackManager::join(unsigned int count, ...)
704{
705  int* trackIDs = new int [count];
706  va_list ID;
707  va_start (ID, count);
708  for(int i = 0; i < count; i++)
709    {
710      trackIDs[i] = va_arg (ID, int);
711    }
712  va_end(ID);
713  this->joinV(count, trackIDs);
714  delete []trackIDs;
715}
716
717/**
718   \brief Joins some Tracks together again.
719   \param count The count of trackElements to join
720
721   \see void TrackManager::join(unsigned int count, ...)
722   The difference to void TrackManager::join(unsigned int count, ...) is, that this function takes
723   the Names of the TrackElements as inputs and not their ID
724*/
725void TrackManager::joinc(unsigned int count, ...)
726{
727  int* trackIDs = new int [count];
728  va_list NAME;
729  va_start (NAME, count);
730  for(int i = 0; i < count; i++)
731    {
732      char* name = va_arg (NAME, char*);
733      TrackElement* tmpElem = this->firstTrackElem->findByName(name);
734      if (tmpElem)
735        trackIDs[i] = tmpElem->ID;
736      else
737        PRINTF(1)("Trying to join a Track, of which the name does not exist: %s\n", name);
738    }
739  va_end(NAME);
740  this->joinV(count, trackIDs);
741  delete []trackIDs;
742}
743
744
745/**
746   \brief joins some tracks together again.
747   \param count The count of Paths to join.
748   \param trackIDs an Array with the trackID's to join
749
750   \see void TrackManager::join(unsigned int count, ...)
751*/
752void TrackManager::joinV(unsigned int count, int* trackIDs)
753{
754  TrackElement* tmpTrackElem;
755  for (int i = 0; i < count; i++)
756    if (!this->firstTrackElem->findByID(trackIDs[i]))
757      {
758        PRINTF(1)("Error trying to Connect Paths that do not exist yet: %d\n Not Joining Anything", trackIDs[i]);
759        return;
760      }
761                 
762
763  PRINTF(3)("Joining %d tracks and merging to Track %d\n", count, trackIDs[0]);
764
765  // checking if there is a back-loop-connection and ERROR if it is.
766  tmpTrackElem = this->firstTrackElem->findByID(trackIDs[0]);
767  if (!tmpTrackElem->backLoopCheck(tmpTrackElem))
768    {
769      PRINTF(2)("Backloop connection detected at joining trackElements\n -> TRACK WILL NOT BE JOINED\n");
770      return;
771    }
772
773  TrackElement* firstJoint =   this->firstTrackElem->findByID(trackIDs[0]);
774  float tmpLatestTime = firstJoint->endTime;
775
776  Vector tmpEndPoint = firstJoint->curve->getNode(firstJoint->curve->getNodeCount());
777  Vector tmpTangentPoint = firstJoint->curve->getNode(firstJoint->curve->getNodeCount()-1);
778  Vector tmpc2Point = firstJoint->curve->getNode(firstJoint->curve->getNodeCount()-2);
779  firstJoint->isJoined = true;
780  //  firstJoint->mainJoin = true;
781  if(!firstJoint->isHotPoint)
782    this->setSavePoint(firstJoint);
783  // Timing:
784  for (int i = 0; i < count; i++)
785    {
786      TrackElement* tmpJoinElem = this->firstTrackElem->findByID(trackIDs[i]);
787      if (tmpJoinElem->childCount == 0
788          && tmpJoinElem->endTime > tmpLatestTime)
789        tmpLatestTime = tmpJoinElem->endTime;
790    }
791  // time the main Join.
792  firstJoint->jumpTime = tmpLatestTime - firstJoint->endTime;
793 
794  // Joining:
795  for (int i = 1; i < count; i++)
796    {
797      TrackElement* tmpJoinElem = this->firstTrackElem->findByID(trackIDs[i]);
798      if (tmpJoinElem->childCount > 0)
799        printf("!!This Curve has children, and as such will not be joined!!\n You can try joining other childless TrackElements to this one!");
800      else
801        {
802          this->addPoint(tmpc2Point, tmpJoinElem);
803          this->addPoint(tmpTangentPoint, tmpJoinElem);
804          this->addPoint(tmpEndPoint, tmpJoinElem);
805          // time all other Joins
806          tmpJoinElem->jumpTime = tmpLatestTime - tmpJoinElem->endTime;
807         
808          //Copying Joint-Info
809          tmpJoinElem->children = firstJoint->children;
810          tmpJoinElem->childCount = firstJoint->childCount;
811          tmpJoinElem->isSavePoint = firstJoint->isSavePoint;
812          tmpJoinElem->isFork = firstJoint->isFork;
813
814          tmpJoinElem->isJoined = true;
815        }
816    }
817  if(firstJoint->children)
818    {
819      //TrackElement* enumElem = firstJoint->children->enumerate();
820      tIterator<TrackElement>* iterator = firstJoint->children->getIterator();
821      TrackElement* enumElem = iterator->nextElement();
822      while (enumElem)
823        {
824          PRINTF(5)("Setting startingTime of %d to %f.\n", enumElem->ID, tmpLatestTime);
825          enumElem->startingTime = tmpLatestTime;
826          enumElem->endTime = tmpLatestTime + enumElem->duration;
827         
828          enumElem = iterator->nextElement();
829        }
830      delete iterator;
831    }
832}
833
834/**
835   \brief finalizes the TrackSystem. after this it will not be editable anymore
836
837   \todo check for any inconsistencies, output errors
838*/
839void TrackManager::finalize(void)
840{
841  for (int i = 1; i<= trackElemCount ;i++)
842    {
843      TrackElement* tmpElem = this->firstTrackElem->findByID(i);
844      if( tmpElem->childCount > 0 && tmpElem->mainJoin)
845        {
846          tIterator<TrackElement>* iterator = tmpElem->children->getIterator();
847          TrackElement* enumElem = iterator->nextElement();
848          //TrackElement* enumElem = tmpElem->children->enumerate();
849          while (enumElem)
850            {
851             
852              // c1-continuity
853              enumElem->curve->addNode(enumElem->curve->getNode(0) +
854                                                   ((enumElem->curve->getNode(0) - 
855                                                    tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-1))
856                                                    ),2);
857              enumElem->nodeCount++;
858              // c2-continuity
859              enumElem->curve->addNode((tmpElem->curve->getNode(tmpElem->curve->getNodeCount())-
860                                                    tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-1)) * 4 +
861                                                   tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-2), 3);
862              enumElem->nodeCount++;                                               
863              PRINTF(5)("accelerations: %d-in: count: %d, %f, %f, %f\n                  %d-out: count: %d %f, %f, %f\n",
864                     tmpElem->ID, tmpElem->nodeCount,
865                     tmpElem->curve->calcAcc(0.999).x, tmpElem->curve->calcAcc(0.999).y, tmpElem->curve->calcAcc(0.999).z,
866                     enumElem->ID, enumElem->nodeCount,
867                     enumElem->curve->calcAcc(0).x, enumElem->curve->calcAcc(0).y, enumElem->curve->calcAcc(0).z);
868             
869              enumElem = iterator->nextElement();
870            }
871          delete iterator;
872        }
873    }
874  for (int i = 1; i <= trackElemCount;i++)
875    if (this->firstTrackElem->findByID(i)->endTime > this->maxTime)
876      this->maxTime = this->firstTrackElem->findByID(i)->endTime; // very bad implemented :/
877}
878
879
880// RUNTIME //
881
882/**
883   \brief calculates the Position for the localTime of the Track.
884   \returns the calculated Position
885*/
886Vector TrackManager::calcPos() const
887{
888  return this->currentTrackElem->curve->calcPos((this->localTime-this->currentTrackElem->startingTime)/this->currentTrackElem->duration);
889}
890
891/**
892   \brief calculates the Rotation for the localTime of the Track.
893   \returns the calculated Rotation
894*/
895Vector TrackManager::calcDir() const
896{
897  return this->currentTrackElem->curve->calcDir((this->localTime - this->currentTrackElem->startingTime)/this->currentTrackElem->duration);
898}
899
900/**
901   \returns the current Width of the track
902*/
903float TrackManager::getWidth(void) const
904{
905  return this->currentTrackElem->width;
906}
907
908/**
909   \brief Advances the local-time of the Track around dt
910   \param dt The time about which to advance.
911
912   This function also checks, if the TrackElement has to be changed.
913*/
914void TrackManager::tick(float dt)
915{
916  dt /= 1000;
917  PRINTF(4)("CurrentTrackID: %d, LocalTime is: %f, timestep is: %f\n", this->currentTrackElem->ID, this->localTime, dt);
918  if (this->localTime <= this->firstTrackElem->duration)
919    this->jumpTo(this->localTime);
920  if (this->localTime <= this->maxTime)
921    this->localTime += dt;
922  if (this->localTime > this->currentTrackElem->endTime
923      && this->currentTrackElem->children)
924    {
925      if (this->currentTrackElem->jumpTime != 0.0)
926        this->jumpTo(this->localTime + this->currentTrackElem->jumpTime);
927      // jump to the next TrackElement and also set the history of the new Element to the old one.
928      TrackElement* tmpHistoryElem = this->currentTrackElem;
929      this->currentTrackElem = this->currentTrackElem->getChild(this->choosePath(this->currentTrackElem));
930      this->currentTrackElem->history = tmpHistoryElem;
931    }
932  if (this->bindSlave)
933    {
934      Vector tmp = this->calcPos();
935      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)); 
936
937      Vector v(0.0, 1.0, 0.0);
938      Quaternion q(-PI/2, v);
939      quat = quat * q;
940
941      this->bindSlave->setAbsCoor(tmp);
942      this->bindSlave->setAbsDir(quat);
943    }
944}
945
946/**
947   \brief Jumps to a certain point on the Track.
948   \param time The time on the Track to jump to.
949
950   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.)
951   Max is trackLengthMax.
952*/
953void TrackManager::jumpTo(float time)
954{
955  if (time == 0)
956    this->currentTrackElem = this->firstTrackElem;
957  this->localTime = time;
958}
959
960/**
961   \brief a Function that decides which Path we should follow.
962   \param trackElem The Path to choose.
963   
964*/
965int TrackManager::choosePath(TrackElement* trackElem)
966{
967  return (trackElem->*(trackElem->condFunc))(trackElem->subject);
968}
969
970/**
971   \brief Sets the PNode, that should be moved along the Tack
972   \param bindSlave the PNode to set
973*/
974void TrackManager::setBindSlave(PNode* bindSlave)
975{
976  this->bindSlave = bindSlave;
977}
978
979/**
980   \returns the main TrackNode
981*/
982PNode* TrackManager::getTrackNode(void)
983{
984  return this->trackNode;
985}
986
987// DEBUG //
988
989/**
990   \brief Imports a model of the Graph into the OpenGL-environment.
991   \param dt The Iterator used in seconds for Painting the Graph.
992
993   This is for testing facility only. Do this if you want to see the Path inside the Level.
994   eventually this will all be packed into a gl-list.
995*/
996void TrackManager::drawGraph(float dt) const
997{
998  for (int i = 1; i <= trackElemCount; i++)
999    {
1000      glBegin(GL_LINE_STRIP);
1001      TrackElement* tmpElem = this->firstTrackElem->findByID(i);
1002      if (tmpElem->curve)
1003        for(float f = 0.0; f < 1.0; f+=dt)
1004          {
1005            //      printf("%f, %f, %f\n",trackManager->calcPos().x, trackManager->calcPos().y, trackManager->calcPos().z);
1006            Vector tmpVector = tmpElem->curve->calcPos(f);
1007            glVertex3f(tmpVector.x, tmpVector.y, tmpVector.z);
1008          }
1009      glEnd();
1010    }
1011}
1012
1013/**
1014   \brief outputs debug information about the trackManager
1015   \param level how much debug
1016*/
1017void TrackManager::debug(unsigned int level) const
1018{
1019  PRINT(0)("=========================================\n");
1020  PRINT(0)("= CLASS TRACKMANAGER::debug information =\n");
1021  PRINT(0)("=========================================\n");
1022  //  PRINT(0)("Status is: %
1023  PRINT(0)(" Consists of %d elements\n", this->trackElemCount);
1024  PRINT(0)(" localTime is: %f\n", this->localTime);
1025  if (level >= 2)
1026    {
1027      for (int i = 1; i <= trackElemCount; i++)
1028        {
1029          TrackElement* tmpElem = this->firstTrackElem->findByID(i);
1030          tmpElem->debug();
1031        }
1032    }
1033  PRINT(0)("-----------------------------------------\n");
1034}
Note: See TracBrowser for help on using the repository browser.