Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: PNode loading complete

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