Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: implemented garbage collector, is not yet collecting, i have to update the list.h first.

File size: 12.9 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
32//#include "vector.h"
33//#include "quaternion.h"
34
35using namespace std;
36
37
38/**
39   \brief standard constructor
40
41   \todo this constructor is not jet implemented - do it
42*/
43PNode::PNode () 
44{
45  init(NULL);
46
47  NullParent* np = NullParent::getInstance();
48  np->addChild(this);
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 (Vector* absCoordinate, PNode* parent )
58{
59  this->init(parent);
60
61  *this->absCoordinate = *absCoordinate;
62  if (parent != NULL)
63    {
64      *this->relCoordinate = *this->absCoordinate - parent->getAbsCoor ();
65      parent->addChild (this);
66    }
67  else 
68    this->relCoordinate = new Vector(0,0,0);
69}
70
71/**
72   \brief standard deconstructor
73
74   \todo this deconstructor is not jet implemented - do it
75*/
76PNode::~PNode () 
77{
78  /*
79  delete &this->children;
80  delete &this->relCoordinate;
81  delete &this->absCoordinate;
82  delete &this->relDirection;
83  delete &this->absDirection;
84  */
85  //this->parent = NULL;
86  /* there is currently a problem with cleaning up - fix*/
87
88  PNode* pn = this->children->enumerate();
89  while( pn != NULL) 
90    { 
91      delete pn;
92      pn = this->children->nextElement();
93
94    }
95   
96  /* this deletes all children in the list */
97  delete this->children;
98
99  delete []this->objectName;
100}
101
102
103void PNode::init(PNode* parent)
104{
105  this->children = new tList<PNode>();
106  this->bRelCoorChanged = true;
107  this->bAbsCoorChanged = false;
108  this->bRelDirChanged = true;
109  this->bAbsDirChanged = false;
110  this->parent = parent; 
111  this->objectName = NULL;
112
113  this->absCoordinate = new Vector();
114  this->relCoordinate = new Vector();
115  this->absDirection = new Quaternion();
116  this->relDirection = new Quaternion();
117  this->lastAbsCoordinate = new Vector();
118}
119
120/**
121   \brief deletes the hole pnode tree
122
123   cleans up all pnodes
124*/
125/*
126void PNode::destroy ()
127{
128  PNode* pn = this->children->enumerate();
129  while( pn != NULL)
130    {
131      pn->destroy ();
132      pn = this->children->nextElement();
133    }
134  // this deletes all children in the list
135  this->children->destroy ();
136
137  static_cast<BaseObject*>(this)->destroy();
138}
139*/
140
141/**
142   \brief get relative coordinates
143   \returns relative coordinates to its parent
144*/
145Vector PNode::getRelCoor ()
146{
147  Vector r = *this->relCoordinate; /* return a copy, so it can't be modified */
148  return r;
149}
150
151
152/**
153   \brief set relative coordinates
154   \param relCoord relative coordinates to its parent
155
156   it is very importand, that you use this function, if you want to update the
157   relCoordinates. If you don't use this, the PNode won't recognize, that something
158   has changed and won't update the children Nodes.
159*/
160void PNode::setRelCoor (Vector* relCoord)
161{
162  this->bRelCoorChanged = true;
163  *this->relCoordinate = *relCoord;
164}
165
166
167/**
168   \brief get absolute coordinates
169   \returns absolute coordinates from (0,0,0)
170*/
171Vector PNode::getAbsCoor ()
172{
173  return *this->absCoordinate;
174}
175
176
177/**
178   \param absCoord set absolute coordinate
179
180   it is very importand, that you use this function, if you want to update the
181   absCoordinates. If you don't use this, the PNode won't recognize, that something
182   has changed and won't update the children Nodes.
183*/
184void PNode::setAbsCoor (Vector* absCoord)
185{
186  this->bAbsCoorChanged = true;
187  *this->absCoordinate = *absCoord;
188}
189
190
191/**
192   \brief shift coordinate (abs and rel)
193   \param shift vector
194
195   this function shifts the current coordinates about the vector shift. this is
196   usefull because from some place else you can:
197   PNode* someNode = ...;
198   Vector objectMovement = calculateShift();
199   someNode->shiftCoor(objectMovement);
200
201   elsewhere you would have to:
202   PNode* someNode = ...;
203   Vector objectMovement = calculateShift();
204   Vector currentCoor = someNode->getRelCoor();
205   Vector newCoor = currentCoor + objectMovement;
206   someNode->setRelCoor(newCoor);
207   
208   yea right... shorter...
209
210*/
211void PNode::shiftCoor (Vector* shift)
212{
213  if( this->bAbsCoorChanged)
214    {
215      *this->absCoordinate = *this->absCoordinate + *shift;
216    }
217  else 
218    {
219      *this->relCoordinate = *this->relCoordinate + *shift;
220      this->bRelCoorChanged = true;
221    }
222}
223
224
225
226/**
227   \brief get relative direction
228   \returns relative direction to its parent
229*/
230Quaternion PNode::getRelDir ()
231{
232  return *this->relDirection;
233}
234
235
236/**
237   \brief set relative direction
238   \param relDir to its parent
239
240   it is very importand, that you use this function, if you want to update the
241   relDirection. If you don't use this, the PNode won't recognize, that something
242   has changed and won't update the children Nodes.
243*/
244void PNode::setRelDir (Quaternion* relDir)
245{
246  this->bRelCoorChanged = true;
247  *this->relDirection = *relDir;
248}
249
250
251/**
252   \brief gets the absolute direction (0,0,1)
253   \returns absolute coordinates
254*/
255Quaternion PNode::getAbsDir ()
256{
257  return *this->absDirection;
258}
259
260
261/**
262   \brief sets the absolute direction (0,0,1)
263   \param absDir absolute coordinates
264
265   it is very importand, that you use this function, if you want to update the
266   absDirection. If you don't use this, the PNode won't recognize, that something
267   has changed and won't update the children Nodes.
268*/
269void PNode::setAbsDir (Quaternion* absDir)
270{
271  this->bAbsDirChanged = true;
272  *this->absDirection = *absDir;
273}
274
275
276/**
277   \brief shift coordinate (abs and rel)
278   \param shift vector
279
280   this function shifts the current coordinates about the vector shift. this is
281   usefull because from some place else you can:
282   PNode* someNode = ...;
283   Quaternion objectMovement = calculateShift();
284   someNode->shiftCoor(objectMovement);
285
286   elsewhere you would have to:
287   PNode* someNode = ...;
288   Quaternion objectMovement = calculateShift();
289   Quaternion currentCoor = someNode->getRelCoor();
290   Quaternion newCoor = currentCoor + objectMovement;
291   someNode->setRelCoor(newCoor);
292   
293   yea right... shorter...
294
295   \todo implement this
296*/
297void PNode::shiftDir (Quaternion* shift)
298{}
299
300
301/**
302   \brief this calculates the current movement speed of the node
303*/
304float PNode::getSpeed()
305{
306  if(this->time == 0)
307    return 0;
308  Vector* diff = new Vector();
309  *diff = *this->absCoordinate - *this->lastAbsCoordinate;
310  float x = diff->len();
311  return x / this->time;
312}
313
314
315/**
316   \brief adds a child and makes this node to a parent
317   \param pNode child reference
318
319   use this to add a child to this node.
320*/
321void PNode::addChild (PNode* pNode)
322{
323  this->addChild(pNode, DEFAULT_MODE);
324}
325
326
327/**
328   \brief adds a child and makes this node to a parent
329   \param pNode child reference
330   \param mode on which changes the child should also change ist state
331
332   use this to add a child to this node.
333*/
334void PNode::addChild (PNode* pNode, int parentingMode)
335{
336  if( pNode->parent != NULL )
337    {
338      PRINTF(2)("PNode::addChild() - reparenting node: removing it and adding it again\n");
339      pNode->parent->children->remove(pNode);
340    }
341  pNode->mode = parentingMode;
342  pNode->parent = this;
343  this->children->add(pNode);
344}
345
346
347/**
348   \brief removes a child from the node
349   \param pNode the child to remove from this pNode.
350
351   Children from pNode will not be lost, they are referenced to NullPointer
352*/
353void PNode::removeChild (PNode* pNode)
354{
355  pNode->remove();
356  //this->children->remove (pNode);
357  pNode->parent = NULL;
358}
359
360
361/**
362   \brief remove this pnode from the tree and adds all following to NullParent
363
364   this can be the case, if an entity in the world is been destroyed.
365*/
366void PNode::remove()
367{
368  NullParent* np = NullParent::getInstance();
369  PNode* pn = this->children->enumerate();
370  while( pn != NULL) 
371    { 
372      this->children->remove(pn);
373      np->addChild(pn, pn->getMode());
374      pn = this->children->nextElement();
375    }
376}
377
378
379/**
380   \brief sets the parent of this PNode
381   \param parent the Parent to set
382*/
383void PNode::setParent (PNode* parent)
384{
385  parent->addChild(this);
386}
387
388
389/**
390   \brief set the mode of this parent manualy
391   \param mode the mode of the bind-type.
392*/
393void PNode::setMode (int parentingMode)
394{
395  this->mode = parentingMode;
396}
397
398
399/**
400   \brief gets the mode of this parent manualy
401   \return the mode of the bind-type.
402*/
403int PNode::getMode()
404{
405  return this->mode;
406}
407
408/**
409   \brief has to be called, if the parent coordinate has changed
410   
411   normaly this will be done by the parent itself automaticaly. If you call this, you
412   will force an update of the coordinated of the node.
413*/
414void PNode::parentCoorChanged ()
415{
416  this->bRelCoorChanged = true;
417}
418
419
420/**
421   \brief has to be called, if the parent direction has changed
422   
423   normaly this will be done by the parent itself automaticaly. If you call this, you
424   will force an update of the direction of the node.
425*/
426void PNode::parentDirChanged ()
427{
428  this->bRelDirChanged = true;
429}
430
431
432/**
433   \brief updates the absCoordinate/absDirection
434   \param timeStamp The timestanp used for to look if calculations should be done
435
436   this is used to go through the parent-tree to update all the absolute coordinates
437   and directions. this update should be done by the engine, so you don't have to
438   worry, normaly...
439*/
440void PNode::update (float dt)
441{
442  this->time = dt;
443  PRINTF(4)("PNode::update - %s - (%f, %f, %f)\n", this->objectName, this->absCoordinate->x, this->absCoordinate->y, this->absCoordinate->z);
444  // printf("%s", this->objectName);
445  if(this->mode & PNODE_MOVEMENT )
446    {
447      if( this->bAbsCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
448        {
449          /* if you have set the absolute coordinates this overrides all other changes */
450          *this->relCoordinate = *this->absCoordinate - parent->getAbsCoor ();
451        }
452      else if( this->bRelCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
453        {
454          /*this is bad style... must be deleted later - just for testing*/
455          if( this->parent == NULL)
456            {
457              *this->absCoordinate = *this->relCoordinate;
458            }
459          else
460            *this->absCoordinate = parent->getAbsCoor() + *this->relCoordinate;       /* update the current absCoordinate */
461        }
462    }
463 
464  if( this->mode & PNODE_LOCAL_ROTATE)
465    {
466      if( this->bAbsDirChanged /*&& this->timeStamp != DataTank::timeStamp*/)
467        {
468          /* if you have set the absolute coordinates this overrides all other changes */
469          *this->relDirection = *this->absDirection - parent->getAbsDir();
470        }
471      else if( this->bRelDirChanged /*&& this->timeStamp != DataTank::timeStamp*/)
472        {
473          /* update the current absDirection - remember * means rotation around sth.*/
474          *this->absDirection = parent->getAbsDir() * *this->relDirection;
475        }
476    }
477 
478  if( this->mode & PNODE_ROTATE_MOVEMENT)
479    {
480      if( this->bAbsCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
481        {
482          /* if you have set the absolute coordinates this overrides all other changes */
483          *this->relCoordinate = *this->absCoordinate - parent->getAbsCoor ();
484        }
485      else if( this->bRelCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
486        {
487          /*this is bad style... must be deleted later - just for testing*/
488          if( this->parent == NULL)
489            *this->absCoordinate = *this->relCoordinate;
490          else
491            *this->absCoordinate = parent->getAbsCoor() + parent->getAbsDir().apply(*this->relCoordinate);            /* update the current absCoordinate */
492        }
493    }
494 
495 
496  PNode* pn = this->children->enumerate();
497  while( pn != NULL) 
498    { 
499      /* if this node has changed, make sure, that all children are updated also */
500      if( this->bRelCoorChanged || this->bAbsCoorChanged)
501        pn->parentCoorChanged ();
502      if( this->bRelDirChanged || this->bAbsDirChanged)
503        pn->parentDirChanged ();
504
505      pn->update(dt);
506      pn = this->children->nextElement();
507    }
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.