From 7843dad35d772a1c0835dd8eb7dba4040ac3d7ff Mon Sep 17 00:00:00 2001
From: fredzio <chardon.frederic@gmail.com>
Date: Sat, 5 Dec 2020 01:09:43 +0100
Subject: [PATCH] Don't let the actor "nowhere" after a teleport but move them
 in their place. This solve the problem where after loading, an empty frame
 was rendered because the player is "nowhere".

---
 apps/openmw/mwphysics/mtphysics.cpp     | 9 ++++++++-
 apps/openmw/mwphysics/mtphysics.hpp     | 2 +-
 apps/openmw/mwphysics/physicssystem.cpp | 9 +--------
 apps/openmw/mwphysics/physicssystem.hpp | 3 ++-
 4 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/apps/openmw/mwphysics/mtphysics.cpp b/apps/openmw/mwphysics/mtphysics.cpp
index bdffcef44..50cfd808f 100644
--- a/apps/openmw/mwphysics/mtphysics.cpp
+++ b/apps/openmw/mwphysics/mtphysics.cpp
@@ -297,12 +297,19 @@ namespace MWPhysics
         return mPreviousMovementResults;
     }
 
-    const PtrPositionList& PhysicsTaskScheduler::resetSimulation()
+    const PtrPositionList& PhysicsTaskScheduler::resetSimulation(const ActorMap& actors)
     {
         std::unique_lock lock(mSimulationMutex);
         mMovementResults.clear();
         mPreviousMovementResults.clear();
         mActorsFrameData.clear();
+
+        for (const auto& [_, actor] : actors)
+        {
+            actor->resetPosition();
+            actor->setStandingOnPtr(nullptr);
+            mMovementResults[actor->getPtr()] = actor->getWorldPosition();
+        }
         return mMovementResults;
     }
 
diff --git a/apps/openmw/mwphysics/mtphysics.hpp b/apps/openmw/mwphysics/mtphysics.hpp
index f7a131ca2..3a761829b 100644
--- a/apps/openmw/mwphysics/mtphysics.hpp
+++ b/apps/openmw/mwphysics/mtphysics.hpp
@@ -34,7 +34,7 @@ namespace MWPhysics
             /// @return new position of each actor
             const PtrPositionList& moveActors(int numSteps, float timeAccum, std::vector<ActorFrameData>&& actorsData, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats);
 
-            const PtrPositionList& resetSimulation();
+            const PtrPositionList& resetSimulation(const ActorMap& actors);
 
             // 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 cdbad2cdd..b750970d9 100644
--- a/apps/openmw/mwphysics/physicssystem.cpp
+++ b/apps/openmw/mwphysics/physicssystem.cpp
@@ -677,14 +677,7 @@ namespace MWPhysics
         mTimeAccum -= numSteps * mPhysicsDt;
 
         if (skipSimulation)
-        {
-            for (auto& [_, actor] : mActors)
-            {
-                actor->resetPosition();
-                actor->setStandingOnPtr(nullptr);
-            }
-            return mTaskScheduler->resetSimulation();
-        }
+            return mTaskScheduler->resetSimulation(mActors);
 
         return mTaskScheduler->moveActors(numSteps, mTimeAccum, prepareFrameData(numSteps), frameStart, frameNumber, stats);
     }
diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp
index 03ae78993..4137b1e09 100644
--- a/apps/openmw/mwphysics/physicssystem.hpp
+++ b/apps/openmw/mwphysics/physicssystem.hpp
@@ -57,6 +57,8 @@ namespace MWPhysics
     class Actor;
     class PhysicsTaskScheduler;
 
+    using ActorMap = std::map<MWWorld::ConstPtr, std::shared_ptr<Actor>>;
+
     struct ContactPoint
     {
         MWWorld::Ptr mObject;
@@ -265,7 +267,6 @@ namespace MWPhysics
 
             std::set<Object*> mAnimatedObjects; // stores pointers to elements in mObjects
 
-            using ActorMap = std::map<MWWorld::ConstPtr, std::shared_ptr<Actor>>;
             ActorMap mActors;
 
             using HeightFieldMap = std::map<std::pair<int, int>, HeightField *>;