From 2a06036fb7c80bf39ce0f4ce032a8147add6dea6 Mon Sep 17 00:00:00 2001 From: hiker Date: Wed, 31 Aug 2016 16:31:59 +1000 Subject: [PATCH] Changed order in which rendering and various updates are done, which results in the physics reacting one frame earlier to user input. --- src/karts/kart.cpp | 25 ++++++++++---------- src/main_loop.cpp | 13 ++++++---- src/modes/world.cpp | 43 +++++++++++++++++++++++----------- src/modes/world.hpp | 5 ++-- src/modes/world_status.cpp | 15 ++++++++++-- src/modes/world_status.hpp | 7 +++--- src/network/rewind_manager.cpp | 1 + 7 files changed, 72 insertions(+), 37 deletions(-) diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index 746f0e1f0..2735b0909 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -1174,18 +1174,6 @@ void Kart::eliminate() */ void Kart::update(float dt) { -#ifdef DEBUG_TO_COMPARE_KART_PHYSICS - // This information is useful when comparing kart physics, e.g. to - // see top speed, acceleration (i.e. time to top speed) etc. - Log::verbose("physics", "%s t %f %f xyz %f %f %f v %f %f %f s %f a %f", - getIdent().c_str(), - World::getWorld()->getTime(), dt, - getXYZ().getX(), getXYZ().getY(), getXYZ().getZ(), - getVelocity().getX(), getVelocity().getY(), getVelocity().getZ(), - getControls().getSteer(), - getControls().getAccel()); -#endif - // update star effect (call will do nothing if stars are not activated) m_stars_effect->update(dt); @@ -1223,6 +1211,19 @@ void Kart::update(float dt) if(!history->replayHistory() && !RewindManager::get()->isRewinding()) m_controller->update(dt); +#undef DEBUG_TO_COMPARE_KART_PHYSICS +#ifdef DEBUG_TO_COMPARE_KART_PHYSICS + // This information is useful when comparing kart physics, e.g. to + // see top speed, acceleration (i.e. time to top speed) etc. + Log::verbose("physics", "%s t %f %f xyz %f %f %f v %f %f %f s %f a %f", + getIdent().c_str(), + World::getWorld()->getTime(), dt, + getXYZ().getX(), getXYZ().getY(), getXYZ().getZ(), + getVelocity().getX(), getVelocity().getY(), getVelocity().getZ(), + getControls().getSteer(), + getControls().getAccel()); +#endif + // if its view is blocked by plunger, decrease remaining time if(m_view_blocked_by_plunger > 0) m_view_blocked_by_plunger -= dt; //unblock the view if kart just became shielded diff --git a/src/main_loop.cpp b/src/main_loop.cpp index 42ef03ab7..13b57950b 100644 --- a/src/main_loop.cpp +++ b/src/main_loop.cpp @@ -213,6 +213,11 @@ void MainLoop::run() m_prev_time = m_curr_time; float dt = getLimitedDt(); + // Render the previous frame, and also handle all user input. + PROFILER_PUSH_CPU_MARKER("IrrDriver update", 0x00, 0x00, 0x7F); + irr_driver->update(dt); + PROFILER_POP_CPU_MARKER(); + if (World::getWorld()) // race is active if world exists { @@ -238,10 +243,6 @@ void MainLoop::run() GUIEngine::update(dt); PROFILER_POP_CPU_MARKER(); - PROFILER_PUSH_CPU_MARKER("IrrDriver update", 0x00, 0x00, 0x7F); - irr_driver->update(dt); - PROFILER_POP_CPU_MARKER(); - // Update sfx and music after graphics, so that graphics code // can use as many threads as possible without interfering // with audia @@ -275,6 +276,10 @@ void MainLoop::run() PROFILER_POP_CPU_MARKER(); } + // Update world time if world exists + if (World::getWorld()) + World::getWorld()->updateTime(dt); + PROFILER_POP_CPU_MARKER(); PROFILER_SYNC_FRAME(); } // while !m_abort diff --git a/src/modes/world.cpp b/src/modes/world.cpp index a9c91fea7..f36ca0685 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -974,7 +974,7 @@ void World::scheduleTutorial() { m_schedule_exit_race = true; m_schedule_tutorial = true; -} +} // scheduleTutorial //----------------------------------------------------------------------------- /** Updates the physics, all karts, the track, and projectile manager. @@ -999,22 +999,14 @@ void World::update(float dt) } #endif - PROFILER_PUSH_CPU_MARKER("World::update (sub-updates)", 0x20, 0x7F, 0x00); - history->update(dt); - if(race_manager->isRecordingRace()) ReplayRecorder::get()->update(dt); - if(history->replayHistory()) dt=history->getNextDelta(); - RewindManager::get()->setCurrentTime(World::getWorld()->getTime(), dt); - RewindManager::get()->saveStates(); WorldStatus::update(dt); - if (m_script_engine) m_script_engine->update(dt); - PROFILER_POP_CPU_MARKER(); - - if (!history->dontDoPhysics()) - { - m_physics->update(dt); - } + RewindManager::get()->saveStates(); PROFILER_PUSH_CPU_MARKER("World::update (Kart::upate)", 0x40, 0x7F, 0x00); + + // Update all the karts. This in turn will also update the controller, + // which causes all AI steering commands set. So in the following + // physics update the new steering is taken into account. const int kart_amount = (int)m_karts.size(); for (int i = 0 ; i < kart_amount; ++i) { @@ -1030,6 +1022,18 @@ void World::update(float dt) } PROFILER_POP_CPU_MARKER(); + PROFILER_PUSH_CPU_MARKER("World::update (sub-updates)", 0x20, 0x7F, 0x00); + history->update(dt); + if(race_manager->isRecordingRace()) ReplayRecorder::get()->update(dt); + if(history->replayHistory()) dt=history->getNextDelta(); + if (m_script_engine) m_script_engine->update(dt); + PROFILER_POP_CPU_MARKER(); + + if (!history->dontDoPhysics()) + { + m_physics->update(dt); + } + PROFILER_PUSH_CPU_MARKER("World::update (weather)", 0x80, 0x7F, 0x00); if (UserConfigParams::m_graphical_effects && m_weather) { @@ -1048,6 +1052,17 @@ void World::update(float dt) #endif } // update +// ---------------------------------------------------------------------------- +/** Compute the new time, and set this new time to be used in the rewind + * manager. + * \param dt Time step size. + */ +void World::updateTime(const float dt) +{ + WorldStatus::updateTime(dt); + RewindManager::get()->setCurrentTime(getTime(), dt); +} // updateTime + // ---------------------------------------------------------------------------- /** Only updates the track. The order in which the various parts of STK are * updated is quite important (i.e. the track can't be updated as part of diff --git a/src/modes/world.hpp b/src/modes/world.hpp index 3a03d0bf2..aeca3c166 100644 --- a/src/modes/world.hpp +++ b/src/modes/world.hpp @@ -178,7 +178,7 @@ protected: virtual void onGo() OVERRIDE; /** Returns true if the race is over. Must be defined by all modes. */ virtual bool isRaceOver() = 0; - virtual void update(float dt); + virtual void update(float dt) OVERRIDE; virtual void createRaceGUI(); void updateTrack(float dt); // ------------------------------------------------------------------------ @@ -252,9 +252,10 @@ public: // ================= virtual void init(); virtual void terminateRace() OVERRIDE; - virtual void reset(); + virtual void reset() OVERRIDE; virtual void pause(Phase phase) OVERRIDE; virtual void unpause() OVERRIDE; + virtual void updateTime(const float dt) OVERRIDE; virtual void getDefaultCollectibles(int *collectible_type, int *amount ); virtual void endRaceEarly() { return; } diff --git a/src/modes/world_status.cpp b/src/modes/world_status.cpp index 81e066a0e..c863caa0c 100644 --- a/src/modes/world_status.cpp +++ b/src/modes/world_status.cpp @@ -153,10 +153,21 @@ void WorldStatus::terminateRace() } // terminateRace //----------------------------------------------------------------------------- -/** Updates all status information, called once per frame. +/** Update, called once per frame. Called early on before physics are + * updated. + * \param dt Time step. + */ +void WorldStatus::update(float dt) +{ +} // update + +//----------------------------------------------------------------------------- +/** Updates the world time and clock (which might be running backwards), and + * all status information, called once per frame at the end of the main + * loop. * \param dt Duration of time step. */ -void WorldStatus::update(const float dt) +void WorldStatus::updateTime(const float dt) { switch (m_phase) { diff --git a/src/modes/world_status.hpp b/src/modes/world_status.hpp index 0a329d8f9..3e2e5fe3c 100644 --- a/src/modes/world_status.hpp +++ b/src/modes/world_status.hpp @@ -122,13 +122,14 @@ public: WorldStatus(); virtual ~WorldStatus(); - void reset(); - void update(const float dt); - void setTime(const float time); + virtual void reset(); + virtual void updateTime(const float dt); + virtual void update(float dt); virtual void pause(Phase phase); virtual void unpause(); virtual void enterRaceOverState(); virtual void terminateRace(); + void setTime(const float time); // ------------------------------------------------------------------------ // Note: GO_PHASE is both: start phase and race phase diff --git a/src/network/rewind_manager.cpp b/src/network/rewind_manager.cpp index 7f06946eb..8ff236e01 100644 --- a/src/network/rewind_manager.cpp +++ b/src/network/rewind_manager.cpp @@ -363,6 +363,7 @@ void RewindManager::rewindTo(float rewind_time) #ifdef SHOW_ROLLBACK irr_driver->update(dt); #endif + world->updateTime(dt); } m_is_rewinding = false;