Changeset 5695 for code/trunk/src/core/GraphicsManager.cc
- Timestamp:
- Aug 30, 2009, 2:22:00 AM (16 years ago)
- Location:
- code/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk
- Property svn:mergeinfo changed
/code/branches/resource2 (added) merged: 3373-3374,5594,5597,5610-5611,5614,5624,5641,5644-5646,5650-5664,5667-5672,5682-5684,5688-5691,5694
- Property svn:mergeinfo changed
-
code/trunk/src/core/GraphicsManager.cc
r3370 r5695 28 28 */ 29 29 30 /**31 @file32 @brief33 Implementation of an partial interface to Ogre.34 */35 36 30 #include "GraphicsManager.h" 37 31 38 32 #include <fstream> 39 #include < memory>33 #include <sstream> 40 34 #include <boost/filesystem.hpp> 41 #include <boost/shared_ ptr.hpp>42 43 #include <Ogre CompositorManager.h>44 #include <Ogre ConfigFile.h>35 #include <boost/shared_array.hpp> 36 37 #include <OgreArchiveFactory.h> 38 #include <OgreArchiveManager.h> 45 39 #include <OgreFrameListener.h> 46 40 #include <OgreRoot.h> 47 41 #include <OgreLogManager.h> 48 #include <OgreException.h>49 42 #include <OgreRenderWindow.h> 50 43 #include <OgreRenderSystem.h> 44 #include <OgreResourceGroupManager.h> 51 45 #include <OgreTextureManager.h> 52 46 #include <OgreViewport.h> … … 64 58 #include "Game.h" 65 59 #include "GameMode.h" 60 #include "Loader.h" 61 #include "MemoryArchive.h" 66 62 #include "WindowEventListener.h" 63 #include "XMLFile.h" 67 64 68 65 namespace orxonox 69 66 { 70 using boost::shared_ptr;71 72 67 class OgreWindowEventListener : public Ogre::WindowEventListener 73 68 { … … 89 84 Non-initialising constructor. 90 85 */ 91 GraphicsManager::GraphicsManager() 92 : ogreRoot_(0) 93 , ogreLogger_(0) 86 GraphicsManager::GraphicsManager(bool bLoadRenderer) 87 : ogreWindowEventListener_(new OgreWindowEventListener()) 88 #if OGRE_VERSION < 0x010600 89 , memoryArchiveFactory_(new MemoryArchiveFactory()) 90 #endif 94 91 , renderWindow_(0) 95 92 , viewport_(0) 96 , ogreWindowEventListener_(new OgreWindowEventListener())97 93 { 98 94 RegisterObject(GraphicsManager); … … 100 96 this->setConfigValues(); 101 97 102 // Ogre setup procedure 103 setupOgre(); 104 105 try 106 { 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 catch (...) 124 { 125 // clean up 126 delete this->ogreRoot_; 127 delete this->ogreLogger_; 128 delete this->ogreWindowEventListener_; 129 throw; 98 // Ogre setup procedure (creating Ogre::Root) 99 this->loadOgreRoot(); 100 // load all the required plugins for Ogre 101 this->loadOgrePlugins(); 102 103 // At first, add the root paths of the data directories as resource locations 104 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(Core::getDataPathString(), "FileSystem", "dataRoot", false); 105 // Load resources 106 resources_.reset(new XMLFile("resources.oxr", "dataRoot")); 107 resources_->setLuaSupport(false); 108 Loader::open(resources_.get()); 109 110 // Only for development runs 111 if (Core::isDevelopmentRun()) 112 { 113 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(Core::getExternalDataPathString(), "FileSystem", "externalDataRoot", false); 114 extResources_.reset(new XMLFile("resources.oxr", "externalDataRoot")); 115 extResources_->setLuaSupport(false); 116 Loader::open(extResources_.get()); 117 } 118 119 if (bLoadRenderer) 120 { 121 // Reads the ogre config and creates the render window 122 this->upgradeToGraphics(); 130 123 } 131 124 } … … 133 126 /** 134 127 @brief 135 Destr oys all the Ogre related objects128 Destruction is done by the member scoped_ptrs. 136 129 */ 137 130 GraphicsManager::~GraphicsManager() 138 131 { 139 /* 140 delete this->ccPrintScreen_; 141 */ 142 143 // unload all compositors (this is only necessary because we don't yet destroy all resources!) 144 Ogre::CompositorManager::getSingleton().removeAll(); 145 146 // Delete OGRE main control organ 147 delete this->ogreRoot_; 148 149 // delete the logManager (since we have created it in the first place). 150 delete this->ogreLogger_; 151 152 delete this->ogreWindowEventListener_; 132 Ogre::WindowEventUtilities::removeWindowEventListener(renderWindow_, ogreWindowEventListener_.get()); 133 // TODO: Destroy the console command 153 134 } 154 135 155 136 void GraphicsManager::setConfigValues() 156 137 { 157 SetConfigValue(resourceFile_, "resources.cfg")158 .description("Location of the resources file in the data path.");159 138 SetConfigValue(ogreConfigFile_, "ogre.cfg") 160 139 .description("Location of the Ogre config file"); 161 SetConfigValue(ogrePlugins Folder_, ORXONOX_OGRE_PLUGINS_FOLDER)140 SetConfigValue(ogrePluginsDirectory_, specialConfig::ogrePluginsDirectory) 162 141 .description("Folder where the Ogre plugins are located."); 163 SetConfigValue(ogrePlugins_, ORXONOX_OGRE_PLUGINS)142 SetConfigValue(ogrePlugins_, specialConfig::ogrePlugins) 164 143 .description("Comma separated list of all plugins to load."); 165 144 SetConfigValue(ogreLogFile_, "ogre.log") … … 173 152 } 174 153 154 /** 155 @brief 156 Loads the renderer and creates the render window if not yet done so. 157 @remarks 158 This operation is irreversible without recreating the GraphicsManager! 159 So if it throws you HAVE to recreate the GraphicsManager!!! 160 It therefore offers almost no exception safety. 161 */ 162 void GraphicsManager::upgradeToGraphics() 163 { 164 if (renderWindow_ != NULL) 165 return; 166 167 this->loadRenderer(); 168 169 #if OGRE_VERSION < 0x010600 170 // WORKAROUND: There is an incompatibility for particle scripts when trying 171 // to support both Ogre 1.4 and 1.6. The hacky solution is to create 172 // scripts for the 1.6 version and then remove the inserted "particle_system" 173 // keyword. But we need to supply these new scripts as well, which is why 174 // there is an extra Ogre::Archive dealing with in the memory. 175 using namespace Ogre; 176 ArchiveManager::getSingleton().addArchiveFactory(memoryArchiveFactory_.get()); 177 const StringVector& groups = ResourceGroupManager::getSingleton().getResourceGroups(); 178 // Travers all groups 179 for (StringVector::const_iterator itGroup = groups.begin(); itGroup != groups.end(); ++itGroup) 180 { 181 FileInfoListPtr files = ResourceGroupManager::getSingleton().findResourceFileInfo(*itGroup, "*.particle"); 182 for (FileInfoList::const_iterator itFile = files->begin(); itFile != files->end(); ++itFile) 183 { 184 // open file 185 Ogre::DataStreamPtr input = ResourceGroupManager::getSingleton().openResource(itFile->filename, *itGroup, false); 186 std::stringstream output; 187 // Parse file and replace "particle_system" with nothing 188 while (!input->eof()) 189 { 190 std::string line = input->getLine(); 191 size_t pos = line.find("particle_system"); 192 if (pos != std::string::npos) 193 { 194 // 15 is the length of "particle_system" 195 line.replace(pos, 15, ""); 196 } 197 output << line << std::endl; 198 } 199 // Add file to the memory archive 200 shared_array<char> data(new char[output.str().size()]); 201 // Debug optimisations 202 const std::string outputStr = output.str(); 203 char* rawData = data.get(); 204 for (unsigned i = 0; i < outputStr.size(); ++i) 205 rawData[i] = outputStr[i]; 206 MemoryArchive::addFile("particle_scripts_ogre_1.4_" + *itGroup, itFile->filename, data, output.str().size()); 207 } 208 if (!files->empty()) 209 { 210 // Declare the files, but using a new group 211 ResourceGroupManager::getSingleton().addResourceLocation("particle_scripts_ogre_1.4_" + *itGroup, 212 "Memory", "particle_scripts_ogre_1.4_" + *itGroup); 213 } 214 } 215 #endif 216 217 // Initialise all resources (do this AFTER the renderer has been loaded!) 218 // Note: You can only do this once! Ogre will check whether a resource group has 219 // already been initialised. If you need to load resources later, you will have to 220 // choose another resource group. 221 Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); 222 } 223 224 /** 225 @brief 226 Creates the Ogre Root object and sets up the ogre log. 227 */ 228 void GraphicsManager::loadOgreRoot() 229 { 230 COUT(3) << "Setting up Ogre..." << std::endl; 231 232 if (ogreConfigFile_ == "") 233 { 234 COUT(2) << "Warning: Ogre config file set to \"\". Defaulting to config.cfg" << std::endl; 235 ModifyConfigValue(ogreConfigFile_, tset, "config.cfg"); 236 } 237 if (ogreLogFile_ == "") 238 { 239 COUT(2) << "Warning: Ogre log file set to \"\". Defaulting to ogre.log" << std::endl; 240 ModifyConfigValue(ogreLogFile_, tset, "ogre.log"); 241 } 242 243 boost::filesystem::path ogreConfigFilepath(Core::getConfigPath() / this->ogreConfigFile_); 244 boost::filesystem::path ogreLogFilepath(Core::getLogPath() / this->ogreLogFile_); 245 246 // create a new logManager 247 // Ogre::Root will detect that we've already created a Log 248 ogreLogger_.reset(new Ogre::LogManager()); 249 COUT(4) << "Ogre LogManager created" << std::endl; 250 251 // create our own log that we can listen to 252 Ogre::Log *myLog; 253 myLog = ogreLogger_->createLog(ogreLogFilepath.string(), true, false, false); 254 COUT(4) << "Ogre Log created" << std::endl; 255 256 myLog->setLogDetail(Ogre::LL_BOREME); 257 myLog->addListener(this); 258 259 COUT(4) << "Creating Ogre Root..." << std::endl; 260 261 // check for config file existence because Ogre displays (caught) exceptions if not 262 if (!boost::filesystem::exists(ogreConfigFilepath)) 263 { 264 // create a zero sized file 265 std::ofstream creator; 266 creator.open(ogreConfigFilepath.string().c_str()); 267 creator.close(); 268 } 269 270 // Leave plugins file empty. We're going to do that part manually later 271 ogreRoot_.reset(new Ogre::Root("", ogreConfigFilepath.string(), ogreLogFilepath.string())); 272 273 COUT(3) << "Ogre set up done." << std::endl; 274 } 275 276 void GraphicsManager::loadOgrePlugins() 277 { 278 // just to make sure the next statement doesn't segfault 279 if (ogrePluginsDirectory_ == "") 280 ogrePluginsDirectory_ = "."; 281 282 boost::filesystem::path folder(ogrePluginsDirectory_); 283 // Do some SubString magic to get the comma separated list of plugins 284 SubString plugins(ogrePlugins_, ",", " ", false, '\\', false, '"', false, '(', ')', false, '\0'); 285 // Use backslash paths on Windows! file_string() already does that though. 286 for (unsigned int i = 0; i < plugins.size(); ++i) 287 ogreRoot_->loadPlugin((folder / plugins[i]).file_string()); 288 } 289 290 void GraphicsManager::loadRenderer() 291 { 292 CCOUT(4) << "Configuring Renderer" << std::endl; 293 294 if (!ogreRoot_->restoreConfig()) 295 if (!ogreRoot_->showConfigDialog()) 296 ThrowException(InitialisationFailed, "OGRE graphics configuration dialogue failed."); 297 298 CCOUT(4) << "Creating render window" << std::endl; 299 300 this->renderWindow_ = ogreRoot_->initialise(true, "Orxonox"); 301 // Propagate the size of the new winodw 302 this->ogreWindowEventListener_->windowResized(renderWindow_); 303 304 Ogre::WindowEventUtilities::addWindowEventListener(this->renderWindow_, ogreWindowEventListener_.get()); 305 306 // create a full screen default viewport 307 // Note: This may throw when adding a viewport with an existing z-order! 308 // But in our case we only have one viewport for now anyway, therefore 309 // no ScopeGuards or anything to handle exceptions. 310 this->viewport_ = this->renderWindow_->addViewport(0, 0); 311 312 Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(0); 313 314 // add console commands 315 FunctorMember<GraphicsManager>* functor1 = createFunctor(&GraphicsManager::printScreen); 316 ccPrintScreen_ = createConsoleCommand(functor1->setObject(this), "printScreen"); 317 CommandExecutor::addConsoleCommandShortcut(ccPrintScreen_); 318 } 319 175 320 void GraphicsManager::update(const Clock& time) 176 321 { … … 207 352 { 208 353 this->viewport_->setCamera(camera); 209 }210 211 /**212 @brief213 Creates the Ogre Root object and sets up the ogre log.214 */215 void GraphicsManager::setupOgre()216 {217 COUT(3) << "Setting up Ogre..." << std::endl;218 219 if (ogreConfigFile_ == "")220 {221 COUT(2) << "Warning: Ogre config file set to \"\". Defaulting to config.cfg" << std::endl;222 ModifyConfigValue(ogreConfigFile_, tset, "config.cfg");223 }224 if (ogreLogFile_ == "")225 {226 COUT(2) << "Warning: Ogre log file set to \"\". Defaulting to ogre.log" << std::endl;227 ModifyConfigValue(ogreLogFile_, tset, "ogre.log");228 }229 230 boost::filesystem::path ogreConfigFilepath(Core::getConfigPath() / this->ogreConfigFile_);231 boost::filesystem::path ogreLogFilepath(Core::getLogPath() / this->ogreLogFile_);232 233 // create a new logManager234 // Ogre::Root will detect that we've already created a Log235 std::auto_ptr<Ogre::LogManager> logger(new Ogre::LogManager());236 COUT(4) << "Ogre LogManager created" << std::endl;237 238 // create our own log that we can listen to239 Ogre::Log *myLog;240 myLog = logger->createLog(ogreLogFilepath.string(), true, false, false);241 COUT(4) << "Ogre Log created" << std::endl;242 243 myLog->setLogDetail(Ogre::LL_BOREME);244 myLog->addListener(this);245 246 COUT(4) << "Creating Ogre Root..." << std::endl;247 248 // check for config file existence because Ogre displays (caught) exceptions if not249 if (!boost::filesystem::exists(ogreConfigFilepath))250 {251 // create a zero sized file252 std::ofstream creator;253 creator.open(ogreConfigFilepath.string().c_str());254 creator.close();255 }256 257 // Leave plugins file empty. We're going to do that part manually later258 ogreRoot_ = new Ogre::Root("", ogreConfigFilepath.string(), ogreLogFilepath.string());259 // In case that new Root failed the logger gets destroyed because of the std::auto_ptr260 ogreLogger_ = logger.release();261 262 COUT(3) << "Ogre set up done." << std::endl;263 }264 265 void GraphicsManager::loadOgrePlugins()266 {267 // just to make sure the next statement doesn't segfault268 if (ogrePluginsFolder_ == "")269 ogrePluginsFolder_ = ".";270 271 boost::filesystem::path folder(ogrePluginsFolder_);272 // Do some SubString magic to get the comma separated list of plugins273 SubString plugins(ogrePlugins_, ",", " ", false, '\\', false, '"', false, '(', ')', false, '\0');274 // Use backslash paths on Windows! file_string() already does that though.275 for (unsigned int i = 0; i < plugins.size(); ++i)276 ogreRoot_->loadPlugin((folder / plugins[i]).file_string());277 }278 279 void GraphicsManager::declareResources()280 {281 CCOUT(4) << "Declaring Resources" << std::endl;282 //TODO: Specify layout of data file and maybe use xml-loader283 //TODO: Work with ressource groups (should be generated by a special loader)284 285 if (resourceFile_ == "")286 {287 COUT(2) << "Warning: Ogre resource file set to \"\". Defaulting to resources.cfg" << std::endl;288 ModifyConfigValue(resourceFile_, tset, "resources.cfg");289 }290 291 // Load resource paths from data file using configfile ressource type292 Ogre::ConfigFile cf;293 try294 {295 cf.load((Core::getMediaPath() / resourceFile_).string());296 }297 catch (...)298 {299 //COUT(1) << ex.getFullDescription() << std::endl;300 COUT(0) << "Have you forgotten to set the data path in orxnox.ini?" << std::endl;301 throw;302 }303 304 // Go through all sections & settings in the file305 Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();306 307 std::string secName, typeName, archName;308 while (seci.hasMoreElements())309 {310 try311 {312 secName = seci.peekNextKey();313 Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();314 Ogre::ConfigFile::SettingsMultiMap::iterator i;315 for (i = settings->begin(); i != settings->end(); ++i)316 {317 typeName = i->first; // for instance "FileSystem" or "Zip"318 archName = i->second; // name (and location) of archive319 320 Ogre::ResourceGroupManager::getSingleton().addResourceLocation(321 (Core::getMediaPath() / archName).string(), typeName, secName);322 }323 }324 catch (Ogre::Exception& ex)325 {326 COUT(1) << ex.getFullDescription() << std::endl;327 }328 }329 }330 331 void GraphicsManager::loadRenderer()332 {333 CCOUT(4) << "Configuring Renderer" << std::endl;334 335 if (!ogreRoot_->restoreConfig())336 if (!ogreRoot_->showConfigDialog())337 ThrowException(InitialisationFailed, "OGRE graphics configuration dialogue failed.");338 339 CCOUT(4) << "Creating render window" << std::endl;340 341 this->renderWindow_ = ogreRoot_->initialise(true, "Orxonox");342 this->ogreWindowEventListener_->windowResized(renderWindow_);343 344 Ogre::WindowEventUtilities::addWindowEventListener(this->renderWindow_, ogreWindowEventListener_);345 346 Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(0);347 348 // create a full screen default viewport349 this->viewport_ = this->renderWindow_->addViewport(0, 0);350 }351 352 void GraphicsManager::initialiseResources()353 {354 CCOUT(4) << "Initialising resources" << std::endl;355 //TODO: Do NOT load all the groups, why are we doing that? And do we really do that? initialise != load...356 //try357 //{358 Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();359 /*Ogre::StringVector str = Ogre::ResourceGroupManager::getSingleton().getResourceGroups();360 for (unsigned int i = 0; i < str.size(); i++)361 {362 Ogre::ResourceGroupManager::getSingleton().loadResourceGroup(str[i]);363 }*/364 //}365 //catch (...)366 //{367 // CCOUT(2) << "Error: There was a serious error when initialising the resources." << std::endl;368 // throw;369 //}370 354 } 371 355 … … 406 390 } 407 391 392 size_t GraphicsManager::getRenderWindowHandle() 393 { 394 size_t windowHnd = 0; 395 renderWindow_->getCustomAttribute("WINDOW", &windowHnd); 396 return windowHnd; 397 } 398 399 bool GraphicsManager::isFullScreen() const 400 { 401 Ogre::ConfigOptionMap& options = ogreRoot_->getRenderSystem()->getConfigOptions(); 402 if (options.find("Full Screen") != options.end()) 403 { 404 if (options["Full Screen"].currentValue == "Yes") 405 return true; 406 else 407 return false; 408 } 409 else 410 { 411 COUT(0) << "Could not find 'Full Screen' render system option. Fix This!!!" << std::endl; 412 return false; 413 } 414 } 415 408 416 void GraphicsManager::printScreen() 409 417 {
Note: See TracChangeset
for help on using the changeset viewer.