Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/resource2/src/core/GraphicsManager.cc @ 5633

Last change on this file since 5633 was 5614, checked in by rgrieder, 16 years ago

Creating Ogre::Root in non graphics mode as well. This allows to always make use of the ResourceGroupManager.
Also removed resource related parts from GraphicsManager.

This revision does not run!

  • Property svn:eol-style set to native
File size: 10.9 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Reto Grieder
24 *      Benjamin Knecht <beni_at_orxonox.net>, (C) 2007
25 *   Co-authors:
26 *      Felix Schulthess
27 *
28 */
29
30/**
31@file
32@brief
33    Implementation of an partial interface to Ogre.
34*/
35
36#include "GraphicsManager.h"
37
38#include <fstream>
39#include <boost/filesystem.hpp>
40
41#include <OgreFrameListener.h>
42#include <OgreRoot.h>
43#include <OgreLogManager.h>
44#include <OgreException.h>
45#include <OgreRenderWindow.h>
46#include <OgreRenderSystem.h>
47#include <OgreViewport.h>
48#include <OgreWindowEventUtilities.h>
49
50#include "SpecialConfig.h"
51#include "util/Exception.h"
52#include "util/StringUtils.h"
53#include "util/SubString.h"
54#include "Clock.h"
55#include "ConsoleCommand.h"
56#include "ConfigValueIncludes.h"
57#include "CoreIncludes.h"
58#include "Core.h"
59#include "Game.h"
60#include "GameMode.h"
61#include "WindowEventListener.h"
62
63namespace orxonox
64{
65    class OgreWindowEventListener : public Ogre::WindowEventListener
66    {
67    public:
68        void windowResized     (Ogre::RenderWindow* rw)
69            { orxonox::WindowEventListener::resizeWindow(rw->getWidth(), rw->getHeight()); }
70        void windowFocusChange (Ogre::RenderWindow* rw)
71            { orxonox::WindowEventListener::changeWindowFocus(); }
72        void windowClosed      (Ogre::RenderWindow* rw)
73            { orxonox::Game::getInstance().stop(); }
74        void windowMoved       (Ogre::RenderWindow* rw)
75            { orxonox::WindowEventListener::moveWindow(); }
76    };
77
78    GraphicsManager* GraphicsManager::singletonPtr_s = 0;
79
80    /**
81    @brief
82        Non-initialising constructor.
83    */
84    GraphicsManager::GraphicsManager(bool bLoadRenderer)
85        : renderWindow_(0)
86        , viewport_(0)
87        , ogreWindowEventListener_(new OgreWindowEventListener())
88    {
89        RegisterObject(GraphicsManager);
90
91        this->setConfigValues();
92
93        // Ogre setup procedure (creating Ogre::Root)
94        this->loadOgreRoot();
95        // load all the required plugins for Ogre
96        this->loadOgrePlugins();
97
98        if (bLoadRenderer)
99        {
100            // Reads the ogre config and creates the render window
101            this->loadRenderer();
102        }
103    }
104
105    /**
106    @brief
107        Destruction is done by the member scoped_ptrs.
108    */
109    GraphicsManager::~GraphicsManager()
110    {
111    }
112
113    void GraphicsManager::setConfigValues()
114    {
115        SetConfigValue(ogreConfigFile_,  "ogre.cfg")
116            .description("Location of the Ogre config file");
117        SetConfigValue(ogrePluginsFolder_, ORXONOX_OGRE_PLUGINS_FOLDER)
118            .description("Folder where the Ogre plugins are located.");
119        SetConfigValue(ogrePlugins_, ORXONOX_OGRE_PLUGINS)
120            .description("Comma separated list of all plugins to load.");
121        SetConfigValue(ogreLogFile_,     "ogre.log")
122            .description("Logfile for messages from Ogre. Use \"\" to suppress log file creation.");
123        SetConfigValue(ogreLogLevelTrivial_ , 5)
124            .description("Corresponding orxonox debug level for ogre Trivial");
125        SetConfigValue(ogreLogLevelNormal_  , 4)
126            .description("Corresponding orxonox debug level for ogre Normal");
127        SetConfigValue(ogreLogLevelCritical_, 2)
128            .description("Corresponding orxonox debug level for ogre Critical");
129    }
130
131    /**
132    @brief
133        Loads the renderer and creates the render window if not yet done so.
134    @remarks
135        This operation is irreversible without recreating the GraphicsManager!
136    */
137    void GraphicsManager::upgradeToGraphics()
138    {
139        if (renderWindow_ == NULL)
140        {
141            this->loadRenderer();
142        }
143    }
144
145    /**
146    @brief
147        Creates the Ogre Root object and sets up the ogre log.
148    */
149    void GraphicsManager::loadOgreRoot()
150    {
151        COUT(3) << "Setting up Ogre..." << std::endl;
152
153        if (ogreConfigFile_ == "")
154        {
155            COUT(2) << "Warning: Ogre config file set to \"\". Defaulting to config.cfg" << std::endl;
156            ModifyConfigValue(ogreConfigFile_, tset, "config.cfg");
157        }
158        if (ogreLogFile_ == "")
159        {
160            COUT(2) << "Warning: Ogre log file set to \"\". Defaulting to ogre.log" << std::endl;
161            ModifyConfigValue(ogreLogFile_, tset, "ogre.log");
162        }
163
164        boost::filesystem::path ogreConfigFilepath(Core::getConfigPath() / this->ogreConfigFile_);
165        boost::filesystem::path ogreLogFilepath(Core::getLogPath() / this->ogreLogFile_);
166
167        // create a new logManager
168        // Ogre::Root will detect that we've already created a Log
169        ogreLogger_.reset(new Ogre::LogManager());
170        COUT(4) << "Ogre LogManager created" << std::endl;
171
172        // create our own log that we can listen to
173        Ogre::Log *myLog;
174        myLog = ogreLogger_->createLog(ogreLogFilepath.string(), true, false, false);
175        COUT(4) << "Ogre Log created" << std::endl;
176
177        myLog->setLogDetail(Ogre::LL_BOREME);
178        myLog->addListener(this);
179
180        COUT(4) << "Creating Ogre Root..." << std::endl;
181
182        // check for config file existence because Ogre displays (caught) exceptions if not
183        if (!boost::filesystem::exists(ogreConfigFilepath))
184        {
185            // create a zero sized file
186            std::ofstream creator;
187            creator.open(ogreConfigFilepath.string().c_str());
188            creator.close();
189        }
190
191        // Leave plugins file empty. We're going to do that part manually later
192        ogreRoot_.reset(new Ogre::Root("", ogreConfigFilepath.string(), ogreLogFilepath.string()));
193
194        COUT(3) << "Ogre set up done." << std::endl;
195    }
196
197    void GraphicsManager::loadOgrePlugins()
198    {
199        // just to make sure the next statement doesn't segfault
200        if (ogrePluginsFolder_ == "")
201            ogrePluginsFolder_ = ".";
202
203        boost::filesystem::path folder(ogrePluginsFolder_);
204        // Do some SubString magic to get the comma separated list of plugins
205        SubString plugins(ogrePlugins_, ",", " ", false, '\\', false, '"', false, '(', ')', false, '\0');
206        // Use backslash paths on Windows! file_string() already does that though.
207        for (unsigned int i = 0; i < plugins.size(); ++i)
208            ogreRoot_->loadPlugin((folder / plugins[i]).file_string());
209    }
210
211    void GraphicsManager::loadRenderer()
212    {
213        CCOUT(4) << "Configuring Renderer" << std::endl;
214
215        if (!ogreRoot_->restoreConfig())
216            if (!ogreRoot_->showConfigDialog())
217                ThrowException(InitialisationFailed, "OGRE graphics configuration dialogue failed.");
218
219        CCOUT(4) << "Creating render window" << std::endl;
220
221        this->renderWindow_ = ogreRoot_->initialise(true, "Orxonox");
222        // Propagate the size of the new winodw
223        this->ogreWindowEventListener_->windowResized(renderWindow_);
224
225        Ogre::WindowEventUtilities::addWindowEventListener(this->renderWindow_, ogreWindowEventListener_.get());
226
227        // create a full screen default viewport
228        // Note: This may throw when adding a viewport with an existing z-order!
229        //       But in our case we only have one viewport for now anyway, therefore
230        //       no ScopeGuards or anything to handle exceptions.
231        this->viewport_ = this->renderWindow_->addViewport(0, 0);
232
233        // add console commands
234        FunctorMember<GraphicsManager>* functor1 = createFunctor(&GraphicsManager::printScreen);
235        ccPrintScreen_ = createConsoleCommand(functor1->setObject(this), "printScreen");
236        CommandExecutor::addConsoleCommandShortcut(ccPrintScreen_);
237    }
238
239    void GraphicsManager::update(const Clock& time)
240    {
241        Ogre::FrameEvent evt;
242        evt.timeSinceLastFrame = time.getDeltaTime();
243        evt.timeSinceLastEvent = time.getDeltaTime(); // note: same time, but shouldn't matter anyway
244
245        // don't forget to call _fireFrameStarted to OGRE to make sure
246        // everything goes smoothly
247        ogreRoot_->_fireFrameStarted(evt);
248
249        // Pump messages in all registered RenderWindows
250        // This calls the WindowEventListener objects.
251        Ogre::WindowEventUtilities::messagePump();
252        // make sure the window stays active even when not focused
253        // (probably only necessary on windows)
254        this->renderWindow_->setActive(true);
255
256        // Time before rendering
257        uint64_t timeBeforeTick = time.getRealMicroseconds();
258
259        // Render frame
260        ogreRoot_->_updateAllRenderTargets();
261
262        uint64_t timeAfterTick = time.getRealMicroseconds();
263        // Subtract the time used for rendering from the tick time counter
264        Game::getInstance().subtractTickTime(timeAfterTick - timeBeforeTick);
265
266        // again, just to be sure OGRE works fine
267        ogreRoot_->_fireFrameEnded(evt); // note: uses the same time as _fireFrameStarted
268    }
269
270    void GraphicsManager::setCamera(Ogre::Camera* camera)
271    {
272        this->viewport_->setCamera(camera);
273    }
274
275    /**
276    @brief
277        Method called by the LogListener interface from Ogre.
278        We use it to capture Ogre log messages and handle it ourselves.
279    @param message
280        The message to be logged
281    @param lml
282        The message level the log is using
283    @param maskDebug
284        If we are printing to the console or not
285    @param logName
286        The name of this log (so you can have several listeners
287        for different logs, and identify them)
288    */
289    void GraphicsManager::messageLogged(const std::string& message,
290        Ogre::LogMessageLevel lml, bool maskDebug, const std::string& logName)
291    {
292        int orxonoxLevel;
293        switch (lml)
294        {
295        case Ogre::LML_TRIVIAL:
296            orxonoxLevel = this->ogreLogLevelTrivial_;
297            break;
298        case Ogre::LML_NORMAL:
299            orxonoxLevel = this->ogreLogLevelNormal_;
300            break;
301        case Ogre::LML_CRITICAL:
302            orxonoxLevel = this->ogreLogLevelCritical_;
303            break;
304        default:
305            orxonoxLevel = 0;
306        }
307        OutputHandler::getOutStream().setOutputLevel(orxonoxLevel)
308            << "Ogre: " << message << std::endl;
309    }
310
311    void GraphicsManager::printScreen()
312    {
313        assert(this->renderWindow_);
314       
315        this->renderWindow_->writeContentsToTimestampedFile(Core::getLogPathString() + "screenShot_", ".jpg");
316    }
317}
Note: See TracBrowser for help on using the repository browser.