Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/christmas_branche/src/world_entities/world_entity.cc @ 6175

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

christmas: the md2model has now const draw functions

File size: 9.8 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 "md2Model.h"
24#include "resource_manager.h"
25#include "load_param.h"
26#include "list.h"
27#include "vector.h"
28#include "obb_tree.h"
29
30#include "state.h"
31
32using namespace std;
33
34SHELL_COMMAND(model, WorldEntity, loadModel)
35    ->describe("sets the Model of the WorldEntity")
36    ->defaultValues(2, "models/ships/fighter.obj", 1.0);
37
38
39/**
40 *  Loads the WordEntity-specific Part of any derived Class
41 *
42 * @param root: Normally NULL, as the Derived Entities define a loadParams Function themeselves,
43 *              that can calls WorldEntities loadParams for itself.
44 */
45WorldEntity::WorldEntity(const TiXmlElement* root)
46  : Synchronizeable()
47{
48  this->setClassID(CL_WORLD_ENTITY, "WorldEntity");
49
50  this->obbTree = NULL;
51
52  if (root != NULL)
53    this->loadParams(root);
54
55  this->setVisibiliy(true);
56
57  this->objectListNumber = OM_INIT;
58  this->objectListIterator = NULL;
59  this->supportsLOD = false;
60
61  this->toList(OM_NULL);
62}
63
64/**
65 *  standard destructor
66*/
67WorldEntity::~WorldEntity ()
68{
69  // Delete the obbTree
70  if( this->obbTree != NULL)
71    delete this->obbTree;
72
73  // Delete the model (unregister it with the ResourceManager)
74  for (unsigned int i = 0; i < this->models.size(); i++)
75    this->setModel(NULL, i);
76
77  State::getObjectManager()->toList(this, OM_INIT);
78}
79
80/**
81 * loads the WorldEntity Specific Parameters.
82 * @param root: the XML-Element to load the Data From
83 */
84void WorldEntity::loadParams(const TiXmlElement* root)
85{
86  // Do the PNode loading stuff
87  static_cast<PNode*>(this)->loadParams(root);
88
89  // Model Loading
90  LoadParam(root, "model", this, WorldEntity, loadModel)
91      .describe("the fileName of the model, that should be loaded onto this world-entity. (must be relative to the data-dir)")
92      .defaultValues(3, NULL, 1.0f, 0);
93
94}
95
96/**
97 * loads a Model onto a WorldEntity
98 * @param fileName the name of the model to load
99 * @param scaling the Scaling of the model
100 *
101 * @todo fix this, so it only has one loadModel-Function.
102*/
103void WorldEntity::loadModel(const char* fileName, float scaling, unsigned int modelNumber)
104{
105  if (fileName != NULL)
106  {
107   // search for the special character # in the LoadParam
108    if (strchr(fileName, '#') != NULL)
109    {
110      PRINTF(4)("Found # in %s... searching for LOD's\n", fileName);
111      char* lodFile = new char[strlen(fileName)+1];
112      strcpy(lodFile, fileName);
113      char* depth = strchr(lodFile, '#');
114      for (unsigned int i = 0; i < 5; i++)
115      {
116        *depth = 48+(int)i;
117        printf("-------%s\n", lodFile);
118        if (ResourceManager::isInDataDir(lodFile))
119          this->loadModel(lodFile, scaling, i);
120      }
121      this->supportsLOD = true;
122      return;
123    }
124
125    if(strstr(fileName, ".obj"))
126    {
127      PRINTF(4)("fetching OBJ file: %s\n", fileName);
128      if (scaling == 1.0)
129        this->setModel((Model*)ResourceManager::getInstance()->load(fileName, OBJ, RP_CAMPAIGN), modelNumber);
130      else
131        this->setModel((Model*)ResourceManager::getInstance()->load(fileName, OBJ, RP_CAMPAIGN, &scaling), modelNumber);
132
133      if( modelNumber == 0)
134        this->buildObbTree(4);
135    }
136    else if(strstr(fileName, ".md2"))
137    {
138      PRINTF(4)("fetching MD2 file: %s\n", fileName);
139//         MD2Model* m = (MD2Model*)ResourceManager::getInstance()->load(fileName, MD2, RP_CAMPAIGN);
140      MD2Model* m = new MD2Model(fileName, "/home/boenzlip/orxonox/data/maps/santa_claus.png");
141      m->debug();
142      this->supportsLOD = false;
143        //this->setModel((Model*)ResourceManager::getInstance()->load(fileName, MD2, RP_CAMPAIGN), 0);
144      this->setModel((Model*)m, 0);
145    }
146  }
147  else
148    this->setModel(NULL);
149}
150
151/**
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{
158  if (this->models.size() <= modelNumber)
159    this->models.resize(modelNumber+1, NULL);
160
161  if (this->models[modelNumber] != NULL)
162  {
163    Resource* resource = ResourceManager::getInstance()->locateResourceByPointer(this->models[modelNumber]);
164//     if (resource != NULL)
165    ResourceManager::getInstance()->unload(resource, RP_LEVEL);
166  }
167  else
168    delete this->models[modelNumber];
169
170  this->models[modelNumber] = model;
171
172
173//   if (this->model != NULL)
174//     this->buildObbTree(4);
175}
176
177
178/**
179 * builds the obb-tree
180 * @param depth the depth to calculate
181 */
182bool WorldEntity::buildObbTree(unsigned int depth)
183{
184  if (this->obbTree)
185    delete this->obbTree;
186
187  if (this->models[0] != NULL)
188  {
189    PRINTF(4)("creating obb tree\n");
190
191
192    this->obbTree = new OBBTree(depth, (sVec3D*)this->models[0]->getVertexArray(), this->models[0]->getVertexCount());
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  }
201}
202
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}
216
217
218
219/**
220 * sets the character attributes of a worldentity
221 * @param character attributes
222 *
223 * these attributes don't have to be set, only use them, if you need them
224*/
225//void WorldEntity::setCharacterAttributes(CharacterAttributes* charAttr)
226//{}
227
228
229/**
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{
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   */
245//  PRINTF(3)("collision %s vs %s @ (%f,%f,%f)\n", this->getClassName(), entity->getClassName(), location.x, location.y, location.z);
246}
247
248
249/**
250 *  this is called immediately after the Entity has been constructed, initialized and then Spawned into the World
251 *
252 */
253void WorldEntity::postSpawn ()
254{
255}
256
257
258/**
259 *  this method is called by the world if the WorldEntity leaves valid gamespace
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).
263 *
264 * NOT YET IMPLEMENTED
265 */
266void WorldEntity::leftWorld ()
267{
268}
269
270
271/**
272 *  this method is called every frame
273 * @param time: the time in seconds that has passed since the last tick
274 *
275 * Handle all stuff that should update with time inside this method (movement, animation, etc.)
276*/
277void WorldEntity::tick(float time)
278{
279}
280
281
282/**
283 *  the entity is drawn onto the screen with this function
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.
287*/
288void WorldEntity::draw() const
289{
290  this->drawLODsafe();
291}
292
293
294/**
295 *  this functions draws the model automaticaly in multiple LOD
296 */
297void WorldEntity::drawLODsafe() const
298{
299  if (!unlikely(this->models.empty()))
300  {
301    if( likely(this->supportsLOD))
302    {
303      glMatrixMode(GL_MODELVIEW);
304      glPushMatrix();
305
306      /* translate */
307      glTranslatef (this->getAbsCoor ().x,
308                    this->getAbsCoor ().y,
309                    this->getAbsCoor ().z);
310      Vector tmpRot = this->getAbsDir().getSpacialAxis();
311      glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );
312
313
314    // This Draws the LOD's
315      float cameraDistance = (State::getCamera()->getAbsCoor() - this->getAbsCoor()).len();
316      if (cameraDistance > 30 && this->models.size() >= 3 && this->models[2] != NULL)
317      {
318        this->models[2]->draw();
319      }
320      else if (cameraDistance > 10 && this->models.size() >= 2 && this->models[1] != NULL)
321      {
322        this->models[1]->draw();
323      }
324      else if (this->models.size() >= 1 && this->models[0] != NULL)
325      {
326        this->models[0]->draw();
327      }
328      glPopMatrix();
329    }
330    else // no LOD
331    {
332      glMatrixMode(GL_MODELVIEW);
333      glPushMatrix();
334
335      /* translate */
336      glTranslatef (this->getAbsCoor ().x,
337                    this->getAbsCoor ().y,
338                    this->getAbsCoor ().z);
339      Vector tmpRot = this->getAbsDir().getSpacialAxis();
340      glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );
341
342      this->models[0]->draw();
343
344      glPopMatrix();
345    }
346  }
347
348}
349
350/**
351 * DEBUG-DRAW OF THE BV-Tree.
352 * @param depth What depth to draw
353 * @param drawMode the mode to draw this entity under
354 */
355void WorldEntity::drawBVTree(unsigned int depth, int drawMode) const
356{
357  glMatrixMode(GL_MODELVIEW);
358  glPushMatrix();
359  /* translate */
360  glTranslatef (this->getAbsCoor ().x,
361                this->getAbsCoor ().y,
362                this->getAbsCoor ().z);
363  /* rotate */
364  Vector tmpRot = this->getAbsDir().getSpacialAxis();
365  glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );
366
367  if (this->obbTree)
368    this->obbTree->drawBV(depth, drawMode);
369  glPopMatrix();
370}
Note: See TracBrowser for help on using the repository browser.