Changeset 1755 for code/trunk/src/orxonox/GraphicsEngine.cc
- Timestamp:
- Sep 10, 2008, 1:37:36 AM (16 years ago)
- Location:
- code/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk
- Property svn:mergeinfo changed
/code/branches/gui (added) merged: 1636,1638,1640-1647,1649-1654,1656,1659-1665,1670,1672-1674,1686,1688-1692,1694-1697,1704 /code/branches/input (added) merged: 1629-1630
- Property svn:mergeinfo changed
-
code/trunk/src/orxonox/GraphicsEngine.cc
r1747 r1755 22 22 * Author: 23 23 * Reto Grieder 24 * Benjamin Knecht <beni_at_orxonox.net>, (C) 2007 24 25 * Co-authors: 25 * Benjamin Knecht <beni_at_orxonox.net>, (C) 2007,Felix Schulthess26 * Felix Schulthess 26 27 * 27 28 */ 28 29 29 /** 30 @file orxonox.cc 31 @brief Orxonox class 32 */ 30 /** 31 @file 32 @brief 33 Implementation of an partial interface to Ogre. 34 */ 33 35 34 36 #include "OrxonoxStableHeaders.h" 35 37 #include "GraphicsEngine.h" 36 38 37 #include <fstream> 38 39 #include <OgreConfigFile.h> 40 #include <OgreException.h> 41 #include <OgreLogManager.h> 42 #include <OgreRoot.h> 43 #include <OgreSceneManager.h> 44 #include <OgreTextureManager.h> 45 #include <OgreViewport.h> 39 #include <OgreRenderWindow.h> 46 40 47 41 #include "core/CoreIncludes.h" 48 42 #include "core/ConfigValueIncludes.h" 49 #include "core/Iterator.h"50 #include "core/CommandExecutor.h"51 #include "core/ConsoleCommand.h"52 43 #include "util/Debug.h" 53 44 54 #include "overlays/console/InGameConsole.h"55 #include "overlays/OverlayGroup.h"56 45 #include "tools/ParticleInterface.h" 57 #include "Settings.h"58 #include "tools/WindowEventListener.h"59 60 46 61 47 namespace orxonox 62 48 { 63 /** 64 @brief Returns the singleton instance and creates it the first time. 65 @return The only instance of GraphicsEngine. 66 */ 67 /*static*/ GraphicsEngine& GraphicsEngine::getSingleton() 68 { 69 static GraphicsEngine theOnlyInstance; 70 return theOnlyInstance; 71 } 49 //SetConsoleCommand(GraphicsEngine, printScreen, true).setKeybindMode(KeybindMode::OnPress); 72 50 73 /** 74 @brief Only use constructor to initialise variables and pointers! 75 */ 76 GraphicsEngine::GraphicsEngine() : 77 root_(0), 78 scene_(0), 79 renderWindow_(0) 80 { 81 RegisterObject(GraphicsEngine); 51 GraphicsEngine* GraphicsEngine::singletonRef_s = 0; 82 52 83 this->detailLevelParticle_ = 0; 84 85 this->setConfigValues(); 86 CCOUT(4) << "Constructed" << std::endl; 87 } 88 89 void GraphicsEngine::setConfigValues() 90 { 91 SetConfigValue(resourceFile_, "resources.cfg").description("Location of the resources file in the data path."); 92 SetConfigValue(ogreConfigFile_, "ogre.cfg").description("Location of the Ogre config file"); 93 SetConfigValue(ogrePluginsFile_, "plugins.cfg").description("Location of the Ogre plugins file"); 94 SetConfigValue(ogreLogFile_, "ogre.log").description("Logfile for messages from Ogre. \ 95 Use \"\" to suppress log file creation."); 96 SetConfigValue(ogreLogLevelTrivial_ , 5).description("Corresponding orxonox debug level for ogre Trivial"); 97 SetConfigValue(ogreLogLevelNormal_ , 4).description("Corresponding orxonox debug level for ogre Normal"); 98 SetConfigValue(ogreLogLevelCritical_, 2).description("Corresponding orxonox debug level for ogre Critical"); 99 100 SetConfigValue(detailLevelParticle_, 2).description("O: off, 1: low, 2: normal, 3: high").callback(this, &GraphicsEngine::detailLevelParticleChanged); 101 } 102 103 void GraphicsEngine::detailLevelParticleChanged() 104 { 105 for (ObjectList<ParticleInterface>::iterator it = ObjectList<ParticleInterface>::begin(); it; ++it) 106 it->detailLevelChanged(this->detailLevelParticle_); 107 } 108 109 /** 110 @brief Called after main() --> call destroyObjects()! 111 */ 112 GraphicsEngine::~GraphicsEngine() 113 { 114 this->destroy(); 115 } 116 117 /** 118 @brief Destroys all the internal objects. Call this method when you 119 normally would call the destructor. 120 */ 121 void GraphicsEngine::destroy() 122 { 123 CCOUT(4) << "Destroying objects..." << std::endl; 124 Ogre::WindowEventUtilities::removeWindowEventListener(this->renderWindow_, this); 125 if (this->root_) 126 delete this->root_; 127 this->root_ = 0; 128 this->scene_ = 0; 129 this->renderWindow_ = 0; 130 // delete the ogre log and the logManager (since we have created it). 131 if (Ogre::LogManager::getSingletonPtr() != 0) 53 /** 54 @brief 55 Returns the singleton instance. 56 @return 57 The only instance of GraphicsEngine. 58 */ 59 /*static*/ GraphicsEngine& GraphicsEngine::getInstance() 132 60 { 133 Ogre::LogManager::getSingleton().getDefaultLog()->removeListener(this); 134 Ogre::LogManager::getSingleton().destroyLog(Ogre::LogManager::getSingleton().getDefaultLog()); 135 delete Ogre::LogManager::getSingletonPtr(); 136 } 137 CCOUT(4) << "Destroying objects done" << std::endl; 138 } 139 140 /** 141 @brief Creates the Ogre Root object and sets up the ogre log. 142 */ 143 bool GraphicsEngine::setup() 144 { 145 CCOUT(3) << "Setting up..." << std::endl; 146 // temporary overwrite of dataPath, change ini file for permanent change 147 148 // TODO: LogManager doesn't work on specific systems. The why is unknown yet. 149 #if ORXONOX_PLATFORM == ORXONOX_PLATFORM_WIN32 150 // create a logManager 151 // note: If there's already a logManager, Ogre will complain by a failed assertation. 152 // but that shouldn't happen, since this is the first time to create a logManager.. 153 Ogre::LogManager* logger = new Ogre::LogManager(); 154 CCOUT(4) << "Ogre LogManager created" << std::endl; 155 156 // create our own log that we can listen to 157 Ogre::Log *myLog; 158 if (this->ogreLogFile_ == "") 159 myLog = logger->createLog("ogre.log", true, false, true); 160 else 161 myLog = logger->createLog(this->ogreLogFile_, true, false, false); 162 CCOUT(4) << "Ogre Log created" << std::endl; 163 164 myLog->setLogDetail(Ogre::LL_BOREME); 165 myLog->addListener(this); 166 #endif 167 168 // Root will detect that we've already created a Log 169 CCOUT(4) << "Creating Ogre Root..." << std::endl; 170 171 if (ogrePluginsFile_ == "") 172 { 173 COUT(1) << "Error: Ogre plugins file set to \"\". Cannot load." << std::endl; 174 return false; 175 } 176 if (ogreConfigFile_ == "") 177 { 178 COUT(1) << "Error: Ogre config file set to \"\". Cannot load." << std::endl; 179 return false; 180 } 181 if (ogreLogFile_ == "") 182 { 183 COUT(1) << "Error: Ogre log file set to \"\". Cannot load." << std::endl; 184 return false; 61 assert(singletonRef_s); 62 return *singletonRef_s; 185 63 } 186 64 187 try 65 /** 66 @brief 67 Non-initialising constructor. 68 */ 69 GraphicsEngine::GraphicsEngine() 70 : root_(0) 71 , renderWindow_(0) 72 , levelSceneManager_(0) 73 , viewport_(0) 188 74 { 189 root_ = new Ogre::Root(ogrePluginsFile_, ogreConfigFile_, ogreLogFile_); 190 } 191 catch (Ogre::Exception ex) 192 { 193 COUT(2) << "Error: There was an exception when creating Ogre Root." << std::endl; 194 return false; 75 RegisterObject(GraphicsEngine); 76 77 assert(singletonRef_s == 0); 78 singletonRef_s = this; 79 80 this->detailLevelParticle_ = 0; 81 82 this->setConfigValues(); 83 CCOUT(4) << "Constructed" << std::endl; 195 84 } 196 85 197 if (!root_->getInstalledPlugins().size())86 void GraphicsEngine::setConfigValues() 198 87 { 199 COUT(1) << "Error: No plugins declared. Cannot load Ogre." << std::endl; 200 COUT(0) << "Is the plugins file correctly declared?" << std::endl; 201 return false; 88 SetConfigValue(detailLevelParticle_, 2).description("O: off, 1: low, 2: normal, 3: high").callback(this, &GraphicsEngine::detailLevelParticleChanged); 202 89 } 203 90 204 #if 0 205 // tame the ogre ouput so we don't get all the mess in the console 206 Ogre::Log* defaultLog = Ogre::LogManager::getSingleton().getDefaultLog(); 207 defaultLog->setDebugOutputEnabled(false); 208 defaultLog->setLogDetail(Ogre::LL_BOREME); 209 defaultLog->addListener(this); 210 #endif 211 212 CCOUT(4) << "Creating Ogre Root done" << std::endl; 213 214 // specify where Ogre has to look for resources. This call doesn't parse anything yet! 215 if (!declareRessourceLocations()) 216 return false; 217 218 CCOUT(3) << "Set up done." << std::endl; 219 return true; 220 } 221 222 bool GraphicsEngine::declareRessourceLocations() 223 { 224 CCOUT(4) << "Declaring Resources" << std::endl; 225 //TODO: Specify layout of data file and maybe use xml-loader 226 //TODO: Work with ressource groups (should be generated by a special loader) 227 228 if (resourceFile_ == "") 91 void GraphicsEngine::detailLevelParticleChanged() 229 92 { 230 COUT(1) << "Error: Resource file set to \"\". Cannot load." << std::endl;231 return false;93 for (ObjectList<ParticleInterface>::iterator it = ObjectList<ParticleInterface>::begin(); it; ++it) 94 it->detailLevelChanged(this->detailLevelParticle_); 232 95 } 233 96 234 // Load resource paths from data file using configfile ressource type 235 Ogre::ConfigFile cf; 236 try 97 /** 98 @brief 99 Destroys all the Ogre related objects 100 */ 101 GraphicsEngine::~GraphicsEngine() 237 102 { 238 cf.load(Settings::getDataPath() + resourceFile_); 239 } 240 catch (Ogre::Exception ex) 241 { 242 COUT(1) << "Error: Could not load resources.cfg in path " << Settings::getDataPath() << std::endl; 243 COUT(0) << "Have you forgotten to set the data path in orxnox.ini?" << std::endl; 244 return false; 103 singletonRef_s = 0; 245 104 } 246 105 247 // Go through all sections & settings in the file 248 Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator(); 249 250 std::string secName, typeName, archName; 251 while (seci.hasMoreElements()) 106 /** 107 @brief 108 Get the width of the render window 109 @return 110 The width of the render window 111 */ 112 int GraphicsEngine::getWindowWidth() const 252 113 { 253 try 254 { 255 secName = seci.peekNextKey(); 256 Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext(); 257 Ogre::ConfigFile::SettingsMultiMap::iterator i; 258 for (i = settings->begin(); i != settings->end(); ++i) 259 { 260 typeName = i->first; // for instance "FileSystem" or "Zip" 261 archName = i->second; // name (and location) of archive 262 263 Ogre::ResourceGroupManager::getSingleton().addResourceLocation( 264 std::string(Settings::getDataPath() + archName), typeName, secName); 265 } 266 } 267 catch (Ogre::Exception ex) 268 { 269 COUT(2) << "Exception while reading resources.cfg. Proceeding.." << ex.getDescription() << std::endl; 270 } 271 } 272 return true; 273 } 274 275 bool GraphicsEngine::loadRenderer() 276 { 277 CCOUT(4) << "Configuring Renderer" << std::endl; 278 279 // check for file existence because Ogre displays exceptions if not 280 std::ifstream probe; 281 probe.open(ogreConfigFile_.c_str()); 282 if (!probe) 283 { 284 // create a zero sized file 285 std::ofstream creator; 286 creator.open(ogreConfigFile_.c_str()); 287 creator.close(); 288 } 289 else 290 probe.close(); 291 292 if (!root_->restoreConfig()) 293 if (!root_->showConfigDialog()) 294 return false; 295 296 CCOUT(4) << "Creating render window" << std::endl; 297 try 298 { 299 this->renderWindow_ = root_->initialise(true, "OrxonoxV2"); 300 } 301 catch (Ogre::Exception ex) 302 { 303 COUT(2) << "Error: There was an exception when initialising Ogre Root." << std::endl; 304 return false; 114 if (this->renderWindow_) 115 return this->renderWindow_->getWidth(); 116 else 117 return 0; 305 118 } 306 119 307 if (!root_->isInitialised()) 120 /** 121 @brief 122 Get the height of the render window 123 @return 124 The height of the render window 125 */ 126 int GraphicsEngine::getWindowHeight() const 308 127 { 309 CCOUT(2) << "Error: Initialising Ogre root object failed." << std::endl; 310 return false; 128 if (this->renderWindow_) 129 return this->renderWindow_->getHeight(); 130 else 131 return 0; 311 132 } 312 Ogre::WindowEventUtilities::addWindowEventListener(this->renderWindow_, this);313 Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);314 return true;315 }316 133 317 bool GraphicsEngine::initialiseResources() 318 { 319 CCOUT(4) << "Initialising resources" << std::endl; 320 //TODO: Do NOT load all the groups, why are we doing that? And do we really do that? initialise != load... 321 try 134 /** 135 @brief 136 Returns the window aspect ratio height/width. 137 @return 138 The window aspect ratio 139 */ 140 float GraphicsEngine::getWindowAspectRatio() const 322 141 { 323 Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); 324 /*Ogre::StringVector str = Ogre::ResourceGroupManager::getSingleton().getResourceGroups(); 325 for (unsigned int i = 0; i < str.size(); i++) 326 { 327 Ogre::ResourceGroupManager::getSingleton().loadResourceGroup(str[i]); 328 }*/ 142 if (this->renderWindow_) 143 return (float)this->renderWindow_->getHeight() / (float)this->renderWindow_->getWidth(); 144 else 145 return 1.0f; 329 146 } 330 catch (Ogre::Exception e)331 {332 CCOUT(2) << "Error: There was an Error when initialising the resources." << std::endl;333 CCOUT(2) << "ErrorMessage: " << e.getFullDescription() << std::endl;334 return false;335 }336 return true;337 }338 339 /**340 * @brief Creates the SceneManager341 */342 bool GraphicsEngine::createNewScene()343 {344 CCOUT(4) << "Creating new SceneManager..." << std::endl;345 if (scene_)346 {347 CCOUT(2) << "SceneManager already exists! Skipping." << std::endl;348 return false;349 }350 scene_ = root_->createSceneManager(Ogre::ST_GENERIC, "Default SceneManager");351 CCOUT(3) << "Created SceneManager: " << scene_ << std::endl;352 return true;353 }354 355 /**356 Returns the window handle of the render window.357 At least the InputHandler uses this to create the OIS::InputManager358 @return The window handle of the render window359 */360 size_t GraphicsEngine::getWindowHandle()361 {362 if (this->renderWindow_)363 {364 size_t windowHnd = 0;365 this->renderWindow_->getCustomAttribute("WINDOW", &windowHnd);366 return windowHnd;367 }368 else369 return 0;370 }371 372 /**373 Get the width of the current render window374 @return The width of the current render window375 */376 int GraphicsEngine::getWindowWidth() const377 {378 if (this->renderWindow_)379 return this->renderWindow_->getWidth();380 else381 return 0;382 }383 384 /**385 Get the height of the current render window386 @return The height of the current render window387 */388 int GraphicsEngine::getWindowHeight() const389 {390 if (this->renderWindow_)391 return this->renderWindow_->getHeight();392 else393 return 0;394 }395 396 /**397 @brief Returns the window aspect ratio height/width.398 @return The ratio399 */400 float GraphicsEngine::getWindowAspectRatio() const401 {402 if (this->renderWindow_)403 return (float)this->renderWindow_->getHeight() / (float)this->renderWindow_->getWidth();404 else405 return 1.0f;406 }407 408 /**409 @brief Method called by the LogListener interface from Ogre.410 We use it to capture Ogre log messages and handle it ourselves.411 @param message The message to be logged412 @param lml The message level the log is using413 @param maskDebug If we are printing to the console or not414 @param logName the name of this log (so you can have several listeners415 for different logs, and identify them)416 */417 void GraphicsEngine::messageLogged(const std::string& message,418 Ogre::LogMessageLevel lml, bool maskDebug, const std::string &logName)419 {420 int orxonoxLevel;421 switch (lml)422 {423 case Ogre::LML_TRIVIAL:424 orxonoxLevel = this->ogreLogLevelTrivial_;425 break;426 case Ogre::LML_NORMAL:427 orxonoxLevel = this->ogreLogLevelNormal_;428 break;429 case Ogre::LML_CRITICAL:430 orxonoxLevel = this->ogreLogLevelCritical_;431 break;432 default:433 orxonoxLevel = 0;434 }435 OutputHandler::getOutStream().setOutputLevel(orxonoxLevel)436 << "Ogre: " << message << std::endl;437 }438 439 /**440 * Window has moved.441 * @param rw The render window it occured in442 */443 void GraphicsEngine::windowMoved(Ogre::RenderWindow *rw)444 {445 for (ObjectList<orxonox::WindowEventListener>::iterator it = ObjectList<orxonox::WindowEventListener>::begin(); it; ++it)446 it->windowMoved();447 }448 449 /**450 * Window has resized.451 * @param rw The render window it occured in452 * @note GraphicsEngine has a render window stored itself. This is the same453 * as rw. But we have to be careful when using multiple render windows!454 */455 void GraphicsEngine::windowResized(Ogre::RenderWindow *rw)456 {457 for (ObjectList<orxonox::WindowEventListener>::iterator it = ObjectList<orxonox::WindowEventListener>::begin(); it; ++it)458 it->windowResized(this->renderWindow_->getWidth(), this->renderWindow_->getHeight());459 }460 461 /**462 * Window has changed Focus.463 * @param rw The render window it occured in464 */465 void GraphicsEngine::windowFocusChanged(Ogre::RenderWindow *rw)466 {467 for (ObjectList<orxonox::WindowEventListener>::iterator it = ObjectList<orxonox::WindowEventListener>::begin(); it; ++it)468 it->windowFocusChanged();469 }470 471 /**472 * Window was closed.473 * @param rw The render window it occured in474 */475 void GraphicsEngine::windowClosed(Ogre::RenderWindow *rw)476 {477 // using CommandExecutor in order to avoid depending on Orxonox.h.478 CommandExecutor::execute("exit", false);479 }480 481 147 }
Note: See TracChangeset
for help on using the changeset viewer.