Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

christmas: model loading progress

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( strchr(fileName, '.obj') != NULL)
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( strchr(fileName, '.md2') != NULL)
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.pcx");
141        m->debug();
142        //this->setModel((Model*)ResourceManager::getInstance()->load(fileName, MD2, RP_CAMPAIGN), 0);
143        this->setModel((Model*)m, 0);
144      }
145  }
146  else
147    this->setModel(NULL);
148}
149
150/**
151 * sets a specific Model for the Object.
152 * @param model The Model to set
153 * @param modelNumber the n'th model in the List to get.
154 */
155void WorldEntity::setModel(Model* model, unsigned int modelNumber)
156{
157  if (this->models.size() <= modelNumber)
158    this->models.resize(modelNumber+1, NULL);
159
160  if (this->models[modelNumber] != NULL)
161  {
162    Resource* resource = ResourceManager::getInstance()->locateResourceByPointer(this->models[modelNumber]);
163//     if (resource != NULL)
164    ResourceManager::getInstance()->unload(resource, RP_LEVEL);
165  }
166  else
167    delete this->models[modelNumber];
168
169  this->models[modelNumber] = model;
170
171
172//   if (this->model != NULL)
173//     this->buildObbTree(4);
174}
175
176
177/**
178 * builds the obb-tree
179 * @param depth the depth to calculate
180 */
181bool WorldEntity::buildObbTree(unsigned int depth)
182{
183  if (this->obbTree)
184    delete this->obbTree;
185
186  if (this->models[0] != NULL)
187  {
188    PRINTF(4)("creating obb tree\n");
189
190
191    this->obbTree = new OBBTree(depth, (sVec3D*)this->models[0]->getVertexArray(), this->models[0]->getVertexCount());
192    return true;
193  }
194  else
195  {
196    PRINTF(2)("could not create obb-tree, because no model was loaded yet\n");
197    this->obbTree = NULL;
198    return false;
199  }
200}
201
202/**
203 * @brief moves this entity to the List OM_List
204 * @param list the list to set this Entity to.
205 *
206 * this is the same as a call to State::getObjectManager()->toList(entity , list);
207 * directly, but with an easier interface.
208 *
209 * @todo inline this (peut etre)
210 */
211void WorldEntity::toList(OM_LIST list)
212{
213  State::getObjectManager()->toList(this, list);
214}
215
216
217
218/**
219 * sets the character attributes of a worldentity
220 * @param character attributes
221 *
222 * these attributes don't have to be set, only use them, if you need them
223*/
224//void WorldEntity::setCharacterAttributes(CharacterAttributes* charAttr)
225//{}
226
227
228/**
229 *  this function is called, when two entities collide
230 * @param entity: the world entity with whom it collides
231 *
232 * Implement behaviour like damage application or other miscellaneous collision stuff in this function
233 */
234void WorldEntity::collidesWith(WorldEntity* entity, const Vector& location)
235{
236  /**
237   * THIS IS A DEFAULT COLLISION-Effect.
238   * IF YOU WANT TO CREATE A SPECIFIC COLLISION ON EACH OBJECT
239   * USE::
240   * if (entity->isA(CL_WHAT_YOU_ARE_LOOKING_FOR)) { printf "dothings"; };
241   *
242   * You can always define a default Action.... don't be affraid just test it :)
243   */
244//  PRINTF(3)("collision %s vs %s @ (%f,%f,%f)\n", this->getClassName(), entity->getClassName(), location.x, location.y, location.z);
245}
246
247
248/**
249 *  this is called immediately after the Entity has been constructed, initialized and then Spawned into the World
250 *
251 */
252void WorldEntity::postSpawn ()
253{
254}
255
256
257/**
258 *  this method is called by the world if the WorldEntity leaves valid gamespace
259 *
260 * For free entities this means it left the Track boundaries. With bound entities it means its Location adresses a
261 * place that is not in the world anymore. In both cases you might have to take extreme measures (a.k.a. call destroy).
262 *
263 * NOT YET IMPLEMENTED
264 */
265void WorldEntity::leftWorld ()
266{
267}
268
269
270/**
271 *  this method is called every frame
272 * @param time: the time in seconds that has passed since the last tick
273 *
274 * Handle all stuff that should update with time inside this method (movement, animation, etc.)
275*/
276void WorldEntity::tick(float time)
277{
278}
279
280
281/**
282 *  the entity is drawn onto the screen with this function
283 *
284 * This is a central function of an entity: call it to let the entity painted to the screen.
285 * Just override this function with whatever you want to be drawn.
286*/
287void WorldEntity::draw() const
288{
289  this->drawLODsafe();
290}
291
292
293/**
294 *  this functions draws the model automaticaly in multiple LOD
295 */
296void WorldEntity::drawLODsafe() const
297{
298  if (!unlikely(this->models.empty()))
299  {
300    if( likely(this->supportsLOD))
301    {
302      glMatrixMode(GL_MODELVIEW);
303      glPushMatrix();
304
305      /* translate */
306      glTranslatef (this->getAbsCoor ().x,
307                    this->getAbsCoor ().y,
308                    this->getAbsCoor ().z);
309      Vector tmpRot = this->getAbsDir().getSpacialAxis();
310      glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );
311
312
313    // This Draws the LOD's
314      float cameraDistance = (State::getCamera()->getAbsCoor() - this->getAbsCoor()).len();
315      if (cameraDistance > 30 && this->models.size() >= 3 && this->models[2] != NULL)
316      {
317        this->models[2]->draw();
318      }
319      else if (cameraDistance > 10 && this->models.size() >= 2 && this->models[1] != NULL)
320      {
321        this->models[1]->draw();
322      }
323      else if (this->models.size() >= 1 && this->models[0] != NULL)
324      {
325        this->models[0]->draw();
326      }
327      glPopMatrix();
328    }
329    else // no LOD
330    {
331      glMatrixMode(GL_MODELVIEW);
332      glPushMatrix();
333
334      /* translate */
335      glTranslatef (this->getAbsCoor ().x,
336                    this->getAbsCoor ().y,
337                    this->getAbsCoor ().z);
338      Vector tmpRot = this->getAbsDir().getSpacialAxis();
339      glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );
340
341      this->models[0]->draw();
342
343      glPopMatrix();
344    }
345  }
346
347}
348
349/**
350 * DEBUG-DRAW OF THE BV-Tree.
351 * @param depth What depth to draw
352 * @param drawMode the mode to draw this entity under
353 */
354void WorldEntity::drawBVTree(unsigned int depth, int drawMode) const
355{
356  glMatrixMode(GL_MODELVIEW);
357  glPushMatrix();
358  /* translate */
359  glTranslatef (this->getAbsCoor ().x,
360                this->getAbsCoor ().y,
361                this->getAbsCoor ().z);
362  /* rotate */
363  Vector tmpRot = this->getAbsDir().getSpacialAxis();
364  glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );
365
366  if (this->obbTree)
367    this->obbTree->drawBV(depth, drawMode);
368  glPopMatrix();
369}
Note: See TracBrowser for help on using the repository browser.