Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: changed pnode interface of setRelCoor and setRelDir

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