Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3477 was 3433, checked in by bensch, 20 years ago

orxonox/trunk: merged back the trackManager to the trunk.
merged with command:
svn merge -r 3369:HEAD branches/trackManager trunk
resolved conflicts in world.cc additive differences.

File size: 18.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
17#include "track_manager.h"
18#include <stdarg.h>
19#include "p_node.h"
20
21using namespace std;
22
23/**
24   \brief initializes a TrackElement (sets the default values)
25*/
26TrackElement::TrackElement(void)
27{
28  this->isFresh = true;
29  this->isHotPoint = false;
30  this->isSavePoint = false;
31  this->isFork = false;
32  this->isJoined = false;
33  this->mainJoin = false;
34  this->cond; //!< todo think!!
35  this->ID = -1;
36  this->startingTime = 0; //!< \todo eventually set this to the max time of TrackManager.
37  this->duration = 1;
38  this->endTime = 1;
39  this->jumpTime = 0;
40  this->curveType = BEZIERCURVE;
41  this->nodeCount = 0;
42  this->childCount = 0;
43  this->name = NULL;
44  this->curve = NULL;
45  this->children = NULL;
46}
47
48/**
49    \brief destroys all alocated memory)
50    \todo eventually when deleting a TrackElement you would not like to delete all its preceding TrackElements
51*/
52TrackElement::~TrackElement(void)
53{
54  if (this->name)
55    delete []name;
56  if (this->curve)
57    delete this->curve;
58  if ((!this->isJoined &&this->childCount > 0) || (this->isJoined && this->mainJoin))
59    {
60      for (int i=0; i < this->childCount; i++)
61        delete this->children[i];
62      delete this->children;
63    }
64}
65
66/**
67   \brief Searches through all the TrackElements for trackID.
68   \param trackID The ID to search for.
69   \returns The TrackElement if Found, NULL otherwise.
70   
71   \todo make this more modular, to search for different things
72*/
73TrackElement* TrackElement::findByID(unsigned int trackID)
74{
75  // return if Found.
76  if (this->ID == trackID)
77    return this;
78  // search on.
79  if (this->childCount > 0)
80    for (int i=0; i < this->childCount; i++)
81      {
82        TrackElement* tmpElem;
83        if ((tmpElem = this->children[i]->findByID(trackID)))
84          return tmpElem;
85      }
86  else return NULL;
87}
88
89
90
91
92
93/////////////////////////////////////
94///// TRACKMANAGER //////////////////
95/////////////////////////////////////
96/**
97   \brief standard constructor
98
99*/
100TrackManager::TrackManager(void)
101{
102  this->setClassName ("TrackManager");
103
104  PRINTF(3)("Initializing the TrackManager\n");
105  this->firstTrackElem = new TrackElement();
106  this->firstTrackElem->ID = 1;
107  this->currentTrackElem = firstTrackElem;
108  this->localTime = 0;
109  this->maxTime = 0;
110  this->trackElemCount = 1;
111  this->bindSlave = NULL;
112}
113
114
115/**
116   \brief standard destructor
117
118*/
119TrackManager::~TrackManager(void)
120{
121  PRINTF(3)("Destruct TrackManager\n");
122
123  PRINTF(3)("Deleting all the TrackElements\n");
124  delete this->firstTrackElem;
125
126  // we do not have a TrackManager anymore
127  singletonRef = NULL;
128}
129
130TrackManager* TrackManager::singletonRef = NULL;
131
132/**
133   \returns The reference on the TrackManager.
134
135   If the TrackManager does not exist, it will be created.
136*/
137TrackManager* TrackManager::getInstance(void) 
138{
139  if (singletonRef)
140    return singletonRef;
141  else
142    return singletonRef = new TrackManager();
143}
144
145/**
146   \brief reserves Space for childCount children
147   \param childCount The Count of children to make space for.
148*/
149void TrackManager::initChildren(unsigned int childCount)
150{
151  this->currentTrackElem->childCount = childCount;
152  this->currentTrackElem->mainJoin = true;
153  this->currentTrackElem->children = new TrackElement*[childCount];
154  for (int i=0; i<childCount; i++)
155    {
156      this->currentTrackElem->children[i] = new TrackElement();
157      this->currentTrackElem->children[i]->ID = ++trackElemCount;
158      this->currentTrackElem->children[i]->startingTime = this->currentTrackElem->endTime + this->currentTrackElem->jumpTime;
159      this->addPoint(this->currentTrackElem->curve->getNode(this->currentTrackElem->curve->getNodeCount()), this->currentTrackElem->children[i]);
160    }
161}
162
163/**
164   \brief Searches for a given trackID.
165   \param trackID the trackID to search for.
166   \returns The TrackElement #trackID if found, NULL otherwise.
167*/
168TrackElement* TrackManager::findTrackElementByID(unsigned int trackID) const
169{
170  return firstTrackElem->findByID(trackID);
171}
172
173// INITIALIZE //
174
175/**
176   \brief Sets the trackID we are working on.
177   \param trackID the trackID we are working on
178*/
179void TrackManager::workOn(unsigned int trackID)
180{
181  TrackElement* tmpElem = findTrackElementByID(trackID);
182  if (tmpElem)
183    this->currentTrackElem = tmpElem;
184  else
185    printf("TrackElement not Found, leaving unchanged\n");
186  printf("now Working on %d\n", this->currentTrackElem->ID);
187
188}
189
190/**
191   \brief Sets the Type of the Curve
192   \brief curveType The Type to set
193*/
194void TrackManager::setCurveType(CurveType curveType, TrackElement* trackElem)
195{
196  if (!trackElem->isFresh)
197    {
198      PRINTF(2)("It is not possible to change the type of a Curve after you have have appended some points to it\n");
199      return;
200    }
201  trackElem->curveType = curveType;
202  switch (curveType)
203    {
204    case BEZIERCURVE:
205      trackElem->curve = new BezierCurve();
206      break;
207    case UPOINTCURVE:
208      trackElem->curve = new UPointCurve();
209      break;
210    }
211}
212
213/**
214   \brief Sets the duration of the current path in seconds.
215   \param time The duration in seconds.
216*/
217
218void TrackManager::setDuration(float time)
219{
220  this->currentTrackElem->duration = time;
221  this->currentTrackElem->endTime = this->currentTrackElem->startingTime + time;
222}
223
224/**
225   \brief adds a point to the current TrackElement
226   \param newPoint The point to add.
227*/
228bool TrackManager::addPoint(Vector newPoint)
229{
230  return this->addPoint(newPoint, this->currentTrackElem);
231}
232
233/**
234   \brief adds a point to trackElem
235   \param newPoint The point to add.
236   \param trackElem The TrackElement to add the Point to
237*/
238bool TrackManager::addPoint(Vector newPoint, TrackElement* trackElem)
239{
240  if (trackElem->isFresh)
241    {
242      this->setCurveType(BEZIERCURVE, trackElem);
243      trackElem->isFresh = false;
244    }
245  trackElem->curve->addNode(newPoint);
246  trackElem->nodeCount++;
247}
248
249/**
250   \brief adds save/splitpoint.
251   \param newPoint The point to add.
252   \returns A Pointer to a newly appended Curve
253*/
254int TrackManager::addHotPoint(Vector newPoint)
255{
256  printf("setting up a HotPoint\n");
257  if (this->currentTrackElem->isFresh)
258    {
259      this->setCurveType(BEZIERCURVE);
260      this->currentTrackElem->isFresh = false;
261    }
262
263  // \todo HotPoint Handling.
264  this->currentTrackElem->curve->addNode(newPoint);
265  this->currentTrackElem->nodeCount++;
266  this->initChildren(1);
267  this->currentTrackElem = this->currentTrackElem->children[0];
268}
269
270/**
271   \brief Sets the last HotPoint into a savePoint.
272   \returns A Pointer to a newly appended Curve
273   
274   If no HotPoint was defined the last added Point will be rendered into a savePoint. \n
275   If the HotPoint was defined as a fork the Point will \b not be set into a savePoint.
276*/
277int TrackManager::setSavePoint(void)
278{
279  printf("setting up a SavePoint.\n");
280  if (this->currentTrackElem->isFork || this->currentTrackElem->isSavePoint)
281    return this->currentTrackElem->children[1]->ID;
282  this->currentTrackElem->isSavePoint = true;
283  this->currentTrackElem->isHotPoint = true;
284
285  this->initChildren(1);
286  this->currentTrackElem = this->currentTrackElem->children[0];
287}
288
289/**
290   \brief adds some interessting non-linear movments through the level.
291   \param count The Count of childrens the current HotPoint will have.
292
293   If no HotPoint was defined the last added Point will be rendered into a fork. \n
294   If the HotPoint was defined as a savePoint the Point will \b not be set into a fork.
295*/
296void TrackManager::fork(unsigned int count, ...)
297{
298  int* trackIDs = new int[count];
299  this->forkV(count, trackIDs);
300  va_list ID;
301  va_start (ID, count);
302  for(int i = 0; i < count; i++)
303    {
304      *va_arg (ID, int*) = trackIDs[i];
305    }
306  va_end(ID); 
307  delete []trackIDs;
308}
309
310/**
311   \brief adds some interessting non-linear movments through the level.
312   \param count The Count of childrens the current HotPoint will have.
313   \param trackIDs A Pointer to an Array of ints which will hold the trackID's (the user will have to reserve space for this).
314
315   \see void TrackManager::fork(int count, ...)
316
317   \todo initialisation is wrong!! also in setSavePoint.
318*/
319void TrackManager::forkV(unsigned int count, int* trackIDs)
320{
321  printf("Forking with %d children\n", count);
322  if (this->currentTrackElem->isSavePoint)
323    return;
324  this->currentTrackElem->isFork = true;
325  this->currentTrackElem->isHotPoint = true;
326  for(int i = 0; i < count; i++)
327    trackIDs[i]=this->trackElemCount+1+i;
328  this->initChildren(count);
329}
330
331/**
332   \brief decides under what condition a certain Path will be chosen.
333   \param groupID the ID on which to choose the preceding move
334   \param cond \todo think about this
335*/
336void TrackManager::condition(unsigned int groupID, PathCondition cond)
337{
338 
339}
340
341/**
342   \brief joins some tracks together again.
343   \param count The count of Paths to join.
344
345   Join will set the localTime to the longest time a Path has to get to this Point. \n
346   Join will join all curves to the first curve, meaning that all the tangents will be matched.
347*/
348void TrackManager::join(unsigned int count, ...)
349{
350  int* trackIDs = new int [count];
351  va_list ID;
352  va_start (ID, count);
353  for(int i = 0; i < count; i++)
354    {
355      trackIDs[i] = va_arg (ID, int);
356    }
357  va_end(ID);
358  this->joinV(count, trackIDs);
359  delete []trackIDs;
360}
361
362/**
363   \brief joins some tracks together again.
364   \param count The count of Paths to join.
365   \param trackIDs an Array with the trackID's to join
366
367   \see void TrackManager::join(int count, ...)
368*/
369void TrackManager::joinV(unsigned int count, int* trackIDs)
370{
371  printf("Joining %d tracks and merging to Track %d\n", count, trackIDs[0]);
372
373  // chanching work-on to temporary value. going back at the end.
374  int tmpCurrentWorkingID = this->currentTrackElem->ID;
375  this->workOn(trackIDs[0]);
376  TrackElement* firstJoint = this->currentTrackElem;
377  float tmpLatestTime = firstJoint->endTime;
378
379  Vector tmpEndPoint = firstJoint->curve->getNode(firstJoint->curve->getNodeCount());
380  Vector tmpTangentPoint = firstJoint->curve->getNode(firstJoint->curve->getNodeCount()-1);
381  Vector tmpc2Point = firstJoint->curve->getNode(firstJoint->curve->getNodeCount()-2);
382  firstJoint->isJoined = true;
383  //  firstJoint->mainJoin = true;
384  if(!firstJoint->isHotPoint)
385    this->setSavePoint();
386  // Timing:
387  for (int i = 0; i < count; i++)
388    {
389      TrackElement* tmpJoinElem = this->findTrackElementByID(trackIDs[i]);
390      if (tmpJoinElem->childCount == 0
391          && tmpJoinElem->endTime > tmpLatestTime)
392        tmpLatestTime = tmpJoinElem->endTime;
393    }
394  // time the main Join.
395  firstJoint->jumpTime = tmpLatestTime - firstJoint->endTime;
396 
397  // Joining:
398  for (int i = 1; i < count; i++)
399    {
400      TrackElement* tmpJoinElem = this->findTrackElementByID(trackIDs[i]);
401      if (tmpJoinElem->childCount > 0)
402        printf("!!This Curve has children, and as such will not be joined!!\n You can try joining other childless TrackElements to this one!");
403      else
404        {
405          this->addPoint(tmpc2Point, tmpJoinElem);
406          this->addPoint(tmpTangentPoint, tmpJoinElem);
407          this->addPoint(tmpEndPoint, tmpJoinElem);
408          // time all other Joins
409          tmpJoinElem->jumpTime = tmpLatestTime - tmpJoinElem->endTime;
410         
411          //Copying Joint-Info
412          tmpJoinElem->children = firstJoint->children;
413          tmpJoinElem->childCount = firstJoint->childCount;
414          tmpJoinElem->isSavePoint = firstJoint->isSavePoint;
415          tmpJoinElem->isFork = firstJoint->isFork;
416
417          tmpJoinElem->isJoined = true;
418        }
419    }
420  if(firstJoint->childCount > 0)
421    for(int i = 0; i < firstJoint->childCount; i++)
422      {
423        printf("Setting startingTime of %d to %f.\n", firstJoint->children[i]->ID, tmpLatestTime);
424        firstJoint->children[i]->startingTime = tmpLatestTime;
425        firstJoint->children[i]->endTime = tmpLatestTime+firstJoint->children[i]->duration;
426      } 
427
428  // returning to the TrackElement we were working on.
429  this->workOn(tmpCurrentWorkingID);
430}
431
432/**
433   \brief finalizes the TrackSystem. after this it will not be editable anymore
434
435   \todo check for any inconsistencies, output errors
436*/
437void TrackManager::finalize(void)
438{
439  for (int i = 1; i<= trackElemCount ;i++)
440    {
441      TrackElement* tmpElem = findTrackElementByID(i);
442      if (tmpElem->childCount>0 && tmpElem->mainJoin)
443        {
444          for (int j = 0; j < tmpElem->childCount; j++)
445            {
446             
447              // c1-continuity
448              tmpElem->children[j]->curve->addNode(tmpElem->children[j]->curve->getNode(0) +
449                                                   ((tmpElem->children[j]->curve->getNode(0) - 
450                                                    tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-1))
451                                                    ),2);
452              tmpElem->children[j]->nodeCount++;
453              // c2-continuity
454              tmpElem->children[j]->curve->addNode((tmpElem->curve->getNode(tmpElem->curve->getNodeCount())-
455                                                    tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-1)) * 4 +
456                                                   tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-2), 3);
457              tmpElem->children[j]->nodeCount++;                                                   
458              printf("accelerations: %d-in: count: %d, %f, %f, %f\n                  %d-out: count: %d %f, %f, %f\n",
459                     tmpElem->ID, tmpElem->nodeCount,
460                     tmpElem->curve->calcAcc(0.999).x, tmpElem->curve->calcAcc(0.999).y, tmpElem->curve->calcAcc(0.999).z,
461                     tmpElem->children[j]->ID, tmpElem->children[j]->nodeCount,
462                     tmpElem->children[j]->curve->calcAcc(0).x, tmpElem->children[j]->curve->calcAcc(0).y, tmpElem->children[j]->curve->calcAcc(0).z);
463            }
464        }
465    }
466}
467
468
469// RUNTIME //
470
471/**
472   \brief calculates the Position for the localTime of the Track.
473   \returns the calculated Position
474*/
475Vector TrackManager::calcPos() const
476{
477  //  PRINTF(0)("TrackElement:%d, localTime: %f\n",this->currentTrackElem->ID, this->localTime);
478  return this->currentTrackElem->curve->calcPos((this->localTime-this->currentTrackElem->startingTime)/this->currentTrackElem->duration);
479}
480
481/**
482   \brief calculates the Rotation for the localTime of the Track.
483   \returns the calculated Rotation
484*/
485Vector TrackManager::calcDir() const
486{
487  return this->currentTrackElem->curve->calcDir((this->localTime - this->currentTrackElem->startingTime)/this->currentTrackElem->duration);
488}
489
490/**
491   \brief Advances the local-time of the Track around dt
492   \param dt The time about which to advance.
493
494   This function also checks, if the TrackElement has to be changed.
495*/
496void TrackManager::tick(float dt)
497{
498  dt /= 1000;
499  printf("CurrentTrackID: %d, LocalTime is: %f, timestep is: %f\n", this->currentTrackElem->ID, this->localTime, dt);
500  if (this->localTime <= this->firstTrackElem->duration)
501    this->jumpTo(this->localTime);
502  this->localTime += dt;
503  if (this->localTime > this->currentTrackElem->endTime
504      && this->currentTrackElem->children)
505    {
506      if (this->currentTrackElem->jumpTime > 0) 
507        this->jumpTo(this->localTime + this->currentTrackElem->jumpTime);
508      this->currentTrackElem = this->currentTrackElem->children[0];
509    }
510  if (this->bindSlave)
511    {
512      Vector tmp = this->calcPos();
513      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)); 
514      this->bindSlave->setAbsCoor(&tmp);
515      this->bindSlave->setAbsDir(&quat);
516    }
517}
518
519/**
520   \brief Jumps to a certain point on the Track.
521   \param time The time on the Track to jump to.
522
523   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.)
524   Max is trackLengthMax.
525*/
526void TrackManager::jumpTo(float time)
527{
528  if (time == 0)
529    this->currentTrackElem = this->firstTrackElem;
530  this->localTime = time;
531}
532
533/**
534   \brief a Function that decides which Path we should follow.
535   \param graphID The Path to choose.
536   
537*/
538void TrackManager::choosePath(int graphID)
539{
540
541}
542
543/**
544   \brief Sets the PNode, that should be moved along the Tack
545   \param bindSlave the PNode to set
546*/
547void TrackManager::setBindSlave(PNode* bindSlave)
548{
549  if (!this->bindSlave)
550    this->bindSlave = bindSlave;
551}
552
553
554// DEBUG //
555
556/**
557   \brief Imports a model of the Graph into the OpenGL-environment.
558   \param dt The Iterator used in seconds for Painting the Graph.
559
560   This is for testing facility only. Do this if you want to see the Path inside the Level.
561   eventually this will all be packed into a gl-list.
562*/
563void TrackManager::drawGraph(float dt) const
564{
565
566  for (int i = 1; i <= trackElemCount; i++)
567    {
568      glBegin(GL_LINE_STRIP);
569      TrackElement* tmpElem = this->findTrackElementByID(i);
570      if (tmpElem->curve)
571        for(float f = 0.0; f < 1.0; f+=dt)
572          {
573            //      printf("%f, %f, %f\n",trackManager->calcPos().x, trackManager->calcPos().y, trackManager->calcPos().z);
574            Vector tmpVector = tmpElem->curve->calcPos(f);
575            glVertex3f(tmpVector.x, tmpVector.y, tmpVector.z);
576          }
577  glEnd();
578    }
579}
580
581/**
582   \brief outputs debug information about the trackManager
583   \param level how much debug
584*/
585void TrackManager::debug(unsigned int level) const
586{
587  printf("::CLASS TRACKMANAGER::debug information::\n");
588  //  printf("Status is: %
589  printf(" Consists of %d elements\n", this->trackElemCount);
590  printf(" localTime is: %f\n", this->localTime);
591  if (level >= 2)
592    {
593      for (int i = 1; i <= trackElemCount; i++)
594        {
595          TrackElement* tmpElem = this->findTrackElementByID(i);
596          printf("  ::TrackElement:%i::", tmpElem->ID);
597          if(tmpElem->name)
598            printf("name:%s::", tmpElem->name);
599          if(tmpElem->isFresh)
600            printf("   has not jet eddited in any way\n");
601          printf("\n   TimeTable: startingTime=%f; endTime=%f; duration=%f; jumpTime=%f\n", tmpElem->startingTime, tmpElem->endTime, tmpElem->duration, tmpElem->jumpTime);
602          printf("   consists of %d Points\n", tmpElem->nodeCount);
603          if (tmpElem->childCount == 0)
604            printf("   has no child\n");           
605          else if (tmpElem->childCount == 1)
606            printf("   has 1 child: ==%d==\n", tmpElem->children[0]->ID);
607          else if (tmpElem->childCount > 1)
608            {
609              printf("   has %d children: ", tmpElem->childCount);
610              for(int i = 0; i < tmpElem->childCount; i++)
611                printf("=%d= ", tmpElem->children[i]->ID);
612              printf("\n");
613            }
614
615          if(tmpElem->isHotPoint)
616            printf("   is a special Point:\n");
617          if(tmpElem->isSavePoint)
618            printf("    is a SavePoint\n");
619          if(tmpElem->isFork)
620            {
621              printf("    is A Fork with with %d children.\n", tmpElem->childCount);
622            }
623          if(tmpElem->isJoined)
624            printf("   is Joined at the End\n");
625        }
626    }
627}
Note: See TracBrowser for help on using the repository browser.