Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 9656 was 9656, checked in by bensch, 18 years ago

orxonox/trunk: merged the proxy bache back with no conflicts

File size: 31.7 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Patrick Boenzli
13   co-programmer: Benjamin Grauer
14*/
15
16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_PNODE
17
18#include "p_node.h"
19
20#include "util/loading/load_param.h"
21#include "class_list.h"
22
23#include "netdefs.h"
24
25#include <algorithm>
26#include "compiler.h"
27#include "debug.h"
28
29#include "glincl.h"
30#include "color.h"
31
32/**
33 * @brief standard constructor
34 * @param parent the Parent of this Node. __NULL__ if __No Parent__ requested, PNode::getNullParent(), if connected to NullParent directly (default)
35 * @param nodeFlags all flags to set. THIS_WILL_OVERWRITE Default_Values.
36 */
37PNode::PNode (PNode* parent, long nodeFlags)
38  : BaseObject(), Synchronizeable()
39{
40  this->setClassID(CL_PARENT_NODE, "PNode");
41
42  this->bRelCoorChanged = true;
43  this->bRelDirChanged = true;
44  this->parent = NULL;
45  this->parentMode = nodeFlags;
46  this->bActive = true;
47
48  // smooth-movers
49  this->toCoordinate = NULL;
50  this->toDirection = NULL;
51  this->bias = 1.0;
52
53  if (parent != NULL)
54    parent->addChild(this);
55
56  this->relCoordinate_handle = this->registerVarId( new SynchronizeableVector( &relCoordinate, &relCoordinate_write, "coordinate", PERMISSION_SERVER ) );
57  this->relDirection_handle = this->registerVarId( new SynchronizeableQuaternion( &relDirection, &relDirection_write, "direction", PERMISSION_SERVER ) );
58}
59
60// NullParent Reference
61PNode* PNode::nullParent = NULL;
62
63/**
64 * @brief standard deconstructor
65 *
66 * There are two general ways to delete a PNode
67 * 1. delete instance;
68 *   -> result
69 *    delete this Node and all its children and children's children...
70 *    (danger if you still need the children's instance somewhere else!!)
71 *
72 * 2. instance->removeNode(); delete instance;
73 *   -> result:
74 *    moves its children to the NullParent
75 *    then deletes the Element.
76 */
77PNode::~PNode ()
78{
79  PRINTF(4)("delete %s::%s\n", this->getClassCName(), this->getCName());
80  // remove the Node, delete it's children (if required).
81  std::list<PNode*>::iterator deleteNode;
82  unsigned int size;
83  while(!this->children.empty())
84  {
85    deleteNode = this->children.begin();
86    size = this->children.size();
87    if ((this->parentMode & PNODE_PROHIBIT_CHILD_DELETE) ||
88        ((*deleteNode)->parentMode & PNODE_PROHIBIT_DELETE_WITH_PARENT))
89    {
90      if (this == PNode::nullParent && (*deleteNode)->parentMode & PNODE_REPARENT_TO_NULL)
91      {
92        PRINTF(4)("%s::%s deletes %s::%s\n",
93                  this->getClassCName(), this->getCName(),
94                  (*deleteNode)->getClassCName(), (*deleteNode)->getCName());
95        delete (*deleteNode);
96      }
97      else
98      {
99        PRINTF(4)("%s::%s reparents %s::%s\n",
100                  this->getClassCName(), this->getCName(),
101                  (*deleteNode)->getClassCName(), (*deleteNode)->getCName());
102        (*deleteNode)->reparent();
103      }
104    }
105    else
106    {
107      PRINTF(4)("%s::%s deletes PNode: %s::%s\n",
108                this->getClassCName(), this->getCName(),
109                (*deleteNode)->getClassCName(), (*deleteNode)->getCName());
110      delete (*deleteNode);
111    }
112  }
113
114  if (this->parent != NULL)
115  {
116    this->parent->eraseChild(this);
117    this->parent = NULL;
118  }
119
120  // remove all other allocated memory.
121  if (this->toCoordinate != NULL)
122    delete this->toCoordinate;
123  if (this->toDirection != NULL)
124    delete this->toDirection;
125
126  if (this == PNode::nullParent)
127    PNode::nullParent = NULL;
128}
129
130
131/**
132 * @brief loads parameters of the PNode
133 * @param root the XML-element to load the properties of
134 */
135void PNode::loadParams(const TiXmlElement* root)
136{
137  BaseObject::loadParams(root);
138
139  LoadParam(root, "rel-coor", this, PNode, setRelCoor)
140  .describe("Sets The relative position of the Node to its parent.");
141
142  LoadParam(root, "abs-coor", this, PNode, setAbsCoor)
143  .describe("Sets The absolute Position of the Node.");
144
145  LoadParam(root, "rel-dir", this, PNode, setRelDir)
146  .describe("Sets The relative rotation of the Node to its parent.");
147
148  LoadParam(root, "abs-dir", this, PNode, setAbsDir)
149  .describe("Sets The absolute rotation of the Node.");
150
151  LoadParam(root, "parent", this, PNode, setParent)
152  .describe("the Name of the Parent to set for this PNode");
153
154  LoadParam(root, "parent-mode", this, PNode, setParentMode)
155  .describe("the mode to connect this node to its parent ()");
156
157  // cycling properties
158  if (root != NULL)
159  {
160    LOAD_PARAM_START_CYCLE(root, element);
161    {
162      LoadParam_CYCLE(element, "child", this, PNode, addChild)
163      .describe("adds a new Child to the current Node.");
164
165    }
166    LOAD_PARAM_END_CYCLE(element);
167  }
168}
169
170
171/**
172 *  init the pnode to a well definied state
173 *
174 * this function actualy only updates the PNode tree
175 */
176void PNode::init()
177{
178  /* just update all aboslute positions via timestep 0.001ms */
179  this->updateNode(0.001f);
180  this->updateNode(0.001f);
181}
182
183
184/**
185 * @brief set relative coordinates
186 * @param relCoord relative coordinates to its parent
187 *
188 *
189 * it is very importand, that you use this function, if you want to update the
190 * relCoordinates. If you don't use this, the PNode won't recognize, that something
191 * has changed and won't update the children Nodes.
192 */
193void PNode::setRelCoor (const Vector& relCoord)
194{
195  if (this->toCoordinate!= NULL)
196  {
197    delete this->toCoordinate;
198    this->toCoordinate = NULL;
199  }
200
201  this->relCoordinate = relCoord;
202  this->bRelCoorChanged = true;
203}
204
205/**
206 * @brief set relative coordinates
207 * @param x x-relative coordinates to its parent
208 * @param y y-relative coordinates to its parent
209 * @param z z-relative coordinates to its parent
210 * @see  void PNode::setRelCoor (const Vector& relCoord)
211 */
212void PNode::setRelCoor (float x, float y, float z)
213{
214  this->setRelCoor(Vector(x, y, z));
215}
216
217/**
218 * @brief sets a new relative position smoothely
219 * @param relCoordSoft the new Position to iterate to
220 * @param bias how fast to iterate to this position
221 */
222void PNode::setRelCoorSoft(const Vector& relCoordSoft, float bias)
223{
224  if (likely(this->toCoordinate == NULL))
225    this->toCoordinate = new Vector();
226
227  *this->toCoordinate = relCoordSoft;
228  this->bias = bias;
229}
230
231
232/**
233 * @brief set relative coordinates smoothely
234 * @param x x-relative coordinates to its parent
235 * @param y y-relative coordinates to its parent
236 * @param z z-relative coordinates to its parent
237 * @see  void PNode::setRelCoorSoft (const Vector&, float)
238 */
239void PNode::setRelCoorSoft (float x, float y, float z, float bias)
240{
241  this->setRelCoorSoft(Vector(x, y, z), bias);
242}
243
244
245/**
246 * @param absCoord set absolute coordinate
247 */
248void PNode::setAbsCoor (const Vector& absCoord)
249{
250  if (this->toCoordinate!= NULL)
251  {
252    delete this->toCoordinate;
253    this->toCoordinate = NULL;
254  }
255
256  if( likely(this->parentMode & PNODE_MOVEMENT))
257  {
258    /* if you have set the absolute coordinates this overrides all other changes */
259    if (likely(this->parent != NULL))
260      this->relCoordinate = absCoord - parent->getAbsCoor ();
261    else
262      this->relCoordinate = absCoord;
263  }
264  if( this->parentMode & PNODE_ROTATE_MOVEMENT)
265  {
266    if (likely(this->parent != NULL))
267      this->relCoordinate = absCoord - parent->getAbsCoor ();
268    else
269      this->relCoordinate = absCoord;
270  }
271
272  this->bRelCoorChanged = true;
273  //  this->absCoordinate = absCoord;
274}
275
276
277/**
278 * @param x x-coordinate.
279 * @param y y-coordinate.
280 * @param z z-coordinate.
281 * @see void PNode::setAbsCoor (const Vector& absCoord)
282 */
283void PNode::setAbsCoor(float x, float y, float z)
284{
285  this->setAbsCoor(Vector(x, y, z));
286}
287
288
289/**
290 * @param absCoord set absolute coordinate
291 * @todo check off
292 */
293void PNode::setAbsCoorSoft (const Vector& absCoordSoft, float bias)
294{
295  if (this->toCoordinate == NULL)
296    this->toCoordinate = new Vector;
297
298  if( likely(this->parentMode & PNODE_MOVEMENT))
299  {
300    /* if you have set the absolute coordinates this overrides all other changes */
301    if (likely(this->parent != NULL))
302      *this->toCoordinate = absCoordSoft - parent->getAbsCoor ();
303    else
304      *this->toCoordinate = absCoordSoft;
305  }
306  if( this->parentMode & PNODE_ROTATE_MOVEMENT)
307  {
308    if (likely(this->parent != NULL))
309      *this->toCoordinate = absCoordSoft - parent->getAbsCoor ();
310    else
311      *this->toCoordinate = absCoordSoft;
312  }
313}
314
315
316/**
317 * @brief shift coordinate relative
318 * @param shift shift vector
319 *
320 * this function shifts the current coordinates about the vector shift. this is
321 * usefull because from some place else you can:
322 * PNode* someNode = ...;
323 * Vector objectMovement = calculateShift();
324 * someNode->shiftCoor(objectMovement);
325 *
326 * this is the internal method of:
327 * PNode* someNode = ...;
328 * Vector objectMovement = calculateShift();
329 * Vector currentCoor = someNode->getRelCoor();
330 * Vector newCoor = currentCoor + objectMovement;
331 * someNode->setRelCoor(newCoor);
332 *
333 */
334void PNode::shiftCoor (const Vector& shift)
335{
336  this->relCoordinate += shift;
337  this->bRelCoorChanged = true;
338}
339
340
341/**
342 * @brief set relative direction
343 * @param relDir to its parent
344 */
345void PNode::setRelDir (const Quaternion& relDir)
346{
347  if (this->toDirection!= NULL)
348  {
349    delete this->toDirection;
350    this->toDirection = NULL;
351  }
352  this->relDirection = relDir;
353
354  this->bRelCoorChanged = true;
355}
356
357
358/**
359 * @see void PNode::setRelDir (const Quaternion& relDir)
360 * @param x the x direction
361 * @param y the y direction
362 * @param z the z direction
363 *
364 * main difference is, that here you give a directional vector, that will be translated into a Quaternion
365 */
366void PNode::setRelDir (float angle, float x, float y, float z)
367{
368  this->setRelDir(Quaternion(angle, Vector(x,y,z)));
369}
370
371
372/**
373 * @brief sets the Relative Direction of this node to its parent in a Smoothed way
374 * @param relDirSoft the direction to iterate to smoothely.
375 * @param bias how fast to iterate to the new Direction
376 */
377void PNode::setRelDirSoft(const Quaternion& relDirSoft, float bias)
378{
379  if (likely(this->toDirection == NULL))
380    this->toDirection = new Quaternion();
381
382  *this->toDirection = relDirSoft;
383  this->bias = bias;
384  this->bRelDirChanged = true;
385}
386
387
388/**
389 * @see void PNode::setRelDirSoft (const Quaternion& relDir)
390 * @param x the x direction
391 * @param y the y direction
392 * @param z the z direction
393 *
394 * main difference is, that here you give a directional vector, that will be translated into a Quaternion
395 */
396void PNode::setRelDirSoft(float angle, float x, float y, float z, float bias)
397{
398  this->setRelDirSoft(Quaternion(angle, Vector(x,y,z)), bias);
399}
400
401
402/**
403 * @brief sets the absolute direction
404 * @param absDir absolute coordinates
405 */
406void PNode::setAbsDir (const Quaternion& absDir)
407{
408  if (this->toDirection!= NULL)
409  {
410    delete this->toDirection;
411    this->toDirection = NULL;
412  }
413
414  if (likely(this->parent != NULL))
415    this->relDirection = absDir / this->parent->getAbsDir();
416  else
417    this->relDirection = absDir;
418
419  this->bRelDirChanged = true;
420}
421
422
423/**
424 * @see void PNode::setAbsDir (const Quaternion& relDir)
425 * @param x the x direction
426 * @param y the y direction
427 * @param z the z direction
428 *
429 * main difference is, that here you give a directional vector, that will be translated into a Quaternion
430 */
431void PNode::setAbsDir (float angle, float x, float y, float z)
432{
433  this->setAbsDir(Quaternion(angle, Vector(x,y,z)));
434}
435
436
437/**
438 * @brief sets the absolute direction
439 * @param absDir absolute coordinates
440 * @param bias how fast to iterator to the new Position
441 */
442void PNode::setAbsDirSoft (const Quaternion& absDirSoft, float bias)
443{
444  if (this->toDirection == NULL)
445    this->toDirection = new Quaternion();
446
447  if (likely(this->parent != NULL))
448    *this->toDirection = absDirSoft / this->parent->getAbsDir();
449  else
450    *this->toDirection = absDirSoft;
451
452  this->bias = bias;
453  this->bRelDirChanged = true;
454}
455
456
457/**
458 * @see void PNode::setAbsDir (const Quaternion& relDir)
459 * @param x the x direction
460 * @param y the y direction
461 * @param z the z direction
462 *
463 * main difference is, that here you give a directional vector, that will be translated into a Quaternion
464 */
465void PNode::setAbsDirSoft (float angle, float x, float y, float z, float bias)
466{
467  this->setAbsDirSoft(Quaternion(angle, Vector(x,y,z)), bias);
468}
469
470
471/**
472 * @brief shift Direction
473 * @param shift the direction around which to shift.
474 */
475void PNode::shiftDir (const Quaternion& shift)
476{
477  this->relDirection = this->relDirection * shift;
478  this->bRelDirChanged = true;
479}
480
481
482/**
483 * @brief adds a child and makes this node to a parent
484 * @param child child reference
485 * use this to add a child to this node.
486 */
487void PNode::addChild (PNode* child)
488{
489  if (unlikely(child->parent == this))
490    return;
491  if( likely(child->parent != NULL))
492    child->parent->eraseChild(child);
493  if (this->checkIntegrity(child))
494  {
495    child->parent = this;
496    if (unlikely(this != NULL))
497      this->children.push_back(child);
498    child->parentCoorChanged();
499
500    //     if(this->getUniqueID() == NET_UID_UNASSIGNED)
501    //     {
502    //       PRINTF(1)("Adding to an UNASSIGNED PNode - looking for next assigned Node\n");
503    //       PNode* node = this->seekNextAssignedPNode(this);
504    //       if( node == NULL)
505    //         PRINTF(1)("    Got NULL - Is this the NULLParent - uid %i\n", this->getUniqueID());
506    //       else
507    //         PRINTF(1)("    Found next assigned node: %i\n", node->getUniqueID());
508    //     }
509  }
510  else
511  {
512    PRINTF(1)("Tried to reparent to own child '%s::%s' to '%s::%s'.\n",
513              this->getClassCName(), this->getCName(), child->getClassCName(), child->getCName());
514    child->parent = NULL;
515    child->parentCoorChanged();
516  }
517}
518
519
520PNode* PNode::seekNextAssignedPNode(PNode* node) const
521{
522  PNode* tmpNode = node->parent;
523  printf("entering seek PNode loop for name: %s, uid: %i\n", node->getCName(), node->getUniqueID());
524  if(tmpNode)
525    printf("  @node name: %s, uid: %d\n", tmpNode->getCName(), tmpNode->getUniqueID());
526  while( tmpNode != NULL && tmpNode->getUniqueID() == NET_UID_UNASSIGNED)
527  {
528    printf("  @node name: %s, uid: %d\n", tmpNode->getCName(), tmpNode->getUniqueID());
529    tmpNode = tmpNode->parent;
530  }
531  printf("leaving PNode loop\n\n");
532
533  return tmpNode;
534}
535
536
537/**
538 * @see PNode::addChild(PNode* child);
539 * @param childName the name of the child to add to this PNode
540 */
541void PNode::addChild (const std::string& childName)
542{
543  PNode* childNode = dynamic_cast<PNode*>(ClassList::getObject(childName, CL_PARENT_NODE));
544  //  PRINTF(0)("Adding the Child: %s to: %s\n", childName, this->getName());
545  //  assert( childNode != NULL );
546  if (childNode != NULL)
547  {
548    this->addChild(childNode);
549  }
550}
551
552
553/**
554 * @brief removes a child from the node
555 * @param child the child to remove from this pNode.
556 *
557 * Children from pNode will not be lost, they are Reparented by the rules of the ParentMode
558 */
559void PNode::removeChild (PNode* child)
560{
561  if (child != NULL)
562    child->removeNode();
563}
564
565
566/**
567 * !! PRIVATE FUNCTION
568 * @brief reparents a node (happens on Parents Node delete or remove and Flags are set.)
569 */
570void PNode::reparent()
571{
572  if (this->parentMode & PNODE_REPARENT_TO_NULL)
573    this->setParent((PNode*)NULL);
574  else if (this->parentMode & PNODE_REPARENT_TO_PARENTS_PARENT && this->parent != NULL)
575    this->setParent(this->parent->getParent());
576  else
577    this->setParent(PNode::getNullParent());
578}
579
580/**
581 * ereases child from the nodes children
582 * @param chuld the child to remove
583 */
584void PNode::eraseChild(PNode* child)
585{
586  std::list<PNode*>::iterator childRemover = std::find(this->children.begin(), this->children.end(), child);
587  if(childRemover != this->children.end())
588    this->children.erase(childRemover);
589}
590
591
592/**
593 * @brief remove this pnode from the tree and adds all following to NullParent
594 *
595 * this can be the case, if an entity in the world is being destroyed.
596 */
597void PNode::removeNode()
598{
599  std::list<PNode*>::iterator child = this->children.begin();
600  std::list<PNode*>::iterator reparenter;
601  while (child != this->children.end())
602  {
603    reparenter = child;
604    child++;
605    if (this->parentMode & PNODE_REPARENT_CHILDREN_ON_REMOVE ||
606        (*reparenter)->parentMode & PNODE_REPARENT_ON_PARENTS_REMOVE)
607    {
608      printf("TEST----------------%s ---- %s\n", this->getClassCName(), (*reparenter)->getClassCName());
609      (*reparenter)->reparent();
610      printf("REPARENTED TO: %s::%s\n",(*reparenter)->getParent()->getClassCName(),(*reparenter)->getParent()->getCName());
611    }
612  }
613  if (this->parent != NULL)
614  {
615    this->parent->eraseChild(this);
616    this->parent = NULL;
617  }
618}
619
620
621/**
622 * @see PNode::setParent(PNode* parent);
623 * @param parentName the name of the Parent to set to this PNode
624 */
625void PNode::setParent (const std::string& parentName)
626{
627  PNode* parentNode = dynamic_cast<PNode*>(ClassList::getObject(parentName, CL_PARENT_NODE));
628  if (parentNode != NULL)
629    parentNode->addChild(this);
630  else
631    PRINTF(2)("Not Found PNode's (%s::%s) new Parent by Name: %s\n",
632        this->getClassCName(), this->getCName(), parentName.c_str());
633}
634
635
636/**
637 * @brief does the reparenting in a very smooth way
638 * @param parentNode the new Node to connect this node to.
639 * @param bias the speed to iterate to this new Positions
640 */
641void PNode::setParentSoft(PNode* parentNode, float bias)
642{
643  // return if the new parent and the old one match
644  if (this->parent == parentNode )
645    return;
646  if (parentNode == NULL)
647    parentNode = PNode::getNullParent();
648
649  // store the Valures to iterate to.
650  if (likely(this->toCoordinate == NULL))
651  {
652    this->toCoordinate = new Vector();
653    *this->toCoordinate = this->getRelCoor();
654  }
655  if (likely(this->toDirection == NULL))
656  {
657    this->toDirection = new Quaternion();
658    *this->toDirection = this->getRelDir();
659  }
660  this->bias = bias;
661
662  Vector tmpV = this->getAbsCoor();
663  Quaternion tmpQ = this->getAbsDir();
664
665  parentNode->addChild(this);
666
667  if (this->parentMode & PNODE_ROTATE_MOVEMENT && this->parent != NULL)
668    this->relCoordinate = this->parent->getAbsDir().inverse().apply(tmpV - this->parent->getAbsCoor());
669  else
670    this->relCoordinate = tmpV - parentNode->getAbsCoor();
671
672  this->relDirection = tmpQ / parentNode->getAbsDir();
673}
674
675
676/**
677 * @brief does the reparenting in a very smooth way
678 * @param parentName the name of the Parent to reconnect to
679 * @param bias the speed to iterate to this new Positions
680 */
681void PNode::setParentSoft(const std::string& parentName, float bias)
682{
683  PNode* parentNode = dynamic_cast<PNode*>(ClassList::getObject(parentName, CL_PARENT_NODE));
684  if (parentNode != NULL)
685    this->setParentSoft(parentNode, bias);
686}
687
688/**
689 * @param parentMode sets the parentingMode of this Node
690 */
691void PNode::setParentMode(PARENT_MODE parentMode)
692{
693  this->parentMode = ((this->parentMode & 0xfff0) | parentMode);
694}
695
696/**
697 * @brief sets the mode of this parent manually
698 * @param parentMode a String representing this parentingMode
699 */
700void PNode::setParentMode (const std::string& parentingMode)
701{
702  this->setParentMode(PNode::stringToParentingMode(parentingMode));
703}
704
705/**
706 * @brief adds special mode Flags to this PNode
707 * @see PARENT_MODE
708 * @param nodeFlags a compsition of PARENT_MODE-flags, split by the '|' (or) operator.
709 */
710void PNode::addNodeFlags(unsigned short nodeFlags)
711{
712  this->parentMode |= nodeFlags;
713}
714
715/**
716 * @brief removes special mode Flags to this PNode
717 * @see PARENT_MODE
718 * @param nodeFlags a compsition of PARENT_MODE-flags, split by the '|' (or) operator.
719 */
720void PNode::removeNodeFlags(unsigned short nodeFlags)
721{
722  this->parentMode &= !nodeFlags;
723}
724
725/**
726 * @returns the NullParent (and if needed creates it)
727 */
728PNode* PNode::createNullParent()
729{
730  if (likely(PNode::nullParent == NULL))
731  {
732    PNode::nullParent = new PNode(NULL, PNODE_PARENT_MODE_DEFAULT | PNODE_REPARENT_TO_NULL);
733    PNode::nullParent->setClassID(CL_NULL_PARENT, "NullParent");
734    PNode::nullParent->setName("NullParent");
735    PNode::nullParent->setSynchronized(true);
736  }
737  return PNode::nullParent;
738}
739
740
741/**
742 * !! PRIVATE FUNCTION
743 * @brief checks the upward integrity (e.g if PNode is somewhere up the Node tree.)
744 * @param checkParent the Parent to check.
745 * @returns true if the integrity-check succeeds, false otherwise.
746 *
747 * If there is a second occurence of checkParent before NULL, then a loop could get
748 * into the Tree, and we do not want this.
749 */
750bool PNode::checkIntegrity(const PNode* checkParent) const
751{
752  const PNode* parent = this;
753  if (this == NULL)
754    return true;
755  while ( (parent = parent->getParent()) != NULL)
756    if (unlikely(parent == checkParent))
757      return false;
758  return true;
759}
760
761
762/**
763 * @brief updates the absCoordinate/absDirection
764 * @param dt The time passed since the last update
765 *
766 * this is used to go through the parent-tree to update all the absolute coordinates
767 * and directions. this update should be done by the engine, so you don't have to
768 * worry, normaly...
769 */
770void PNode::updateNode (float dt)
771{
772  if (!(this->parentMode & PNODE_STATIC_NODE))
773  {
774    if( likely(this->parent != NULL))
775    {
776      // movement for nodes with smoothMove enabled
777      if (unlikely(this->toCoordinate != NULL))
778      {
779        float shiftLen = fabsf(dt)*bias;
780        if (unlikely(shiftLen >= 1.0))
781          shiftLen = 1.0;
782        Vector moveVect = (*this->toCoordinate - this->relCoordinate) * shiftLen;
783        if (likely(moveVect.len() >= PNODE_ITERATION_DELTA))
784        {
785          this->shiftCoor(moveVect);
786        }
787        else
788        {
789          delete this->toCoordinate;
790          this->toCoordinate = NULL;
791          PRINTF(5)("SmoothMove of %s finished\n", this->getCName());
792        }
793      }
794      if (unlikely(this->toDirection != NULL))
795      {
796        float shiftLen = fabsf(dt)*bias;
797        if (unlikely (shiftLen >= 1.0))
798          shiftLen = 1.0;
799        //printf("%s::%s %f\n", this->getClassCName(), this->getName(), this->toStep );
800        Quaternion rotQuat = Quaternion::quatSlerp(this->relDirection,*this->toDirection, shiftLen);
801        if (this->relDirection.distance(rotQuat) > PNODE_ITERATION_DELTA)
802        {
803          this->relDirection = rotQuat;
804          this->bRelDirChanged = true;
805        }
806        else
807        {
808          delete this->toDirection;
809          this->toDirection = NULL;
810          PRINTF(5)("SmoothRotate of %s finished\n", this->getCName());
811          this->bRelDirChanged = true;
812        }
813      }
814
815      // MAIN UPDATE /////////////////////////////////////
816      this->lastAbsCoordinate = this->absCoordinate;
817
818      PRINTF(5)("PNode::update - '%s::%s' - (%f, %f, %f)\n", this->getClassCName(), this->getCName(),
819                this->absCoordinate.x, this->absCoordinate.y, this->absCoordinate.z);
820
821
822      if(this->bRelDirChanged && this->parentMode & PNODE_LOCAL_ROTATE )
823      {
824        /* update the current absDirection - remember * means rotation around sth.*/
825        this->prevRelCoordinate = this->relCoordinate;
826        this->absDirection = parent->getAbsDir() * this->relDirection;
827      }
828
829      if(likely(this->bRelCoorChanged && this->parentMode & PNODE_MOVEMENT))
830      {
831        /* update the current absCoordinate */
832        this->prevRelCoordinate = this->relCoordinate;
833        this->absCoordinate = this->parent->getAbsCoor() + this->relCoordinate;
834      }
835      else if( this->parentMode & PNODE_ROTATE_MOVEMENT && (this->bRelCoorChanged || this->bRelDirChanged))
836      {
837        /* update the current absCoordinate */
838        this->prevRelCoordinate = this->relCoordinate;
839        this->absCoordinate = this->parent->getAbsCoor() + parent->getAbsDir().apply(this->relCoordinate);
840      }
841      /////////////////////////////////////////////////
842    }
843
844    else // Nodes without a Parent are handled faster :: MOST LIKELY THE NULLPARENT
845    {
846      PRINTF(4)("update ParentLess Node (%s::%s) - (%f, %f, %f)\n", this->getClassCName(), this->getCName(),
847                this->absCoordinate.x, this->absCoordinate.y, this->absCoordinate.z);
848      if (this->bRelCoorChanged)
849      {
850        this->prevRelCoordinate = this->relCoordinate;
851        this->absCoordinate = this->relCoordinate;
852      }
853      if (this->bRelDirChanged)
854      {
855        this->prevRelDirection = this->relDirection;
856        this->absDirection = this->getAbsDir () * this->relDirection;
857      }
858    }
859  }
860
861  if(!this->children.empty() && (this->bActive || this->parentMode & PNODE_UPDATE_CHILDREN_IF_INACTIVE ))
862  {
863    std::list<PNode*>::iterator child;
864    for (child = this->children.begin(); child != this->children.end(); child ++)
865    {
866      /* if this node has changed, make sure, that all children are updated also */
867      if( likely(this->bRelCoorChanged))
868        (*child)->parentCoorChanged ();
869      if( likely(this->bRelDirChanged))
870        (*child)->parentDirChanged ();
871
872      (*child)->updateNode(dt);
873    }
874  }
875  this->velocity = (this->absCoordinate - this->lastAbsCoordinate) / dt;
876  this->bRelCoorChanged = false;
877  this->bRelDirChanged = false;
878}
879
880
881
882
883
884/*************
885 * DEBUGGING *
886 *************/
887/**
888 * @brief counts total amount the children walking through the entire tree.
889 * @param nodes the counter
890 */
891void PNode::countChildNodes(int& nodes) const
892{
893  nodes++;
894  std::list<PNode*>::const_iterator child;
895  for (child = this->children.begin(); child != this->children.end(); child ++)
896    (*child)->countChildNodes(nodes);
897}
898
899
900/**
901 * @brief displays some information about this pNode
902 * @param depth The deph into which to debug the children of this PNode to.
903 * (0: all children will be debugged, 1: only this PNode, 2: this and direct children, ...)
904 * @param level !! INTERNAL !! The n-th level of the Node we draw (this is internal and only for nice output).
905 */
906void PNode::debugNode(unsigned int depth, unsigned int level) const
907{
908  for (unsigned int i = 0; i < level; i++)
909    PRINT(0)(" |");
910  if (this->children.size() > 0)
911    PRINT(0)(" +");
912  else
913    PRINT(0)(" -");
914
915  int childNodeCount = 0;
916  this->countChildNodes(childNodeCount);
917
918  PRINT(0)("PNode(%s::%s) - absCoord: (%0.2f, %0.2f, %0.2f), relCoord(%0.2f, %0.2f, %0.2f), direction(%0.2f, %0.2f, %0.2f) - %s - %d childs\n",
919           this->getClassCName(),
920           this->getCName(),
921           this->absCoordinate.x,
922           this->absCoordinate.y,
923           this->absCoordinate.z,
924           this->relCoordinate.x,
925           this->relCoordinate.y,
926           this->relCoordinate.z,
927           this->getAbsDirV().x,
928           this->getAbsDirV().y,
929           this->getAbsDirV().z,
930           this->parentingModeToString(parentMode),
931           childNodeCount);
932  if (depth >= 2 || depth == 0)
933  {
934    std::list<PNode*>::const_iterator child;
935    for (child = this->children.begin(); child != this->children.end(); child ++)
936    {
937      if (depth == 0)
938        (*child)->debugNode(0, level + 1);
939      else
940        (*child)->debugNode(depth - 1, level +1);
941    }
942  }
943}
944
945/**
946 * @brief displays the PNode at its position with its rotation as a cube.
947 * @param  depth The deph into which to debug the children of this PNode to.
948 * (0: all children will be displayed, 1: only this PNode, 2: this and direct children, ...)
949 * @param size the Size of the Box to draw.
950 * @param color the color of the Box to display.
951 * @param level !! INTERNAL !! The n-th level of the Node we draw (this is internal and only for nice output).
952 */
953void PNode::debugDraw(unsigned int depth, float size, const Vector& color, unsigned int level) const
954{
955  // if this is the first Element we draw
956  if (level == 0)
957  {
958    glPushAttrib(GL_ENABLE_BIT); // save the Enable-attributes
959    glMatrixMode(GL_MODELVIEW);  // goto the ModelView Matrix
960
961    glDisable(GL_LIGHTING);      // disable lighting (we do not need them for just lighting)
962    glDisable(GL_BLEND);         // ''
963    glDisable(GL_TEXTURE_2D);    // ''
964    glDisable(GL_DEPTH_TEST);    // ''
965  }
966
967  glPushMatrix();                // repush the Matrix-stack
968  /* translate */
969  glTranslatef (this->getAbsCoor ().x,
970                this->getAbsCoor ().y,
971                this->getAbsCoor ().z);
972  //  this->getAbsDir ().matrix (matrix);
973
974  /* rotate */
975  Vector tmpRot = this->getAbsDir().getSpacialAxis();
976  glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );
977  /* set the new Color */
978  glColor3f(color.x, color.y, color.z);
979  { /* draw a cube of size size */
980    glBegin(GL_LINE_STRIP);
981    glVertex3f(-.5*size, -.5*size,  -.5*size);
982    glVertex3f(+.5*size, -.5*size,  -.5*size);
983    glVertex3f(+.5*size, -.5*size,  +.5*size);
984    glVertex3f(-.5*size, -.5*size,  +.5*size);
985    glVertex3f(-.5*size, -.5*size,  -.5*size);
986    glEnd();
987    glBegin(GL_LINE_STRIP);
988    glVertex3f(-.5*size, +.5*size,  -.5*size);
989    glVertex3f(+.5*size, +.5*size,  -.5*size);
990    glVertex3f(+.5*size, +.5*size,  +.5*size);
991    glVertex3f(-.5*size, +.5*size,  +.5*size);
992    glVertex3f(-.5*size, +.5*size,  -.5*size);
993    glEnd();
994
995    glBegin(GL_LINES);
996    glVertex3f(-.5*size, -.5*size,  -.5*size);
997    glVertex3f(-.5*size, +.5*size,  -.5*size);
998    glVertex3f(+.5*size, -.5*size,  -.5*size);
999    glVertex3f(+.5*size, +.5*size,  -.5*size);
1000    glVertex3f(+.5*size, -.5*size,  +.5*size);
1001    glVertex3f(+.5*size, +.5*size,  +.5*size);
1002    glVertex3f(-.5*size, -.5*size,  +.5*size);
1003    glVertex3f(-.5*size, +.5*size,  +.5*size);
1004    glEnd();
1005  }
1006  glPopMatrix();
1007
1008  if (depth >= 2 || depth == 0)
1009  {
1010    /* rotate the current color in HSV space around 20 degree */
1011    Vector childColor =  Color::HSVtoRGB(Color::RGBtoHSV(color)+Vector(20,0,.0));
1012    std::list<PNode*>::const_iterator child;
1013    for (child = this->children.begin(); child != this->children.end(); child ++)
1014    {
1015      // drawing the Dependency graph
1016      if (this != PNode::getNullParent())
1017      {
1018        glBegin(GL_LINES);
1019        glColor3f(color.x, color.y, color.z);
1020        glVertex3f(this->getAbsCoor ().x,
1021                   this->getAbsCoor ().y,
1022                   this->getAbsCoor ().z);
1023        glColor3f(childColor.x, childColor.y, childColor.z);
1024        glVertex3f((*child)->getAbsCoor ().x,
1025                   (*child)->getAbsCoor ().y,
1026                   (*child)->getAbsCoor ().z);
1027        glEnd();
1028      }
1029
1030      /* if we want to draw the children too */
1031      if (depth == 0) /* -> all of them */
1032        (*child)->debugDraw(0, size, childColor, level+1);
1033      else            /* -> only the Next one */
1034        (*child)->debugDraw(depth - 1, size, childColor, level +1);
1035    }
1036  }
1037  if (level == 0)
1038    glPopAttrib(); /* pop the saved attributes back out */
1039}
1040
1041
1042
1043/////////////////////
1044// HELPER_FUCTIONS //
1045/////////////////////
1046
1047/**
1048 * @brief converts a parentingMode into a string that is the name of it
1049 * @param parentingMode the ParentingMode to convert
1050 * @return the converted string
1051 */
1052const char* PNode::parentingModeToString(int parentingMode)
1053{
1054  if (parentingMode == PNODE_LOCAL_ROTATE)
1055    return "local-rotate";
1056  else if (parentingMode == PNODE_ROTATE_MOVEMENT)
1057    return "rotate-movement";
1058  else if (parentingMode == PNODE_MOVEMENT)
1059    return "movement";
1060  else if (parentingMode == PNODE_ALL)
1061    return "all";
1062  else if (parentingMode == PNODE_ROTATE_AND_MOVE)
1063    return "rotate-and-move";
1064  else
1065    return "all";
1066}
1067
1068/**
1069 * @brief converts a parenting-mode-string into a int
1070 * @param parentingMode the string naming the parentingMode
1071 * @return the int corresponding to the named parentingMode
1072 */
1073PARENT_MODE PNode::stringToParentingMode(const std::string& parentingMode)
1074{
1075  if (parentingMode == "local-rotate")
1076    return (PNODE_LOCAL_ROTATE);
1077  else  if (parentingMode == "rotate-movement")
1078    return (PNODE_ROTATE_MOVEMENT);
1079  else  if (parentingMode == "movement")
1080    return (PNODE_MOVEMENT);
1081  else  if (parentingMode == "all")
1082    return (PNODE_ALL);
1083  else  if (parentingMode == "rotate-and-move")
1084    return (PNODE_ROTATE_AND_MOVE);
1085  else
1086    return PNODE_ALL;
1087}
1088
1089/**
1090 * handles changes in synchronizable variables
1091 * @param id id's which changed
1092 */
1093void PNode::varChangeHandler( std::list< int > & id )
1094{
1095  Synchronizeable::varChangeHandler( id );
1096
1097  if ( std::find( id.begin(), id.end(), relCoordinate_handle ) != id.end() )
1098  {
1099    setRelCoor( relCoordinate_write );
1100  }
1101
1102  if ( std::find( id.begin(), id.end(), relDirection_handle ) != id.end() )
1103  {
1104    setRelDir( relDirection_write );
1105  }
1106}
1107
1108
Note: See TracBrowser for help on using the repository browser.