Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/single_player_map/src/world_entities/world_entity.cc @ 8941

Last change on this file since 8941 was 8941, checked in by patrick, 18 years ago

isOnGround bug found and repair station workd

File size: 21.6 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: Christian Meyer
16*/
17#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD_ENTITY
18
19#include "world_entity.h"
20#include "shell_command.h"
21
22#include "model.h"
23#include "md2/md2Model.h"
24#include "md3/md3_model.h"
25
26#include "aabb_tree_node.h"
27
28#include "util/loading/resource_manager.h"
29#include "util/loading/load_param.h"
30#include "vector.h"
31#include "obb_tree.h"
32
33#include "glgui_bar.h"
34
35#include "state.h"
36#include "camera.h"
37
38#include "collision_handle.h"
39#include "collision_event.h"
40#include "game_rules.h"
41#include "kill.h"
42
43#include <stdarg.h>
44
45
46using namespace std;
47
48SHELL_COMMAND(model, WorldEntity, loadModel)
49->describe("sets the Model of the WorldEntity")
50->defaultValues("models/ships/fighter.obj", 1.0f);
51
52SHELL_COMMAND(debugEntity, WorldEntity, debugWE);
53
54/**
55 *  Loads the WordEntity-specific Part of any derived Class
56 *
57 * @param root: Normally NULL, as the Derived Entities define a loadParams Function themeselves,
58 *              that can calls WorldEntities loadParams for itself.
59 */
60WorldEntity::WorldEntity()
61    : Synchronizeable()
62{
63  this->setClassID(CL_WORLD_ENTITY, "WorldEntity");
64
65  this->obbTree = NULL;
66  this->aabbNode = NULL;
67  this->healthWidget = NULL;
68  this->healthMax = 1.0f;
69  this->health = 1.0f;
70  this->damage = 0.0f; // no damage dealt by a default entity
71  this->scaling = 1.0f;
72
73  /* OSOLETE */
74  this->bVisible = true;
75  this->bCollide = true;
76
77  this->objectListNumber = OM_INIT;
78  this->lastObjectListNumber = OM_INIT;
79  this->objectListIterator = NULL;
80
81  // reset all collision handles to NULL == unsubscribed state
82  for(int i = 0; i < CREngine::CR_NUMBER; ++i)
83    this->collisionHandles[i] = NULL;
84  this->bReactive = false;
85  this->bOnGround = false;
86
87  // registering default reactions:
88  this->subscribeReaction(CREngine::CR_OBJECT_DAMAGE, CL_WORLD_ENTITY);
89
90  this->toList(OM_NULL);
91
92  modelFileName_handle = registerVarId( new SynchronizeableString( &modelFileName, &modelFileName, "modelFileName" ) );
93  scaling_handle = registerVarId( new SynchronizeableFloat( &scaling, &scaling, "scaling" ) );
94}
95
96/**
97 *  standard destructor
98*/
99WorldEntity::~WorldEntity ()
100{
101  State::getObjectManager()->toList(this, OM_INIT);
102
103  // Delete the model (unregister it with the ResourceManager)
104  for (unsigned int i = 0; i < this->models.size(); i++)
105    this->setModel(NULL, i);
106
107  // Delete the obbTree
108  if( this->obbTree != NULL)
109    delete this->obbTree;
110
111  if (this->healthWidget != NULL)
112    delete this->healthWidget;
113
114  this->unsubscribeReaction();
115}
116
117/**
118 * loads the WorldEntity Specific Parameters.
119 * @param root: the XML-Element to load the Data From
120 */
121void WorldEntity::loadParams(const TiXmlElement* root)
122{
123  // Do the PNode loading stuff
124  PNode::loadParams(root);
125
126  LoadParam(root, "md2texture", this, WorldEntity, loadMD2Texture)
127  .describe("the fileName of the texture, that should be loaded onto this world-entity. (must be relative to the data-dir)")
128  .defaultValues("");
129
130  // Model Loading
131  LoadParam(root, "model", this, WorldEntity, loadModel)
132  .describe("the fileName of the model, that should be loaded onto this world-entity. (must be relative to the data-dir)")
133  .defaultValues("", 1.0f, 0);
134
135  LoadParam(root, "maxHealth", this, WorldEntity, setHealthMax)
136  .describe("The Maximum health that can be loaded onto this entity")
137  .defaultValues(1.0f);
138
139  LoadParam(root, "health", this, WorldEntity, setHealth)
140  .describe("The Health the WorldEntity has at this moment")
141  .defaultValues(1.0f);
142}
143
144
145/**
146 * loads a Model onto a WorldEntity
147 * @param fileName the name of the model to load
148 * @param scaling the Scaling of the model
149 *
150 * FIXME
151 * @todo: separate the obb tree generation from the model
152 */
153void WorldEntity::loadModel(const std::string& fileName, float scaling, unsigned int modelNumber, unsigned int obbTreeDepth)
154{
155  this->modelLODName = fileName;
156  this->scaling = scaling;
157
158  std::string name = fileName;
159
160  if (  name.find( ResourceManager::getInstance()->getDataDir() ) == 0 )
161  {
162    name.erase(ResourceManager::getInstance()->getDataDir().size());
163  }
164
165  this->modelFileName = name;
166
167  if (!fileName.empty())
168  {
169    // search for the special character # in the LoadParam
170    if (fileName.find('#') != std::string::npos)
171    {
172      PRINTF(4)("Found # in %s... searching for LOD's\n", fileName.c_str());
173      std::string lodFile = fileName;
174      unsigned int offset = lodFile.find('#');
175      for (unsigned int i = 0; i < 3; i++)
176      {
177        lodFile[offset] = 48+(int)i;
178        if (ResourceManager::isInDataDir(lodFile))
179          this->loadModel(lodFile, scaling, i);
180      }
181      return;
182    }
183    if (this->scaling <= 0.0)
184    {
185      PRINTF(1)("YOU GAVE ME A CRAPY SCALE resetting to 1.0\n");
186      this->scaling = 1.0;
187    }
188    if(fileName.find(".obj") != std::string::npos)
189    {
190      PRINTF(4)("fetching OBJ file: %s\n", fileName.c_str());
191      BaseObject* loadedModel = ResourceManager::getInstance()->load(fileName, OBJ, RP_CAMPAIGN, this->scaling);
192      if (loadedModel != NULL)
193        this->setModel(dynamic_cast<Model*>(loadedModel), modelNumber);
194      else
195        PRINTF(1)("OBJ-File %s not found.\n", fileName.c_str());
196
197      if( modelNumber == 0 && !this->isA(CL_WEAPON))
198        this->buildObbTree(obbTreeDepth);
199    }
200    else if(fileName.find(".md2") != std::string::npos)
201    {
202      PRINTF(4)("fetching MD2 file: %s\n", fileName.c_str());
203      Model* m = new MD2Model(fileName, this->md2TextureFileName, this->scaling);
204      //this->setModel((Model*)ResourceManager::getInstance()->load(fileName, MD2, RP_CAMPAIGN), 0);
205      this->setModel(m, 0);
206
207      if( m != NULL)
208        this->buildObbTree(obbTreeDepth);
209    }
210    else /*if(fileName.find(".md3") != std::string::npos)*/
211    {
212      PRINTF(4)("fetching MD3 file: %s\n", fileName.c_str());
213      Model* m = new md3::MD3Model(fileName, this->scaling);
214      this->setModel(m, 0);
215
216//       if( m != NULL)
217//         this->buildObbTree(obbTreeDepth);
218    }
219  }
220  else
221  {
222    this->setModel(NULL);
223  }
224}
225
226/**
227 * sets a specific Model for the Object.
228 * @param model The Model to set
229 * @param modelNumber the n'th model in the List to get.
230 */
231void WorldEntity::setModel(Model* model, unsigned int modelNumber)
232{
233  if (this->models.size() <= modelNumber)
234    this->models.resize(modelNumber+1, NULL);
235
236  if (this->models[modelNumber] != NULL)
237  {
238    Resource* resource = ResourceManager::getInstance()->locateResourceByPointer(dynamic_cast<BaseObject*>(this->models[modelNumber]));
239    if (resource != NULL)
240      ResourceManager::getInstance()->unload(resource, RP_LEVEL);
241    else
242    {
243      PRINTF(4)("Forcing model deletion\n");
244      delete this->models[modelNumber];
245    }
246  }
247
248  this->models[modelNumber] = model;
249}
250
251
252/**
253 * builds the obb-tree
254 * @param depth the depth to calculate
255 */
256bool WorldEntity::buildObbTree(int depth)
257{
258  if (this->obbTree)
259    delete this->obbTree;
260
261  if (this->models[0] != NULL)
262    this->obbTree = new OBBTree(depth, models[0]->getModelInfo(), this);
263  else
264  {
265    PRINTF(1)("could not create obb-tree, because no model was loaded yet\n");
266    this->obbTree = NULL;
267    return false;
268  }
269
270
271  // create the axis aligned bounding box
272  if( this->aabbNode != NULL)
273  {
274    delete this->aabbNode;
275    this->aabbNode = NULL;
276  }
277
278  if( this->models[0] != NULL) {
279    this->aabbNode = new AABBTreeNode();
280    this->aabbNode->spawnBVTree(this->models[0]);
281  }
282  return true;
283}
284
285
286/**
287 * subscribes this world entity to a collision reaction
288 *  @param type the type of reaction to subscribe to
289 *  @param target1 a filter target (classID)
290 */
291void WorldEntity::subscribeReaction(CREngine::CRType type, long target1)
292{
293  this->subscribeReaction(type);
294
295  // add the target filter
296  this->collisionHandles[type]->addTarget(target1);
297}
298
299
300/**
301 * subscribes this world entity to a collision reaction
302 *  @param type the type of reaction to subscribe to
303 *  @param target1 a filter target (classID)
304 */
305void WorldEntity::subscribeReaction(CREngine::CRType type, long target1, long target2)
306{
307  this->subscribeReaction(type);
308
309  // add the target filter
310  this->collisionHandles[type]->addTarget(target1);
311  this->collisionHandles[type]->addTarget(target2);
312}
313
314
315/**
316 * subscribes this world entity to a collision reaction
317 *  @param type the type of reaction to subscribe to
318 *  @param target1 a filter target (classID)
319 */
320void WorldEntity::subscribeReaction(CREngine::CRType type, long target1, long target2, long target3)
321{
322  this->subscribeReaction(type);
323
324  // add the target filter
325  this->collisionHandles[type]->addTarget(target1);
326  this->collisionHandles[type]->addTarget(target2);
327  this->collisionHandles[type]->addTarget(target3);
328}
329
330
331/**
332 * subscribes this world entity to a collision reaction
333 *  @param type the type of reaction to subscribe to
334 *  @param target1 a filter target (classID)
335 */
336void WorldEntity::subscribeReaction(CREngine::CRType type, long target1, long target2, long target3, long target4)
337{
338  this->subscribeReaction(type);
339
340  // add the target filter
341  this->collisionHandles[type]->addTarget(target1);
342  this->collisionHandles[type]->addTarget(target2);
343  this->collisionHandles[type]->addTarget(target3);
344  this->collisionHandles[type]->addTarget(target4);
345}
346
347
348/**
349 * subscribes this world entity to a collision reaction
350 *  @param type the type of reaction to subscribe to
351 *  @param nrOfTargets number of target filters
352 *  @param ... the targets as classIDs
353 */
354void WorldEntity::subscribeReaction(CREngine::CRType type)
355{
356  if( this->collisionHandles[type] != NULL)  {
357    PRINTF(2)("Registering for a CollisionReaction already subscribed to! Skipping\n");
358    return;
359  }
360
361  this->collisionHandles[type] = CREngine::getInstance()->subscribeReaction(this, type);
362
363  // now there is at least one collision reaction subscribed
364  this->bReactive = true;
365}
366
367
368/**
369 * unsubscribes a specific reaction from the worldentity
370 *  @param type the reaction to unsubscribe
371 */
372void WorldEntity::unsubscribeReaction(CREngine::CRType type)
373{
374  if( this->collisionHandles[type] == NULL)
375    return;
376
377  CREngine::getInstance()->unsubscribeReaction(this->collisionHandles[type]);
378  this->collisionHandles[type] = NULL;
379
380  // check if there is still any handler registered
381  for(int i = 0; i < CREngine::CR_NUMBER; ++i)
382  {
383    if( this->collisionHandles[i] != NULL)
384    {
385      this->bReactive = true;
386      return;
387    }
388  }
389  this->bReactive = false;
390}
391
392
393/**
394 * unsubscribes all collision reactions
395 */
396void WorldEntity::unsubscribeReaction()
397{
398  for( int i = 0; i < CREngine::CR_NUMBER; i++)
399    this->unsubscribeReaction((CREngine::CRType)i);
400
401  // there are no reactions subscribed from now on
402  this->bReactive = false;
403}
404
405
406/**
407 * registers a new collision event to this world entity
408 *  @param entityA entity of the collision
409 *  @param entityB entity of the collision
410 *  @param bvA colliding bounding volume of entityA
411 *  @param bvB colliding bounding volume of entityA
412 */
413bool WorldEntity::registerCollision(WorldEntity* entityA, WorldEntity* entityB, BoundingVolume* bvA, BoundingVolume* bvB)
414{
415  // is there any handler listening?
416  if( !this->bReactive)
417    return false;
418
419  // get a collision event
420  CollisionEvent* c = CREngine::getInstance()->popCollisionEventObject();
421  assert(c != NULL); // if this should fail: we got not enough precached CollisionEvents: alter value in cr_defs.h
422  c->collide(COLLISION_TYPE_OBB, entityA, entityB, bvA, bvB);
423
424  for( int i = 0; i < CREngine::CR_NUMBER; ++i)
425    if( this->collisionHandles[i] != NULL)
426      this->collisionHandles[i]->registerCollisionEvent(c);
427  return true;
428}
429
430
431/**
432 * registers a new collision event to this woeld entity
433 *  @param entity the entity that collides
434 *  @param plane it stands on
435 *  @param position it collides on the plane
436 */
437bool WorldEntity::registerCollision(int type, WorldEntity* entity, WorldEntity* groundEntity, Vector normal, Vector position, bool bInWall)
438{
439  // is there any handler listening?
440  if( !this->bReactive)
441    return false;
442
443  // get a collision event
444  CollisionEvent* c = CREngine::getInstance()->popCollisionEventObject();
445  assert(c != NULL); // if this should fail: we got not enough precached CollisionEvents: alter value in cr_defs.h
446  c->collide(type, entity, groundEntity, normal, position, bInWall);
447
448  for( int i = 0; i < CREngine::CR_NUMBER; ++i)
449    if( this->collisionHandles[i] != NULL)
450      this->collisionHandles[i]->registerCollisionEvent(c);
451  return true;
452}
453
454
455/**
456 * @brief moves this entity to the List OM_List
457 * @param list the list to set this Entity to.
458 *
459 * this is the same as a call to State::getObjectManager()->toList(entity , list);
460 * directly, but with an easier interface.
461 *
462 * @todo inline this (peut etre)
463 */
464void WorldEntity::toList(OM_LIST list)
465{
466  State::getObjectManager()->toList(this, list);
467}
468
469void WorldEntity::toReflectionList()
470{
471  State::getObjectManager()->toReflectionList( this );
472}
473
474void removeFromReflectionList()
475{
476/// TODO
477///  State::getObject
478}
479
480/**
481 * sets the character attributes of a worldentity
482 * @param character attributes
483 *
484 * these attributes don't have to be set, only use them, if you need them
485*/
486//void WorldEntity::setCharacterAttributes(CharacterAttributes* charAttr)
487//{}
488
489
490/**
491 *  this function is called, when two entities collide
492 * @param entity: the world entity with whom it collides
493 *
494 * Implement behaviour like damage application or other miscellaneous collision stuff in this function
495 */
496void WorldEntity::collidesWith(WorldEntity* entity, const Vector& location)
497{
498  /**
499   * THIS IS A DEFAULT COLLISION-Effect.
500   * IF YOU WANT TO CREATE A SPECIFIC COLLISION ON EACH OBJECT
501   * USE::
502   * if (entity->isA(CL_WHAT_YOU_ARE_LOOKING_FOR)) { printf "dothings"; };
503   *
504   * You can always define a default Action.... don't be affraid just test it :)
505   */
506  //  PRINTF(3)("collision %s vs %s @ (%f,%f,%f)\n", this->getClassName(), entity->getClassName(), location.x, location.y, location.z);
507}
508
509
510/**
511 *  this function is called, when two entities collide
512 * @param entity: the world entity with whom it collides
513 *
514 * Implement behaviour like damage application or other miscellaneous collision stuff in this function
515 */
516void WorldEntity::collidesWithGround(const Vector& location)
517{
518  PRINTF(0)("BSP_GROUND: %s collides \n", this->getClassName() );
519}
520
521void WorldEntity::collidesWithGround(const Vector& feet, const Vector& ray_1, const Vector& ray_2)
522{
523
524  // PRINTF(0)("BSP_GROUND: Player collides \n", this->getClassName() );
525
526  Vector v = this->getAbsDirX();
527  v.x *= 10.1;
528  v.y *= 10.1;
529  v.z *= 10.1;
530  Vector u = Vector(0.0,-20.0,0.0);
531
532
533  if(!(this->getAbsCoor().x == ray_2.x && this->getAbsCoor().y == ray_2.y && this->getAbsCoor().z == ray_2.z) )
534  {
535
536  this->setAbsCoor(ray_2 - v);
537
538  }
539    else
540  {
541    if(ray_1.x == this->getAbsCoor().x + v.x && ray_1.y == this->getAbsCoor().y + v.y + 0.1 && ray_1.z ==this->getAbsCoor().z + v.z)
542    {
543      this->setAbsCoor(feet -u );
544    }
545
546    this->setAbsCoor(ray_2 - v);
547
548  }
549
550
551}
552
553/**
554 *  this is called immediately after the Entity has been constructed, initialized and then Spawned into the World
555 *
556 */
557void WorldEntity::postSpawn ()
558{}
559
560
561/**
562 *  this method is called by the world if the WorldEntity leaves the game
563 */
564void WorldEntity::leaveWorld ()
565{}
566
567
568/**
569 * resets the WorldEntity to its initial values. eg. used for multiplayer games: respawning
570 */
571void WorldEntity::reset()
572{}
573
574/**
575 *  this method is called every frame
576 * @param time: the time in seconds that has passed since the last tick
577 *
578 * Handle all stuff that should update with time inside this method (movement, animation, etc.)
579*/
580void WorldEntity::tick(float time)
581{}
582
583
584/**
585 *  the entity is drawn onto the screen with this function
586 *
587 * This is a central function of an entity: call it to let the entity painted to the screen.
588 * Just override this function with whatever you want to be drawn.
589*/
590void WorldEntity::draw() const
591{
592  //PRINTF(0)("(%s::%s)\n", this->getClassName(), this->getName());
593  //  assert(!unlikely(this->models.empty()));
594  {
595    glMatrixMode(GL_MODELVIEW);
596    glPushMatrix();
597
598    /* translate */
599    glTranslatef (this->getAbsCoor ().x,
600                  this->getAbsCoor ().y,
601                  this->getAbsCoor ().z);
602    Vector tmpRot = this->getAbsDir().getSpacialAxis();
603    glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );
604
605
606    // This Draws the LOD's
607    float cameraDistance = State::getCamera()->distance(this);
608    if (cameraDistance > 30 && this->models.size() >= 3 && this->models[2] != NULL)
609    {
610      this->models[2]->draw();
611    }
612    else if (cameraDistance > 10 && this->models.size() >= 2 && this->models[1] != NULL)
613    {
614      this->models[1]->draw();
615    }
616    else if (this->models.size() >= 1 && this->models[0] != NULL)
617    {
618      this->models[0]->draw();
619    }
620
621//     if( this->aabbNode != NULL)
622//       this->aabbNode->drawBV(0, DRAW_BV_POLYGON, Vector(1, 0.6, 0.2), true);
623
624    glPopMatrix();
625  }
626}
627
628/**
629 * @param health the Health to add.
630 * @returns the health left (this->healthMax - health+this->health)
631 */
632float WorldEntity::increaseHealth(float health)
633{
634  this->health += health;
635  if (this->health > this->healthMax)
636  {
637    float retHealth = this->healthMax - this->health;
638    this->health = this->healthMax;
639    this->updateHealthWidget();
640    return retHealth;
641  }
642  this->updateHealthWidget();
643  return 0.0;
644}
645
646/**
647 * @param health the Health to be removed
648 * @returns 0.0 or the rest, that was not substracted (bellow 0.0)
649 */
650float WorldEntity::decreaseHealth(float health)
651{
652  this->health -= health;
653
654  if (this->health < 0)
655  {
656    float retHealth = -this->health;
657    this->health = 0.0f;
658    this->updateHealthWidget();
659    return retHealth;
660  }
661  this->updateHealthWidget();
662  return 0.0;
663
664}
665
666/**
667 * @param maxHealth the maximal health that can be loaded onto the entity.
668 */
669void WorldEntity::setHealthMax(float healthMax)
670{
671  this->healthMax = healthMax;
672  if (this->health > this->healthMax)
673  {
674    PRINTF(3)("new maxHealth is bigger as the old health. Did you really intend to do this for (%s::%s)\n", this->getClassName(), this->getName());
675    this->health = this->healthMax;
676  }
677  this->updateHealthWidget();
678}
679
680/**
681 * @brief creates the HealthWidget
682 *
683 * since not all entities need an HealthWidget, it is only created on request.
684 */
685void WorldEntity::createHealthWidget()
686{
687  if (this->healthWidget == NULL)
688  {
689    this->healthWidget = new OrxGui::GLGuiBar();
690    this->healthWidget->setSize2D(30,400);
691    this->healthWidget->setAbsCoor2D(10,100);
692
693    this->updateHealthWidget();
694  }
695  else
696    PRINTF(3)("Allready created the HealthWidget for %s::%s\n", this->getClassName(), this->getName());
697}
698
699void WorldEntity::increaseHealthMax(float increaseHealth)
700{
701  this->healthMax += increaseHealth;
702  this->updateHealthWidget();
703}
704
705
706OrxGui::GLGuiWidget* WorldEntity::getHealthWidget()
707{
708  this->createHealthWidget();
709  return this->healthWidget;
710}
711
712/**
713 * @param visibility shows or hides the health-bar
714 * (creates the widget if needed)
715 */
716void WorldEntity::setHealthWidgetVisibilit(bool visibility)
717{
718  if (visibility)
719  {
720    if (this->healthWidget != NULL)
721      this->healthWidget->show();
722    else
723    {
724      this->createHealthWidget();
725      this->updateHealthWidget();
726      this->healthWidget->show();
727    }
728  }
729  else if (this->healthWidget != NULL)
730    this->healthWidget->hide();
731}
732
733
734/**
735 * hit the world entity with
736 *  @param damage damage to be dealt
737 */
738void WorldEntity::hit(float damage)
739{
740  this->decreaseHealth(damage);
741
742  PRINTF(5)("Hit me: %s now only %f/%f health\n", this->getClassName(), this->getHealth(), this->getHealthMax());
743
744  if( this->getHealth() > 0)
745  {
746    // any small explosion animaitions
747  }
748  else
749  {
750    this->destroy();
751
752    if( State::getGameRules() != NULL)
753      State::getGameRules()->registerKill(Kill(NULL, this));
754  }
755}
756
757
758/**
759 * destoys the world entity
760 */
761void WorldEntity::destroy()
762{
763  this->toList(OM_DEAD);
764}
765
766
767/**
768 * @brief updates the HealthWidget
769 */
770void WorldEntity::updateHealthWidget()
771{
772  if (this->healthWidget != NULL)
773  {
774    this->healthWidget->setMaximum(this->healthMax);
775    this->healthWidget->setValue(this->health);
776  }
777}
778
779
780/**
781 * DEBUG-DRAW OF THE BV-Tree.
782 * @param depth What depth to draw
783 * @param drawMode the mode to draw this entity under
784 */
785void WorldEntity::drawBVTree(int depth, int drawMode) const
786{
787  glMatrixMode(GL_MODELVIEW);
788  glPushMatrix();
789  /* translate */
790  glTranslatef (this->getAbsCoor ().x,
791                this->getAbsCoor ().y,
792                this->getAbsCoor ().z);
793  /* rotate */
794  Vector tmpRot = this->getAbsDir().getSpacialAxis();
795  glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );
796
797
798  if (this->obbTree)
799    this->obbTree->drawBV(depth, drawMode);
800
801
802  glPopMatrix();
803}
804
805
806/**
807 * Debug the WorldEntity
808 */
809void WorldEntity::debugEntity() const
810{
811  PRINT(0)("WorldEntity %s::%s  (DEBUG)\n", this->getClassName(), this->getName());
812  this->debugNode();
813  PRINT(0)("List: %s ; ModelCount %d - ", ObjectManager::OMListToString(this->objectListNumber) , this->models.size());
814  for (unsigned int i = 0; i < this->models.size(); i++)
815  {
816    if (models[i] != NULL)
817      PRINT(0)(" : %d:%s", i, this->models[i]->getName());
818  }
819  PRINT(0)("\n");
820
821}
822
823
824/**
825 * handler for changes on registred vars
826 * @param id id's which changed
827 */
828void WorldEntity::varChangeHandler( std::list< int > & id )
829{
830  if ( std::find( id.begin(), id.end(), modelFileName_handle ) != id.end() ||
831       std::find( id.begin(), id.end(), scaling_handle ) != id.end()
832     )
833  {
834    loadModel( modelFileName, scaling );
835  }
836
837  PNode::varChangeHandler( id );
838}
839
Note: See TracBrowser for help on using the repository browser.