Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: introducing smooth-PNode

File size: 18.9 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  this->toPosition->debug();
191  printf("=-==============\n");
192}
193
194/**
195 * @param absCoord set absolute coordinate
196
197   it is very importand, that you use this function, if you want to update the
198   absCoordinates. If you don't use this, the PNode won't recognize, that something
199   has changed and won't update the children Nodes.
200*/
201void PNode::setAbsCoor (const Vector& absCoord)
202{
203  this->bAbsCoorChanged = true;
204  this->absCoordinate = absCoord;
205}
206
207/**
208 * @param x x-coordinate.
209 * @param y y-coordinate.
210 * @param z z-coordinate.
211 * @see void PNode::setAbsCoor (const Vector& absCoord)
212 */
213void PNode::setAbsCoor(float x, float y, float z)
214{
215  this->setAbsCoor(Vector(x, y, z));
216}
217
218/**
219 *  shift coordinate (abs and rel)
220 * @param shift shift vector
221
222   this function shifts the current coordinates about the vector shift. this is
223   usefull because from some place else you can:
224   PNode* someNode = ...;
225   Vector objectMovement = calculateShift();
226   someNode->shiftCoor(objectMovement);
227
228   elsewhere you would have to:
229   PNode* someNode = ...;
230   Vector objectMovement = calculateShift();
231   Vector currentCoor = someNode->getRelCoor();
232   Vector newCoor = currentCoor + objectMovement;
233   someNode->setRelCoor(newCoor);
234
235   yea right... shorter...
236 *
237 * @todo this is ambiguous, from the outside one does not know it absCoor has been changed
238 * this might lead to strange artefacts !!
239
240*/
241void PNode::shiftCoor (const Vector& shift)
242{
243
244  if( unlikely(this->bAbsCoorChanged))
245    {
246      this->absCoordinate += shift;
247    }
248  else
249    {
250      this->relCoordinate += shift;
251      this->bRelCoorChanged = true;
252    }
253}
254
255/**
256 *  set relative direction
257 * @param relDir to its parent
258
259   it is very importand, that you use this function, if you want to update the
260   relDirection. If you don't use this, the PNode won't recognize, that something
261   has changed and won't update the children Nodes.
262*/
263void PNode::setRelDir (const Quaternion& relDir)
264{
265  this->bRelCoorChanged = true;
266  this->relDirection = relDir;
267}
268
269/**
270 * @see void PNode::setRelDir (const Quaternion& relDir)
271 * @param x the x direction
272 * @param y the y direction
273 * @param z the z direction
274 *
275 * main difference is, that here you give a directional vector, that will be translated into a Quaternion
276 */
277void PNode::setRelDir (float x, float y, float z)
278{
279  this->setRelDir(Quaternion(Vector(x,y,z), Vector(0,1,0)));
280}
281
282/**
283 *  sets the absolute direction (0,0,1)
284 * @param absDir absolute coordinates
285
286   it is very importand, that you use this function, if you want to update the
287   absDirection. If you don't use this, the PNode won't recognize, that something
288   has changed and won't update the children Nodes.
289*/
290void PNode::setAbsDir (const Quaternion& absDir)
291{
292  this->bAbsDirChanged = true;
293  this->absDirection = absDir;
294}
295
296/**
297 * @see void PNode::setAbsDir (const Quaternion& relDir)
298 * @param x the x direction
299 * @param y the y direction
300 * @param z the z direction
301 *
302 * main difference is, that here you give a directional vector, that will be translated into a Quaternion
303 */
304void PNode::setAbsDir (float x, float y, float z)
305{
306  this->setAbsDir(Quaternion(Vector(x,y,z), Vector(0,1,0)));
307}
308
309/**
310 *  shift coordinate (abs and rel)
311 * @param shift vector
312
313   this function shifts the current coordinates about the vector shift. this is
314   usefull because from some place else you can:
315   PNode* someNode = ...;
316   Quaternion objectMovement = calculateShift();
317   someNode->shiftCoor(objectMovement);
318
319   elsewhere you would have to:
320   PNode* someNode = ...;
321   Quaternion objectMovement = calculateShift();
322   Quaternion currentCoor = someNode->getRelCoor();
323   Quaternion newCoor = currentCoor + objectMovement;
324   someNode->setRelCoor(newCoor);
325
326   yea right... shorter...
327
328   @todo implement this
329*/
330void PNode::shiftDir (const Quaternion& shift)
331{
332  this->bRelDirChanged = true;
333  this->relDirection = this->relDirection * shift;
334}
335
336/**
337 *  adds a child and makes this node to a parent
338 * @param pNode child reference
339 * @param parentMode on which changes the child should also change ist state
340
341   use this to add a child to this node.
342*/
343void PNode::addChild (PNode* pNode, int parentMode)
344{
345  if( likely(pNode->parent != NULL))
346    {
347      PRINTF(3)("PNode::addChild() - reparenting node: removing it and adding it again\n");
348      pNode->parent->children->remove(pNode);
349    }
350  pNode->parentMode = parentMode;
351  pNode->parent = this;
352  this->children->add(pNode);
353}
354
355/**
356 * @see PNode::addChild(PNode* parent);
357 * @param childName the name of the child to add to this PNode
358 */
359void PNode::addChild (const char* childName)
360{
361  PNode* childNode = dynamic_cast<PNode*>(ClassList::getObject(childName, CL_PARENT_NODE));
362  if (childNode != NULL)
363    this->addChild(childNode);
364}
365
366
367/**
368 *  removes a child from the node
369 * @param pNode the child to remove from this pNode.
370
371   Children from pNode will not be lost, they are referenced to NullPointer
372*/
373void PNode::removeChild (PNode* pNode)
374{
375  pNode->remove();
376  this->children->remove (pNode);
377  pNode->parent = NULL;
378}
379
380
381/**
382 *  remove this pnode from the tree and adds all following to NullParent
383
384   this can be the case, if an entity in the world is been destroyed.
385*/
386void PNode::remove()
387{
388  NullParent* nullParent = NullParent::getInstance();
389
390  tIterator<PNode>* iterator = this->children->getIterator();
391  PNode* pn = iterator->nextElement();
392
393  while( pn != NULL)
394    {
395      nullParent->addChild(pn, pn->getParentMode());
396      pn = iterator->nextElement();
397    }
398  delete iterator;
399  this->parent->children->remove(this);
400}
401
402
403/**
404 *  sets the parent of this PNode
405 * @param parent the Parent to set
406*/
407void PNode::setParent (PNode* parent)
408{
409  parent->addChild(this);
410}
411
412/**
413 * @see PNode::setParent(PNode* parent);
414 * @param parentName the name of the Parent to set to this PNode
415 */
416void PNode::setParent (const char* parentName)
417{
418  PNode* parentNode = dynamic_cast<PNode*>(ClassList::getObject(parentName, CL_PARENT_NODE));
419  if (parentNode != NULL)
420    parentNode->addChild(this);
421}
422
423void PNode::softReparent(PNode* parentNode)
424{
425  if (likely(this->toPosition == NULL))
426    this->toPosition = new Vector();
427
428  *this->toPosition = parentNode->getAbsCoor() + this->getRelCoor();
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
497
498  if( likely(this->parent != NULL))
499    {
500      // movement for nodes with smoothMove enabled
501      if (unlikely(this->toPosition != NULL))
502      {
503        Vector moveVect = (*this->toPosition - this->getRelCoor()) *dt;
504
505        if (likely(moveVect.len() >= .001))
506        {
507          this->shiftCoor(moveVect);
508          moveVect.debug();
509        }
510        else
511        {
512          delete this->toPosition;
513          this->toPosition = NULL;
514          PRINTF(0)("SmoothMove of %s finished\n", this->getName());
515        }
516      }
517
518      this->lastAbsCoordinate = this->absCoordinate;
519
520      PRINTF(5)("PNode::update - %s - (%f, %f, %f)\n", this->getName(), this->absCoordinate.x, this->absCoordinate.y, this->absCoordinate.z);
521
522      if( likely(this->parentMode & PNODE_MOVEMENT))
523        {
524          if( unlikely(this->bAbsCoorChanged))
525            {
526              /* if you have set the absolute coordinates this overrides all other changes */
527              this->relCoordinate = this->absCoordinate - parent->getAbsCoor ();
528            }
529          if( likely(this->bRelCoorChanged))
530            {
531              /* update the current absCoordinate */
532              this->absCoordinate = parent->getAbsCoor() + this->relCoordinate;
533            }
534        }
535
536      if( this->parentMode & PNODE_LOCAL_ROTATE)
537        {
538          if( unlikely(this->bAbsDirChanged))
539            {
540              /* if you have set the absolute coordinates this overrides all other changes */
541              this->relDirection = this->absDirection - parent->getAbsDir();
542            }
543          else if( likely(this->bRelDirChanged))
544            {
545              /* update the current absDirection - remember * means rotation around sth.*/
546              this->absDirection = parent->getAbsDir() * this->relDirection;
547            }
548        }
549
550      if( this->parentMode & PNODE_ROTATE_MOVEMENT)
551        {
552          if( unlikely(this->bAbsCoorChanged))
553            {
554              /* if you have set the absolute coordinates this overrides all other changes */
555              this->relCoordinate = this->absCoordinate - parent->getAbsCoor ();
556            }
557          else if( likely(this->bRelCoorChanged))
558            {
559              /* update the current absCoordinate */
560              this->absCoordinate = parent->getAbsCoor() + parent->getAbsDir().apply(this->relCoordinate);
561            }
562        }
563
564
565      tIterator<PNode>* iterator = this->children->getIterator();
566      PNode* pn = iterator->nextElement();
567      while( pn != NULL)
568        {
569          /* if this node has changed, make sure, that all children are updated also */
570          if( likely(this->bRelCoorChanged || this->bAbsCoorChanged))
571            pn->parentCoorChanged ();
572          if( likely(this->bRelDirChanged || this->bAbsDirChanged))
573            pn->parentDirChanged ();
574
575          pn->update(dt);
576          //pn = this->children->nextElement();
577          pn = iterator->nextElement();
578        }
579      delete iterator;
580
581      this->velocity = (this->absCoordinate - this->lastAbsCoordinate) / dt;
582      this->bRelCoorChanged = false;
583      this->bAbsCoorChanged = false;
584      this->bRelDirChanged = false;
585      this->bAbsDirChanged = false;
586    }
587  else
588    {
589      PRINTF(4)("NullParent::update - (%f, %f, %f)\n", this->absCoordinate.x, this->absCoordinate.y, this->absCoordinate.z);
590      this->absCoordinate = this->relCoordinate;
591      this->absDirection = this->getAbsDir () * this->relDirection;
592
593      tIterator<PNode>* iterator = this->children->getIterator();
594      //PNode* pn = this->children->enumerate ();
595      PNode* pn = iterator->nextElement();
596      while( pn != NULL)
597      {
598        /* if this node has changed, make sure, that all children are updated also */
599          if( this->bRelCoorChanged || this->bAbsCoorChanged)
600            pn->parentCoorChanged ();
601          if( this->bRelDirChanged || this->bAbsDirChanged)
602            pn->parentDirChanged ();
603          pn->update (dt);
604          //pn = this->children->nextElement ();
605          pn = iterator->nextElement();
606        }
607      delete iterator;
608      this->bRelCoorChanged = false;
609      this->bAbsCoorChanged = false;
610      this->bRelDirChanged = false;
611      this->bAbsDirChanged = false;
612    }
613}
614
615/**
616 *  displays some information about this pNode
617 * @param depth The deph into which to debug the children of this PNode to.
618  (0: all children will be debugged, 1: only this PNode, 2: this and direct children...)
619 * @param level The n-th level of the Node we draw (this is internal and only for nice output)
620*/
621void PNode::debug(unsigned int depth, unsigned int level) const
622{
623  for (unsigned int i = 0; i < level; i++)
624    PRINT(0)(" |");
625  if (this->children->getSize() > 0)
626    PRINT(0)(" +");
627  else
628    PRINT(0)(" -");
629  PRINT(0)("PNode(%s::%s) - absCoord: (%0.2f, %0.2f, %0.2f), relCoord(%0.2f, %0.2f, %0.2f)\n",
630           this->getClassName(),
631           this->getName(),
632           this->absCoordinate.x,
633           this->absCoordinate.y,
634           this->absCoordinate.z,
635           this->relCoordinate.x,
636           this->relCoordinate.y,
637           this->relCoordinate.z );
638  if (depth >= 2 || depth == 0)
639  {
640    tIterator<PNode>* iterator = this->children->getIterator();
641      //PNode* pn = this->children->enumerate ();
642    PNode* pn = iterator->nextElement();
643    while( pn != NULL)
644    {
645      if (depth == 0)
646        pn->debug(0, level + 1);
647      else
648        pn->debug(depth - 1, level +1);
649      pn = iterator->nextElement();
650    }
651    delete iterator;
652  }
653}
654
655/**
656   displays the PNode at its position with its rotation as a cube.
657*/
658void PNode::debugDraw(float size) const
659{
660  glMatrixMode(GL_MODELVIEW);
661  glPushMatrix();
662  float matrix[4][4];
663
664  /* translate */
665  glTranslatef (this->getAbsCoor ().x,
666                this->getAbsCoor ().y,
667                this->getAbsCoor ().z);
668  /* rotate */
669  this->getAbsDir ().matrix (matrix);
670  glMultMatrixf((float*)matrix);
671  {
672    glBegin(GL_LINE_STRIP);
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    glVertex3f( .5*size, -.5*size, -.5*size);
679    glVertex3f(-.5*size, -.5*size, -.5*size);
680    glVertex3f(-.5*size,  .5*size, -.5*size);
681    glEnd();
682    glBegin(GL_LINE_STRIP);
683    glVertex3f(-.5*size, -.5*size, -.5*size);
684    glVertex3f(-.5*size, -.5*size,  .5*size);
685    glVertex3f( .5*size, -.5*size,  .5*size);
686    glVertex3f( .5*size, -.5*size, -.5*size);
687    glEnd();
688    glBegin(GL_LINES);
689    glVertex3f( .5*size, -.5*size,  .5*size);
690    glVertex3f( .5*size,  .5*size,  .5*size);
691    glVertex3f(-.5*size, -.5*size,  .5*size);
692    glVertex3f(-.5*size,  .5*size,  .5*size);
693    glEnd();
694  }
695
696  glPopMatrix();
697}
Note: See TracBrowser for help on using the repository browser.