Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: merged the network branche back to the trunk, so we do not get away from each other to fast

File size: 10.3 KB
RevLine 
[2036]1
2
[4570]3/*
[2036]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
[2190]15   co-programmer: Christian Meyer
[2036]16*/
[5300]17#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD_ENTITY
[2036]18
19#include "world_entity.h"
[5208]20#include "shell_command.h"
[5143]21
[5511]22#include "model.h"
[6222]23#include "md2Model.h"
[5143]24#include "resource_manager.h"
25#include "load_param.h"
[3803]26#include "vector.h"
[4682]27#include "obb_tree.h"
[3608]28
[6002]29#include "state.h"
30
[2036]31using namespace std;
32
[5208]33SHELL_COMMAND(model, WorldEntity, loadModel)
34    ->describe("sets the Model of the WorldEntity")
[5555]35    ->defaultValues(2, "models/ships/fighter.obj", 1.0);
[5208]36
37
[2043]38/**
[4836]39 *  Loads the WordEntity-specific Part of any derived Class
[5498]40 *
41 * @param root: Normally NULL, as the Derived Entities define a loadParams Function themeselves,
42 *              that can calls WorldEntities loadParams for itself.
43 */
[4261]44WorldEntity::WorldEntity(const TiXmlElement* root)
[5996]45  : Synchronizeable()
[2190]46{
[4320]47  this->setClassID(CL_WORLD_ENTITY, "WorldEntity");
[4597]48
[4682]49  this->obbTree = NULL;
[4261]50
[5995]51  if (root != NULL)
[4261]52    this->loadParams(root);
53
[4885]54  this->setVisibiliy(true);
[6142]55
56  this->objectListNumber = OM_INIT;
57  this->objectListIterator = NULL;
58
59  this->toList(OM_NULL);
[2190]60}
[2043]61
62/**
[4836]63 *  standard destructor
[2043]64*/
[2190]65WorldEntity::~WorldEntity ()
[2036]66{
[5498]67  // Delete the obbTree
[5302]68  if( this->obbTree != NULL)
[4814]69    delete this->obbTree;
[5994]70
71  // Delete the model (unregister it with the ResourceManager)
[6005]72  for (unsigned int i = 0; i < this->models.size(); i++)
73    this->setModel(NULL, i);
[6142]74
75  State::getObjectManager()->toList(this, OM_INIT);
[3531]76}
77
[5498]78/**
79 * loads the WorldEntity Specific Parameters.
80 * @param root: the XML-Element to load the Data From
81 */
[4436]82void WorldEntity::loadParams(const TiXmlElement* root)
83{
[5498]84  // Do the PNode loading stuff
[4436]85  static_cast<PNode*>(this)->loadParams(root);
[5498]86
[6222]87  LoadParam(root, "md2texture", this, WorldEntity, loadMD2Texture)
88      .describe("the fileName of the texture, that should be loaded onto this world-entity. (must be relative to the data-dir)")
89      .defaultValues(1, NULL);
90
[4436]91  // Model Loading
[5671]92  LoadParam(root, "model", this, WorldEntity, loadModel)
[5652]93      .describe("the fileName of the model, that should be loaded onto this world-entity. (must be relative to the data-dir)")
[5995]94      .defaultValues(3, NULL, 1.0f, 0);
[4436]95}
96
[6222]97
[3531]98/**
[4885]99 * loads a Model onto a WorldEntity
[4836]100 * @param fileName the name of the model to load
[5057]101 * @param scaling the Scaling of the model
[5498]102 *
103 * @todo fix this, so it only has one loadModel-Function.
[4261]104*/
[5995]105void WorldEntity::loadModel(const char* fileName, float scaling, unsigned int modelNumber)
[4261]106{
[6341]107  if ( fileName != NULL && strcmp(fileName, "") )
[6142]108  {
[6222]109   // search for the special character # in the LoadParam
[6005]110    if (strchr(fileName, '#') != NULL)
[6222]111    {
112      PRINTF(4)("Found # in %s... searching for LOD's\n", fileName);
113      char* lodFile = new char[strlen(fileName)+1];
114      strcpy(lodFile, fileName);
115      char* depth = strchr(lodFile, '#');
116      for (unsigned int i = 0; i < 5; i++)
[6005]117      {
[6222]118        *depth = 48+(int)i;
119        printf("-------%s\n", lodFile);
120        if (ResourceManager::isInDataDir(lodFile))
121          this->loadModel(lodFile, scaling, i);
[6005]122      }
[6222]123      return;
124    }
[6005]125
[6222]126    if(strstr(fileName, ".obj"))
127    {
128      PRINTF(4)("fetching OBJ file: %s\n", fileName);
129      if (scaling == 1.0)
130        this->setModel((Model*)ResourceManager::getInstance()->load(fileName, OBJ, RP_CAMPAIGN), modelNumber);
131      else
132        this->setModel((Model*)ResourceManager::getInstance()->load(fileName, OBJ, RP_CAMPAIGN, &scaling), modelNumber);
133
134      if( modelNumber == 0)
135        this->buildObbTree(4);
136    }
137    else if(strstr(fileName, ".md2"))
138    {
139      PRINTF(4)("fetching MD2 file: %s\n", fileName);
140      Model* m = new MD2Model(fileName, this->md2TextureFileName);
141        //this->setModel((Model*)ResourceManager::getInstance()->load(fileName, MD2, RP_CAMPAIGN), 0);
142      this->setModel(m, 0);
143    }
[4732]144  }
145  else
[6341]146  {
[5995]147    this->setModel(NULL);
[6341]148  }
[4261]149}
150
[5061]151/**
[5994]152 * sets a specific Model for the Object.
153 * @param model The Model to set
154 * @param modelNumber the n'th model in the List to get.
155 */
156void WorldEntity::setModel(Model* model, unsigned int modelNumber)
157{
[5995]158  if (this->models.size() <= modelNumber)
159    this->models.resize(modelNumber+1, NULL);
160
161  if (this->models[modelNumber] != NULL)
[6004]162  {
[5995]163    Resource* resource = ResourceManager::getInstance()->locateResourceByPointer(this->models[modelNumber]);
[6222]164//     if (resource != NULL)
165    ResourceManager::getInstance()->unload(resource, RP_LEVEL);
[5994]166  }
[6222]167  else
168    delete this->models[modelNumber];
169
[5995]170  this->models[modelNumber] = model;
[5994]171
[6222]172
[6004]173//   if (this->model != NULL)
[5994]174//     this->buildObbTree(4);
175}
176
177
178/**
[5061]179 * builds the obb-tree
180 * @param depth the depth to calculate
181 */
182bool WorldEntity::buildObbTree(unsigned int depth)
183{
[5428]184  if (this->obbTree)
185    delete this->obbTree;
186
[5995]187  if (this->models[0] != NULL)
[5428]188  {
189    PRINTF(4)("creating obb tree\n");
[5708]190
191
[5995]192    this->obbTree = new OBBTree(depth, (sVec3D*)this->models[0]->getVertexArray(), this->models[0]->getVertexCount());
[5428]193    return true;
194  }
195  else
196  {
197    PRINTF(2)("could not create obb-tree, because no model was loaded yet\n");
198    this->obbTree = NULL;
199    return false;
200  }
[5061]201}
[5057]202
[6142]203/**
204 * @brief moves this entity to the List OM_List
205 * @param list the list to set this Entity to.
206 *
207 * this is the same as a call to State::getObjectManager()->toList(entity , list);
208 * directly, but with an easier interface.
209 *
210 * @todo inline this (peut etre)
211 */
212void WorldEntity::toList(OM_LIST list)
213{
214  State::getObjectManager()->toList(this, list);
215}
[5061]216
[6142]217
218
[4261]219/**
[4885]220 * sets the character attributes of a worldentity
[4836]221 * @param character attributes
[4885]222 *
223 * these attributes don't have to be set, only use them, if you need them
[2043]224*/
[5498]225//void WorldEntity::setCharacterAttributes(CharacterAttributes* charAttr)
226//{}
[2036]227
[3583]228
[2043]229/**
[5029]230 *  this function is called, when two entities collide
231 * @param entity: the world entity with whom it collides
232 *
233 * Implement behaviour like damage application or other miscellaneous collision stuff in this function
234 */
235void WorldEntity::collidesWith(WorldEntity* entity, const Vector& location)
236{
[5498]237  /**
238   * THIS IS A DEFAULT COLLISION-Effect.
239   * IF YOU WANT TO CREATE A SPECIFIC COLLISION ON EACH OBJECT
240   * USE::
241   * if (entity->isA(CL_WHAT_YOU_ARE_LOOKING_FOR)) { printf "dothings"; };
242   *
243   * You can always define a default Action.... don't be affraid just test it :)
244   */
[5257]245//  PRINTF(3)("collision %s vs %s @ (%f,%f,%f)\n", this->getClassName(), entity->getClassName(), location.x, location.y, location.z);
[5029]246}
247
[2043]248
249/**
[5498]250 *  this is called immediately after the Entity has been constructed, initialized and then Spawned into the World
[4885]251 *
[5498]252 */
[3229]253void WorldEntity::postSpawn ()
[2190]254{
255}
[2043]256
[3583]257
[2043]258/**
[4836]259 *  this method is called by the world if the WorldEntity leaves valid gamespace
[4885]260 *
261 * For free entities this means it left the Track boundaries. With bound entities it means its Location adresses a
262 * place that is not in the world anymore. In both cases you might have to take extreme measures (a.k.a. call destroy).
[5498]263 *
264 * NOT YET IMPLEMENTED
265 */
[3583]266void WorldEntity::leftWorld ()
[2190]267{
268}
[2043]269
[3583]270
[2190]271/**
[4836]272 *  this method is called every frame
273 * @param time: the time in seconds that has passed since the last tick
[4885]274 *
275 * Handle all stuff that should update with time inside this method (movement, animation, etc.)
[2043]276*/
[4570]277void WorldEntity::tick(float time)
[2190]278{
279}
[3583]280
[5498]281
[3583]282/**
[4836]283 *  the entity is drawn onto the screen with this function
[4885]284 *
285 * This is a central function of an entity: call it to let the entity painted to the screen.
286 * Just override this function with whatever you want to be drawn.
[3365]287*/
[5500]288void WorldEntity::draw() const
[3803]289{
[6281]290    //PRINTF(0)("(%s::%s)\n", this->getClassName(), this->getName());
291  //  assert(!unlikely(this->models.empty()));
[6002]292  {
293    glMatrixMode(GL_MODELVIEW);
294    glPushMatrix();
[4570]295
[6002]296    /* translate */
297    glTranslatef (this->getAbsCoor ().x,
298                  this->getAbsCoor ().y,
299                  this->getAbsCoor ().z);
[6004]300    Vector tmpRot = this->getAbsDir().getSpacialAxis();
301    glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );
[2043]302
[6004]303
304    // This Draws the LOD's
[6002]305    float cameraDistance = (State::getCamera()->getAbsCoor() - this->getAbsCoor()).len();
[6004]306    if (cameraDistance > 30 && this->models.size() >= 3 && this->models[2] != NULL)
[6002]307    {
[6222]308      this->models[2]->draw();
[6004]309    }
310    else if (cameraDistance > 10 && this->models.size() >= 2 && this->models[1] != NULL)
[6002]311    {
312      this->models[1]->draw();
[6004]313    }
314    else if (this->models.size() >= 1 && this->models[0] != NULL)
[6002]315    {
316      this->models[0]->draw();
317    }
318    glPopMatrix();
319  }
[3803]320}
[3583]321
[6281]322
[5498]323/**
324 * DEBUG-DRAW OF THE BV-Tree.
325 * @param depth What depth to draw
326 * @param drawMode the mode to draw this entity under
327 */
[5501]328void WorldEntity::drawBVTree(unsigned int depth, int drawMode) const
[4684]329{
330  glMatrixMode(GL_MODELVIEW);
331  glPushMatrix();
332  /* translate */
333  glTranslatef (this->getAbsCoor ().x,
334                this->getAbsCoor ().y,
335                this->getAbsCoor ().z);
336  /* rotate */
[4998]337  Vector tmpRot = this->getAbsDir().getSpacialAxis();
338  glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );
[4684]339
340  if (this->obbTree)
341    this->obbTree->drawBV(depth, drawMode);
342  glPopMatrix();
343}
[6341]344
345/**
346 * Writes data from network containing information about the state
347 * @param data pointer to data
348 * @param length length of data
349 * @param sender hostID of sender
350 */
351int WorldEntity::writeState( const byte * data, int length, int sender )
352{
353  char* modelFileName;
354  SYNCHELP_READ_BEGIN();
355
356  SYNCHELP_READ_FKT( PNode::writeState );
357
358  SYNCHELP_READ_STRINGM( modelFileName );
359  SYNCHELP_READ_FLOAT( scaling );
360  //check if modelFileName is relative to datadir or absolute
361  if ( strstr(modelFileName, ResourceManager::getInstance()->getDataDir()) )
362  {
363    loadModel( modelFileName+strlen(ResourceManager::getInstance()->getDataDir()), scaling );
364  }
365  else
366  {
367    loadModel( modelFileName, scaling );
368  }
369  delete[] modelFileName;
370
371  return SYNCHELP_READ_N;
372}
373
374/**
375 * data copied in data will bee sent to another host
376 * @param data pointer to data
377 * @param maxLength max length of data
378 * @return the number of bytes writen
379 */
380int WorldEntity::readState( byte * data, int maxLength )
381{
382  SYNCHELP_WRITE_BEGIN();
383
384  SYNCHELP_WRITE_FKT( PNode::readState );
385
386  SYNCHELP_WRITE_STRING( getModel( 0 )->getName() );
387  SYNCHELP_WRITE_FLOAT( scaling );
388  return SYNCHELP_WRITE_N;
389}
Note: See TracBrowser for help on using the repository browser.