Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: merged branches/particleEngine into the trunk, because of the new vector class
merged with command:
svn merge -r 3922:HEAD particleEngine/ ../trunk/

not merged src/story_entities/world.cc. will do this at a later time (do not forget)

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