Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: some more performance tweaks on PNode: making arguments const, functions also if possible. regrouping code to speedup perfomance

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