Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: BaseObject now only knows setClassID → standartisation

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