Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3809 was 3809, checked in by patrick, 19 years ago

orxonox/trunk: changing pnode interface to const arguments

File size: 16.0 KB
Line 
1
2
3/*
4   orxonox - the future of 3D-vertical-scrollers
5
6   Copyright (C) 2004 orx
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2, or (at your option)
11   any later version.
12
13   ### File Specific:
14   main-programmer: Patrick Boenzli
15   co-programmer:
16
17   \todo Smooth-Parent: delay, speed
18*/
19
20#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_PNODE
21
22#include "p_node.h"
23#include "stdincl.h"
24
25#include "error.h"
26#include "debug.h"
27#include "list.h"
28#include "vector.h"
29#include "null_parent.h"
30
31//#include "vector.h"
32//#include "quaternion.h"
33
34using namespace std;
35
36
37/**
38   \brief standard constructor
39
40   \todo this constructor is not jet implemented - do it
41*/
42PNode::PNode () 
43{
44  init(NULL);
45
46  NullParent* np = NullParent::getInstance();
47  np->addChild(this);
48}
49
50
51
52/**
53   \brief constructor with coodinates
54   \param absCoordinate the Absolute coordinate of the Object
55   \param parent The parent-node of this node.
56*/
57PNode::PNode (const Vector& absCoordinate, PNode* parent )
58{
59  this->init(parent);
60
61  *this->absCoordinate = absCoordinate;
62
63  __LIKELY_IF(parent != NULL)
64  {
65    *this->relCoordinate = *this->absCoordinate - parent->getAbsCoor ();
66    parent->addChild (this);
67  }
68  else 
69    this->relCoordinate = new Vector(0,0,0);
70}
71
72/**
73   \brief standard deconstructor
74*/
75PNode::~PNode () 
76{
77  tIterator<PNode>* iterator = this->children->getIterator();
78  PNode* pn = iterator->nextElement();
79  while( pn != NULL) 
80    { 
81      delete pn;
82      pn = iterator->nextElement();
83    }
84  delete iterator;
85  /* this deletes all children in the list */
86  delete this->children;
87  this->parent = NULL;
88  delete []this->objectName;
89
90  delete this->relCoordinate;
91  delete this->absCoordinate;
92  delete this->relDirection;
93  delete this->absDirection;
94  delete this->lastAbsCoordinate;
95  delete this->diffCoordinate;
96}
97
98
99void PNode::init(PNode* parent)
100{
101  this->children = new tList<PNode>();
102  this->bRelCoorChanged = true;
103  this->bAbsCoorChanged = false;
104  this->bRelDirChanged = true;
105  this->bAbsDirChanged = false;
106  this->parent = parent; 
107  this->objectName = NULL;
108
109  this->absCoordinate = new Vector();
110  this->relCoordinate = new Vector();
111  this->absDirection = new Quaternion();
112  this->relDirection = new Quaternion();
113  this->lastAbsCoordinate = new Vector();
114  this->diffCoordinate = new Vector();
115}
116
117/**
118   \brief deletes the hole pnode tree
119
120   cleans up all pnodes
121*/
122/*
123void PNode::destroy ()
124{
125  PNode* pn = this->children->enumerate();
126  while( pn != NULL)
127    {
128      pn->destroy ();
129      pn = this->children->nextElement();
130    }
131  // this deletes all children in the list
132  this->children->destroy ();
133
134  static_cast<BaseObject*>(this)->destroy();
135}
136*/
137
138/**
139   \brief get relative coordinates
140   \returns relative coordinates to its parent
141   
142   the reference that is returned is a pointer to the real relCoor, so don't
143   change it unless you realy know what you are doing.
144*/
145//Vector* PNode::getRelCoor () const
146
147
148
149/**
150   \brief set relative coordinates
151   \param relCoord relative coordinates to its parent
152
153   it is very importand, that you use this function, if you want to update the
154   relCoordinates. If you don't use this, the PNode won't recognize, that something
155   has changed and won't update the children Nodes.
156*/
157void PNode::setRelCoor (Vector* relCoord)
158{
159  this->bRelCoorChanged = true;
160  *this->relCoordinate = *relCoord;
161}
162
163
164/**
165   \brief set relative coordinates
166   \param relCoord relative coordinates to its parent
167
168   it is very importand, that you use this function, if you want to update the
169   relCoordinates. If you don't use this, the PNode won't recognize, that something
170   has changed and won't update the children Nodes.
171*/
172void PNode::setRelCoor (Vector relCoord)
173{
174  this->bRelCoorChanged = true;
175  *this->relCoordinate = relCoord;
176}
177
178
179/**
180   \brief get absolute coordinates
181   \returns absolute coordinates from (0,0,0)
182*/
183//Vector PNode::getAbsCoor () const
184
185
186/**
187   \param absCoord set absolute coordinate
188
189   it is very importand, that you use this function, if you want to update the
190   absCoordinates. If you don't use this, the PNode won't recognize, that something
191   has changed and won't update the children Nodes.
192*/
193/*
194void PNode::setAbsCoor (Vector* absCoord)
195{
196  this->bAbsCoorChanged = true;
197  *this->absCoordinate = *absCoord;
198}
199*/
200
201
202/**
203   \param absCoord set absolute coordinate
204
205   it is very importand, that you use this function, if you want to update the
206   absCoordinates. If you don't use this, the PNode won't recognize, that something
207   has changed and won't update the children Nodes.
208*/
209void PNode::setAbsCoor (const Vector& absCoord)
210{
211  this->bAbsCoorChanged = true;
212  *this->absCoordinate = absCoord;
213}
214
215
216/**
217   \brief shift coordinate (abs and rel)
218   \param shift vector
219
220   this function shifts the current coordinates about the vector shift. this is
221   usefull because from some place else you can:
222   PNode* someNode = ...;
223   Vector objectMovement = calculateShift();
224   someNode->shiftCoor(objectMovement);
225
226   elsewhere you would have to:
227   PNode* someNode = ...;
228   Vector objectMovement = calculateShift();
229   Vector currentCoor = someNode->getRelCoor();
230   Vector newCoor = currentCoor + objectMovement;
231   someNode->setRelCoor(newCoor);
232   
233   yea right... shorter...
234
235*/
236void PNode::shiftCoor (Vector* shift)
237{
238
239  __UNLIKELY_IF( this->bAbsCoorChanged)
240    {
241      *this->absCoordinate = *this->absCoordinate + *shift;
242    }
243  else 
244    {
245      *this->relCoordinate = *this->relCoordinate + *shift;
246      this->bRelCoorChanged = true;
247    }
248}
249
250
251
252/**
253   \brief shift coordinate (abs and rel)
254   \param shift vector
255
256   this function shifts the current coordinates about the vector shift. this is
257   usefull because from some place else you can:
258   PNode* someNode = ...;
259   Vector objectMovement = calculateShift();
260   someNode->shiftCoor(objectMovement);
261
262   elsewhere you would have to:
263   PNode* someNode = ...;
264   Vector objectMovement = calculateShift();
265   Vector currentCoor = someNode->getRelCoor();
266   Vector newCoor = currentCoor + objectMovement;
267   someNode->setRelCoor(newCoor);
268   
269   yea right... shorter...
270
271*/
272void PNode::shiftCoor (const Vector& shift)
273{
274
275  __UNLIKELY_IF( this->bAbsCoorChanged)
276    {
277      *this->absCoordinate = *this->absCoordinate + shift;
278    }
279  else 
280    {
281      *this->relCoordinate = *this->relCoordinate + shift;
282      this->bRelCoorChanged = true;
283    }
284}
285
286
287
288/**
289   \brief get relative direction
290   \returns relative direction to its parent
291*/
292//Quaternion* PNode::getRelDir () const
293
294
295
296/**
297   \brief set relative direction
298   \param relDir to its parent
299
300   it is very importand, that you use this function, if you want to update the
301   relDirection. If you don't use this, the PNode won't recognize, that something
302   has changed and won't update the children Nodes.
303*/
304void PNode::setRelDir (Quaternion* relDir)
305{
306  this->bRelCoorChanged = true;
307  *this->relDirection = *relDir;
308}
309
310
311void PNode::setRelDir (Quaternion relDir)
312{
313  this->bRelCoorChanged = true;
314  *this->relDirection = relDir;
315}
316
317
318/**
319   \brief gets the absolute direction (0,0,1)
320   \returns absolute coordinates
321*/
322//Quaternion PNode::getAbsDir () const
323
324
325
326/**
327   \brief sets the absolute direction (0,0,1)
328   \param absDir absolute coordinates
329
330   it is very importand, that you use this function, if you want to update the
331   absDirection. If you don't use this, the PNode won't recognize, that something
332   has changed and won't update the children Nodes.
333*/
334void PNode::setAbsDir (Quaternion* absDir)
335{
336  this->bAbsDirChanged = true;
337  *this->absDirection = *absDir;
338}
339
340
341
342/**
343   \brief sets the absolute direction (0,0,1)
344   \param absDir absolute coordinates
345
346   it is very importand, that you use this function, if you want to update the
347   absDirection. If you don't use this, the PNode won't recognize, that something
348   has changed and won't update the children Nodes.
349*/
350void PNode::setAbsDir (Quaternion absDir)
351{
352  this->bAbsDirChanged = true;
353  *this->absDirection = absDir;
354}
355
356
357
358/**
359   \brief shift coordinate (abs and rel)
360   \param shift vector
361
362   this function shifts the current coordinates about the vector shift. this is
363   usefull because from some place else you can:
364   PNode* someNode = ...;
365   Quaternion objectMovement = calculateShift();
366   someNode->shiftCoor(objectMovement);
367
368   elsewhere you would have to:
369   PNode* someNode = ...;
370   Quaternion objectMovement = calculateShift();
371   Quaternion currentCoor = someNode->getRelCoor();
372   Quaternion newCoor = currentCoor + objectMovement;
373   someNode->setRelCoor(newCoor);
374   
375   yea right... shorter...
376
377   \todo implement this
378*/
379void PNode::shiftDir (const Quaternion& shift)
380{
381  this->bRelDirChanged = true;
382  *this->relDirection = *this->relDirection * shift;
383}
384
385
386/**
387   \brief shift coordinate (abs and rel)
388   \param shift vector
389
390   this function shifts the current coordinates about the vector shift. this is
391   usefull because from some place else you can:
392   PNode* someNode = ...;
393   Quaternion objectMovement = calculateShift();
394   someNode->shiftCoor(objectMovement);
395
396   elsewhere you would have to:
397   PNode* someNode = ...;
398   Quaternion objectMovement = calculateShift();
399   Quaternion currentCoor = someNode->getRelCoor();
400   Quaternion newCoor = currentCoor + objectMovement;
401   someNode->setRelCoor(newCoor);
402   
403   yea right... shorter...
404
405   \todo implement this
406*/
407void PNode::shiftDir (Quaternion shift)
408{}
409
410
411/**
412   \brief this calculates the current movement speed of the node
413*/
414float PNode::getSpeed() const
415{
416  __UNLIKELY_IF( this->time == 0)
417    return 1000;
418  *this->diffCoordinate = *this->absCoordinate - *this->lastAbsCoordinate;
419  return this->diffCoordinate->len() / this->time;
420}
421
422
423/**
424   \brief adds a child and makes this node to a parent
425   \param pNode child reference
426   \param mode on which changes the child should also change ist state
427
428   use this to add a child to this node.
429*/
430void PNode::addChild (PNode* pNode, int parentingMode)
431{
432
433  __UNLIKELY_IF( pNode->parent != NULL)
434    {
435      PRINTF(3)("PNode::addChild() - reparenting node: removing it and adding it again\n");
436      pNode->parent->children->remove(pNode);
437    }
438  pNode->mode = parentingMode;
439  pNode->parent = this;
440  this->children->add(pNode);
441}
442
443
444/**
445   \brief removes a child from the node
446   \param pNode the child to remove from this pNode.
447
448   Children from pNode will not be lost, they are referenced to NullPointer
449*/
450void PNode::removeChild (PNode* pNode)
451{
452  pNode->remove();
453  this->children->remove (pNode);
454  pNode->parent = NULL;
455}
456
457
458/**
459   \brief remove this pnode from the tree and adds all following to NullParent
460
461   this can be the case, if an entity in the world is been destroyed.
462*/
463void PNode::remove()
464{
465  NullParent* nullParent = NullParent::getInstance();
466
467  tIterator<PNode>* iterator = this->children->getIterator();
468  PNode* pn = iterator->nextElement();
469 
470  while( pn != NULL) 
471    { 
472      //this->children->remove(pn);
473      nullParent->addChild(pn, pn->getMode());
474      pn = iterator->nextElement();
475    }
476  delete iterator;
477  this->parent->children->remove(this);
478}
479
480
481/**
482   \brief sets the parent of this PNode
483   \param parent the Parent to set
484*/
485void PNode::setParent (PNode* parent)
486{
487  parent->addChild(this);
488}
489
490
491/**
492   \brief set the mode of this parent manualy
493   \param mode the mode of the bind-type.
494*/
495void PNode::setMode (int parentingMode)
496{
497  this->mode = parentingMode;
498}
499
500
501/**
502   \brief gets the mode of this parent manualy
503   \return the mode of the bind-type.
504*/
505int PNode::getMode()
506{
507  return this->mode;
508}
509
510/**
511   \brief has to be called, if the parent coordinate has changed
512   
513   normaly this will be done by the parent itself automaticaly. If you call this, you
514   will force an update of the coordinated of the node.
515*/
516void PNode::parentCoorChanged ()
517{
518  this->bRelCoorChanged = true;
519}
520
521
522/**
523   \brief has to be called, if the parent direction has changed
524   
525   normaly this will be done by the parent itself automaticaly. If you call this, you
526   will force an update of the direction of the node.
527*/
528void PNode::parentDirChanged ()
529{
530  this->bRelDirChanged = true;
531}
532
533
534/**
535   \brief updates the absCoordinate/absDirection
536   \param timeStamp The timestanp used for to look if calculations should be done
537
538   this is used to go through the parent-tree to update all the absolute coordinates
539   and directions. this update should be done by the engine, so you don't have to
540   worry, normaly...
541*/
542void PNode::update (float dt)
543{
544  *this->lastAbsCoordinate = *this->absCoordinate;
545  this->time = dt;
546  PRINTF(4)("PNode::update - %s - (%f, %f, %f)\n", this->objectName, this->absCoordinate->x, this->absCoordinate->y, this->absCoordinate->z);
547
548
549  __LIKELY_IF( this->mode & PNODE_MOVEMENT)
550    {
551      __UNLIKELY_IF(this->bAbsCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
552        {
553          /* if you have set the absolute coordinates this overrides all other changes */
554          *this->relCoordinate = *this->absCoordinate - parent->getAbsCoor ();
555        }
556      __LIKELY_IF(this->bRelCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
557
558        {
559          /*this is bad style... must be deleted later - just for testing*/
560
561          /*
562          __UNLIKELY_IF( this->parent == NULL)
563            {
564              *this->absCoordinate = *this->relCoordinate;
565            }
566            else */
567          *this->absCoordinate = parent->getAbsCoor() + *this->relCoordinate;         /* update the current absCoordinate */
568        }
569    }
570 
571  if( this->mode & PNODE_LOCAL_ROTATE)
572    {
573      __UNLIKELY_IF( this->bAbsDirChanged /*&& this->timeStamp != DataTank::timeStamp*/)
574        {
575          /* if you have set the absolute coordinates this overrides all other changes */
576          *this->relDirection = *this->absDirection - parent->getAbsDir();
577        }
578      else __LIKELY_IF( this->bRelDirChanged /*&& this->timeStamp != DataTank::timeStamp*/)
579        {
580          /* update the current absDirection - remember * means rotation around sth.*/
581          *this->absDirection = parent->getAbsDir() * *this->relDirection;
582        }
583    }
584 
585  if( this->mode & PNODE_ROTATE_MOVEMENT)
586    {
587      __UNLIKELY_IF( this->bAbsCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
588        {
589          /* if you have set the absolute coordinates this overrides all other changes */
590          *this->relCoordinate = *this->absCoordinate - parent->getAbsCoor ();
591        }
592      else __LIKELY_IF( this->bRelCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
593        {
594          /*this is bad style... must be deleted later - just for testing*/
595          /*if( this->parent == NULL)
596            *this->absCoordinate = *this->relCoordinate;
597            else*/
598          *this->absCoordinate = parent->getAbsCoor() + parent->getAbsDir().apply(*this->relCoordinate);              /* update the current absCoordinate */
599        }
600    }
601 
602 
603  tIterator<PNode>* iterator = this->children->getIterator();
604  //PNode* pn = this->children->enumerate();
605  PNode* pn = iterator->nextElement();
606  while( pn != NULL) 
607    { 
608      /* if this node has changed, make sure, that all children are updated also */
609      __LIKELY_IF( this->bRelCoorChanged || this->bAbsCoorChanged)
610        pn->parentCoorChanged ();
611      __LIKELY_IF( this->bRelDirChanged || this->bAbsDirChanged)
612        pn->parentDirChanged ();
613
614      pn->update(dt);
615      //pn = this->children->nextElement();
616      pn = iterator->nextElement();
617    }
618  delete iterator;
619
620  this->timeStamp = timeStamp;
621  this->bRelCoorChanged = false;
622  this->bAbsCoorChanged = false;
623  this->bRelDirChanged = false;
624  this->bAbsDirChanged = false;
625}
626
627
628/**
629  \brief tick
630  \param dt time to tick
631*/
632void PNode::processTick (float dt)
633{
634  //this->tick (dt);
635  PNode* pn = this->children->enumerate();
636  while( pn != NULL) 
637    { 
638      pn->processTick (dt);
639      pn = this->children->nextElement();
640    } 
641}
642
643
644/**
645   \brief displays some information about this pNode
646*/
647void PNode::debug()
648{
649  PRINTF(2)("PNode::debug() - absCoord: (%f, %f, %f)\n", 
650         this->absCoordinate->x, 
651         this->absCoordinate->y,
652         this->absCoordinate->z);
653}
654
655
656/**
657  \brief set the name of the node
658
659  for debug purposes realy usefull, not used to work properly
660*/
661void PNode::setName (char* newName)
662{
663  this->objectName = new char[strlen(newName)+1];
664  strcpy(this->objectName,newName);
665}
666
667
668/**
669  \brief gets the name of the node
670*/
671char* PNode::getName ()
672{
673  return this->objectName;
674}
675
Note: See TracBrowser for help on using the repository browser.