Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: merged particleSystem back into the Trunk
merged with command:
svn merge particleEngine/ ../trunk/ -r 3966:HEAD
U ../trunk/src/lib/graphics/particles/particle_emitter.cc
U ../trunk/src/lib/graphics/particles/particle_system.cc
U ../trunk/src/lib/graphics/particles/particle_system.h

as you can see, no conflicts

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