Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: minor design-update

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