From 5a4872393a77c0dc35f1f633a15143bf13e87dba Mon Sep 17 00:00:00 2001 From: fredzio Date: Thu, 3 Dec 2020 12:57:57 +0100 Subject: [PATCH] Rework actor position reset. While solving the issue with invalid position being used under heavy load, I introduced a regression that prevented the position to be updated in case of teleport. Move the logic in its own function and decide in PhysicsSystem whether a reset is needed. --- apps/openmw/mwphysics/mtphysics.cpp | 25 ++++++++++--------------- apps/openmw/mwphysics/mtphysics.hpp | 4 +++- apps/openmw/mwphysics/physicssystem.cpp | 12 +++++++++++- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwphysics/mtphysics.cpp b/apps/openmw/mwphysics/mtphysics.cpp index 2d4009e7d8..bdffcef44f 100644 --- a/apps/openmw/mwphysics/mtphysics.cpp +++ b/apps/openmw/mwphysics/mtphysics.cpp @@ -212,7 +212,7 @@ namespace MWPhysics thread.join(); } - const PtrPositionList& PhysicsTaskScheduler::moveActors(int numSteps, float timeAccum, std::vector&& actorsData, bool skipSimulation, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) + const PtrPositionList& PhysicsTaskScheduler::moveActors(int numSteps, float timeAccum, std::vector&& actorsData, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) { // This function run in the main thread. // While the mSimulationMutex is held, background physics threads can't run. @@ -263,20 +263,6 @@ namespace MWPhysics if (mAdvanceSimulation) mWorldFrameData = std::make_unique(); - // we are asked to skip the simulation (load a savegame for instance) - // just return the actors' reference position without applying the movements - if (skipSimulation) - { - mMovementResults.clear(); - for (const auto& m : mActorsFrameData) - { - m.mActorRaw->setStandingOnPtr(nullptr); - m.mActorRaw->resetPosition(); - mMovementResults[m.mPtr] = m.mActorRaw->getWorldPosition(); - } - return mMovementResults; - } - if (mNumThreads == 0) { mMovementResults.clear(); @@ -311,6 +297,15 @@ namespace MWPhysics return mPreviousMovementResults; } + const PtrPositionList& PhysicsTaskScheduler::resetSimulation() + { + std::unique_lock lock(mSimulationMutex); + mMovementResults.clear(); + mPreviousMovementResults.clear(); + mActorsFrameData.clear(); + return mMovementResults; + } + void PhysicsTaskScheduler::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const { MaybeSharedLock lock(mCollisionWorldMutex, mThreadSafeBullet); diff --git a/apps/openmw/mwphysics/mtphysics.hpp b/apps/openmw/mwphysics/mtphysics.hpp index c061fe01da..f7a131ca26 100644 --- a/apps/openmw/mwphysics/mtphysics.hpp +++ b/apps/openmw/mwphysics/mtphysics.hpp @@ -32,7 +32,9 @@ namespace MWPhysics /// @param timeAccum accumulated time from previous run to interpolate movements /// @param actorsData per actor data needed to compute new positions /// @return new position of each actor - const PtrPositionList& moveActors(int numSteps, float timeAccum, std::vector&& actorsData, bool skip, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats); + const PtrPositionList& moveActors(int numSteps, float timeAccum, std::vector&& actorsData, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats); + + const PtrPositionList& resetSimulation(); // Thread safe wrappers void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const; diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 7aa1f59141..cdbad2cddd 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -676,7 +676,17 @@ namespace MWPhysics mTimeAccum -= numSteps * mPhysicsDt; - return mTaskScheduler->moveActors(numSteps, mTimeAccum, prepareFrameData(numSteps), skipSimulation, frameStart, frameNumber, stats); + if (skipSimulation) + { + for (auto& [_, actor] : mActors) + { + actor->resetPosition(); + actor->setStandingOnPtr(nullptr); + } + return mTaskScheduler->resetSimulation(); + } + + return mTaskScheduler->moveActors(numSteps, mTimeAccum, prepareFrameData(numSteps), frameStart, frameNumber, stats); } std::vector PhysicsSystem::prepareFrameData(int numSteps)