Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ogre/src/orxonox/GraphicsEngine.cc @ 1416

Last change on this file since 1416 was 1260, checked in by rgrieder, 17 years ago
  • moved variable initialisation of class hierarchy members into initialiser list
  • added windowClosed (Ogre::WindowEventUtilities::WindowEventListener) event to GraphicsEngine
File size: 11.3 KB
RevLine 
[612]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
[1056]3 *                    > www.orxonox.net <
[612]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 *      Benjamin Knecht <beni_at_orxonox.net>, (C) 2007
24 *   Co-authors:
[1032]25 *      Reto Grieder
[612]26 *
27 */
[1035]28
[612]29 /**
30    @file orxonox.cc
31    @brief Orxonox class
32  */
33
[1021]34#include "OrxonoxStableHeaders.h"
[1039]35#include "GraphicsEngine.h"
[612]36
37#include <OgreRoot.h>
[1021]38#include <OgreException.h>
[612]39#include <OgreConfigFile.h>
[1024]40#include <OgreLogManager.h>
[612]41#include <OgreTextureManager.h>
[1214]42#include "core/InputManager.h"
[1052]43#include "core/CoreIncludes.h"
44#include "core/ConfigValueIncludes.h"
[1214]45#include "core/Debug.h"
[1260]46#include "core/CommandExecutor.h"
[1032]47
[612]48
49namespace orxonox {
50
[1032]51  /**
52    @brief Returns the singleton instance and creates it the first time.
53    @return The only instance of GraphicsEngine.
54  */
[1249]55  /*static*/ GraphicsEngine& GraphicsEngine::getSingleton()
[1032]56  {
57    static GraphicsEngine theOnlyInstance;
58    return theOnlyInstance;
59  }
60
61  /**
62    @brief Only use constructor to initialise variables and pointers!
63  */
[1249]64  GraphicsEngine::GraphicsEngine() :
65    root_(0),
66    scene_(0),
67    renderWindow_(0),
68    //configPath_(""),
69    dataPath_(""),
70    ogreLogfile_("")
[612]71  {
[1021]72    RegisterObject(GraphicsEngine);
[1249]73
[1243]74    this->setConfigValues();
[1244]75    CCOUT(4) << "Constructed" << std::endl;
[612]76  }
77
[1249]78  void GraphicsEngine::setConfigValues()
79  {
80    SetConfigValue(dataPath_, "../../Media/").description("relative path to media data");
81    SetConfigValue(ogreLogfile_, "ogre.log").description("Logfile for messages from Ogre. Use \"\" to suppress log file creation.");
82    SetConfigValue(ogreLogLevelTrivial_ , 5).description("Corresponding orxonox debug level for ogre Trivial");
83    SetConfigValue(ogreLogLevelNormal_  , 4).description("Corresponding orxonox debug level for ogre Normal");
84    SetConfigValue(ogreLogLevelCritical_, 2).description("Corresponding orxonox debug level for ogre Critical");
85  }
86
[1032]87  /**
88    @brief Called after main() --> call destroyObjects()!
89  */
[612]90  GraphicsEngine::~GraphicsEngine()
91  {
[1032]92    this->destroy();
93  }
94
95  /**
96    @brief Destroys all the internal objects. Call this method when you
97           normally would call the destructor.
98  */
99  void GraphicsEngine::destroy()
100  {
[1244]101    COUT(4) << "Destroying objects..." << std::endl;
[1214]102    Ogre::WindowEventUtilities::removeWindowEventListener(this->renderWindow_, this);
[1024]103    if (this->root_)
[1021]104      delete this->root_;
[1032]105    this->root_ = 0;
106    this->scene_ = 0;
107    this->renderWindow_ = 0;
108    // delete the ogre log and the logManager (since we have created it).
[1052]109    if (Ogre::LogManager::getSingletonPtr() != 0)
[1024]110    {
[1052]111      Ogre::LogManager::getSingleton().getDefaultLog()->removeListener(this);
112      Ogre::LogManager::getSingleton().destroyLog(Ogre::LogManager::getSingleton().getDefaultLog());
113      delete Ogre::LogManager::getSingletonPtr();
[1024]114    }
[1244]115    COUT(4) << "Destroying objects done" << std::endl;
[612]116  }
117
[1024]118  /**
119    @brief Creates the Ogre Root object and sets up the ogre log.
120  */
[1243]121  bool GraphicsEngine::setup(std::string& dataPath)
[612]122  {
[1244]123    CCOUT(3) << "Setting up..." << std::endl;
[1243]124    // temporary overwrite of dataPath, change ini file for permanent change
125    if (dataPath != "")
126      dataPath_ = dataPath;
127    if (dataPath_ == "")
128      return false;
129    if (dataPath_[dataPath_.size() - 1] != '/')
130      dataPath_ += "/";
131
[612]132    //TODO: Check if file exists (maybe not here)
[1021]133#if ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC && defined(_DEBUG)
[715]134    std::string plugin_filename = "plugins_d.cfg";
[679]135#else
[715]136    std::string plugin_filename = "plugins.cfg";
[679]137#endif
[1024]138
139    // create a logManager
[1062]140    Ogre::LogManager *logger;
[1260]141    if (Ogre::LogManager::getSingletonPtr() == 0)
142      logger = new Ogre::LogManager();
[1024]143    else
[1062]144      logger = Ogre::LogManager::getSingletonPtr();
[1244]145    CCOUT(4) << "Ogre LogManager created/assigned" << std::endl;
[1024]146
147    // create our own log that we can listen to
[1062]148    Ogre::Log *myLog;
[1024]149    if (this->ogreLogfile_ == "")
150      myLog = logger->createLog("ogre.log", true, false, true);
151    else
152      myLog = logger->createLog(this->ogreLogfile_, true, false, false);
[1032]153    COUT(4) << "*** GraphicsEngine: Ogre Log created" << std::endl;
[1024]154
[1062]155    myLog->setLogDetail(Ogre::LL_BOREME);
156    myLog->addListener(this);
[1024]157
158    // Root will detect that we've already created a Log
[1244]159    CCOUT(4) << "Creating Ogre Root..." << std::endl;
[1052]160    root_ = new Ogre::Root(plugin_filename);
[1244]161    CCOUT(4) << "Creating Ogre Root done" << std::endl;
[612]162
[1243]163    // specify where Ogre has to look for resources. This call doesn't parse anything yet!
164    declareRessourceLocations();
[612]165
[1244]166    CCOUT(3) << "Set up done." << std::endl;
[612]167    return true;
168  }
169
[1243]170  void GraphicsEngine::declareRessourceLocations()
[612]171  {
[1244]172    CCOUT(4) << "Declaring Resources" << std::endl;
[612]173    //TODO: Specify layout of data file and maybe use xml-loader
174    //TODO: Work with ressource groups (should be generated by a special loader)
175    // Load resource paths from data file using configfile ressource type
[1052]176    Ogre::ConfigFile cf;
[1243]177    cf.load(dataPath_ + "resources.cfg");
[612]178
179    // Go through all sections & settings in the file
[1052]180    Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
[612]181
[715]182    std::string secName, typeName, archName;
[612]183    while (seci.hasMoreElements())
184    {
185      secName = seci.peekNextKey();
[1052]186      Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
187      Ogre::ConfigFile::SettingsMultiMap::iterator i;
[612]188      for (i = settings->begin(); i != settings->end(); ++i)
189      {
190        typeName = i->first; // for instance "FileSystem" or "Zip"
191        archName = i->second; // name (and location) of archive
192
[1052]193        Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
[1243]194                                           std::string(dataPath_ + archName),
[612]195                                           typeName, secName);
196      }
197    }
198  }
199
[1243]200  bool GraphicsEngine::loadRenderer()
201  {
[1244]202    CCOUT(4) << "Configuring Renderer" << std::endl;
[1243]203    if (!root_->restoreConfig() && !root_->showConfigDialog())
204      return false;
205
[1244]206    CCOUT(4) << "Creating render window" << std::endl;
[1243]207    this->renderWindow_ = root_->initialise(true, "OrxonoxV2");
208    if (!root_->isInitialised())
[1244]209    {
210      CCOUT(2) << "Error: Creating Ogre root object failed" << std::endl;
[1243]211      return false;
[1244]212    }
[1243]213    Ogre::WindowEventUtilities::addWindowEventListener(this->renderWindow_, this);
214    Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
215    return true;
216  }
217
[1244]218  bool GraphicsEngine::initialiseResources()
[1243]219  {
[1244]220    CCOUT(4) << "Initialising resources" << std::endl;
[1243]221    //TODO: Do NOT load all the groups, why are we doing that? And do we really do that? initialise != load...
[1244]222    try
223    {
224      Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
[1260]225      /*Ogre::StringVector str = Ogre::ResourceGroupManager::getSingleton().getResourceGroups();
[1252]226      for (unsigned int i = 0; i < str.size(); i++)
227      {
228        Ogre::ResourceGroupManager::getSingleton().loadResourceGroup(str[i]);
[1260]229      }*/
[1244]230    }
231    catch (Ogre::Exception e)
232    {
233      CCOUT(2) << "Error: There was an Error when initialising the resources." << std::endl;
234      CCOUT(2) << "ErrorMessage: " << e.getFullDescription() << std::endl;
235      return false;
236    }
237    return true;
[1243]238  }
239
[1021]240  /**
[1243]241   * @brief Creates the SceneManager
242   */
243  bool GraphicsEngine::createNewScene()
244  {
[1244]245    CCOUT(4) << "Creating new SceneManager" << std::endl;
[1243]246    if (scene_)
[1244]247    {
248      CCOUT(2) << "SceneManager already exists! Skipping." << std::endl;
[1243]249      return false;
[1244]250    }
[1243]251    scene_ = root_->createSceneManager(Ogre::ST_GENERIC, "Default SceneManager");
[1244]252    CCOUT(3) << "Created SceneManager: " << scene_ << std::endl;
[1243]253    return true;
254  }
255
256  /**
[1021]257    Returns the window handle of the render window.
258    At least the InputHandler uses this to create the OIS::InputManager
259    @return The window handle of the render window
260  */
261  size_t GraphicsEngine::getWindowHandle()
262  {
263    if (this->renderWindow_)
264    {
[1024]265      size_t windowHnd = 0;
[1032]266      this->renderWindow_->getCustomAttribute("WINDOW", &windowHnd);
[1024]267      return windowHnd;
268    }
[1021]269    else
270      return 0;
271  }
[612]272
[1021]273  /**
274    Get the width of the current render window
275    @return The width of the current render window
276  */
277  int GraphicsEngine::getWindowWidth() const
278  {
279    if (this->renderWindow_)
280      return this->renderWindow_->getWidth();
281    else
282      return 0;
283  }
284
285  /**
286    Get the height of the current render window
287    @return The height of the current render window
288  */
289  int GraphicsEngine::getWindowHeight() const
290  {
291    if (this->renderWindow_)
292      return this->renderWindow_->getHeight();
293    else
294      return 0;
295  }
296
[1024]297  /**
298    @brief Method called by the LogListener interface from Ogre.
299    We use it to capture Ogre log messages and handle it ourselves.
300    @param message The message to be logged
301    @param lml The message level the log is using
302    @param maskDebug If we are printing to the console or not
303    @param logName the name of this log (so you can have several listeners
304                   for different logs, and identify them)
305  */
306  void GraphicsEngine::messageLogged(const std::string& message,
[1052]307    Ogre::LogMessageLevel lml, bool maskDebug, const std::string &logName)
[1024]308  {
309    int orxonoxLevel;
310    switch (lml)
311    {
[1052]312      case Ogre::LML_TRIVIAL:
[1024]313        orxonoxLevel = this->ogreLogLevelTrivial_;
314        break;
[1052]315      case Ogre::LML_NORMAL:
[1024]316        orxonoxLevel = this->ogreLogLevelNormal_;
317        break;
[1052]318      case Ogre::LML_CRITICAL:
[1024]319        orxonoxLevel = this->ogreLogLevelCritical_;
320        break;
321      default:
322        orxonoxLevel = 0;
323    }
324    OutputHandler::getOutStream().setOutputLevel(orxonoxLevel)
[1243]325        << "Ogre: " << message << std::endl;
[1024]326  }
[1214]327
[1260]328  /**
329  * Window has resized.
330  * @param rw The render window it occured in
331  */
332  void GraphicsEngine::windowMoved(Ogre::RenderWindow *rw)
333  {
334    // note: this doesn't change the window extents
335  }
[1214]336
[1260]337  /**
338  * Window has resized.
339  * @param rw The render window it occured in
340  * @note GraphicsEngine has a render window stored itself. This is the same
341  *       as rw. But we have to be careful when using multiple render windows!
342  */
343  void GraphicsEngine::windowResized(Ogre::RenderWindow *rw)
344  {
345    // change the mouse clipping size for absolute mouse movements
346    int w = rw->getWidth();
347    int h = rw->getHeight();
348    InputManager::setWindowExtents(w, h);
349  }
[1214]350
[1260]351  /**
352  * Window has resized.
353  * @param rw The render window it occured in
354  */
355  void GraphicsEngine::windowFocusChanged(Ogre::RenderWindow *rw)
356  {
357    // note: this doesn't change the window extents
358  }
359
360  /**
361  * Window has resized.
362  * @param rw The render window it occured in
363  */
364  void GraphicsEngine::windowClosed(Ogre::RenderWindow *rw)
365  {
366    // using CommandExecutor in order to avoid depending on Orxonox class.
367    CommandExecutor::execute("exit", false);
368  }
[612]369}
Note: See TracBrowser for help on using the repository browser.