Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

cleanup

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