Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/soundEngine/src/track_manager.cc @ 3874

Last change on this file since 3874 was 3495, checked in by bensch, 20 years ago

orxonox/trunk: taken curve and matrix out of stdincl.h because they are not needed very often.

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
19#include "p_node.h"
20
21#include <stdarg.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 + this->currentTrackElem->jumpTime;
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 and merging 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  TrackElement* firstJoint = this->currentTrackElem;
379  float tmpLatestTime = firstJoint->endTime;
380
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  // time the main Join.
397  firstJoint->jumpTime = tmpLatestTime - firstJoint->endTime;
398 
399  // Joining:
400  for (int i = 1; i < count; i++)
401    {
402      TrackElement* tmpJoinElem = this->findTrackElementByID(trackIDs[i]);
403      if (tmpJoinElem->childCount > 0)
404        printf("!!This Curve has children, and as such will not be joined!!\n You can try joining other childless TrackElements to this one!");
405      else
406        {
407          this->addPoint(tmpc2Point, tmpJoinElem);
408          this->addPoint(tmpTangentPoint, tmpJoinElem);
409          this->addPoint(tmpEndPoint, tmpJoinElem);
410          // time all other Joins
411          tmpJoinElem->jumpTime = tmpLatestTime - tmpJoinElem->endTime;
412         
413          //Copying Joint-Info
414          tmpJoinElem->children = firstJoint->children;
415          tmpJoinElem->childCount = firstJoint->childCount;
416          tmpJoinElem->isSavePoint = firstJoint->isSavePoint;
417          tmpJoinElem->isFork = firstJoint->isFork;
418
419          tmpJoinElem->isJoined = true;
420        }
421    }
422  if(firstJoint->childCount > 0)
423    for(int i = 0; i < firstJoint->childCount; i++)
424      {
425        printf("Setting startingTime of %d to %f.\n", firstJoint->children[i]->ID, tmpLatestTime);
426        firstJoint->children[i]->startingTime = tmpLatestTime;
427        firstJoint->children[i]->endTime = tmpLatestTime+firstJoint->children[i]->duration;
428      } 
429
430  // returning to the TrackElement we were working on.
431  this->workOn(tmpCurrentWorkingID);
432}
433
434/**
435   \brief finalizes the TrackSystem. after this it will not be editable anymore
436
437   \todo check for any inconsistencies, output errors
438*/
439void TrackManager::finalize(void)
440{
441  for (int i = 1; i<= trackElemCount ;i++)
442    {
443      TrackElement* tmpElem = findTrackElementByID(i);
444      if (tmpElem->childCount>0 && tmpElem->mainJoin)
445        {
446          for (int j = 0; j < tmpElem->childCount; j++)
447            {
448             
449              // c1-continuity
450              tmpElem->children[j]->curve->addNode(tmpElem->children[j]->curve->getNode(0) +
451                                                   ((tmpElem->children[j]->curve->getNode(0) - 
452                                                    tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-1))
453                                                    ),2);
454              tmpElem->children[j]->nodeCount++;
455              // c2-continuity
456              tmpElem->children[j]->curve->addNode((tmpElem->curve->getNode(tmpElem->curve->getNodeCount())-
457                                                    tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-1)) * 4 +
458                                                   tmpElem->curve->getNode(tmpElem->curve->getNodeCount()-2), 3);
459              tmpElem->children[j]->nodeCount++;                                                   
460              printf("accelerations: %d-in: count: %d, %f, %f, %f\n                  %d-out: count: %d %f, %f, %f\n",
461                     tmpElem->ID, tmpElem->nodeCount,
462                     tmpElem->curve->calcAcc(0.999).x, tmpElem->curve->calcAcc(0.999).y, tmpElem->curve->calcAcc(0.999).z,
463                     tmpElem->children[j]->ID, tmpElem->children[j]->nodeCount,
464                     tmpElem->children[j]->curve->calcAcc(0).x, tmpElem->children[j]->curve->calcAcc(0).y, tmpElem->children[j]->curve->calcAcc(0).z);
465            }
466        }
467    }
468}
469
470
471// RUNTIME //
472
473/**
474   \brief calculates the Position for the localTime of the Track.
475   \returns the calculated Position
476*/
477Vector TrackManager::calcPos() const
478{
479  //  PRINTF(0)("TrackElement:%d, localTime: %f\n",this->currentTrackElem->ID, this->localTime);
480  return this->currentTrackElem->curve->calcPos((this->localTime-this->currentTrackElem->startingTime)/this->currentTrackElem->duration);
481}
482
483/**
484   \brief calculates the Rotation for the localTime of the Track.
485   \returns the calculated Rotation
486*/
487Vector TrackManager::calcDir() const
488{
489  return this->currentTrackElem->curve->calcDir((this->localTime - this->currentTrackElem->startingTime)/this->currentTrackElem->duration);
490}
491
492/**
493   \brief Advances the local-time of the Track around dt
494   \param dt The time about which to advance.
495
496   This function also checks, if the TrackElement has to be changed.
497*/
498void TrackManager::tick(float dt)
499{
500  dt /= 1000;
501  printf("CurrentTrackID: %d, LocalTime is: %f, timestep is: %f\n", this->currentTrackElem->ID, this->localTime, dt);
502  if (this->localTime <= this->firstTrackElem->duration)
503    this->jumpTo(this->localTime);
504  this->localTime += dt;
505  if (this->localTime > this->currentTrackElem->endTime
506      && this->currentTrackElem->children)
507    {
508      if (this->currentTrackElem->jumpTime > 0) 
509        this->jumpTo(this->localTime + this->currentTrackElem->jumpTime);
510      this->currentTrackElem = this->currentTrackElem->children[0];
511    }
512  if (this->bindSlave)
513    {
514      Vector tmp = this->calcPos();
515      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)); 
516      this->bindSlave->setAbsCoor(&tmp);
517      this->bindSlave->setAbsDir(&quat);
518    }
519}
520
521/**
522   \brief Jumps to a certain point on the Track.
523   \param time The time on the Track to jump to.
524
525   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.)
526   Max is trackLengthMax.
527*/
528void TrackManager::jumpTo(float time)
529{
530  if (time == 0)
531    this->currentTrackElem = this->firstTrackElem;
532  this->localTime = time;
533}
534
535/**
536   \brief a Function that decides which Path we should follow.
537   \param graphID The Path to choose.
538   
539*/
540void TrackManager::choosePath(int graphID)
541{
542
543}
544
545/**
546   \brief Sets the PNode, that should be moved along the Tack
547   \param bindSlave the PNode to set
548*/
549void TrackManager::setBindSlave(PNode* bindSlave)
550{
551  if (!this->bindSlave)
552    this->bindSlave = bindSlave;
553}
554
555
556// DEBUG //
557
558/**
559   \brief Imports a model of the Graph into the OpenGL-environment.
560   \param dt The Iterator used in seconds for Painting the Graph.
561
562   This is for testing facility only. Do this if you want to see the Path inside the Level.
563   eventually this will all be packed into a gl-list.
564*/
565void TrackManager::drawGraph(float dt) const
566{
567
568  for (int i = 1; i <= trackElemCount; i++)
569    {
570      glBegin(GL_LINE_STRIP);
571      TrackElement* tmpElem = this->findTrackElementByID(i);
572      if (tmpElem->curve)
573        for(float f = 0.0; f < 1.0; f+=dt)
574          {
575            //      printf("%f, %f, %f\n",trackManager->calcPos().x, trackManager->calcPos().y, trackManager->calcPos().z);
576            Vector tmpVector = tmpElem->curve->calcPos(f);
577            glVertex3f(tmpVector.x, tmpVector.y, tmpVector.z);
578          }
579  glEnd();
580    }
581}
582
583/**
584   \brief outputs debug information about the trackManager
585   \param level how much debug
586*/
587void TrackManager::debug(unsigned int level) const
588{
589  printf("::CLASS TRACKMANAGER::debug information::\n");
590  //  printf("Status is: %
591  printf(" Consists of %d elements\n", this->trackElemCount);
592  printf(" localTime is: %f\n", this->localTime);
593  if (level >= 2)
594    {
595      for (int i = 1; i <= trackElemCount; i++)
596        {
597          TrackElement* tmpElem = this->findTrackElementByID(i);
598          printf("  ::TrackElement:%i::", tmpElem->ID);
599          if(tmpElem->name)
600            printf("name:%s::", tmpElem->name);
601          if(tmpElem->isFresh)
602            printf("   has not jet eddited in any way\n");
603          printf("\n   TimeTable: startingTime=%f; endTime=%f; duration=%f; jumpTime=%f\n", tmpElem->startingTime, tmpElem->endTime, tmpElem->duration, tmpElem->jumpTime);
604          printf("   consists of %d Points\n", tmpElem->nodeCount);
605          if (tmpElem->childCount == 0)
606            printf("   has no child\n");           
607          else if (tmpElem->childCount == 1)
608            printf("   has 1 child: ==%d==\n", tmpElem->children[0]->ID);
609          else if (tmpElem->childCount > 1)
610            {
611              printf("   has %d children: ", tmpElem->childCount);
612              for(int i = 0; i < tmpElem->childCount; i++)
613                printf("=%d= ", tmpElem->children[i]->ID);
614              printf("\n");
615            }
616
617          if(tmpElem->isHotPoint)
618            printf("   is a special Point:\n");
619          if(tmpElem->isSavePoint)
620            printf("    is a SavePoint\n");
621          if(tmpElem->isFork)
622            {
623              printf("    is A Fork with with %d children.\n", tmpElem->childCount);
624            }
625          if(tmpElem->isJoined)
626            printf("   is Joined at the End\n");
627        }
628    }
629}
Note: See TracBrowser for help on using the repository browser.