Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3414 was 3376, checked in by bensch, 20 years ago

orxonox/branches/trackManager: c2-continuity-patch (mathematically correct, but does not look to good.)

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