Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/gui/src/orxonox/GraphicsEngine.cc @ 1651

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

tolua seems to be created correctly. I the existing toluabind.c file to create a tolua application that creates the actual pimped tolua application. But be aware that modifying the *.lua files will not cause a recompile. You need to tell iit manually.

There was quite a stupid issue with static initialisation (I'm really wondering how that could even work with msvc).

However things don't seem to work yet on tardis, at least not remotely. It seems like Ogre can't initialise when using a vnc session. I'll have to look into that locally at ETZ.

  • Property svn:eol-style set to native
File size: 16.1 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 "OrxonoxStableHeaders.h"
37#include "GraphicsEngine.h"
38
39#include <fstream>
40
41#include <OgreConfigFile.h>
42#include <OgreException.h>
43#include <OgreLogManager.h>
44#include <OgreRoot.h>
45#include <OgreSceneManager.h>
46#include <OgreTextureManager.h>
47#include <OgreViewport.h>
48
49#include "core/CoreIncludes.h"
50#include "core/ConfigValueIncludes.h"
51#include "core/Debug.h"
52#include "core/CommandExecutor.h"
53#include "core/ConsoleCommand.h"
54#include "core/Exception.h"
55
56#include "overlays/console/InGameConsole.h"
57#include "overlays/OverlayGroup.h"
58#include "tools/ParticleInterface.h"
59#include "Settings.h"
60#include "tools/WindowEventListener.h"
61
62#include "objects/CameraHandler.h"
63
64namespace orxonox
65{
66    GraphicsEngine* GraphicsEngine::singletonRef_s = 0;
67
68    /**
69    @brief
70        Returns the singleton instance.
71    @return
72        The only instance of GraphicsEngine.
73    */
74    /*static*/ GraphicsEngine& GraphicsEngine::getSingleton()
75    {
76        assert(singletonRef_s);
77        return *singletonRef_s;
78    }
79
80    /**
81    @brief
82        Non-initialising constructor.
83    */
84    GraphicsEngine::GraphicsEngine()
85        : root_(0)
86        , renderWindow_(0)
87        , levelSceneManager_(0)
88        , viewport_(0)
89    {
90        RegisterObject(GraphicsEngine);
91
92        assert(singletonRef_s == 0);
93        singletonRef_s = this;
94
95        this->detailLevelParticle_ = 0;
96
97        this->setConfigValues();
98        CCOUT(4) << "Constructed" << std::endl;
99    }
100
101    void GraphicsEngine::setConfigValues()
102    {
103        SetConfigValue(resourceFile_,    "resources.cfg").description("Location of the resources file in the data path.");
104        SetConfigValue(ogreConfigFile_,  "ogre.cfg").description("Location of the Ogre config file");
105        SetConfigValue(ogrePluginsFile_, "plugins.cfg").description("Location of the Ogre plugins file");
106        SetConfigValue(ogreLogFile_,     "ogre.log").description("Logfile for messages from Ogre. \
107                                                                 Use \"\" to suppress log file creation.");
108        SetConfigValue(ogreLogLevelTrivial_ , 5).description("Corresponding orxonox debug level for ogre Trivial");
109        SetConfigValue(ogreLogLevelNormal_  , 4).description("Corresponding orxonox debug level for ogre Normal");
110        SetConfigValue(ogreLogLevelCritical_, 2).description("Corresponding orxonox debug level for ogre Critical");
111
112        unsigned int old = this->detailLevelParticle_;
113        SetConfigValue(detailLevelParticle_, 2).description("O: off, 1: low, 2: normal, 3: high");
114
115        if (this->detailLevelParticle_ != old)
116            for (Iterator<ParticleInterface> it = ObjectList<ParticleInterface>::begin(); it; ++it)
117                it->detailLevelChanged(this->detailLevelParticle_);
118    }
119
120    /**
121    @brief
122        Destroys all the Ogre related objects
123    */
124    GraphicsEngine::~GraphicsEngine()
125    {
126        CCOUT(4) << "Destroying objects..." << std::endl;
127        Ogre::WindowEventUtilities::removeWindowEventListener(this->renderWindow_, this);
128        if (this->root_)
129            delete this->root_;
130        this->root_ = 0;
131        this->levelSceneManager_ = 0;
132        this->renderWindow_ = 0;
133
134#if ORXONOX_PLATFORM == ORXONOX_PLATFORM_WIN32
135        // delete the ogre log and the logManager (since we have created it).
136        if (Ogre::LogManager::getSingletonPtr() != 0)
137        {
138            Ogre::LogManager::getSingleton().getDefaultLog()->removeListener(this);
139            Ogre::LogManager::getSingleton().destroyLog(Ogre::LogManager::getSingleton().getDefaultLog());
140            delete Ogre::LogManager::getSingletonPtr();
141        }
142        CCOUT(4) << "Destroying objects done" << std::endl;
143#endif
144
145        singletonRef_s = 0;
146    }
147
148    /**
149    @brief
150        Creates the Ogre Root object and sets up the ogre log.
151    */
152    void GraphicsEngine::setup()
153    {
154        CCOUT(3) << "Setting up..." << std::endl;
155
156        // TODO: LogManager doesn't work on linux platform. The why is yet unknown.
157#if ORXONOX_PLATFORM == ORXONOX_PLATFORM_WIN32
158        // create a new logManager
159        Ogre::LogManager* logger = new Ogre::LogManager();
160        CCOUT(4) << "Ogre LogManager created" << std::endl;
161
162        // create our own log that we can listen to
163        Ogre::Log *myLog;
164        if (this->ogreLogFile_ == "")
165            myLog = logger->createLog("ogre.log", true, false, true);
166        else
167            myLog = logger->createLog(this->ogreLogFile_, true, false, false);
168        CCOUT(4) << "Ogre Log created" << std::endl;
169
170        myLog->setLogDetail(Ogre::LL_BOREME);
171        myLog->addListener(this);
172#endif
173
174        // Root will detect that we've already created a Log
175        CCOUT(4) << "Creating Ogre Root..." << std::endl;
176
177        if (ogrePluginsFile_ == "")
178        {
179            COUT(2) << "Warning: Ogre plugins file set to \"\". Defaulting to plugins.cfg" << std::endl;
180            ModifyConfigValue(ogrePluginsFile_, tset, "plugins.cfg");
181        }
182        if (ogreConfigFile_ == "")
183        {
184            COUT(2) << "Warning: Ogre config file set to \"\". Defaulting to config.cfg" << std::endl;
185            ModifyConfigValue(ogreConfigFile_, tset, "config.cfg");
186        }
187        if (ogreLogFile_ == "")
188        {
189            COUT(2) << "Warning: Ogre log file set to \"\". Defaulting to ogre.log" << std::endl;
190            ModifyConfigValue(ogreLogFile_, tset, "ogre.log");
191        }
192
193        root_ = new Ogre::Root(ogrePluginsFile_, ogreConfigFile_, ogreLogFile_);
194
195        if (!root_->getInstalledPlugins().size())
196        {
197            ThrowException(PluginsNotFound, "No Ogre plugins declared. Cannot load Ogre.");
198        }
199
200#if 0 // Ogre 1.4.3 doesn't support setDebugOutputEnabled(.)
201//#if ORXONOX_PLATFORM != ORXONOX_PLATFORM_WIN32
202        // tame the ogre ouput so we don't get all the mess in the console
203        Ogre::Log* defaultLog = Ogre::LogManager::getSingleton().getDefaultLog();
204        defaultLog->setDebugOutputEnabled(false);
205        defaultLog->setLogDetail(Ogre::LL_BOREME);
206        defaultLog->addListener(this);
207#endif
208
209        CCOUT(4) << "Creating Ogre Root done" << std::endl;
210
211        // specify where Ogre has to look for resources. This call doesn't parse anything yet!
212        declareRessourceLocations();
213
214        CCOUT(3) << "Set up done." << std::endl;
215    }
216
217    void GraphicsEngine::declareRessourceLocations()
218    {
219        CCOUT(4) << "Declaring Resources" << std::endl;
220        //TODO: Specify layout of data file and maybe use xml-loader
221        //TODO: Work with ressource groups (should be generated by a special loader)
222
223        if (resourceFile_ == "")
224        {
225            COUT(2) << "Warning: Ogre resource file set to \"\". Defaulting to resources.cfg" << std::endl;
226            ModifyConfigValue(resourceFile_, tset, "resources.cfg");
227        }
228
229        // Load resource paths from data file using configfile ressource type
230        Ogre::ConfigFile cf;
231        try
232        {
233            cf.load(Settings::getDataPath() + resourceFile_);
234        }
235        catch (Ogre::Exception& ex)
236        {
237            COUT(1) << ex.getFullDescription() << std::endl;
238            COUT(0) << "Have you forgotten to set the data path in orxnox.ini?" << std::endl;
239            throw;
240        }
241
242        // Go through all sections & settings in the file
243        Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
244
245        std::string secName, typeName, archName;
246        while (seci.hasMoreElements())
247        {
248            try
249            {
250                secName = seci.peekNextKey();
251                Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
252                Ogre::ConfigFile::SettingsMultiMap::iterator i;
253                for (i = settings->begin(); i != settings->end(); ++i)
254                {
255                    typeName = i->first; // for instance "FileSystem" or "Zip"
256                    archName = i->second; // name (and location) of archive
257
258                    Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
259                        std::string(Settings::getDataPath() + archName), typeName, secName);
260                }
261            }
262            catch (Ogre::Exception& ex)
263            {
264                COUT(1) << ex.getFullDescription() << std::endl;
265            }
266        }
267    }
268
269    bool GraphicsEngine::loadRenderer()
270    {
271        CCOUT(4) << "Configuring Renderer" << std::endl;
272
273        // check for file existence because Ogre displays exceptions if not
274        std::ifstream probe;
275        probe.open(ogreConfigFile_.c_str());
276        if (!probe)
277        {
278            // create a zero sized file
279            std::ofstream creator;
280            creator.open(ogreConfigFile_.c_str());
281            creator.close();
282        }
283        else
284            probe.close();
285
286        if (!root_->restoreConfig())
287            if (!root_->showConfigDialog())
288                return false;
289
290        CCOUT(4) << "Creating render window" << std::endl;
291        try
292        {
293            this->renderWindow_ = root_->initialise(true, "OrxonoxV2");
294        }
295        catch (std::exception& ex)
296        {
297            COUT(2) << "Error: There was an exception when initialising Ogre Root." << std::endl;
298                        COUT(1) << ex.what() << std::endl;
299            return false;
300        }
301
302        if (!root_->isInitialised())
303        {
304            CCOUT(2) << "Error: Initialising Ogre root object failed." << std::endl;
305            return false;
306        }
307        Ogre::WindowEventUtilities::addWindowEventListener(this->renderWindow_, this);
308        //Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
309
310        // create a full screen viewport
311        this->viewport_ = this->renderWindow_->addViewport(0, 0);
312
313        return true;
314    }
315
316    bool GraphicsEngine::initialiseResources()
317    {
318        CCOUT(4) << "Initialising resources" << std::endl;
319        //TODO: Do NOT load all the groups, why are we doing that? And do we really do that? initialise != load...
320        try
321        {
322            Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
323            /*Ogre::StringVector str = Ogre::ResourceGroupManager::getSingleton().getResourceGroups();
324            for (unsigned int i = 0; i < str.size(); i++)
325            {
326            Ogre::ResourceGroupManager::getSingleton().loadResourceGroup(str[i]);
327            }*/
328        }
329        catch (Ogre::Exception& e)
330        {
331            CCOUT(2) << "Error: There was an Error when initialising the resources." << std::endl;
332            CCOUT(2) << "ErrorMessage: " << e.getFullDescription() << std::endl;
333            return false;
334        }
335        return true;
336    }
337
338    /**
339    @brief
340        Creates the SceneManager
341    */
342    bool GraphicsEngine::createNewScene()
343    {
344        CCOUT(4) << "Creating new SceneManager..." << std::endl;
345        if (levelSceneManager_)
346        {
347            CCOUT(2) << "SceneManager already exists! Skipping." << std::endl;
348            return false;
349        }
350        this->levelSceneManager_ = this->root_->createSceneManager(Ogre::ST_GENERIC, "LevelSceneManager");
351        CCOUT(3) << "Created SceneManager: " << levelSceneManager_ << std::endl;
352        return true;
353    }
354
355    /**
356    @brief
357        Returns the window handle of the render window.
358        At least the InputHandler uses this to create the OIS::InputManager
359    @return
360        The window handle of the render window
361    */
362    size_t GraphicsEngine::getWindowHandle()
363    {
364        if (this->renderWindow_)
365        {
366            size_t windowHnd = 0;
367            this->renderWindow_->getCustomAttribute("WINDOW", &windowHnd);
368            return windowHnd;
369        }
370        else
371            return 0;
372    }
373
374    /**
375    @brief
376        Get the width of the render window
377    @return
378        The width of the render window
379    */
380    int GraphicsEngine::getWindowWidth() const
381    {
382        if (this->renderWindow_)
383            return this->renderWindow_->getWidth();
384        else
385            return 0;
386    }
387
388    /**
389    @brief
390        Get the height of the render window
391    @return
392        The height of the render window
393    */
394    int GraphicsEngine::getWindowHeight() const
395    {
396        if (this->renderWindow_)
397            return this->renderWindow_->getHeight();
398        else
399            return 0;
400    }
401
402    /**
403    @brief
404        Returns the window aspect ratio height/width.
405    @return
406        The window aspect ratio
407    */
408    float GraphicsEngine::getWindowAspectRatio() const
409    {
410        if (this->renderWindow_)
411            return (float)this->renderWindow_->getHeight() / (float)this->renderWindow_->getWidth();
412        else
413            return 1.0f;
414    }
415
416    /**
417    @brief
418        Method called by the LogListener interface from Ogre.
419        We use it to capture Ogre log messages and handle it ourselves.
420    @param message
421        The message to be logged
422    @param lml
423        The message level the log is using
424    @param maskDebug
425        If we are printing to the console or not
426    @param logName
427        The name of this log (so you can have several listeners
428        for different logs, and identify them)
429    */
430    void GraphicsEngine::messageLogged(const std::string& message,
431        Ogre::LogMessageLevel lml, bool maskDebug, const std::string &logName)
432    {
433        int orxonoxLevel;
434        switch (lml)
435        {
436        case Ogre::LML_TRIVIAL:
437            orxonoxLevel = this->ogreLogLevelTrivial_;
438            break;
439        case Ogre::LML_NORMAL:
440            orxonoxLevel = this->ogreLogLevelNormal_;
441            break;
442        case Ogre::LML_CRITICAL:
443            orxonoxLevel = this->ogreLogLevelCritical_;
444            break;
445        default:
446            orxonoxLevel = 0;
447        }
448        OutputHandler::getOutStream().setOutputLevel(orxonoxLevel)
449            << "Ogre: " << message << std::endl;
450    }
451
452    /**
453    @brief
454        Window has moved.
455    @param rw
456        The render window it occured in
457    */
458    void GraphicsEngine::windowMoved(Ogre::RenderWindow *rw)
459    {
460        for (Iterator<orxonox::WindowEventListener> it = ObjectList<orxonox::WindowEventListener>::start(); it; ++it)
461            it->windowMoved();
462    }
463
464    /**
465    @brief
466        Window has resized.
467    @param rw
468        The render window it occured in
469    @note
470        GraphicsEngine has a render window stored itself. This is the same
471        as rw. But we have to be careful when using multiple render windows!
472    */
473    void GraphicsEngine::windowResized(Ogre::RenderWindow *rw)
474    {
475        for (Iterator<orxonox::WindowEventListener> it = ObjectList<orxonox::WindowEventListener>::start(); it; ++it)
476            it->windowResized(this->renderWindow_->getWidth(), this->renderWindow_->getHeight());
477    }
478
479    /**
480    @brief
481        Window focus has changed.
482    @param rw
483        The render window it occured in
484    */
485    void GraphicsEngine::windowFocusChanged(Ogre::RenderWindow *rw)
486    {
487        for (Iterator<orxonox::WindowEventListener> it = ObjectList<orxonox::WindowEventListener>::start(); it; ++it)
488            it->windowFocusChanged();
489    }
490
491    /**
492    @brief
493        Window was closed.
494    @param rw
495        The render window it occured in
496    */
497    void GraphicsEngine::windowClosed(Ogre::RenderWindow *rw)
498    {
499        // using CommandExecutor in order to avoid depending on Orxonox.h.
500        CommandExecutor::execute("exit", false);
501    }
502
503}
Note: See TracBrowser for help on using the repository browser.