Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: error in loading of PNode fixed, and the Framework starts again, (also loads the settings of the GraphicsEngine)

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