Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network/src/orxonox/GraphicsEngine.cc @ 1477

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