Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk:make

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* nullParent = NullParent::getInstance();
369
370  PNode* pn = this->children->enumerate();
371  while( pn != NULL) 
372    { 
373      //this->children->remove(pn);
374      nullParent->addChild(pn, pn->getMode());
375      pn = this->children->nextElement();
376    }
377}
378
379
380/**
381   \brief sets the parent of this PNode
382   \param parent the Parent to set
383*/
384void PNode::setParent (PNode* parent)
385{
386  parent->addChild(this);
387}
388
389
390/**
391   \brief set the mode of this parent manualy
392   \param mode the mode of the bind-type.
393*/
394void PNode::setMode (int parentingMode)
395{
396  this->mode = parentingMode;
397}
398
399
400/**
401   \brief gets the mode of this parent manualy
402   \return the mode of the bind-type.
403*/
404int PNode::getMode()
405{
406  return this->mode;
407}
408
409/**
410   \brief has to be called, if the parent coordinate 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 coordinated of the node.
414*/
415void PNode::parentCoorChanged ()
416{
417  this->bRelCoorChanged = true;
418}
419
420
421/**
422   \brief has to be called, if the parent direction has changed
423   
424   normaly this will be done by the parent itself automaticaly. If you call this, you
425   will force an update of the direction of the node.
426*/
427void PNode::parentDirChanged ()
428{
429  this->bRelDirChanged = true;
430}
431
432
433/**
434   \brief updates the absCoordinate/absDirection
435   \param timeStamp The timestanp used for to look if calculations should be done
436
437   this is used to go through the parent-tree to update all the absolute coordinates
438   and directions. this update should be done by the engine, so you don't have to
439   worry, normaly...
440*/
441void PNode::update (float dt)
442{
443  this->time = dt;
444  PRINTF(4)("PNode::update - %s - (%f, %f, %f)\n", this->objectName, this->absCoordinate->x, this->absCoordinate->y, this->absCoordinate->z);
445  // printf("%s", this->objectName);
446  if(this->mode & PNODE_MOVEMENT )
447    {
448      if( this->bAbsCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
449        {
450          /* if you have set the absolute coordinates this overrides all other changes */
451          *this->relCoordinate = *this->absCoordinate - parent->getAbsCoor ();
452        }
453      else if( this->bRelCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
454        {
455          /*this is bad style... must be deleted later - just for testing*/
456          if( this->parent == NULL)
457            {
458              *this->absCoordinate = *this->relCoordinate;
459            }
460          else
461            *this->absCoordinate = parent->getAbsCoor() + *this->relCoordinate;       /* update the current absCoordinate */
462        }
463    }
464 
465  if( this->mode & PNODE_LOCAL_ROTATE)
466    {
467      if( this->bAbsDirChanged /*&& this->timeStamp != DataTank::timeStamp*/)
468        {
469          /* if you have set the absolute coordinates this overrides all other changes */
470          *this->relDirection = *this->absDirection - parent->getAbsDir();
471        }
472      else if( this->bRelDirChanged /*&& this->timeStamp != DataTank::timeStamp*/)
473        {
474          /* update the current absDirection - remember * means rotation around sth.*/
475          *this->absDirection = parent->getAbsDir() * *this->relDirection;
476        }
477    }
478 
479  if( this->mode & PNODE_ROTATE_MOVEMENT)
480    {
481      if( this->bAbsCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
482        {
483          /* if you have set the absolute coordinates this overrides all other changes */
484          *this->relCoordinate = *this->absCoordinate - parent->getAbsCoor ();
485        }
486      else if( this->bRelCoorChanged /*&& this->timeStamp != DataTank::timeStamp*/)
487        {
488          /*this is bad style... must be deleted later - just for testing*/
489          if( this->parent == NULL)
490            *this->absCoordinate = *this->relCoordinate;
491          else
492            *this->absCoordinate = parent->getAbsCoor() + parent->getAbsDir().apply(*this->relCoordinate);            /* update the current absCoordinate */
493        }
494    }
495 
496 
497  PNode* pn = this->children->enumerate();
498  while( pn != NULL) 
499    { 
500      /* if this node has changed, make sure, that all children are updated also */
501      if( this->bRelCoorChanged || this->bAbsCoorChanged)
502        pn->parentCoorChanged ();
503      if( this->bRelDirChanged || this->bAbsDirChanged)
504        pn->parentDirChanged ();
505
506      pn->update(dt);
507      pn = this->children->nextElement();
508    }
509
510  this->timeStamp = timeStamp;
511  this->bRelCoorChanged = false;
512  this->bAbsCoorChanged = false;
513  this->bRelDirChanged = false;
514  this->bAbsDirChanged = false;
515}
516
517
518/**
519  \brief tick
520  \param dt time to tick
521*/
522void PNode::processTick (float dt)
523{
524  //this->tick (dt);
525  PNode* pn = this->children->enumerate();
526  while( pn != NULL) 
527    { 
528      pn->processTick (dt);
529      pn = this->children->nextElement();
530    } 
531}
532
533
534/**
535   \brief displays some information about this pNode
536*/
537void PNode::debug()
538{
539  PRINTF(2)("PNode::debug() - absCoord: (%f, %f, %f)\n", 
540         this->absCoordinate->x, 
541         this->absCoordinate->y,
542         this->absCoordinate->z);
543}
544
545
546/**
547  \brief set the name of the node
548
549  for debug purposes realy usefull, not used to work properly
550*/
551void PNode::setName (char* newName)
552{
553  this->objectName = new char[strlen(newName)+1];
554  strcpy(this->objectName,newName);
555}
556
557
558/**
559  \brief gets the name of the node
560*/
561char* PNode::getName ()
562{
563  return this->objectName;
564}
565
Note: See TracBrowser for help on using the repository browser.