Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Mar 18, 2008, 12:27:16 PM (16 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)
File:
1 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}
Note: See TracChangeset for help on using the changeset viewer.