Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/world_entities/world_entity.cc @ 8974

Last change on this file since 8974 was 8974, checked in by bensch, 18 years ago

trunk: better implemented

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