Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 1454 was 1454, checked in by landauf, 17 years ago

fixed tcl initialisation bug

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