Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/levelloader/src/track_manager.cc @ 3728

Last change on this file since 3728 was 3605, checked in by bensch, 20 years ago

orxonox/trunk: merged trunk back to levelloader
merged with command:
svn merge -r 3499:HEAD trunk branches/levelloader

Conflicts in
C track_manager.h
C world_entities/player.cc
C world_entities/player.h
C world_entities/environment.h
C lib/coord/p_node.cc
C defs/debug.h
C track_manager.cc
C story_entities/campaign.h

solved in merge-favouring. It was quite easy because Chris only worked on the headers, and he didi it quite clean. Thats the spirit :)

Conflits in world.cc are a MESS: fix it

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