Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: using G_LIKELY() as Atilla suggested, seems only to work on linux, so its in ifdef

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