diff --git a/apps/openmw/mwphysics/mtphysics.cpp b/apps/openmw/mwphysics/mtphysics.cpp index f66af8bae4..81b1dc34d6 100644 --- a/apps/openmw/mwphysics/mtphysics.cpp +++ b/apps/openmw/mwphysics/mtphysics.cpp @@ -230,7 +230,7 @@ namespace MWPhysics return std::make_tuple(numSteps, actualDelta); } - const std::vector& PhysicsTaskScheduler::moveActors(float & timeAccum, std::vector&& actorsData, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) + void PhysicsTaskScheduler::applyQueuedMovements(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. @@ -239,8 +239,6 @@ namespace MWPhysics double timeStart = mTimer->tick(); - mMovedActors.clear(); - // start by finishing previous background computation if (mNumThreads != 0) { @@ -260,7 +258,6 @@ namespace MWPhysics if (mAdvanceSimulation) data.mActorRaw->setStandingOnPtr(data.mStandingOn); data.mActorRaw->setSimulationPosition(interpolateMovements(data, mTimeAccum, mPhysicsDt)); - mMovedActors.emplace_back(data.mActorRaw->getPtr()); } } if(mAdvanceSimulation) @@ -296,7 +293,7 @@ namespace MWPhysics syncComputation(); if(mAdvanceSimulation) mBudget.update(mTimer->delta_s(timeStart, mTimer->tick()), numSteps, mBudgetCursor); - return mMovedActors; + return; } mAsyncStartTime = mTimer->tick(); @@ -304,23 +301,19 @@ namespace MWPhysics mHasJob.notify_all(); if (mAdvanceSimulation) mBudget.update(mTimer->delta_s(timeStart, mTimer->tick()), 1, mBudgetCursor); - return mMovedActors; } - const std::vector& PhysicsTaskScheduler::resetSimulation(const ActorMap& actors) + void PhysicsTaskScheduler::resetSimulation(const ActorMap& actors) { std::unique_lock lock(mSimulationMutex); mBudget.reset(mDefaultPhysicsDt); mAsyncBudget.reset(0.0f); - mMovedActors.clear(); mActorsFrameData.clear(); for (const auto& [_, actor] : actors) { actor->updatePosition(); actor->updateCollisionObjectPosition(); - mMovedActors.emplace_back(actor->getPtr()); } - return mMovedActors; } void PhysicsTaskScheduler::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const @@ -561,7 +554,6 @@ namespace MWPhysics handleFall(actorData, mAdvanceSimulation); actorData.mActorRaw->setSimulationPosition(interpolateMovements(actorData, mTimeAccum, mPhysicsDt)); updateMechanics(actorData); - mMovedActors.emplace_back(actorData.mActorRaw->getPtr()); if (mAdvanceSimulation) actorData.mActorRaw->setStandingOnPtr(actorData.mStandingOn); } diff --git a/apps/openmw/mwphysics/mtphysics.hpp b/apps/openmw/mwphysics/mtphysics.hpp index ae82727c56..21698e52bd 100644 --- a/apps/openmw/mwphysics/mtphysics.hpp +++ b/apps/openmw/mwphysics/mtphysics.hpp @@ -38,9 +38,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 std::vector& moveActors(float & timeAccum, std::vector&& actorsData, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats); + void applyQueuedMovements(float & timeAccum, std::vector&& actorsData, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats); - const std::vector& resetSimulation(const ActorMap& actors); + void resetSimulation(const ActorMap& actors); // Thread safe wrappers void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const; @@ -72,7 +72,6 @@ namespace MWPhysics std::unique_ptr mWorldFrameData; std::vector mActorsFrameData; - std::vector mMovedActors; float mDefaultPhysicsDt; float mPhysicsDt; float mTimeAccum; diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 63f25eb5f5..67766e4bf9 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -751,17 +751,6 @@ namespace MWPhysics actor->setVelocity(osg::Vec3f()); } - const std::vector& PhysicsSystem::applyQueuedMovement(float dt, bool skipSimulation, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) - { - mTimeAccum += dt; - - if (skipSimulation) - return mTaskScheduler->resetSimulation(mActors); - - // modifies mTimeAccum - return mTaskScheduler->moveActors(mTimeAccum, prepareFrameData(mTimeAccum >= mPhysicsDt), frameStart, frameNumber, stats); - } - std::vector PhysicsSystem::prepareFrameData(bool willSimulate) { std::vector actorsFrameData; @@ -798,20 +787,43 @@ namespace MWPhysics return actorsFrameData; } - void PhysicsSystem::stepSimulation() + void PhysicsSystem::stepSimulation(float dt, bool skipSimulation, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) { for (Object* animatedObject : mAnimatedObjects) + { if (animatedObject->animateCollisionShapes()) { auto obj = mObjects.find(animatedObject->getPtr()); assert(obj != mObjects.end()); mTaskScheduler->updateSingleAabb(obj->second); } + } #ifndef BT_NO_PROFILE CProfileManager::Reset(); CProfileManager::Increment_Frame_Counter(); #endif + + mTimeAccum += dt; + + if (skipSimulation) + mTaskScheduler->resetSimulation(mActors); + else + // modifies mTimeAccum + mTaskScheduler->applyQueuedMovements(mTimeAccum, prepareFrameData(mTimeAccum >= mPhysicsDt), frameStart, frameNumber, stats); + } + + void PhysicsSystem::moveActors() + { + auto* player = getActor(MWMechanics::getPlayer()); + auto* world = MWBase::Environment::get().getWorld(); + for (auto& [ptr, physicActor] : mActors) + { + if (physicActor.get() == player) + continue; + world->moveObject(physicActor->getPtr(), physicActor->getSimulationPosition(), false, false); + } + world->moveObject(player->getPtr(), player->getSimulationPosition(), false, false); } void PhysicsSystem::updateAnimatedCollisionShape(const MWWorld::Ptr& object) diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index 1eb1fd419a..ee62ab6ace 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -154,7 +154,11 @@ namespace MWPhysics bool toggleCollisionMode(); - void stepSimulation(); + /// Determine new position based on all queued movements, then clear the list. + void stepSimulation(float dt, bool skipSimulation, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats); + + /// Apply new positions to actors + void moveActors(); void debugDraw(); std::vector getCollisions(const MWWorld::ConstPtr &ptr, int collisionGroup, int collisionMask) const; ///< get handles this object collides with @@ -204,12 +208,9 @@ namespace MWPhysics osg::BoundingBox getBoundingBox(const MWWorld::ConstPtr &object) const; /// Queues velocity movement for a Ptr. If a Ptr is already queued, its velocity will - /// be overwritten. Valid until the next call to applyQueuedMovement. + /// be overwritten. Valid until the next call to stepSimulation void queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity); - /// Apply all queued movements, then clear the list. - const std::vector& applyQueuedMovement(float dt, bool skipSimulation, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats); - /// Clear the queued movements list without applying. void clearQueuedMovement(); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 38785740a9..5fcab477cf 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1508,35 +1508,12 @@ namespace MWWorld void World::doPhysics(float duration, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats) { - mPhysics->stepSimulation(); processDoors(duration); - mProjectileManager->update(duration); - - const auto& results = mPhysics->applyQueuedMovement(duration, mDiscardMovements, frameStart, frameNumber, stats); + mPhysics->stepSimulation(duration, mDiscardMovements, frameStart, frameNumber, stats); mProjectileManager->processHits(); mDiscardMovements = false; - - for(const auto& actor : results) - { - // Handle player last, in case a cell transition occurs - if(actor != getPlayerPtr()) - { - auto* physactor = mPhysics->getActor(actor); - assert(physactor); - const auto position = physactor->getSimulationPosition(); - moveObject(actor, position, false, false); - } - } - - const auto player = std::find(results.begin(), results.end(), getPlayerPtr()); - if (player != results.end()) - { - auto* physactor = mPhysics->getActor(*player); - assert(physactor); - const auto position = physactor->getSimulationPosition(); - moveObject(*player, position, false, false); - } + mPhysics->moveActors(); } void World::updateNavigator()