Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3623 was 3608, checked in by patrick, 20 years ago

orxonox/trunk: now there is a real speedup in compiling time when dependencies are modified: just realy only includes, what is needed. Byside the speedup, there is more overview! never add an orxonox class to stdincl.h if it doesn't have to be

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