/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Patrick Boenzli co-programmer: Christian Meyer */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD_ENTITY #include "world_entity.h" #include "shell_command.h" #include "model.h" #include "resource_manager.h" #include "load_param.h" #include "list.h" #include "vector.h" #include "obb_tree.h" using namespace std; SHELL_COMMAND(model, WorldEntity, loadModel) ->describe("sets the Model of the WorldEntity") ->defaultValues(2, "models/ships/fighter.obj", 1.0); /** * Loads the WordEntity-specific Part of any derived Class * * @param root: Normally NULL, as the Derived Entities define a loadParams Function themeselves, * that can calls WorldEntities loadParams for itself. */ WorldEntity::WorldEntity(const TiXmlElement* root) : Synchronizeable() { this->setClassID(CL_WORLD_ENTITY, "WorldEntity"); this->obbTree = NULL; if (root != NULL) this->loadParams(root); this->setVisibiliy(true); } /** * standard destructor */ WorldEntity::~WorldEntity () { // Delete the obbTree if( this->obbTree != NULL) delete this->obbTree; // Delete the model (unregister it with the ResourceManager) this->setModel(NULL); } /** * loads the WorldEntity Specific Parameters. * @param root: the XML-Element to load the Data From */ void WorldEntity::loadParams(const TiXmlElement* root) { // Do the PNode loading stuff static_cast(this)->loadParams(root); // Model Loading LoadParam(root, "model", this, WorldEntity, loadModel) .describe("the fileName of the model, that should be loaded onto this world-entity. (must be relative to the data-dir)") .defaultValues(3, NULL, 1.0f, 0); } /** * loads a Model onto a WorldEntity * @param fileName the name of the model to load * @param scaling the Scaling of the model * * @todo fix this, so it only has one loadModel-Function. */ void WorldEntity::loadModel(const char* fileName, float scaling, unsigned int modelNumber) { if (fileName != NULL) { PRINTF(4)("fetching %s\n", fileName); if (scaling == 1.0) this->setModel((Model*)ResourceManager::getInstance()->load(fileName, OBJ, RP_CAMPAIGN)); else this->setModel((Model*)ResourceManager::getInstance()->load(fileName, OBJ, RP_CAMPAIGN, &scaling)); this->buildObbTree(4); } else this->setModel(NULL); } /** * sets a specific Model for the Object. * @param model The Model to set * @param modelNumber the n'th model in the List to get. */ void WorldEntity::setModel(Model* model, unsigned int modelNumber) { if (this->models.size() <= modelNumber) this->models.resize(modelNumber+1, NULL); if (this->models[modelNumber] != NULL) { Resource* resource = ResourceManager::getInstance()->locateResourceByPointer(this->models[modelNumber]); if (resource != NULL) ResourceManager::getInstance()->unload(resource, RP_LEVEL); else delete this->models[modelNumber]; } this->models[modelNumber] = model; // if (this->model != NULL) // this->buildObbTree(4); } /** * builds the obb-tree * @param depth the depth to calculate */ bool WorldEntity::buildObbTree(unsigned int depth) { if (this->obbTree) delete this->obbTree; if (this->models[0] != NULL) { PRINTF(4)("creating obb tree\n"); this->obbTree = new OBBTree(depth, (sVec3D*)this->models[0]->getVertexArray(), this->models[0]->getVertexCount()); return true; } else { PRINTF(2)("could not create obb-tree, because no model was loaded yet\n"); this->obbTree = NULL; return false; } } /** * sets the character attributes of a worldentity * @param character attributes * * these attributes don't have to be set, only use them, if you need them */ //void WorldEntity::setCharacterAttributes(CharacterAttributes* charAttr) //{} /** * this function is called, when two entities collide * @param entity: the world entity with whom it collides * * Implement behaviour like damage application or other miscellaneous collision stuff in this function */ void WorldEntity::collidesWith(WorldEntity* entity, const Vector& location) { /** * THIS IS A DEFAULT COLLISION-Effect. * IF YOU WANT TO CREATE A SPECIFIC COLLISION ON EACH OBJECT * USE:: * if (entity->isA(CL_WHAT_YOU_ARE_LOOKING_FOR)) { printf "dothings"; }; * * You can always define a default Action.... don't be affraid just test it :) */ // PRINTF(3)("collision %s vs %s @ (%f,%f,%f)\n", this->getClassName(), entity->getClassName(), location.x, location.y, location.z); } /** * this is called immediately after the Entity has been constructed, initialized and then Spawned into the World * */ void WorldEntity::postSpawn () { } /** * this method is called by the world if the WorldEntity leaves valid gamespace * * For free entities this means it left the Track boundaries. With bound entities it means its Location adresses a * place that is not in the world anymore. In both cases you might have to take extreme measures (a.k.a. call destroy). * * NOT YET IMPLEMENTED */ void WorldEntity::leftWorld () { } /** * this method is called every frame * @param time: the time in seconds that has passed since the last tick * * Handle all stuff that should update with time inside this method (movement, animation, etc.) */ void WorldEntity::tick(float time) { } /** * the entity is drawn onto the screen with this function * * This is a central function of an entity: call it to let the entity painted to the screen. * Just override this function with whatever you want to be drawn. */ void WorldEntity::draw() const { glMatrixMode(GL_MODELVIEW); glPushMatrix(); float matrix[4][4]; /* translate */ glTranslatef (this->getAbsCoor ().x, this->getAbsCoor ().y, this->getAbsCoor ().z); /* rotate */ // FIXME: devise a new Way to rotate this this->getAbsDir ().matrix (matrix); glMultMatrixf((float*)matrix); if (this->models[0]) this->models[0]->draw(); glPopMatrix(); } /** * DEBUG-DRAW OF THE BV-Tree. * @param depth What depth to draw * @param drawMode the mode to draw this entity under */ void WorldEntity::drawBVTree(unsigned int depth, int drawMode) const { glMatrixMode(GL_MODELVIEW); glPushMatrix(); /* translate */ glTranslatef (this->getAbsCoor ().x, this->getAbsCoor ().y, this->getAbsCoor ().z); /* rotate */ Vector tmpRot = this->getAbsDir().getSpacialAxis(); glRotatef (this->getAbsDir().getSpacialAxisAngle(), tmpRot.x, tmpRot.y, tmpRot.z ); if (this->obbTree) this->obbTree->drawBV(depth, drawMode); glPopMatrix(); }