Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: performance tweaking on PNode continiued: inlined all interface functions that are processed often (>100'000 times per game of 7sec.)

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