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
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*/
75PNode::~PNode () 
76{
77  tIterator<PNode>* iterator = this->children->getIterator();
78  PNode* pn = iterator->nextElement();
79  while( pn != NULL) 
80    { 
81      delete pn;
82      pn = iterator->nextElement();
83    }
84  delete iterator;
85  /* this deletes all children in the list */
86  delete this->children;
87  this->parent = NULL;
88  delete []this->objectName;
89
90  delete this->relCoordinate;
91  delete this->absCoordinate;
92  delete this->relDirection;
93  delete this->absDirection;
94  delete this->lastAbsCoordinate;
95  delete this->diffCoordinate;
96}
97
98
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;
108
109  this->absCoordinate = new Vector();
110  this->relCoordinate = new Vector();
111  this->absDirection = new Quaternion();
112  this->relDirection = new Quaternion();
113  this->lastAbsCoordinate = new Vector();
114  this->diffCoordinate = new Vector();
115}
116
117/**
118   \brief deletes the hole pnode tree
119
120   cleans up all pnodes
121*/
122/*
123void PNode::destroy ()
124{
125  PNode* pn = this->children->enumerate();
126  while( pn != NULL)
127    {
128      pn->destroy ();
129      pn = this->children->nextElement();
130    }
131  // this deletes all children in the list
132  this->children->destroy ();
133
134  static_cast<BaseObject*>(this)->destroy();
135}
136*/
137
138/**
139   \brief get relative coordinates
140   \returns relative coordinates to its parent
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.
144*/
145//Vector* PNode::getRelCoor () const
146
147
148
149/**
150   \brief set relative coordinates
151   \param relCoord relative coordinates to its parent
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;
160  *this->relCoordinate = *relCoord;
161}
162
163
164/**
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/**
180   \brief get absolute coordinates
181   \returns absolute coordinates from (0,0,0)
182*/
183//Vector PNode::getAbsCoor () const
184
185
186/**
187   \param absCoord set absolute coordinate
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;
196  *this->absCoordinate = *absCoord;
197}
198
199
200
201/**
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/**
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{
237
238  __UNLIKELY_IF( this->bAbsCoorChanged)
239    {
240      *this->absCoordinate = *this->absCoordinate + *shift;
241    }
242  else 
243    {
244      *this->relCoordinate = *this->relCoordinate + *shift;
245      this->bRelCoorChanged = true;
246    }
247}
248
249
250
251/**
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{
273
274  __UNLIKELY_IF( this->bAbsCoorChanged)
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/**
288   \brief get relative direction
289   \returns relative direction to its parent
290*/
291//Quaternion* PNode::getRelDir () const
292
293
294
295/**
296   \brief set relative direction
297   \param relDir to its parent
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;
306  *this->relDirection = *relDir;
307}
308
309
310void PNode::setRelDir (Quaternion relDir)
311{
312  this->bRelCoorChanged = true;
313  *this->relDirection = relDir;
314}
315
316
317/**
318   \brief gets the absolute direction (0,0,1)
319   \returns absolute coordinates
320*/
321//Quaternion PNode::getAbsDir () const
322
323
324
325/**
326   \brief sets the absolute direction (0,0,1)
327   \param absDir absolute coordinates
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)
334{
335  this->bAbsDirChanged = true;
336  *this->absDirection = *absDir;
337}
338
339
340
341/**
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/**
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
376   \todo implement this
377*/
378void PNode::shiftDir (const Quaternion& shift)
379{
380  this->bRelDirChanged = true;
381  *this->relDirection = *this->relDirection * shift;
382}
383
384
385/**
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/**
411   \brief this calculates the current movement speed of the node
412*/
413float PNode::getSpeed() const
414{
415  __UNLIKELY_IF( this->time == 0)
416    return 1000;
417  *this->diffCoordinate = *this->absCoordinate - *this->lastAbsCoordinate;
418  return this->diffCoordinate->len() / this->time;
419}
420
421
422/**
423   \brief adds a child and makes this node to a parent
424   \param pNode child reference
425   \param mode on which changes the child should also change ist state
426
427   use this to add a child to this node.
428*/
429void PNode::addChild (PNode* pNode, int parentingMode)
430{
431
432  __UNLIKELY_IF( pNode->parent != NULL)
433    {
434      PRINTF(3)("PNode::addChild() - reparenting node: removing it and adding it again\n");
435      pNode->parent->children->remove(pNode);
436    }
437  pNode->mode = parentingMode;
438  pNode->parent = this;
439  this->children->add(pNode);
440}
441
442
443/**
444   \brief removes a child from the node
445   \param pNode the child to remove from this pNode.
446
447   Children from pNode will not be lost, they are referenced to NullPointer
448*/
449void PNode::removeChild (PNode* pNode)
450{
451  pNode->remove();
452  this->children->remove (pNode);
453  pNode->parent = NULL;
454}
455
456
457/**
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{
464  NullParent* nullParent = NullParent::getInstance();
465
466  tIterator<PNode>* iterator = this->children->getIterator();
467  PNode* pn = iterator->nextElement();
468 
469  while( pn != NULL) 
470    { 
471      //this->children->remove(pn);
472      nullParent->addChild(pn, pn->getMode());
473      pn = iterator->nextElement();
474    }
475  delete iterator;
476  this->parent->children->remove(this);
477}
478
479
480/**
481   \brief sets the parent of this PNode
482   \param parent the Parent to set
483*/
484void PNode::setParent (PNode* parent)
485{
486  parent->addChild(this);
487}
488
489
490/**
491   \brief set the mode of this parent manualy
492   \param mode the mode of the bind-type.
493*/
494void PNode::setMode (int parentingMode)
495{
496  this->mode = parentingMode;
497}
498
499
500/**
501   \brief gets the mode of this parent manualy
502   \return the mode of the bind-type.
503*/
504int PNode::getMode()
505{
506  return this->mode;
507}
508
509/**
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
535   \param timeStamp The timestanp used for to look if calculations should be done
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*/
541void PNode::update (float dt)
542{
543  *this->lastAbsCoordinate = *this->absCoordinate;
544  this->time = dt;
545  PRINTF(4)("PNode::update - %s - (%f, %f, %f)\n", this->objectName, this->absCoordinate->x, this->absCoordinate->y, this->absCoordinate->z);
546
547
548  __LIKELY_IF( this->mode & PNODE_MOVEMENT)
549    {
550      __UNLIKELY_IF(this->bAbsCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
551        {
552          /* if you have set the absolute coordinates this overrides all other changes */
553          *this->relCoordinate = *this->absCoordinate - parent->getAbsCoor ();
554        }
555      __LIKELY_IF(this->bRelCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
556
557        {
558          /*this is bad style... must be deleted later - just for testing*/
559
560          /*
561          __UNLIKELY_IF( this->parent == NULL)
562            {
563              *this->absCoordinate = *this->relCoordinate;
564            }
565            else */
566          *this->absCoordinate = parent->getAbsCoor() + *this->relCoordinate;         /* update the current absCoordinate */
567        }
568    }
569 
570  if( this->mode & PNODE_LOCAL_ROTATE)
571    {
572      __UNLIKELY_IF( this->bAbsDirChanged /*&& this->timeStamp != DataTank::timeStamp*/)
573        {
574          /* if you have set the absolute coordinates this overrides all other changes */
575          *this->relDirection = *this->absDirection - parent->getAbsDir();
576        }
577      else __LIKELY_IF( this->bRelDirChanged /*&& this->timeStamp != DataTank::timeStamp*/)
578        {
579          /* update the current absDirection - remember * means rotation around sth.*/
580          *this->absDirection = parent->getAbsDir() * *this->relDirection;
581        }
582    }
583 
584  if( this->mode & PNODE_ROTATE_MOVEMENT)
585    {
586      __UNLIKELY_IF( this->bAbsCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
587        {
588          /* if you have set the absolute coordinates this overrides all other changes */
589          *this->relCoordinate = *this->absCoordinate - parent->getAbsCoor ();
590        }
591      else __LIKELY_IF( this->bRelCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
592        {
593          /*this is bad style... must be deleted later - just for testing*/
594          /*if( this->parent == NULL)
595            *this->absCoordinate = *this->relCoordinate;
596            else*/
597          *this->absCoordinate = parent->getAbsCoor() + parent->getAbsDir().apply(*this->relCoordinate);              /* update the current absCoordinate */
598        }
599    }
600 
601 
602  tIterator<PNode>* iterator = this->children->getIterator();
603  //PNode* pn = this->children->enumerate();
604  PNode* pn = iterator->nextElement();
605  while( pn != NULL) 
606    { 
607      /* if this node has changed, make sure, that all children are updated also */
608      __LIKELY_IF( this->bRelCoorChanged || this->bAbsCoorChanged)
609        pn->parentCoorChanged ();
610      __LIKELY_IF( this->bRelDirChanged || this->bAbsDirChanged)
611        pn->parentDirChanged ();
612
613      pn->update(dt);
614      //pn = this->children->nextElement();
615      pn = iterator->nextElement();
616    }
617  delete iterator;
618
619  this->timeStamp = timeStamp;
620  this->bRelCoorChanged = false;
621  this->bAbsCoorChanged = false;
622  this->bRelDirChanged = false;
623  this->bAbsDirChanged = false;
624}
625
626
627/**
628  \brief tick
629  \param dt time to tick
630*/
631void PNode::processTick (float dt)
632{
633  //this->tick (dt);
634  PNode* pn = this->children->enumerate();
635  while( pn != NULL) 
636    { 
637      pn->processTick (dt);
638      pn = this->children->nextElement();
639    } 
640}
641
642
643/**
644   \brief displays some information about this pNode
645*/
646void PNode::debug()
647{
648  PRINTF(2)("PNode::debug() - absCoord: (%f, %f, %f)\n", 
649         this->absCoordinate->x, 
650         this->absCoordinate->y,
651         this->absCoordinate->z);
652}
653
654
655/**
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{
662  this->objectName = new char[strlen(newName)+1];
663  strcpy(this->objectName,newName);
664}
665
666
667/**
668  \brief gets the name of the node
669*/
670char* PNode::getName ()
671{
672  return this->objectName;
673}
674
Note: See TracBrowser for help on using the repository browser.