Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 1587 was 1564, checked in by landauf, 16 years ago
  • several small changes in most of the HUD classes (code cleanup): removed obsolete variables, privatized all member variables, removed resizing functioncalls from tick, destroying overlayelements, added some const qualifiers.
  • moved calculation functions for RadarObject-position to Math.h and changed the phi/right/radius format to Vector2. the functions are used too by SpaceShipAI.
  • cycleNavigationFocus takes the nearest object if focus was NULL
  • BarOverlayElement works in both directions (left to right and right to left)
  • fixed bug causing SpaceShipAI to not stop shooting when losing target - this also speeds up orxonox a lot, because there are less projectiles

####################################

!! UPDATE YOUR MEDIA REPOSITORY !!

####################################
…or the BarOverlayElement will look strange

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