Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/trackManager/src/track_manager.cc @ 3498

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

orxonox/branches/trackManager: merged trunk back to tracManager R3440:3497 → 3498
merged with command:
svn merge ../trunk/ trackManager/ -r 3430:HEAD
conflicts resolved in favor of the Trunk

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