Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 4761 was 4761, checked in by bensch, 20 years ago

orxonox/trunk: Global identifiers and PNode-parenting via LoadParam works

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