Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6127 was 6005, checked in by bensch, 19 years ago

orxonox/trunk: automatic LOD-loading

File size: 8.0 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
57/**
58 *  standard destructor
59*/
60WorldEntity::~WorldEntity ()
61{
62  // Delete the obbTree
63  if( this->obbTree != NULL)
64    delete this->obbTree;
65
66  // Delete the model (unregister it with the ResourceManager)
67  for (unsigned int i = 0; i < this->models.size(); i++)
68    this->setModel(NULL, i);
69}
70
71/**
72 * loads the WorldEntity Specific Parameters.
73 * @param root: the XML-Element to load the Data From
74 */
75void WorldEntity::loadParams(const TiXmlElement* root)
76{
77  // Do the PNode loading stuff
78  static_cast<PNode*>(this)->loadParams(root);
79
80  // Model Loading
81  LoadParam(root, "model", this, WorldEntity, loadModel)
82      .describe("the fileName of the model, that should be loaded onto this world-entity. (must be relative to the data-dir)")
83      .defaultValues(3, NULL, 1.0f, 0);
84
85}
86
87/**
88 * loads a Model onto a WorldEntity
89 * @param fileName the name of the model to load
90 * @param scaling the Scaling of the model
91 *
92 * @todo fix this, so it only has one loadModel-Function.
93*/
94void WorldEntity::loadModel(const char* fileName, float scaling, unsigned int modelNumber)
95{
96  if (fileName != NULL)
97  { 
98    // search for the special character # in the LoadParam
99    if (strchr(fileName, '#') != NULL)
100      {
101        PRINTF(4)("Found # in %s... searching for LOD's\n", fileName);
102        char* lodFile = new char[strlen(fileName)+1];
103        strcpy(lodFile, fileName);
104        char* depth = strchr(lodFile, '#');
105        for (unsigned int i = 0; i < 5; i++)
106          {
107            *depth = 48+(int)i;
108            printf("-------%s\n", lodFile);
109            if (ResourceManager::isInDataDir(lodFile))
110              this->loadModel(lodFile, scaling, i);
111          }
112        return;
113      }
114
115    PRINTF(4)("fetching %s\n", fileName);
116    if (scaling == 1.0)
117      this->setModel((Model*)ResourceManager::getInstance()->load(fileName, OBJ, RP_CAMPAIGN), modelNumber);
118    else
119      this->setModel((Model*)ResourceManager::getInstance()->load(fileName, OBJ, RP_CAMPAIGN, &scaling), modelNumber);
120    if (modelNumber == 0)
121    this->buildObbTree(4);
122  }
123  else
124    this->setModel(NULL);
125}
126
127/**
128 * sets a specific Model for the Object.
129 * @param model The Model to set
130 * @param modelNumber the n'th model in the List to get.
131 */
132void WorldEntity::setModel(Model* model, unsigned int modelNumber)
133{
134  if (this->models.size() <= modelNumber)
135    this->models.resize(modelNumber+1, NULL);
136
137  if (this->models[modelNumber] != NULL)
138  {
139    Resource* resource = ResourceManager::getInstance()->locateResourceByPointer(this->models[modelNumber]);
140    if (resource != NULL)
141      ResourceManager::getInstance()->unload(resource, RP_LEVEL);
142    else
143      delete this->models[modelNumber];
144  }
145  this->models[modelNumber] = model;
146
147//   if (this->model != NULL)
148//     this->buildObbTree(4);
149}
150
151
152/**
153 * builds the obb-tree
154 * @param depth the depth to calculate
155 */
156bool WorldEntity::buildObbTree(unsigned int depth)
157{
158  if (this->obbTree)
159    delete this->obbTree;
160
161  if (this->models[0] != NULL)
162  {
163    PRINTF(4)("creating obb tree\n");
164
165
166    this->obbTree = new OBBTree(depth, (sVec3D*)this->models[0]->getVertexArray(), this->models[0]->getVertexCount());
167    return true;
168  }
169  else
170  {
171    PRINTF(2)("could not create obb-tree, because no model was loaded yet\n");
172    this->obbTree = NULL;
173    return false;
174  }
175}
176
177
178/**
179 * sets the character attributes of a worldentity
180 * @param character attributes
181 *
182 * these attributes don't have to be set, only use them, if you need them
183*/
184//void WorldEntity::setCharacterAttributes(CharacterAttributes* charAttr)
185//{}
186
187
188/**
189 *  this function is called, when two entities collide
190 * @param entity: the world entity with whom it collides
191 *
192 * Implement behaviour like damage application or other miscellaneous collision stuff in this function
193 */
194void WorldEntity::collidesWith(WorldEntity* entity, const Vector& location)
195{
196  /**
197   * THIS IS A DEFAULT COLLISION-Effect.
198   * IF YOU WANT TO CREATE A SPECIFIC COLLISION ON EACH OBJECT
199   * USE::
200   * if (entity->isA(CL_WHAT_YOU_ARE_LOOKING_FOR)) { printf "dothings"; };
201   *
202   * You can always define a default Action.... don't be affraid just test it :)
203   */
204//  PRINTF(3)("collision %s vs %s @ (%f,%f,%f)\n", this->getClassName(), entity->getClassName(), location.x, location.y, location.z);
205}
206
207
208/**
209 *  this is called immediately after the Entity has been constructed, initialized and then Spawned into the World
210 *
211 */
212void WorldEntity::postSpawn ()
213{
214}
215
216
217/**
218 *  this method is called by the world if the WorldEntity leaves valid gamespace
219 *
220 * For free entities this means it left the Track boundaries. With bound entities it means its Location adresses a
221 * place that is not in the world anymore. In both cases you might have to take extreme measures (a.k.a. call destroy).
222 *
223 * NOT YET IMPLEMENTED
224 */
225void WorldEntity::leftWorld ()
226{
227}
228
229
230/**
231 *  this method is called every frame
232 * @param time: the time in seconds that has passed since the last tick
233 *
234 * Handle all stuff that should update with time inside this method (movement, animation, etc.)
235*/
236void WorldEntity::tick(float time)
237{
238}
239
240
241/**
242 *  the entity is drawn onto the screen with this function
243 *
244 * This is a central function of an entity: call it to let the entity painted to the screen.
245 * Just override this function with whatever you want to be drawn.
246*/
247void WorldEntity::draw() const
248{
249  this->drawLODsafe();
250}
251
252void WorldEntity::drawLODsafe() const
253{
254  if (!this->models.empty())
255  {
256    glMatrixMode(GL_MODELVIEW);
257    glPushMatrix();
258
259    /* translate */
260    glTranslatef (this->getAbsCoor ().x,
261                  this->getAbsCoor ().y,
262                  this->getAbsCoor ().z);
263    Vector tmpRot = this->getAbsDir().getSpacialAxis();
264    glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );
265
266
267    // This Draws the LOD's
268    float cameraDistance = (State::getCamera()->getAbsCoor() - this->getAbsCoor()).len();
269    if (cameraDistance > 30 && this->models.size() >= 3 && this->models[2] != NULL)
270    {
271       this->models[2]->draw();
272    }
273    else if (cameraDistance > 10 && this->models.size() >= 2 && this->models[1] != NULL)
274    {
275      this->models[1]->draw();
276    }
277    else if (this->models.size() >= 1 && this->models[0] != NULL)
278    {
279      this->models[0]->draw();
280    }
281    glPopMatrix();
282  }
283}
284
285/**
286 * DEBUG-DRAW OF THE BV-Tree.
287 * @param depth What depth to draw
288 * @param drawMode the mode to draw this entity under
289 */
290void WorldEntity::drawBVTree(unsigned int depth, int drawMode) const
291{
292  glMatrixMode(GL_MODELVIEW);
293  glPushMatrix();
294  /* translate */
295  glTranslatef (this->getAbsCoor ().x,
296                this->getAbsCoor ().y,
297                this->getAbsCoor ().z);
298  /* rotate */
299  Vector tmpRot = this->getAbsDir().getSpacialAxis();
300  glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z );
301
302  if (this->obbTree)
303    this->obbTree->drawBV(depth, drawMode);
304  glPopMatrix();
305}
Note: See TracBrowser for help on using the repository browser.