Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/new_class_id/src/lib/coord/p_node.cc @ 9684

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

orxonox/branches/new_class_id: slowly but surely reimplementing to the new groove… way to go

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