Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: softPNode finished for Movement only

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