Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Aug 30, 2009, 2:22:00 AM (15 years ago)
Author:
rgrieder
Message:

Merged resource2 branch back to trunk.

IMPORTANT NOTE:
Upon this merge you need to specifically call your data directory "data_extern" when checking it out (when you don't provide a name, it will be just called 'trunk').
The new CMake variable is EXTERNAL_DATA_DIRECTORY. DATA_DIRECTORY now points to the one the source part of the repository.
UPDATE YOUR DATA DIRECTORY AS WELL!!!

Location:
code/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/trunk

  • code/trunk/src/core/GraphicsManager.cc

    r3370 r5695  
    2828 */
    2929
    30 /**
    31 @file
    32 @brief
    33     Implementation of an partial interface to Ogre.
    34 */
    35 
    3630#include "GraphicsManager.h"
    3731
    3832#include <fstream>
    39 #include <memory>
     33#include <sstream>
    4034#include <boost/filesystem.hpp>
    41 #include <boost/shared_ptr.hpp>
    42 
    43 #include <OgreCompositorManager.h>
    44 #include <OgreConfigFile.h>
     35#include <boost/shared_array.hpp>
     36
     37#include <OgreArchiveFactory.h>
     38#include <OgreArchiveManager.h>
    4539#include <OgreFrameListener.h>
    4640#include <OgreRoot.h>
    4741#include <OgreLogManager.h>
    48 #include <OgreException.h>
    4942#include <OgreRenderWindow.h>
    5043#include <OgreRenderSystem.h>
     44#include <OgreResourceGroupManager.h>
    5145#include <OgreTextureManager.h>
    5246#include <OgreViewport.h>
     
    6458#include "Game.h"
    6559#include "GameMode.h"
     60#include "Loader.h"
     61#include "MemoryArchive.h"
    6662#include "WindowEventListener.h"
     63#include "XMLFile.h"
    6764
    6865namespace orxonox
    6966{
    70     using boost::shared_ptr;
    71 
    7267    class OgreWindowEventListener : public Ogre::WindowEventListener
    7368    {
     
    8984        Non-initialising constructor.
    9085    */
    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
    9491        , renderWindow_(0)
    9592        , viewport_(0)
    96         , ogreWindowEventListener_(new OgreWindowEventListener())
    9793    {
    9894        RegisterObject(GraphicsManager);
     
    10096        this->setConfigValues();
    10197
    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();
    130123        }
    131124    }
     
    133126    /**
    134127    @brief
    135         Destroys all the Ogre related objects
     128        Destruction is done by the member scoped_ptrs.
    136129    */
    137130    GraphicsManager::~GraphicsManager()
    138131    {
    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
    153134    }
    154135
    155136    void GraphicsManager::setConfigValues()
    156137    {
    157         SetConfigValue(resourceFile_,    "resources.cfg")
    158             .description("Location of the resources file in the data path.");
    159138        SetConfigValue(ogreConfigFile_,  "ogre.cfg")
    160139            .description("Location of the Ogre config file");
    161         SetConfigValue(ogrePluginsFolder_, ORXONOX_OGRE_PLUGINS_FOLDER)
     140        SetConfigValue(ogrePluginsDirectory_, specialConfig::ogrePluginsDirectory)
    162141            .description("Folder where the Ogre plugins are located.");
    163         SetConfigValue(ogrePlugins_, ORXONOX_OGRE_PLUGINS)
     142        SetConfigValue(ogrePlugins_, specialConfig::ogrePlugins)
    164143            .description("Comma separated list of all plugins to load.");
    165144        SetConfigValue(ogreLogFile_,     "ogre.log")
     
    173152    }
    174153
     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
    175320    void GraphicsManager::update(const Clock& time)
    176321    {
     
    207352    {
    208353        this->viewport_->setCamera(camera);
    209     }
    210 
    211     /**
    212     @brief
    213         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 logManager
    234         // Ogre::Root will detect that we've already created a Log
    235         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 to
    239         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 not
    249         if (!boost::filesystem::exists(ogreConfigFilepath))
    250         {
    251             // create a zero sized file
    252             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 later
    258         ogreRoot_ = new Ogre::Root("", ogreConfigFilepath.string(), ogreLogFilepath.string());
    259         // In case that new Root failed the logger gets destroyed because of the std::auto_ptr
    260         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 segfault
    268         if (ogrePluginsFolder_ == "")
    269             ogrePluginsFolder_ = ".";
    270 
    271         boost::filesystem::path folder(ogrePluginsFolder_);
    272         // Do some SubString magic to get the comma separated list of plugins
    273         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-loader
    283         //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 type
    292         Ogre::ConfigFile cf;
    293         try
    294         {
    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 file
    305         Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
    306 
    307         std::string secName, typeName, archName;
    308         while (seci.hasMoreElements())
    309         {
    310             try
    311             {
    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 archive
    319 
    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 viewport
    349         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         //try
    357         //{
    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         //}
    370354    }
    371355
     
    406390    }
    407391
     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
    408416    void GraphicsManager::printScreen()
    409417    {
Note: See TracChangeset for help on using the changeset viewer.