Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

renamed newclassid to classid and newobjectlist to objectlist

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