Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/GraphicsEngine.cc @ 1505

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

f* svn: It doesn't even inform you if you attempt to set a non existing property. It is svn:eol-style and not eol-style when using the command by the way…

  • Property svn:eol-style set to native
File size: 14.2 KB
RevLine 
[612]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
[1293]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
[1349]11 *   of the License, or (at your option) any later version.
12 *
[612]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"
[1293]43#include "core/CoreIncludes.h"
44#include "core/ConfigValueIncludes.h"
45#include "core/Debug.h"
[1505]46#include "core/CommandExecutor.h"
[1502]47#include "core/TclBind.h"
48#include "console/InGameConsole.h"
[1032]49
[1502]50#include "core/ConsoleCommand.h"
51#include <OgreSceneManager.h>
52#include <OgreCompositorManager.h>
53#include <OgreViewport.h>
[612]54
55namespace orxonox {
[1032]56  /**
57    @brief Returns the singleton instance and creates it the first time.
58    @return The only instance of GraphicsEngine.
59  */
[1293]60  /*static*/ GraphicsEngine& GraphicsEngine::getSingleton()
[1032]61  {
62    static GraphicsEngine theOnlyInstance;
63    return theOnlyInstance;
64  }
65
66  /**
67    @brief Only use constructor to initialise variables and pointers!
68  */
[1293]69  GraphicsEngine::GraphicsEngine() :
70    root_(0),
71    scene_(0),
72    renderWindow_(0),
73    //configPath_(""),
74    dataPath_(""),
75    ogreLogfile_("")
[612]76  {
[1021]77    RegisterObject(GraphicsEngine);
[1293]78
[1021]79    this->setConfigValues();
[1293]80    CCOUT(4) << "Constructed" << std::endl;
[612]81  }
82
[1293]83  void GraphicsEngine::setConfigValues()
84  {
85    SetConfigValue(dataPath_, "../../Media/").description("relative path to media data");
86    SetConfigValue(ogreLogfile_, "ogre.log").description("Logfile for messages from Ogre. Use \"\" to suppress log file creation.");
87    SetConfigValue(ogreLogLevelTrivial_ , 5).description("Corresponding orxonox debug level for ogre Trivial");
88    SetConfigValue(ogreLogLevelNormal_  , 4).description("Corresponding orxonox debug level for ogre Normal");
[1505]89    SetConfigValue(ogreLogLevelCritical_, 2).description("Corresponding orxonox debug level for ogre Critical");
90
[1502]91    TclBind::getInstance().setDataPath(this->dataPath_);
[1293]92  }
93
[1032]94  /**
95    @brief Called after main() --> call destroyObjects()!
96  */
[612]97  GraphicsEngine::~GraphicsEngine()
98  {
[1032]99    this->destroy();
100  }
101
102  /**
103    @brief Destroys all the internal objects. Call this method when you
104           normally would call the destructor.
105  */
106  void GraphicsEngine::destroy()
107  {
[1293]108    CCOUT(4) << "Destroying objects..." << std::endl;
[1214]109    Ogre::WindowEventUtilities::removeWindowEventListener(this->renderWindow_, this);
[1024]110    if (this->root_)
[1021]111      delete this->root_;
[1032]112    this->root_ = 0;
113    this->scene_ = 0;
114    this->renderWindow_ = 0;
115    // delete the ogre log and the logManager (since we have created it).
[1052]116    if (Ogre::LogManager::getSingletonPtr() != 0)
[1024]117    {
[1052]118      Ogre::LogManager::getSingleton().getDefaultLog()->removeListener(this);
119      Ogre::LogManager::getSingleton().destroyLog(Ogre::LogManager::getSingleton().getDefaultLog());
120      delete Ogre::LogManager::getSingletonPtr();
[1024]121    }
[1293]122    CCOUT(4) << "Destroying objects done" << std::endl;
[612]123  }
124
[1024]125  /**
126    @brief Creates the Ogre Root object and sets up the ogre log.
127  */
[1293]128  bool GraphicsEngine::setup(std::string& dataPath)
[612]129  {
[1293]130    CCOUT(3) << "Setting up..." << std::endl;
131    // temporary overwrite of dataPath, change ini file for permanent change
132    if (dataPath != "")
133      dataPath_ = dataPath;
134    if (dataPath_ == "")
135      return false;
136    if (dataPath_[dataPath_.size() - 1] != '/')
137      dataPath_ += "/";
138
[612]139    //TODO: Check if file exists (maybe not here)
[1021]140#if ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC && defined(_DEBUG)
[715]141    std::string plugin_filename = "plugins_d.cfg";
[679]142#else
[715]143    std::string plugin_filename = "plugins.cfg";
[679]144#endif
[1024]145
[1502]146// TODO: LogManager doesn't work on specific systems. The why is unknown yet.
147#if ORXONOX_PLATFORM == ORXONOX_PLATFORM_WIN32
148    // create a logManager
[1293]149    // note: If there's already a logManager, Ogre will complain by a failed assertation.
150    // but that shouldn't happen, since this is the first time to create a logManager..
151    Ogre::LogManager* logger = new Ogre::LogManager();
152    CCOUT(4) << "Ogre LogManager created" << std::endl;
[1024]153
154    // create our own log that we can listen to
[1062]155    Ogre::Log *myLog;
[1024]156    if (this->ogreLogfile_ == "")
157      myLog = logger->createLog("ogre.log", true, false, true);
158    else
[1502]159      myLog = logger->createLog(this->ogreLogfile_, true, false, false);
[1293]160    CCOUT(4) << "Ogre Log created" << std::endl;
[1024]161
[1062]162    myLog->setLogDetail(Ogre::LL_BOREME);
[1502]163    myLog->addListener(this);
164#endif
[1024]165
166    // Root will detect that we've already created a Log
[1293]167    CCOUT(4) << "Creating Ogre Root..." << std::endl;
[1502]168
169    root_ = new Ogre::Root(plugin_filename, "ogre.cfg", this->ogreLogfile_);
170
171#if ORXONOX_PLATFORM != ORXONOX_PLATFORM_WIN32
172    // tame the ogre ouput so we don't get all the mess in the console
173    Ogre::Log* defaultLog = Ogre::LogManager::getSingleton().getDefaultLog();
174    defaultLog->setDebugOutputEnabled(false);
175    defaultLog->setLogDetail(Ogre::LL_BOREME);
176    defaultLog->addListener(this);
177#endif
178
[1293]179    CCOUT(4) << "Creating Ogre Root done" << std::endl;
[612]180
[1293]181    // specify where Ogre has to look for resources. This call doesn't parse anything yet!
182    declareRessourceLocations();
[612]183
[1293]184    CCOUT(3) << "Set up done." << std::endl;
[612]185    return true;
186  }
187
[1293]188  void GraphicsEngine::declareRessourceLocations()
[612]189  {
[1293]190    CCOUT(4) << "Declaring Resources" << std::endl;
[612]191    //TODO: Specify layout of data file and maybe use xml-loader
192    //TODO: Work with ressource groups (should be generated by a special loader)
193    // Load resource paths from data file using configfile ressource type
[1052]194    Ogre::ConfigFile cf;
[1293]195    cf.load(dataPath_ + "resources.cfg");
[612]196
197    // Go through all sections & settings in the file
[1052]198    Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
[612]199
[715]200    std::string secName, typeName, archName;
[612]201    while (seci.hasMoreElements())
202    {
203      secName = seci.peekNextKey();
[1052]204      Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
205      Ogre::ConfigFile::SettingsMultiMap::iterator i;
[612]206      for (i = settings->begin(); i != settings->end(); ++i)
207      {
208        typeName = i->first; // for instance "FileSystem" or "Zip"
209        archName = i->second; // name (and location) of archive
210
[1052]211        Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
[1293]212                                           std::string(dataPath_ + archName),
[612]213                                           typeName, secName);
214      }
215    }
216  }
217
[1293]218  bool GraphicsEngine::loadRenderer()
219  {
220    CCOUT(4) << "Configuring Renderer" << std::endl;
221    if (!root_->restoreConfig() && !root_->showConfigDialog())
222      return false;
223
224    CCOUT(4) << "Creating render window" << std::endl;
225    this->renderWindow_ = root_->initialise(true, "OrxonoxV2");
226    if (!root_->isInitialised())
227    {
228      CCOUT(2) << "Error: Creating Ogre root object failed" << std::endl;
229      return false;
230    }
231    Ogre::WindowEventUtilities::addWindowEventListener(this->renderWindow_, this);
232    Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
233    return true;
234  }
235
236  bool GraphicsEngine::initialiseResources()
237  {
238    CCOUT(4) << "Initialising resources" << std::endl;
239    //TODO: Do NOT load all the groups, why are we doing that? And do we really do that? initialise != load...
240    try
241    {
242      Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
243      /*Ogre::StringVector str = Ogre::ResourceGroupManager::getSingleton().getResourceGroups();
244      for (unsigned int i = 0; i < str.size(); i++)
245      {
246        Ogre::ResourceGroupManager::getSingleton().loadResourceGroup(str[i]);
247      }*/
248    }
249    catch (Ogre::Exception e)
250    {
251      CCOUT(2) << "Error: There was an Error when initialising the resources." << std::endl;
252      CCOUT(2) << "ErrorMessage: " << e.getFullDescription() << std::endl;
253      return false;
254    }
255    return true;
256  }
257
[1021]258  /**
[1293]259   * @brief Creates the SceneManager
260   */
261  bool GraphicsEngine::createNewScene()
262  {
[1502]263    CCOUT(4) << "Creating new SceneManager..." << std::endl;
[1293]264    if (scene_)
265    {
266      CCOUT(2) << "SceneManager already exists! Skipping." << std::endl;
267      return false;
268    }
269    scene_ = root_->createSceneManager(Ogre::ST_GENERIC, "Default SceneManager");
270    CCOUT(3) << "Created SceneManager: " << scene_ << std::endl;
271    return true;
272  }
273
274  /**
[1021]275    Returns the window handle of the render window.
276    At least the InputHandler uses this to create the OIS::InputManager
277    @return The window handle of the render window
278  */
279  size_t GraphicsEngine::getWindowHandle()
280  {
281    if (this->renderWindow_)
282    {
[1024]283      size_t windowHnd = 0;
[1032]284      this->renderWindow_->getCustomAttribute("WINDOW", &windowHnd);
[1024]285      return windowHnd;
286    }
[1021]287    else
288      return 0;
289  }
[612]290
[1021]291  /**
292    Get the width of the current render window
293    @return The width of the current render window
294  */
295  int GraphicsEngine::getWindowWidth() const
296  {
297    if (this->renderWindow_)
298      return this->renderWindow_->getWidth();
299    else
300      return 0;
301  }
302
303  /**
304    Get the height of the current render window
305    @return The height of the current render window
306  */
307  int GraphicsEngine::getWindowHeight() const
308  {
309    if (this->renderWindow_)
310      return this->renderWindow_->getHeight();
311    else
312      return 0;
313  }
314
[1024]315  /**
[1505]316    @brief Returns the window aspect ratio height/width.
317    @return The ratio
318  */
319  float GraphicsEngine::getWindowAspectRatio() const
320  {
321    if (this->renderWindow_)
322        return (float)this->renderWindow_->getHeight() / (float)this->renderWindow_->getWidth();
323    else
324        return 1.0f;
325  }
326
327  /**
[1024]328    @brief Method called by the LogListener interface from Ogre.
329    We use it to capture Ogre log messages and handle it ourselves.
330    @param message The message to be logged
331    @param lml The message level the log is using
332    @param maskDebug If we are printing to the console or not
333    @param logName the name of this log (so you can have several listeners
334                   for different logs, and identify them)
335  */
336  void GraphicsEngine::messageLogged(const std::string& message,
[1052]337    Ogre::LogMessageLevel lml, bool maskDebug, const std::string &logName)
[1024]338  {
339    int orxonoxLevel;
340    switch (lml)
341    {
[1052]342      case Ogre::LML_TRIVIAL:
[1024]343        orxonoxLevel = this->ogreLogLevelTrivial_;
344        break;
[1052]345      case Ogre::LML_NORMAL:
[1024]346        orxonoxLevel = this->ogreLogLevelNormal_;
347        break;
[1052]348      case Ogre::LML_CRITICAL:
[1024]349        orxonoxLevel = this->ogreLogLevelCritical_;
350        break;
351      default:
352        orxonoxLevel = 0;
353    }
354    OutputHandler::getOutStream().setOutputLevel(orxonoxLevel)
[1293]355        << "Ogre: " << message << std::endl;
[1024]356  }
[1214]357
[1293]358  /**
359  * Window has resized.
360  * @param rw The render window it occured in
361  */
362  void GraphicsEngine::windowMoved(Ogre::RenderWindow *rw)
363  {
364    // note: this doesn't change the window extents
365  }
[1214]366
[1293]367  /**
368  * Window has resized.
369  * @param rw The render window it occured in
370  * @note GraphicsEngine has a render window stored itself. This is the same
371  *       as rw. But we have to be careful when using multiple render windows!
372  */
[1505]373  void GraphicsEngine::windowResized(Ogre::RenderWindow *rw)
374  {
[1293]375    // change the mouse clipping size for absolute mouse movements
376    int w = rw->getWidth();
377    int h = rw->getHeight();
378    InputManager::setWindowExtents(w, h);
[1502]379    InGameConsole::getInstance().resize();
[1293]380  }
[1214]381
[1293]382  /**
383  * Window has resized.
384  * @param rw The render window it occured in
385  */
386  void GraphicsEngine::windowFocusChanged(Ogre::RenderWindow *rw)
387  {
388    // note: this doesn't change the window extents
389  }
390
391  /**
392  * Window has resized.
393  * @param rw The render window it occured in
394  */
395  void GraphicsEngine::windowClosed(Ogre::RenderWindow *rw)
396  {
397    // using CommandExecutor in order to avoid depending on Orxonox class.
398    CommandExecutor::execute("exit", false);
399  }
[1502]400
401  //HACK!!
402  /*SetConsoleCommandShortcut(GraphicsEngine, CompositorBloomOn).setAccessLevel(AccessLevel::User);
403  SetConsoleCommandShortcut(GraphicsEngine, CompositorMotionBlurOn).setAccessLevel(AccessLevel::User);
404  SetConsoleCommandShortcut(GraphicsEngine, CompositorBloomOff).setAccessLevel(AccessLevel::User);
405  SetConsoleCommandShortcut(GraphicsEngine, CompositorMotionBlurOff).setAccessLevel(AccessLevel::User);
406  void GraphicsEngine::CompositorBloomOn()
407  {
408    Ogre::SceneManager* mSceneMgr = GraphicsEngine::getSingleton().getSceneManager();
409    Ogre::Viewport* mViewport = mSceneMgr->getCurrentViewport();
410    Ogre::CompositorManager::getSingleton().addCompositor(mViewport, "Bloom");
411    Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Bloom", true);
412  }
413  void GraphicsEngine::CompositorBloomOff()
414  {
415    Ogre::SceneManager* mSceneMgr = GraphicsEngine::getSingleton().getSceneManager();
416    Ogre::Viewport* mViewport = mSceneMgr->getCurrentViewport();
417    Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Bloom", false);
418  }
419
420  void GraphicsEngine::CompositorMotionBlurOn()
421  {
422    Ogre::SceneManager* mSceneMgr = GraphicsEngine::getSingleton().getSceneManager();
423    Ogre::Viewport* mViewport = mSceneMgr->getCurrentViewport();
424    Ogre::CompositorManager::getSingleton().addCompositor(mViewport, "MotionBlur");
425    Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "MotionBlur", true);
426  }
427  void GraphicsEngine::CompositorMotionBlurOff()
428  {
429    Ogre::SceneManager* mSceneMgr = GraphicsEngine::getSingleton().getSceneManager();
430    Ogre::Viewport* mViewport = mSceneMgr->getCurrentViewport();
431    Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "MotionBlur", false);
432  }*/
[612]433}
Note: See TracBrowser for help on using the repository browser.