Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/lib/coord/p_node.cc @ 3800

Last change on this file since 3800 was 3800, checked in by patrick, 19 years ago

orxonox/trunk: defined macro for likely function, PNode now uses this branche prediction mechanism

File size: 16.3 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   \todo Smooth-Parent: delay, speed
18*/
19
20#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_PNODE
21
22#include "p_node.h"
23#include "stdincl.h"
24
25#include "error.h"
26#include "debug.h"
27#include "list.h"
28#include "vector.h"
29#include "null_parent.h"
30
31//#include "vector.h"
32//#include "quaternion.h"
33
34using namespace std;
35
36
37/**
38   \brief standard constructor
39
40   \todo this constructor is not jet implemented - do it
41*/
42PNode::PNode () 
43{
44  init(NULL);
45
46  NullParent* np = NullParent::getInstance();
47  np->addChild(this);
48}
49
50
51
52/**
53   \brief constructor with coodinates
54   \param absCoordinate the Absolute coordinate of the Object
55   \param parent The parent-node of this node.
56*/
57PNode::PNode (Vector* absCoordinate, PNode* parent )
58{
59  this->init(parent);
60
61  *this->absCoordinate = *absCoordinate;
62
63  __LIKELY_IF(parent != NULL)
64  {
65    *this->relCoordinate = *this->absCoordinate - parent->getAbsCoor ();
66    parent->addChild (this);
67  }
68  else 
69    this->relCoordinate = new Vector(0,0,0);
70}
71
72/**
73   \brief standard deconstructor
74
75   \todo this deconstructor is not jet implemented - do it
76*/
77PNode::~PNode () 
78{
79  /*
80  delete &this->children;
81  delete &this->relCoordinate;
82  delete &this->absCoordinate;
83  delete &this->relDirection;
84  delete &this->absDirection;
85  */
86  //this->parent = NULL;
87  /* there is currently a problem with cleaning up - fix*/
88
89  PNode* pn = this->children->enumerate();
90  while( pn != NULL) 
91    { 
92      delete pn;
93      pn = this->children->nextElement();
94
95    }
96   
97  /* this deletes all children in the list */
98  delete this->children;
99
100  delete []this->objectName;
101}
102
103
104void PNode::init(PNode* parent)
105{
106  this->children = new tList<PNode>();
107  this->bRelCoorChanged = true;
108  this->bAbsCoorChanged = false;
109  this->bRelDirChanged = true;
110  this->bAbsDirChanged = false;
111  this->parent = parent; 
112  this->objectName = NULL;
113
114  this->absCoordinate = new Vector();
115  this->relCoordinate = new Vector();
116  this->absDirection = new Quaternion();
117  this->relDirection = new Quaternion();
118  this->lastAbsCoordinate = new Vector();
119}
120
121/**
122   \brief deletes the hole pnode tree
123
124   cleans up all pnodes
125*/
126/*
127void PNode::destroy ()
128{
129  PNode* pn = this->children->enumerate();
130  while( pn != NULL)
131    {
132      pn->destroy ();
133      pn = this->children->nextElement();
134    }
135  // this deletes all children in the list
136  this->children->destroy ();
137
138  static_cast<BaseObject*>(this)->destroy();
139}
140*/
141
142/**
143   \brief get relative coordinates
144   \returns relative coordinates to its parent
145   
146   the reference that is returned is a pointer to the real relCoor, so don't
147   change it unless you realy know what you are doing.
148*/
149Vector* PNode::getRelCoor ()
150{
151  //Vector r = *this->relCoordinate; /* return a copy, so it can't be modified */
152  return this->relCoordinate;
153}
154
155
156/**
157   \brief set relative coordinates
158   \param relCoord relative coordinates to its parent
159
160   it is very importand, that you use this function, if you want to update the
161   relCoordinates. If you don't use this, the PNode won't recognize, that something
162   has changed and won't update the children Nodes.
163*/
164void PNode::setRelCoor (Vector* relCoord)
165{
166  this->bRelCoorChanged = true;
167  *this->relCoordinate = *relCoord;
168}
169
170
171/**
172   \brief set relative coordinates
173   \param relCoord relative coordinates to its parent
174
175   it is very importand, that you use this function, if you want to update the
176   relCoordinates. If you don't use this, the PNode won't recognize, that something
177   has changed and won't update the children Nodes.
178*/
179void PNode::setRelCoor (Vector relCoord)
180{
181  this->bRelCoorChanged = true;
182  *this->relCoordinate = relCoord;
183}
184
185
186/**
187   \brief get absolute coordinates
188   \returns absolute coordinates from (0,0,0)
189*/
190Vector PNode::getAbsCoor ()
191{
192  return *this->absCoordinate;
193}
194
195
196/**
197   \param absCoord set absolute coordinate
198
199   it is very importand, that you use this function, if you want to update the
200   absCoordinates. If you don't use this, the PNode won't recognize, that something
201   has changed and won't update the children Nodes.
202*/
203void PNode::setAbsCoor (Vector* absCoord)
204{
205  this->bAbsCoorChanged = true;
206  *this->absCoordinate = *absCoord;
207}
208
209
210
211/**
212   \param absCoord set absolute coordinate
213
214   it is very importand, that you use this function, if you want to update the
215   absCoordinates. If you don't use this, the PNode won't recognize, that something
216   has changed and won't update the children Nodes.
217*/
218void PNode::setAbsCoor (Vector absCoord)
219{
220  this->bAbsCoorChanged = true;
221  *this->absCoordinate = absCoord;
222}
223
224
225/**
226   \brief shift coordinate (abs and rel)
227   \param shift vector
228
229   this function shifts the current coordinates about the vector shift. this is
230   usefull because from some place else you can:
231   PNode* someNode = ...;
232   Vector objectMovement = calculateShift();
233   someNode->shiftCoor(objectMovement);
234
235   elsewhere you would have to:
236   PNode* someNode = ...;
237   Vector objectMovement = calculateShift();
238   Vector currentCoor = someNode->getRelCoor();
239   Vector newCoor = currentCoor + objectMovement;
240   someNode->setRelCoor(newCoor);
241   
242   yea right... shorter...
243
244*/
245void PNode::shiftCoor (Vector* shift)
246{
247
248  __UNLIKELY_IF( this->bAbsCoorChanged)
249    {
250      *this->absCoordinate = *this->absCoordinate + *shift;
251    }
252  else 
253    {
254      *this->relCoordinate = *this->relCoordinate + *shift;
255      this->bRelCoorChanged = true;
256    }
257}
258
259
260
261/**
262   \brief shift coordinate (abs and rel)
263   \param shift vector
264
265   this function shifts the current coordinates about the vector shift. this is
266   usefull because from some place else you can:
267   PNode* someNode = ...;
268   Vector objectMovement = calculateShift();
269   someNode->shiftCoor(objectMovement);
270
271   elsewhere you would have to:
272   PNode* someNode = ...;
273   Vector objectMovement = calculateShift();
274   Vector currentCoor = someNode->getRelCoor();
275   Vector newCoor = currentCoor + objectMovement;
276   someNode->setRelCoor(newCoor);
277   
278   yea right... shorter...
279
280*/
281void PNode::shiftCoor (Vector shift)
282{
283
284  __UNLIKELY_IF( this->bAbsCoorChanged)
285    {
286      *this->absCoordinate = *this->absCoordinate + shift;
287    }
288  else 
289    {
290      *this->relCoordinate = *this->relCoordinate + shift;
291      this->bRelCoorChanged = true;
292    }
293}
294
295
296
297/**
298   \brief get relative direction
299   \returns relative direction to its parent
300*/
301Quaternion PNode::getRelDir ()
302{
303  return *this->relDirection;
304}
305
306
307/**
308   \brief set relative direction
309   \param relDir to its parent
310
311   it is very importand, that you use this function, if you want to update the
312   relDirection. If you don't use this, the PNode won't recognize, that something
313   has changed and won't update the children Nodes.
314*/
315void PNode::setRelDir (Quaternion* relDir)
316{
317  this->bRelCoorChanged = true;
318  *this->relDirection = *relDir;
319}
320
321
322void PNode::setRelDir (Quaternion relDir)
323{
324  this->bRelCoorChanged = true;
325  *this->relDirection = relDir;
326}
327
328
329/**
330   \brief gets the absolute direction (0,0,1)
331   \returns absolute coordinates
332*/
333Quaternion PNode::getAbsDir ()
334{
335  return *this->absDirection;
336}
337
338
339/**
340   \brief sets the absolute direction (0,0,1)
341   \param absDir absolute coordinates
342
343   it is very importand, that you use this function, if you want to update the
344   absDirection. If you don't use this, the PNode won't recognize, that something
345   has changed and won't update the children Nodes.
346*/
347void PNode::setAbsDir (Quaternion* absDir)
348{
349  this->bAbsDirChanged = true;
350  *this->absDirection = *absDir;
351}
352
353
354
355/**
356   \brief sets the absolute direction (0,0,1)
357   \param absDir absolute coordinates
358
359   it is very importand, that you use this function, if you want to update the
360   absDirection. If you don't use this, the PNode won't recognize, that something
361   has changed and won't update the children Nodes.
362*/
363void PNode::setAbsDir (Quaternion absDir)
364{
365  this->bAbsDirChanged = true;
366  *this->absDirection = absDir;
367}
368
369
370
371/**
372   \brief shift coordinate (abs and rel)
373   \param shift vector
374
375   this function shifts the current coordinates about the vector shift. this is
376   usefull because from some place else you can:
377   PNode* someNode = ...;
378   Quaternion objectMovement = calculateShift();
379   someNode->shiftCoor(objectMovement);
380
381   elsewhere you would have to:
382   PNode* someNode = ...;
383   Quaternion objectMovement = calculateShift();
384   Quaternion currentCoor = someNode->getRelCoor();
385   Quaternion newCoor = currentCoor + objectMovement;
386   someNode->setRelCoor(newCoor);
387   
388   yea right... shorter...
389
390   \todo implement this
391*/
392void PNode::shiftDir (Quaternion* shift)
393{}
394
395
396/**
397   \brief shift coordinate (abs and rel)
398   \param shift vector
399
400   this function shifts the current coordinates about the vector shift. this is
401   usefull because from some place else you can:
402   PNode* someNode = ...;
403   Quaternion objectMovement = calculateShift();
404   someNode->shiftCoor(objectMovement);
405
406   elsewhere you would have to:
407   PNode* someNode = ...;
408   Quaternion objectMovement = calculateShift();
409   Quaternion currentCoor = someNode->getRelCoor();
410   Quaternion newCoor = currentCoor + objectMovement;
411   someNode->setRelCoor(newCoor);
412   
413   yea right... shorter...
414
415   \todo implement this
416*/
417void PNode::shiftDir (Quaternion shift)
418{}
419
420
421/**
422   \brief this calculates the current movement speed of the node
423*/
424float PNode::getSpeed()
425{
426  __UNLIKELY_IF( this->time == 0)
427    return 1000;
428  Vector diff;
429  diff = *this->absCoordinate - *this->lastAbsCoordinate;
430  float x = diff.len();
431  return x / this->time;
432}
433
434
435/**
436   \brief adds a child and makes this node to a parent
437   \param pNode child reference
438
439   use this to add a child to this node.
440*/
441void PNode::addChild (PNode* pNode)
442{
443  this->addChild(pNode, DEFAULT_MODE);
444}
445
446
447/**
448   \brief adds a child and makes this node to a parent
449   \param pNode child reference
450   \param mode on which changes the child should also change ist state
451
452   use this to add a child to this node.
453*/
454void PNode::addChild (PNode* pNode, int parentingMode)
455{
456
457  __UNLIKELY_IF( pNode->parent != NULL)
458    {
459      PRINTF(3)("PNode::addChild() - reparenting node: removing it and adding it again\n");
460      pNode->parent->children->remove(pNode);
461    }
462  pNode->mode = parentingMode;
463  pNode->parent = this;
464  this->children->add(pNode);
465}
466
467
468/**
469   \brief removes a child from the node
470   \param pNode the child to remove from this pNode.
471
472   Children from pNode will not be lost, they are referenced to NullPointer
473*/
474void PNode::removeChild (PNode* pNode)
475{
476  pNode->remove();
477  this->children->remove (pNode);
478  pNode->parent = NULL;
479}
480
481
482/**
483   \brief remove this pnode from the tree and adds all following to NullParent
484
485   this can be the case, if an entity in the world is been destroyed.
486*/
487void PNode::remove()
488{
489  NullParent* nullParent = NullParent::getInstance();
490
491  tIterator<PNode>* iterator = this->children->getIterator();
492  PNode* pn = iterator->nextElement();
493 
494  while( pn != NULL) 
495    { 
496      //this->children->remove(pn);
497      nullParent->addChild(pn, pn->getMode());
498      pn = iterator->nextElement();
499    }
500  delete iterator;
501  this->parent->children->remove(this);
502}
503
504
505/**
506   \brief sets the parent of this PNode
507   \param parent the Parent to set
508*/
509void PNode::setParent (PNode* parent)
510{
511  parent->addChild(this);
512}
513
514
515/**
516   \brief set the mode of this parent manualy
517   \param mode the mode of the bind-type.
518*/
519void PNode::setMode (int parentingMode)
520{
521  this->mode = parentingMode;
522}
523
524
525/**
526   \brief gets the mode of this parent manualy
527   \return the mode of the bind-type.
528*/
529int PNode::getMode()
530{
531  return this->mode;
532}
533
534/**
535   \brief has to be called, if the parent coordinate has changed
536   
537   normaly this will be done by the parent itself automaticaly. If you call this, you
538   will force an update of the coordinated of the node.
539*/
540void PNode::parentCoorChanged ()
541{
542  this->bRelCoorChanged = true;
543}
544
545
546/**
547   \brief has to be called, if the parent direction has changed
548   
549   normaly this will be done by the parent itself automaticaly. If you call this, you
550   will force an update of the direction of the node.
551*/
552void PNode::parentDirChanged ()
553{
554  this->bRelDirChanged = true;
555}
556
557
558/**
559   \brief updates the absCoordinate/absDirection
560   \param timeStamp The timestanp used for to look if calculations should be done
561
562   this is used to go through the parent-tree to update all the absolute coordinates
563   and directions. this update should be done by the engine, so you don't have to
564   worry, normaly...
565*/
566void PNode::update (float dt)
567{
568  *this->lastAbsCoordinate = *this->absCoordinate;
569  this->time = dt;
570  PRINTF(4)("PNode::update - %s - (%f, %f, %f)\n", this->objectName, this->absCoordinate->x, this->absCoordinate->y, this->absCoordinate->z);
571
572
573  __LIKELY_IF( this->mode & PNODE_MOVEMENT)
574    {
575      __UNLIKELY_IF(this->bAbsCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
576        {
577          /* if you have set the absolute coordinates this overrides all other changes */
578          *this->relCoordinate = *this->absCoordinate - parent->getAbsCoor ();
579        }
580      __LIKELY_IF(this->bRelCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
581
582        {
583          /*this is bad style... must be deleted later - just for testing*/
584
585          /*
586          __UNLIKELY_IF( this->parent == NULL)
587            {
588              *this->absCoordinate = *this->relCoordinate;
589            }
590            else */
591          *this->absCoordinate = parent->getAbsCoor() + *this->relCoordinate;         /* update the current absCoordinate */
592        }
593    }
594 
595  if( this->mode & PNODE_LOCAL_ROTATE)
596    {
597      __UNLIKELY_IF( this->bAbsDirChanged /*&& this->timeStamp != DataTank::timeStamp*/)
598        {
599          /* if you have set the absolute coordinates this overrides all other changes */
600          *this->relDirection = *this->absDirection - parent->getAbsDir();
601        }
602      else __LIKELY_IF( this->bRelDirChanged /*&& this->timeStamp != DataTank::timeStamp*/)
603        {
604          /* update the current absDirection - remember * means rotation around sth.*/
605          *this->absDirection = parent->getAbsDir() * *this->relDirection;
606        }
607    }
608 
609  if( this->mode & PNODE_ROTATE_MOVEMENT)
610    {
611      __UNLIKELY_IF( this->bAbsCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
612        {
613          /* if you have set the absolute coordinates this overrides all other changes */
614          *this->relCoordinate = *this->absCoordinate - parent->getAbsCoor ();
615        }
616      else __LIKELY_IF( this->bRelCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
617        {
618          /*this is bad style... must be deleted later - just for testing*/
619          /*if( this->parent == NULL)
620            *this->absCoordinate = *this->relCoordinate;
621            else*/
622          *this->absCoordinate = parent->getAbsCoor() + parent->getAbsDir().apply(*this->relCoordinate);              /* update the current absCoordinate */
623        }
624    }
625 
626 
627  tIterator<PNode>* iterator = this->children->getIterator();
628  //PNode* pn = this->children->enumerate();
629  PNode* pn = iterator->nextElement();
630  while( pn != NULL) 
631    { 
632      /* if this node has changed, make sure, that all children are updated also */
633      __LIKELY_IF( this->bRelCoorChanged || this->bAbsCoorChanged)
634        pn->parentCoorChanged ();
635      __LIKELY_IF( this->bRelDirChanged || this->bAbsDirChanged)
636        pn->parentDirChanged ();
637
638      pn->update(dt);
639      //pn = this->children->nextElement();
640      pn = iterator->nextElement();
641    }
642  delete iterator;
643
644  this->timeStamp = timeStamp;
645  this->bRelCoorChanged = false;
646  this->bAbsCoorChanged = false;
647  this->bRelDirChanged = false;
648  this->bAbsDirChanged = false;
649}
650
651
652/**
653  \brief tick
654  \param dt time to tick
655*/
656void PNode::processTick (float dt)
657{
658  //this->tick (dt);
659  PNode* pn = this->children->enumerate();
660  while( pn != NULL) 
661    { 
662      pn->processTick (dt);
663      pn = this->children->nextElement();
664    } 
665}
666
667
668/**
669   \brief displays some information about this pNode
670*/
671void PNode::debug()
672{
673  PRINTF(2)("PNode::debug() - absCoord: (%f, %f, %f)\n", 
674         this->absCoordinate->x, 
675         this->absCoordinate->y,
676         this->absCoordinate->z);
677}
678
679
680/**
681  \brief set the name of the node
682
683  for debug purposes realy usefull, not used to work properly
684*/
685void PNode::setName (char* newName)
686{
687  this->objectName = new char[strlen(newName)+1];
688  strcpy(this->objectName,newName);
689}
690
691
692/**
693  \brief gets the name of the node
694*/
695char* PNode::getName ()
696{
697  return this->objectName;
698}
699
Note: See TracBrowser for help on using the repository browser.