Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 900


Ignore:
Timestamp:
Mar 18, 2008, 12:27:16 PM (17 years ago)
Author:
rgrieder
Message:
  • implemented a new main loop, calling the ticks and the timers. —> removed the (Timer/Tick)FrameListener and displaced the code to Orxonox.cc (don't like it yet)
Location:
code/branches/input
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • code/branches/input/src/orxonox/Orxonox.cc

    r871 r900  
    4444#include <OgreOverlay.h>
    4545#include <OgreOverlayManager.h>
     46#include <OgreTimer.h>
     47#include <OgreWindowEventUtilities.h>
    4648
    4749//****** OIS *******
     
    140142    this->frameListener_ = 0;
    141143    this->root_ = 0;
     144    // turn frame smoothing on by setting a value different from 0
     145    this->frameSmoothingTime_ = 0.1f;
    142146  }
    143147
     
    368372  }
    369373
    370   /**
    371    *
    372    * @param
    373    */
    374374  void Orxonox::createScene(void)
    375375  {
     
    386386
    387387    Ogre::Overlay* hudOverlay = Ogre::OverlayManager::getSingleton().getByName("Orxonox/HUD1.2");
    388     HUD* orxonoxHud;
    389     orxonoxHud = new HUD();
    390     orxonoxHud->setEnergyValue(20);
    391     orxonoxHud->setEnergyDistr(20,20,60);
     388    //HUD* orxonoxHud;
     389    orxonoxHUD_ = new HUD();
     390    orxonoxHUD_->setEnergyValue(20);
     391    orxonoxHUD_->setEnergyDistr(20,20,60);
    392392    hudOverlay->show();
    393393
     
    401401
    402402
    403   /**
    404    *
    405    */
    406403  void Orxonox::setupScene()
    407404  {
     
    454451  void Orxonox::createFrameListener()
    455452  {
    456     TickFrameListener* TickFL = new TickFrameListener();
    457     ogre_->getRoot()->addFrameListener(TickFL);
    458 
    459     TimerFrameListener* TimerFL = new TimerFrameListener();
    460     ogre_->getRoot()->addFrameListener(TimerFL);
     453    //TickFrameListener* TickFL = new TickFrameListener();
     454    //ogre_->getRoot()->addFrameListener(TickFL);
     455
     456    //TimerFrameListener* TimerFL = new TimerFrameListener();
     457    //ogre_->getRoot()->addFrameListener(TimerFL);
    461458
    462459    //if(mode_!=CLIENT) // FIXME just a hack ------- remove this in future
     
    480477      ms.height = height;
    481478    }
    482     ogre_->getRoot()->startRendering();
     479    //ogre_->getRoot()->startRendering();
     480    mainLoop();
     481  }
     482
     483  /**
     484    Main loop of the orxonox game.
     485    This is a new solution, using the ogre engine instead of beeing used by it.
     486    An alternative solution would be to simply use the timer of the Root object,
     487    but that implies using Ogre in any case. There would be no way to test
     488    our code without the help of the root object.
     489    There's even a chance that we can dispose of the root object entirely
     490    in server mode.
     491    About the loop: The design is almost exactly like the one in ogre, so that
     492    if any part of ogre registers a framelisteners, it will still behave
     493    correctly. Furthermore I have taken over the time smoothing feature from
     494    ogre. If turned on (see orxonox constructor), it will calculate the dt_n by
     495    means of the recent most dt_n-1, dt_n-2, etc.
     496  */
     497  void Orxonox::mainLoop()
     498  {
     499    // use the ogre timer class to measure time.
     500    Ogre::Timer *timer = new Ogre::Timer();
     501    timer->reset();
     502
     503    // Contains the times of recently fired events
     504    std::deque<unsigned long> eventTimes[3];
     505    // Clear event times
     506    for (int i = 0; i < 3; ++i)
     507      eventTimes[i].clear();
     508
     509          while (true)
     510          {
     511                  //Pump messages in all registered RenderWindows
     512      Ogre::WindowEventUtilities::messagePump();
     513
     514      // get current time
     515      unsigned long now = timer->getMilliseconds();
     516
     517      // create an event to pass to the frameStarted method in ogre
     518      Ogre::FrameEvent evt;
     519      evt.timeSinceLastEvent = calculateEventTime(now, eventTimes[0]);
     520      evt.timeSinceLastFrame = calculateEventTime(now, eventTimes[1]);
     521
     522      // show the current time in the HUD
     523      orxonoxHUD_->setTime((int)now, 0);
     524
     525      // don't forget to call _fireFrameStarted in ogre to make sure
     526      // everything goes smoothly
     527      if (!ogre_->getRoot()->_fireFrameStarted(evt))
     528        break;
     529
     530      // Iterate through all Tickables and call their tick(dt) function
     531      for (Iterator<Tickable> it = ObjectList<Tickable>::start(); it; )
     532        (it++)->tick((float)evt.timeSinceLastFrame);
     533
     534      // Update the timers
     535      updateTimers((float)evt.timeSinceLastFrame);
     536
     537      if (mode_ != SERVER)
     538      {
     539        // only render in non-server mode
     540        ogre_->getRoot()->_updateAllRenderTargets();
     541      }
     542
     543      // get current time
     544      now = timer->getMilliseconds();
     545
     546      // create an event to pass to the frameEnded method in ogre
     547      evt.timeSinceLastEvent = calculateEventTime(now, eventTimes[0]);
     548      evt.timeSinceLastFrame = calculateEventTime(now, eventTimes[2]);
     549
     550      // again, just to be sure ogre works fine
     551      if (!ogre_->getRoot()->_fireFrameEnded(evt))
     552        break;
     553          }
     554  }
     555
     556  /**
     557    Timer updater function.
     558    Updates all timers with the current dt.
     559    Timers have been tested since their displacement.
     560    @param dt The delta time
     561  */
     562  void Orxonox::updateTimers(float dt)
     563  {
     564    // Iterate through all Timers
     565    for (Iterator<TimerBase> it = ObjectList<TimerBase>::start(); it; )
     566    {
     567      if (it->isActive())
     568      {
     569        // If active: Decrease the timer by the duration of the last frame
     570        it->time_ -= dt;
     571
     572        if (it->time_ <= 0)
     573        {
     574          // It's time to call the function
     575          if (it->bLoop_)
     576            it->time_ += it->interval_; // Q: Why '+=' and not '='? A: Think about it. It's more accurate like that. Seriously.
     577          else
     578            it->stopTimer(); // Stop the timer if we don't want to loop
     579
     580          (it++)->run();
     581        }
     582        else
     583        ++it;
     584      }
     585      else
     586      ++it;
     587    }
     588
     589  }
     590  /**
     591    Method for calculating the average time between recently fired events.
     592    Code directly taken from OgreRoot.cc
     593    @param now The current time in ms.
     594    @param type The type of event to be considered.
     595  */
     596  float Orxonox::calculateEventTime(unsigned long now, std::deque<unsigned long> &times)
     597  {
     598    // Calculate the average time passed between events of the given type
     599    // during the last mFrameSmoothingTime seconds.
     600
     601    times.push_back(now);
     602
     603    if(times.size() == 1)
     604      return 0;
     605
     606    // Times up to mFrameSmoothingTime seconds old should be kept
     607    unsigned long discardThreshold =
     608      static_cast<unsigned long>(frameSmoothingTime_ * 1000.0f);
     609
     610    // Find the oldest time to keep
     611    std::deque<unsigned long>::iterator it = times.begin(),
     612      end = times.end()-2; // We need at least two times
     613    while(it != end)
     614    {
     615      if (now - *it > discardThreshold)
     616        ++it;
     617      else
     618        break;
     619    }
     620
     621    // Remove old times
     622    times.erase(times.begin(), it);
     623
     624    return (float)(times.back() - times.front()) / ((times.size()-1) * 1000);
    483625  }
    484626}
  • code/branches/input/src/orxonox/Orxonox.h

    r871 r900  
    99
    1010#include <string>
     11#include <deque>
    1112
    1213#include <OgrePrerequisites.h>
     
    6566      void createFrameListener();
    6667      void startRenderLoop();
     68      void mainLoop();
     69      void updateTimers(float);
     70      float calculateEventTime(unsigned long, std::deque<unsigned long>&);
    6771
    6872    private:
     
    7882      OrxListener*          frameListener_;
    7983      Ogre::Root*           root_;
     84      // TODO: make this a config-value by creating a config class for orxonox
     85      float                 frameSmoothingTime_;
     86      // little hack to actually show something dynamic in the HUD
     87      HUD*                  orxonoxHUD_;
    8088
    8189      // this is used to identify the mode (server/client/...) we're in
  • code/branches/input/src/orxonox/OrxonoxStableHeaders.h

    r893 r900  
    7373//#include "audio/AudioManager.h"
    7474
    75 //#include "core/CoreIncludes.h"
     75#include "core/CoreIncludes.h"
    7676#include "core/BaseObject.h"
    7777//#include "core/ArgReader.h"
    7878#include "core/Error.h"
     79#include "core/Loader.h"
     80#include "core/XMLPort.h"
    7981
    8082#include "network/Synchronisable.h"
  • code/branches/input/src/orxonox/objects/Tickable.h

    r871 r900  
    3535    Attention:
    3636    Classes derived from a Tickable that want to have a tick(dt) function on their part, MUST call the
    37     parent::tick(dt) function explicit in their implementation of tick(dt) because it's a virtual function.
     37    parent::tick(dt) function explicitly in their implementation of tick(dt) because it's a virtual function.
    3838*/
    3939
     
    4848namespace orxonox
    4949{
    50     class TickFrameListener; // Forward declaration
     50    //class TickFrameListener; // Forward declaration
    5151
    5252    //! The Tickable interface provides a tick(dt) function, that gets called every frame.
     
    6464    };
    6565
     66#if 0
    6667    //! The TickFrameListener calls the tick(dt) function of all Tickables every frame.
    6768    class _OrxonoxExport TickFrameListener : public Ogre::FrameListener
     
    7879            }
    7980    };
     81#endif
    8082}
    8183
  • code/branches/input/src/orxonox/tools/Timer.h

    r871 r900  
    6666    class _OrxonoxExport TimerBase : public OrxonoxClass
    6767    {
    68         friend class TimerFrameListener;
     68        //friend class TimerFrameListener;
     69        friend class Orxonox;
    6970
    7071        public:
     
    145146    };
    146147
     148#if 0
    147149    //! The TimerFrameListener manages all Timers in the game.
    148150    class TimerFrameListener : public Ogre::FrameListener
     
    180182            }
    181183    };
     184#endif
    182185}
    183186
  • code/branches/input/visual_studio/base_properties.vsprops

    r893 r900  
    3333        <UserMacro
    3434                Name="DependencyDir"
    35                 Value="$(RootDir)dependencies\"
     35                Value="D:\orxonox\dependencies\orxonox\"
    3636        />
    3737        <UserMacro
Note: See TracChangeset for help on using the changeset viewer.