Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: the thing with the rotation is again above my insight…
have to do this later, but the effect works
hit 2 to focus to the Player and realease 2 to focus back again

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