Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/vs-enhencements/src/lib/coord/p_node.cc @ 10691

Last change on this file since 10691 was 10678, checked in by nicolasc, 18 years ago

xfer

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