Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: added a possibility to join tracks by name

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