Changeset 1021 for code/trunk/src/orxonox/Orxonox.cc
- Timestamp:
- Apr 10, 2008, 5:03:34 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk/src/orxonox/Orxonox.cc
r871 r1021 35 35 36 36 //****** OGRE ****** 37 #include <OgreException.h> 38 #include <OgreRoot.h> 37 //#include <OgreException.h> 39 38 #include <OgreFrameListener.h> 40 #include <OgreRenderWindow.h>41 #include <OgreTextureManager.h>42 #include <OgreResourceGroupManager.h>43 #include <OgreConfigFile.h>44 39 #include <OgreOverlay.h> 45 40 #include <OgreOverlayManager.h> 46 47 //****** OIS ******* 48 #include <OIS/OIS.h> 41 #include <OgreTimer.h> 42 #include <OgreWindowEventUtilities.h> 49 43 50 44 //****** STD ******* 51 #include <iostream> 52 #include <exception> 45 //#include <iostream> 46 //#include <exception> 47 #include <deque> 53 48 54 49 //***** ORXONOX **** 55 50 //misc 56 #include "util/Sleep.h" 57 58 // loader and audio 59 //#include "loader/LevelLoader.h" 51 //#include "util/Sleep.h" 52 53 // audio 60 54 #include "audio/AudioManager.h" 61 55 … … 63 57 #include "network/Server.h" 64 58 #include "network/Client.h" 65 #include "network/NetworkFrameListener.h" 59 network::Client *client_g; 60 network::Server *server_g; 66 61 67 62 // objects 68 #include "objects/Tickable.h" 63 #include "core/ArgReader.h" 64 #include "core/Debug.h" 65 #include "core/Factory.h" 66 #include "core/Loader.h" 67 #include "core/Tickable.h" 68 #include "hud/HUD.h" 69 69 #include "tools/Timer.h" 70 #include "objects/NPC.h"71 #include "core/ArgReader.h"72 #include "core/Factory.h"73 #include "core/Debug.h"74 #include "core/Loader.h"75 #include "hud/HUD.h"76 70 #include "objects/weapon/BulletManager.h" 77 #include "GraphicsEngine.h" 71 72 #include "InputHandler.h" 78 73 79 74 #include "Orxonox.h" … … 81 76 namespace orxonox 82 77 { 83 // put this in a seperate Class or solve the problem in another fashion 84 class OrxListener : public Ogre::FrameListener 85 { 86 public: 87 OrxListener(OIS::Keyboard *keyboard, audio::AudioManager* auMan, gameMode mode) 88 { 89 mKeyboard = keyboard; 90 mode_=mode; 91 auMan_ = auMan; 92 } 93 94 bool frameStarted(const Ogre::FrameEvent& evt) 95 { 96 auMan_->update(); 97 updateAI(); 98 99 if(mode_ == PRESENTATION) 100 server_g->tick(evt.timeSinceLastFrame); 101 else if(mode_ == CLIENT) 102 client_g->tick(evt.timeSinceLastFrame); 103 104 usleep(10); 105 106 mKeyboard->capture(); 107 return !mKeyboard->isKeyDown(OIS::KC_ESCAPE); 108 } 109 110 void updateAI() 111 { 112 for(Iterator<NPC> it = ObjectList<NPC>::start(); it; ++it) 113 { 114 it->update(); 115 } 116 } 117 118 private: 119 gameMode mode_; 120 OIS::Keyboard *mKeyboard; 121 audio::AudioManager* auMan_; 122 }; 123 124 // init static singleton reference of Orxonox 125 Orxonox* Orxonox::singletonRef_ = NULL; 78 /** 79 @brief Reference to the only instance of the class. 80 */ 81 Orxonox *Orxonox::singletonRef_s = 0; 126 82 127 83 /** … … 131 87 { 132 88 this->ogre_ = new GraphicsEngine(); 89 this->timer_ = 0; 133 90 this->dataPath_ = ""; 134 // this->loader_ = 0;135 91 this->auMan_ = 0; 136 this->singletonRef_ = 0; 137 this->keyboard_ = 0; 138 this->mouse_ = 0; 139 this->inputManager_ = 0; 140 this->frameListener_ = 0; 141 this->root_ = 0; 92 this->inputHandler_ = 0; 93 //this->root_ = 0; 94 // turn on frame smoothing by setting a value different from 0 95 this->frameSmoothingTime_ = 0.0f; 96 this->bAbort_ = false; 142 97 } 143 98 … … 147 102 Orxonox::~Orxonox() 148 103 { 149 // nothing to delete as for now 104 // keep in mind: the order of deletion is very important! 105 if (this->bulletMgr_) 106 delete this->bulletMgr_; 107 if (this->orxonoxHUD_) 108 delete this->orxonoxHUD_; 109 Loader::close(); 110 InputHandler::destroy(); 111 if (this->auMan_) 112 delete this->auMan_; 113 if (this->timer_) 114 delete this->timer_; 115 if (this->ogre_) 116 delete this->ogre_; 117 118 if (client_g) 119 delete client_g; 120 if (server_g) 121 delete server_g; 122 } 123 124 /** 125 * error kills orxonox 126 */ 127 void Orxonox::abortImmediate(/* some error code */) 128 { 129 //TODO: destroy and destruct everything and print nice error msg 130 delete this; 131 } 132 133 /** 134 Asks the mainloop nicely to abort. 135 */ 136 void Orxonox::abortRequest() 137 { 138 bAbort_ = true; 139 } 140 141 /** 142 * @return singleton object 143 */ 144 Orxonox* Orxonox::getSingleton() 145 { 146 if (!singletonRef_s) 147 singletonRef_s = new Orxonox(); 148 return singletonRef_s; 149 //static Orxonox theOnlyInstance; 150 //return &theOnlyInstance; 151 } 152 153 /** 154 @brief Destroys the Orxonox singleton. 155 */ 156 void Orxonox::destroy() 157 { 158 if (singletonRef_s) 159 delete singletonRef_s; 160 singletonRef_s = 0; 150 161 } 151 162 … … 153 164 * initialization of Orxonox object 154 165 * @param argc argument counter 155 * @param argv list of argumen ts166 * @param argv list of argumenst 156 167 * @param path path to config (in home dir or something) 157 168 */ … … 162 173 //TODO: give config file to Ogre 163 174 std::string mode; 164 // if(argc>=2) 165 // mode = std::string(argv[1]); 166 // else 167 // mode = ""; 175 168 176 ArgReader ar = ArgReader(argc, argv); 169 177 ar.checkArgument("mode", mode, false); 170 178 ar.checkArgument("data", this->dataPath_, false); 171 179 ar.checkArgument("ip", serverIp_, false); 172 //mode = "presentation"; 173 if(ar.errorHandling()) die(); 174 if(mode == std::string("server")) 180 if(ar.errorHandling()) abortImmediate(); 181 if(mode == std::string("client")) 175 182 { 183 mode_ = CLIENT; 184 clientInit(path); 185 } 186 else if(mode== std::string("server")){ 187 mode_ = SERVER; 176 188 serverInit(path); 177 mode_ = SERVER;178 }179 else if(mode == std::string("client"))180 {181 clientInit(path);182 mode_ = CLIENT;183 }184 else if(mode == std::string("presentation"))185 {186 serverInit(path);187 mode_ = PRESENTATION;188 189 } 189 190 else{ 191 mode_ = STANDALONE; 190 192 standaloneInit(path); 191 mode_ = STANDALONE;192 193 } 193 194 } 194 195 195 /** 196 * start modules 197 */ 198 void Orxonox::start() 199 { 200 //TODO: start modules 201 ogre_->startRender(); 202 //TODO: run engine 203 Factory::createClassHierarchy(); 204 createScene(); 205 setupScene(); 206 setupInputSystem(); 207 if(mode_!=CLIENT){ // remove this in future ---- presentation hack 208 } 209 else 210 std::cout << "client here" << std::endl; 211 createFrameListener(); 212 switch(mode_){ 213 case PRESENTATION: 214 //ogre_->getRoot()->addFrameListener(new network::ServerFrameListener()); 215 //std::cout << "could not add framelistener" << std::endl; 216 server_g->open(); 217 break; 218 case CLIENT: 219 client_g->establishConnection(); 220 break; 221 case SERVER: 222 case STANDALONE: 223 default: 224 break; 225 } 226 startRenderLoop(); 227 } 228 229 /** 230 * @return singleton object 231 */ 232 Orxonox* Orxonox::getSingleton() 233 { 234 if (!singletonRef_) 235 singletonRef_ = new Orxonox(); 236 return singletonRef_; 237 } 238 239 /** 240 * error kills orxonox 241 */ 242 void Orxonox::die(/* some error code */) 243 { 244 //TODO: destroy and destruct everything and print nice error msg 245 delete this; 246 } 247 248 void Orxonox::standaloneInit(std::string path) 249 { 196 void Orxonox::serverInit(std::string path) 197 { 198 COUT(2) << "initialising server" << std::endl; 199 250 200 ogre_->setConfigPath(path); 251 201 ogre_->setup(); 252 root_ = ogre_->getRoot(); 253 if(!ogre_->load()) die(/* unable to load */); 254 255 //defineResources(); 256 //setupRenderSystem(); 257 //createRenderWindow(); 258 //initializeResourceGroups(); 259 /*createScene(); 260 setupScene(); 261 setupInputSystem(); 262 createFrameListener(); 263 Factory::createClassHierarchy(); 264 startRenderLoop();*/ 265 } 266 267 void Orxonox::playableServer(std::string path) 268 { 269 ogre_->setConfigPath(path); 270 ogre_->setup(); 271 root_ = ogre_->getRoot(); 272 defineResources(); 273 setupRenderSystem(); 274 createRenderWindow(); 275 initializeResourceGroups(); 276 setupInputSystem(); 277 Factory::createClassHierarchy(); 278 createScene(); 279 setupScene(); 280 createFrameListener(); 281 try{ 282 server_g = new network::Server(); //!< add port and bindadress 283 server_g->open(); //!< open server and create listener thread 284 if(ogre_ && ogre_->getRoot()) 285 ogre_->getRoot()->addFrameListener(new network::ServerFrameListener()); // adds a framelistener for the server 286 COUT(3) << "Info: network framelistener added" << std::endl; 287 } 288 catch(...) 289 { 290 COUT(1) << "Error: There was a problem initialising the server :(" << std::endl; 291 } 292 startRenderLoop(); 293 } 294 295 void Orxonox::standalone(){ 296 297 298 299 } 300 301 void Orxonox::serverInit(std::string path) 302 { 303 COUT(2) << "initialising server" << std::endl; 304 ogre_->setConfigPath(path); 305 ogre_->setup(); 306 server_g = new network::Server(); // FIXME add some settings if wanted 307 if(!ogre_->load()) die(/* unable to load */); 308 // FIXME add network framelistener 202 //root_ = ogre_->getRoot(); 203 if(!ogre_->load(this->dataPath_)) abortImmediate(/* unable to load */); 204 205 server_g = new network::Server(); 309 206 } 310 207 311 208 void Orxonox::clientInit(std::string path) 312 209 { 313 COUT(2) << "initialising client" << std::endl; 210 COUT(2) << "initialising client" << std::endl;\ 211 314 212 ogre_->setConfigPath(path); 315 213 ogre_->setup(); … … 317 215 client_g = new network::Client(); 318 216 else 319 client_g = new network::Client(serverIp_, 55556); 320 if(!ogre_->load()) die(/* unable to load */); 321 ogre_->getRoot()->addFrameListener(new network::ClientFrameListener()); 322 } 323 324 void Orxonox::defineResources() 325 { 326 std::string secName, typeName, archName; 327 Ogre::ConfigFile cf; 328 #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE 329 cf.load(macBundlePath() + "/Contents/Resources/resources.cfg"); 330 #else 331 cf.load(dataPath_ + "resources.cfg"); 332 #endif 333 334 Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator(); 335 while (seci.hasMoreElements()) 336 { 337 secName = seci.peekNextKey(); 338 Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext(); 339 Ogre::ConfigFile::SettingsMultiMap::iterator i; 340 for (i = settings->begin(); i != settings->end(); ++i) 341 { 342 typeName = i->first; 343 archName = i->second; 344 #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE 345 Ogre::ResourceGroupManager::getSingleton().addResourceLocation( std::string(macBundlePath() + "/" + archName), typeName, secName); 346 #else 347 Ogre::ResourceGroupManager::getSingleton().addResourceLocation( archName, typeName, secName); 348 #endif 349 } 217 client_g = new network::Client(serverIp_, NETWORK_PORT); 218 if(!ogre_->load(this->dataPath_)) abortImmediate(/* unable to load */); 219 } 220 221 void Orxonox::standaloneInit(std::string path) 222 { 223 COUT(2) << "initialising standalone mode" << std::endl; 224 225 ogre_->setConfigPath(path); 226 ogre_->setup(); 227 //root_ = ogre_->getRoot(); 228 if(!ogre_->load(this->dataPath_)) abortImmediate(/* unable to load */); 229 } 230 231 /** 232 * start modules 233 */ 234 void Orxonox::start() 235 { 236 switch(mode_){ 237 case CLIENT: 238 clientStart(); 239 break; 240 case SERVER: 241 serverStart(); 242 break; 243 default: 244 standaloneStart(); 350 245 } 351 246 } 352 353 void Orxonox::setupRenderSystem() 354 { 355 if (!root_->restoreConfig() && !root_->showConfigDialog()) 356 throw Ogre::Exception(52, "User canceled the config dialog!", "OrxApplication::setupRenderSystem()"); 357 } 358 359 void Orxonox::createRenderWindow() 360 { 361 root_->initialise(true, "OrxonoxV2"); 362 } 363 364 void Orxonox::initializeResourceGroups() 365 { 366 Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5); 367 Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); 368 } 369 370 /** 371 * 372 * @param 373 */ 374 void Orxonox::createScene(void) 375 { 376 // Init audio 247 248 void Orxonox::clientStart(){ 249 ogre_->initialise(); 250 Factory::createClassHierarchy(); 251 252 377 253 auMan_ = new audio::AudioManager(); 378 254 379 255 bulletMgr_ = new BulletManager(); 380 381 // load this file from config 382 // loader_ = new loader::LevelLoader("sample.oxw"); 383 // loader_->loadLevel(); 384 Level* startlevel = new Level("levels/sample.oxw"); 385 Loader::open(startlevel); 386 256 387 257 Ogre::Overlay* hudOverlay = Ogre::OverlayManager::getSingleton().getByName("Orxonox/HUD1.2"); 388 258 HUD* orxonoxHud; … … 391 261 orxonoxHud->setEnergyDistr(20,20,60); 392 262 hudOverlay->show(); 263 264 client_g->establishConnection(); 265 client_g->tick(0); 266 267 268 //setupInputSystem(); 269 270 startRenderLoop(); 271 } 272 273 void Orxonox::serverStart(){ 274 //TODO: start modules 275 ogre_->initialise(); 276 //TODO: run engine 277 Factory::createClassHierarchy(); 278 createScene(); 279 setupInputSystem(); 280 281 server_g->open(); 282 283 startRenderLoop(); 284 } 285 286 void Orxonox::standaloneStart(){ 287 //TODO: start modules 288 ogre_->initialise(); 289 //TODO: run engine 290 Factory::createClassHierarchy(); 291 createScene(); 292 setupInputSystem(); 293 294 startRenderLoop(); 295 } 296 297 void Orxonox::createScene(void) 298 { 299 // Init audio 300 auMan_ = new audio::AudioManager(); 301 302 bulletMgr_ = new BulletManager(); 303 304 // load this file from config 305 Level* startlevel = new Level("levels/sample.oxw"); 306 Loader::open(startlevel); 307 308 Ogre::Overlay* hudOverlay = Ogre::OverlayManager::getSingleton().getByName("Orxonox/HUD1.2"); 309 orxonoxHUD_ = new HUD(); 310 orxonoxHUD_->setEnergyValue(20); 311 orxonoxHUD_->setEnergyDistr(20,20,60); 312 hudOverlay->show(); 393 313 394 314 /* … … 396 316 auMan_->ambientAdd("a2"); 397 317 auMan_->ambientAdd("a3"); 398 //auMan->ambientAdd("ambient1"); 399 auMan_->ambientStart();*/ 400 } 401 402 403 /** 404 * 405 */ 406 void Orxonox::setupScene() 407 { 408 // SceneManager *mgr = ogre_->getSceneManager(); 409 410 411 // SceneNode* node = (SceneNode*)mgr->getRootSceneNode()->getChild("OgreHeadNode"); 412 // SceneNode *node = mgr->getRootSceneNode()->createChildSceneNode("OgreHeadNode", Vector3(0,0,0)); 413 414 415 /* 416 particle::ParticleInterface *e = new particle::ParticleInterface(mgr,"engine","Orxonox/strahl"); 417 e->particleSystem_->setParameter("local_space","true"); 418 e->setPositionOfEmitter(0, Vector3(0,-10,0)); 419 e->setDirection(Vector3(0,0,-1)); 420 e->addToSceneNode(node); 421 */ 422 } 423 424 318 //auMan->ambientAdd("ambient1"); 319 auMan_->ambientStart(); 320 */ 321 } 322 323 /** 324 @brief Calls the InputHandler which sets up the input devices. 325 The render window width and height are used to set up the mouse movement. 326 */ 425 327 void Orxonox::setupInputSystem() 426 328 { 427 size_t windowHnd = 0; 428 std::ostringstream windowHndStr; 429 OIS::ParamList pl; 430 431 // fixes auto repeat problem 432 #if defined OIS_LINUX_PLATFORM 433 pl.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true"))); 434 #endif 435 436 Ogre::RenderWindow *win = ogre_->getRoot()->getAutoCreatedWindow(); 437 win->getCustomAttribute("WINDOW", &windowHnd); 438 windowHndStr << windowHnd; 439 pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str())); 440 inputManager_ = OIS::InputManager::createInputSystem(pl); 441 442 try 329 inputHandler_ = InputHandler::getSingleton(); 330 if (!inputHandler_->initialise(ogre_->getWindowHandle(), 331 ogre_->getWindowWidth(), ogre_->getWindowHeight())) 332 abortImmediate(); 333 } 334 335 /** 336 Main loop of the orxonox game. 337 This is a new solution, using the ogre engine instead of being used by it. 338 An alternative solution would be to simply use the timer of the Root object, 339 but that implies using Ogre in any case. There would be no way to test 340 our code without the help of the root object. 341 There's even a chance that we can dispose of the root object entirely 342 in server mode. 343 About the loop: The design is almost exactly like the one in ogre, so that 344 if any part of ogre registers a framelisteners, it will still behave 345 correctly. Furthermore I have taken over the time smoothing feature from 346 ogre. If turned on (see orxonox constructor), it will calculate the dt_n by 347 means of the recent most dt_n-1, dt_n-2, etc. 348 */ 349 void Orxonox::startRenderLoop() 350 { 351 // use the ogre timer class to measure time. 352 if (!timer_) 353 timer_ = new Ogre::Timer(); 354 timer_->reset(); 355 356 // Contains the times of recently fired events 357 std::deque<unsigned long> eventTimes[3]; 358 // Clear event times 359 for (int i = 0; i < 3; ++i) 360 eventTimes[i].clear(); 361 362 while (!bAbort_) 363 { 364 // Pump messages in all registered RenderWindows 365 Ogre::WindowEventUtilities::messagePump(); 366 367 // get current time 368 unsigned long now = timer_->getMilliseconds(); 369 370 // create an event to pass to the frameStarted method in ogre 371 Ogre::FrameEvent evt; 372 evt.timeSinceLastEvent = calculateEventTime(now, eventTimes[0]); 373 evt.timeSinceLastFrame = calculateEventTime(now, eventTimes[1]); 374 375 // show the current time in the HUD 376 orxonoxHUD_->setTime((int)now, 0); 377 378 // Iterate through all Tickables and call their tick(dt) function 379 for (Iterator<Tickable> it = ObjectList<Tickable>::start(); it; ) 380 (it++)->tick((float)evt.timeSinceLastFrame); 381 382 // don't forget to call _fireFrameStarted in ogre to make sure 383 // everything goes smoothly 384 ogre_->frameStarted(evt); 385 386 if (mode_ != SERVER) 387 ogre_->renderOneFrame(); // only render in non-server mode 388 389 // get current time 390 now = timer_->getMilliseconds(); 391 392 // create an event to pass to the frameEnded method in ogre 393 evt.timeSinceLastEvent = calculateEventTime(now, eventTimes[0]); 394 evt.timeSinceLastFrame = calculateEventTime(now, eventTimes[2]); 395 396 // again, just to be sure ogre works fine 397 ogre_->frameEnded(evt); 398 } 399 } 400 401 /** 402 Method for calculating the average time between recently fired events. 403 Code directly taken from OgreRoot.cc 404 @param now The current time in ms. 405 @param type The type of event to be considered. 406 */ 407 float Orxonox::calculateEventTime(unsigned long now, std::deque<unsigned long> ×) 408 { 409 // Calculate the average time passed between events of the given type 410 // during the last mFrameSmoothingTime seconds. 411 412 times.push_back(now); 413 414 if(times.size() == 1) 415 return 0; 416 417 // Times up to mFrameSmoothingTime seconds old should be kept 418 unsigned long discardThreshold = 419 static_cast<unsigned long>(frameSmoothingTime_ * 1000.0f); 420 421 // Find the oldest time to keep 422 std::deque<unsigned long>::iterator it = times.begin(), 423 end = times.end()-2; // We need at least two times 424 while(it != end) 443 425 { 444 keyboard_ = static_cast<OIS::Keyboard*>(inputManager_->createInputObject(OIS::OISKeyboard, false)); 445 mouse_ = static_cast<OIS::Mouse*>(inputManager_->createInputObject(OIS::OISMouse, true)); 426 if (now - *it > discardThreshold) 427 ++it; 428 else 429 break; 446 430 } 447 catch (const OIS::Exception &e) 448 { 449 throw new Ogre::Exception(42, e.eText, "OrxApplication::setupInputSystem"); 450 } 451 } 452 453 // FIXME we actually want to do this differently... 454 void Orxonox::createFrameListener() 455 { 456 TickFrameListener* TickFL = new TickFrameListener(); 457 ogre_->getRoot()->addFrameListener(TickFL); 458 459 TimerFrameListener* TimerFL = new TimerFrameListener(); 460 ogre_->getRoot()->addFrameListener(TimerFL); 461 462 //if(mode_!=CLIENT) // FIXME just a hack ------- remove this in future 463 frameListener_ = new OrxListener(keyboard_, auMan_, mode_); 464 ogre_->getRoot()->addFrameListener(frameListener_); 465 } 466 467 void Orxonox::startRenderLoop() 468 { 469 // FIXME 470 // this is a hack!!! 471 // the call to reset the mouse clipping size should probably be somewhere 472 // else, however this works for the moment. 473 unsigned int width, height, depth; 474 int left, top; 475 ogre_->getRoot()->getAutoCreatedWindow()->getMetrics(width, height, depth, left, top); 476 477 if(mode_!=CLIENT){ 478 const OIS::MouseState &ms = mouse_->getMouseState(); 479 ms.width = width; 480 ms.height = height; 481 } 482 ogre_->getRoot()->startRendering(); 431 432 // Remove old times 433 times.erase(times.begin(), it); 434 435 return (float)(times.back() - times.front()) / ((times.size()-1) * 1000); 436 } 437 438 /** 439 @brief Test method for the InputHandler. 440 But: Is actually responsible for catching an exit event.. 441 */ 442 void Orxonox::eventOccured(InputEvent &evt) 443 { 444 if (evt.id == 1) 445 this->abortRequest(); 483 446 } 484 447 }
Note: See TracChangeset
for help on using the changeset viewer.