Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/network/src/world_entities/world_entity.cc @ 6326

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