Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/particleEngine/src/lib/coord/p_node.cc @ 3938

Last change on this file since 3938 was 3938, checked in by bensch, 19 years ago

orxonox/branches/particleEngine: inherit speed from emitter is now also an option
for this i had to write a new PNode function, getVelocity (patrick: you could also use this one in the shoot-class, maybe).

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