Changeset 2801 for code/branches/gui/src/orxonox/GraphicsManager.cc
- Timestamp:
- Mar 19, 2009, 10:58:43 AM (16 years ago)
- File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
code/branches/gui/src/orxonox/GraphicsManager.cc
r2797 r2801 35 35 36 36 #include "OrxonoxStableHeaders.h" 37 #include "GraphicsEngine.h" 38 37 #include "GraphicsManager.h" 38 39 #include <fstream> 40 #include <boost/filesystem.hpp> 41 42 #include <OgreCompositorManager.h> 43 #include <OgreConfigFile.h> 44 #include <OgreFrameListener.h> 45 #include <OgreRoot.h> 46 #include <OgreLogManager.h> 47 #include <OgreException.h> 39 48 #include <OgreRenderWindow.h> 40 49 #include <OgreRenderSystem.h> 50 #include <OgreTextureManager.h> 51 #include <OgreViewport.h> 52 #include <OgreWindowEventUtilities.h> 53 54 #include "SpecialConfig.h" 55 #include "util/Debug.h" 56 #include "util/Exception.h" 57 #include "util/String.h" 58 #include "util/SubString.h" 59 #include "core/ConsoleCommand.h" 60 #include "core/ConfigValueIncludes.h" 41 61 #include "core/CoreIncludes.h" 42 #include "core/ConfigValueIncludes.h" 43 #include "util/Debug.h" 44 62 #include "core/Core.h" 63 #include "tools/WindowEventListener.h" 45 64 #include "tools/ParticleInterface.h" 46 65 47 66 namespace orxonox 48 67 { 49 //SetConsoleCommand(GraphicsEngine, printScreen, true).setKeybindMode(KeybindMode::OnPress); 50 51 GraphicsEngine* GraphicsEngine::singletonRef_s = 0; 52 53 /** 54 @brief 55 Returns the singleton instance. 56 @return 57 The only instance of GraphicsEngine. 58 */ 59 /*static*/ GraphicsEngine& GraphicsEngine::getInstance() 60 { 61 assert(singletonRef_s); 62 return *singletonRef_s; 63 } 68 class _OrxonoxExport OgreWindowEventListener : public Ogre::WindowEventListener 69 { 70 void windowResized (Ogre::RenderWindow* rw); 71 void windowFocusChange (Ogre::RenderWindow* rw); 72 void windowClosed (Ogre::RenderWindow* rw); 73 //void windowMoved (Ogre::RenderWindow* rw); 74 }; 75 76 GraphicsManager* GraphicsManager::singletonRef_s = 0; 64 77 65 78 /** … … 67 80 Non-initialising constructor. 68 81 */ 69 GraphicsEngine::GraphicsEngine() 70 // : root_(0) 71 // , renderWindow_(0) 72 // , viewport_(0) 73 { 74 RegisterObject(GraphicsEngine); 82 GraphicsManager::GraphicsManager() 83 : ogreRoot_(0) 84 , ogreLogger_(0) 85 , renderWindow_(0) 86 , viewport_(0) 87 , ogreWindowEventListener_(0) 88 , avgTickTime_(0.0f) 89 , avgFramesPerSecond_(0.0f) 90 { 91 RegisterObject(GraphicsManager); 75 92 76 93 assert(singletonRef_s == 0); 77 94 singletonRef_s = this; 78 95 79 this->viewport_ = 0; 80 81 this->detailLevelParticle_ = 0; 96 this->loaded_ = false; 82 97 83 98 this->setConfigValues(); 84 CCOUT(4) << "Constructed" << std::endl; 85 } 86 87 void GraphicsEngine::setConfigValues() 88 { 89 SetConfigValue(detailLevelParticle_, 2).description("O: off, 1: low, 2: normal, 3: high").callback(this, &GraphicsEngine::detailLevelParticleChanged); 90 } 91 92 void GraphicsEngine::detailLevelParticleChanged() 93 { 94 for (ObjectList<ParticleInterface>::iterator it = ObjectList<ParticleInterface>::begin(); it; ++it) 95 it->detailLevelChanged(this->detailLevelParticle_); 99 } 100 101 void GraphicsManager::initialise() 102 { 103 Core::setShowsGraphics(true); 104 105 // Ogre setup procedure 106 setupOgre(); 107 // load all the required plugins for Ogre 108 loadOgrePlugins(); 109 // read resource declaration file 110 this->declareResources(); 111 // Reads ogre config and creates the render window 112 this->loadRenderer(); 113 114 // TODO: Spread this 115 this->initialiseResources(); 116 117 // add console commands 118 FunctorMember<GraphicsManager>* functor1 = createFunctor(&GraphicsManager::printScreen); 119 functor1->setObject(this); 120 ccPrintScreen_ = createConsoleCommand(functor1, "printScreen"); 121 CommandExecutor::addConsoleCommandShortcut(ccPrintScreen_); 122 123 this->loaded_ = true; 96 124 } 97 125 … … 100 128 Destroys all the Ogre related objects 101 129 */ 102 GraphicsEngine::~GraphicsEngine() 103 { 130 GraphicsManager::~GraphicsManager() 131 { 132 if (this->loaded_) 133 { 134 delete this->ccPrintScreen_; 135 136 if (this->ogreWindowEventListener_) 137 { 138 // remove our WindowEventListener first to avoid bad calls after the window has been destroyed 139 Ogre::WindowEventUtilities::removeWindowEventListener(this->renderWindow_, this->ogreWindowEventListener_); 140 delete this->ogreWindowEventListener_; 141 } 142 143 // unload all compositors 144 Ogre::CompositorManager::getSingleton().removeAll(); 145 146 // destroy render window 147 Ogre::RenderSystem* renderer = this->ogreRoot_->getRenderSystem(); 148 renderer->destroyRenderWindow("Orxonox"); 149 150 // Delete OGRE main control organ 151 delete this->ogreRoot_; 152 153 // delete the ogre log and the logManager (since we have created it in the first place). 154 this->ogreLogger_->getDefaultLog()->removeListener(this); 155 this->ogreLogger_->destroyLog(Ogre::LogManager::getSingleton().getDefaultLog()); 156 delete this->ogreLogger_; 157 158 // Don't showing graphics anymore 159 Core::setShowsGraphics(false); 160 } 161 162 assert(singletonRef_s); 104 163 singletonRef_s = 0; 105 164 } 165 166 void GraphicsManager::setConfigValues() 167 { 168 SetConfigValue(resourceFile_, "resources.cfg") 169 .description("Location of the resources file in the data path."); 170 SetConfigValue(ogreConfigFile_, "ogre.cfg") 171 .description("Location of the Ogre config file"); 172 SetConfigValue(ogrePluginsFolder_, ORXONOX_OGRE_PLUGINS_FOLDER) 173 .description("Folder where the Ogre plugins are located."); 174 SetConfigValue(ogrePlugins_, ORXONOX_OGRE_PLUGINS) 175 .description("Comma separated list of all plugins to load."); 176 SetConfigValue(ogreLogFile_, "ogre.log") 177 .description("Logfile for messages from Ogre. Use \"\" to suppress log file creation."); 178 SetConfigValue(ogreLogLevelTrivial_ , 5) 179 .description("Corresponding orxonox debug level for ogre Trivial"); 180 SetConfigValue(ogreLogLevelNormal_ , 4) 181 .description("Corresponding orxonox debug level for ogre Normal"); 182 SetConfigValue(ogreLogLevelCritical_, 2) 183 .description("Corresponding orxonox debug level for ogre Critical"); 184 SetConfigValue(detailLevelParticle_, 2) 185 .description("O: off, 1: low, 2: normal, 3: high").callback(this, &GraphicsManager::detailLevelParticleChanged); 186 } 187 188 void GraphicsManager::detailLevelParticleChanged() 189 { 190 for (ObjectList<ParticleInterface>::iterator it = ObjectList<ParticleInterface>::begin(); it; ++it) 191 it->detailLevelChanged(this->detailLevelParticle_); 192 } 193 194 void GraphicsManager::update(const Clock& time) 195 { 196 if (this->loaded_) 197 { 198 Ogre::FrameEvent evt; 199 evt.timeSinceLastFrame = time.getDeltaTime(); 200 evt.timeSinceLastEvent = time.getDeltaTime(); // note: same time, but shouldn't matter anyway 201 202 // don't forget to call _fireFrameStarted to OGRE to make sure 203 // everything goes smoothly 204 ogreRoot_->_fireFrameStarted(evt); 205 206 // Pump messages in all registered RenderWindows 207 // This calls the WindowEventListener objects. 208 Ogre::WindowEventUtilities::messagePump(); 209 // make sure the window stays active even when not focused 210 // (probably only necessary on windows) 211 this->renderWindow_->setActive(true); 212 213 // render 214 ogreRoot_->_updateAllRenderTargets(); 215 216 // again, just to be sure OGRE works fine 217 ogreRoot_->_fireFrameEnded(evt); // note: uses the same time as _fireFrameStarted 218 } 219 } 220 221 /** 222 @brief 223 Creates the Ogre Root object and sets up the ogre log. 224 */ 225 void GraphicsManager::setupOgre() 226 { 227 COUT(3) << "Setting up Ogre..." << std::endl; 228 229 if (ogreConfigFile_ == "") 230 { 231 COUT(2) << "Warning: Ogre config file set to \"\". Defaulting to config.cfg" << std::endl; 232 ModifyConfigValue(ogreConfigFile_, tset, "config.cfg"); 233 } 234 if (ogreLogFile_ == "") 235 { 236 COUT(2) << "Warning: Ogre log file set to \"\". Defaulting to ogre.log" << std::endl; 237 ModifyConfigValue(ogreLogFile_, tset, "ogre.log"); 238 } 239 240 boost::filesystem::path ogreConfigFilepath(Core::getConfigPath() / this->ogreConfigFile_); 241 boost::filesystem::path ogreLogFilepath(Core::getLogPath() / this->ogreLogFile_); 242 243 // create a new logManager 244 // Ogre::Root will detect that we've already created a Log 245 ogreLogger_ = new Ogre::LogManager(); 246 COUT(4) << "Ogre LogManager created" << std::endl; 247 248 // create our own log that we can listen to 249 Ogre::Log *myLog; 250 myLog = ogreLogger_->createLog(ogreLogFilepath.string(), true, false, false); 251 COUT(4) << "Ogre Log created" << std::endl; 252 253 myLog->setLogDetail(Ogre::LL_BOREME); 254 myLog->addListener(this); 255 256 COUT(4) << "Creating Ogre Root..." << std::endl; 257 258 // check for config file existence because Ogre displays (caught) exceptions if not 259 if (!boost::filesystem::exists(ogreConfigFilepath)) 260 { 261 // create a zero sized file 262 std::ofstream creator; 263 creator.open(ogreConfigFilepath.string().c_str()); 264 creator.close(); 265 } 266 267 // Leave plugins file empty. We're going to do that part manually later 268 ogreRoot_ = new Ogre::Root("", ogreConfigFilepath.string(), ogreLogFilepath.string()); 269 270 COUT(3) << "Ogre set up done." << std::endl; 271 } 272 273 void GraphicsManager::loadOgrePlugins() 274 { 275 // just to make sure the next statement doesn't segfault 276 if (ogrePluginsFolder_ == "") 277 ogrePluginsFolder_ = "."; 278 279 boost::filesystem::path folder(ogrePluginsFolder_); 280 // Do some SubString magic to get the comma separated list of plugins 281 SubString plugins(ogrePlugins_, ",", " ", false, 92, false, 34, false, 40, 41, false, '\0'); 282 // Use backslash paths on Windows! file_string() already does that though. 283 for (unsigned int i = 0; i < plugins.size(); ++i) 284 ogreRoot_->loadPlugin((folder / plugins[i]).file_string()); 285 } 286 287 void GraphicsManager::declareResources() 288 { 289 CCOUT(4) << "Declaring Resources" << std::endl; 290 //TODO: Specify layout of data file and maybe use xml-loader 291 //TODO: Work with ressource groups (should be generated by a special loader) 292 293 if (resourceFile_ == "") 294 { 295 COUT(2) << "Warning: Ogre resource file set to \"\". Defaulting to resources.cfg" << std::endl; 296 ModifyConfigValue(resourceFile_, tset, "resources.cfg"); 297 } 298 299 // Load resource paths from data file using configfile ressource type 300 Ogre::ConfigFile cf; 301 try 302 { 303 cf.load((Core::getMediaPath() / resourceFile_).string()); 304 } 305 catch (...) 306 { 307 //COUT(1) << ex.getFullDescription() << std::endl; 308 COUT(0) << "Have you forgotten to set the data path in orxnox.ini?" << std::endl; 309 throw; 310 } 311 312 // Go through all sections & settings in the file 313 Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator(); 314 315 std::string secName, typeName, archName; 316 while (seci.hasMoreElements()) 317 { 318 try 319 { 320 secName = seci.peekNextKey(); 321 Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext(); 322 Ogre::ConfigFile::SettingsMultiMap::iterator i; 323 for (i = settings->begin(); i != settings->end(); ++i) 324 { 325 typeName = i->first; // for instance "FileSystem" or "Zip" 326 archName = i->second; // name (and location) of archive 327 328 Ogre::ResourceGroupManager::getSingleton().addResourceLocation( 329 (Core::getMediaPath() / archName).string(), typeName, secName); 330 } 331 } 332 catch (Ogre::Exception& ex) 333 { 334 COUT(1) << ex.getFullDescription() << std::endl; 335 } 336 } 337 } 338 339 void GraphicsManager::loadRenderer() 340 { 341 CCOUT(4) << "Configuring Renderer" << std::endl; 342 343 if (!ogreRoot_->restoreConfig()) 344 if (!ogreRoot_->showConfigDialog()) 345 ThrowException(InitialisationFailed, "Could not show Ogre configuration dialogue."); 346 347 CCOUT(4) << "Creating render window" << std::endl; 348 349 this->renderWindow_ = ogreRoot_->initialise(true, "Orxonox"); 350 351 this->ogreWindowEventListener_ = new OgreWindowEventListener(); 352 Ogre::WindowEventUtilities::addWindowEventListener(this->renderWindow_, ogreWindowEventListener_); 353 354 Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(0); 355 356 // create a full screen default viewport 357 this->viewport_ = this->renderWindow_->addViewport(0, 0); 358 } 359 360 void GraphicsManager::initialiseResources() 361 { 362 CCOUT(4) << "Initialising resources" << std::endl; 363 //TODO: Do NOT load all the groups, why are we doing that? And do we really do that? initialise != load... 364 //try 365 //{ 366 Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); 367 /*Ogre::StringVector str = Ogre::ResourceGroupManager::getSingleton().getResourceGroups(); 368 for (unsigned int i = 0; i < str.size(); i++) 369 { 370 Ogre::ResourceGroupManager::getSingleton().loadResourceGroup(str[i]); 371 }*/ 372 //} 373 //catch (...) 374 //{ 375 // CCOUT(2) << "Error: There was a serious error when initialising the resources." << std::endl; 376 // throw; 377 //} 378 } 379 380 /** 381 @brief 382 Method called by the LogListener interface from Ogre. 383 We use it to capture Ogre log messages and handle it ourselves. 384 @param message 385 The message to be logged 386 @param lml 387 The message level the log is using 388 @param maskDebug 389 If we are printing to the console or not 390 @param logName 391 The name of this log (so you can have several listeners 392 for different logs, and identify them) 393 */ 394 void GraphicsManager::messageLogged(const std::string& message, 395 Ogre::LogMessageLevel lml, bool maskDebug, const std::string& logName) 396 { 397 int orxonoxLevel; 398 switch (lml) 399 { 400 case Ogre::LML_TRIVIAL: 401 orxonoxLevel = this->ogreLogLevelTrivial_; 402 break; 403 case Ogre::LML_NORMAL: 404 orxonoxLevel = this->ogreLogLevelNormal_; 405 break; 406 case Ogre::LML_CRITICAL: 407 orxonoxLevel = this->ogreLogLevelCritical_; 408 break; 409 default: 410 orxonoxLevel = 0; 411 } 412 OutputHandler::getOutStream().setOutputLevel(orxonoxLevel) 413 << "Ogre: " << message << std::endl; 414 } 415 416 void GraphicsManager::printScreen() 417 { 418 assert(this->renderWindow_); 419 420 this->renderWindow_->writeContentsToTimestampedFile(Core::getLogPathString() + "screenShot_", ".jpg"); 421 } 422 423 424 /****** OgreWindowEventListener ******/ 425 426 void OgreWindowEventListener::windowResized(Ogre::RenderWindow* rw) 427 { 428 for (ObjectList<orxonox::WindowEventListener>::iterator it 429 = ObjectList<orxonox::WindowEventListener>::begin(); it; ++it) 430 it->windowResized(rw->getWidth(), rw->getHeight()); 431 } 432 void OgreWindowEventListener::windowFocusChange(Ogre::RenderWindow* rw) 433 { 434 for (ObjectList<orxonox::WindowEventListener>::iterator it 435 = ObjectList<orxonox::WindowEventListener>::begin(); it; ++it) 436 it->windowFocusChanged(); 437 } 438 void OgreWindowEventListener::windowClosed(Ogre::RenderWindow* rw) 439 { 440 // TODO: Notify the right class to shut down the Game 441 } 106 442 }
Note: See TracChangeset
for help on using the changeset viewer.