Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3860 was 3860, checked in by bensch, 19 years ago

orxonox/trunk: moved likely to compiler.h in defs
also reset all the UNLIKELY_IF functions to how they should look.

the old approach is still valid, but depricated.

@patrick: i hope this is ok for you, for it is LINUX-standard.
and i think windows is also able to handle likely/unlikely because it is a compiler issue not a system issue

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