Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3820 was 3813, checked in by patrick, 20 years ago

orxonox/trunk: finished work on tweaking pnode. pnode is now as fast as it can get:)

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