diff --git a/apps/openmw/mwphysics/movementsolver.cpp b/apps/openmw/mwphysics/movementsolver.cpp index 990000b257..2401f78367 100644 --- a/apps/openmw/mwphysics/movementsolver.cpp +++ b/apps/openmw/mwphysics/movementsolver.cpp @@ -345,13 +345,9 @@ namespace MWPhysics { isOnGround = true; isOnSlope = !isWalkableSlope(tracer.mPlaneNormal); + actor.mStandingOn = tracer.mHitObject; - const btCollisionObject* standingOn = tracer.mHitObject; - PtrHolder* ptrHolder = static_cast(standingOn->getUserPointer()); - if (ptrHolder) - actor.mStandingOn = ptrHolder->getPtr(); - - if (standingOn->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Water) + if (actor.mStandingOn->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Water) actor.mWalkingOnWater = true; if (!actor.mFlying && !isOnSlope) { diff --git a/apps/openmw/mwphysics/mtphysics.cpp b/apps/openmw/mwphysics/mtphysics.cpp index 8c2250c05c..41cec6facc 100644 --- a/apps/openmw/mwphysics/mtphysics.cpp +++ b/apps/openmw/mwphysics/mtphysics.cpp @@ -83,21 +83,6 @@ namespace return actorData.mPosition * interpolationFactor + actor.getPreviousPosition() * (1.f - interpolationFactor); } - void updateActor(MWPhysics::Actor& actor, MWPhysics::ActorFrameData& actorData, bool simulationPerformed, float timeAccum, float dt) - { - actor.setSimulationPosition(interpolateMovements(actor, actorData, timeAccum, dt)); - actor.setLastStuckPosition(actorData.mLastStuckPosition); - actor.setStuckFrames(actorData.mStuckFrames); - if (simulationPerformed) - { - actor.setStandingOnPtr(actorData.mStandingOn); - actor.setOnGround(actorData.mIsOnGround); - actor.setOnSlope(actorData.mIsOnSlope); - actor.setWalkingOnWater(actorData.mWalkingOnWater); - actor.setInertialForce(actorData.mInertia); - } - } - namespace Config { /// @return either the number of thread as configured by the user, or 1 if Bullet doesn't support multithreading @@ -357,12 +342,14 @@ namespace MWPhysics void PhysicsTaskScheduler::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask) { + mCollisionObjects.insert(collisionObject); std::unique_lock lock(mCollisionWorldMutex); mCollisionWorld->addCollisionObject(collisionObject, collisionFilterGroup, collisionFilterMask); } void PhysicsTaskScheduler::removeCollisionObject(btCollisionObject* collisionObject) { + mCollisionObjects.erase(collisionObject); std::unique_lock lock(mCollisionWorldMutex); mCollisionWorld->removeCollisionObject(collisionObject); } @@ -506,6 +493,27 @@ namespace MWPhysics } } + void PhysicsTaskScheduler::updateActor(Actor& actor, ActorFrameData& actorData, bool simulationPerformed, float timeAccum, float dt) const + { + actor.setSimulationPosition(interpolateMovements(actor, actorData, timeAccum, dt)); + actor.setLastStuckPosition(actorData.mLastStuckPosition); + actor.setStuckFrames(actorData.mStuckFrames); + if (simulationPerformed) + { + MWWorld::Ptr standingOn; + auto* ptrHolder = static_cast(getUserPointer(actorData.mStandingOn)); + if (ptrHolder) + standingOn = ptrHolder->getPtr(); + actor.setStandingOnPtr(standingOn); + // the "on ground" state of an actor might have been updated by a traceDown, don't overwrite the change + if (actor.getOnGround() == actorData.mWasOnGround) + actor.setOnGround(actorData.mIsOnGround); + actor.setOnSlope(actorData.mIsOnSlope); + actor.setWalkingOnWater(actorData.mWalkingOnWater); + actor.setInertialForce(actorData.mInertia); + } + } + bool PhysicsTaskScheduler::hasLineOfSight(const Actor* actor1, const Actor* actor2) { btVector3 pos1 = Misc::Convert::toBullet(actor1->getCollisionObjectPosition() + osg::Vec3f(0,0,actor1->getHalfExtents().z() * 0.9)); // eye level @@ -566,6 +574,14 @@ namespace MWPhysics mDebugDrawer->step(); } + void* PhysicsTaskScheduler::getUserPointer(const btCollisionObject* object) const + { + auto it = mCollisionObjects.find(object); + if (it == mCollisionObjects.end()) + return nullptr; + return (*it)->getUserPointer(); + } + void PhysicsTaskScheduler::afterPreStep() { updateAabbs(); diff --git a/apps/openmw/mwphysics/mtphysics.hpp b/apps/openmw/mwphysics/mtphysics.hpp index 6c2116f18f..e758c557e2 100644 --- a/apps/openmw/mwphysics/mtphysics.hpp +++ b/apps/openmw/mwphysics/mtphysics.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -55,11 +56,13 @@ namespace MWPhysics void updateSingleAabb(std::weak_ptr ptr, bool immediate=false); bool getLineOfSight(const std::weak_ptr& actor1, const std::weak_ptr& actor2); void debugDraw(); + void* getUserPointer(const btCollisionObject* object) const; private: void syncComputation(); void worker(); void updateActorsPositions(); + void updateActor(Actor& actor, ActorFrameData& actorData, bool simulationPerformed, float timeAccum, float dt) const; bool hasLineOfSight(const Actor* actor1, const Actor* actor2); void refreshLOSCache(); void updateAabbs(); @@ -73,6 +76,7 @@ namespace MWPhysics std::unique_ptr mWorldFrameData; std::vector> mActors; std::vector mActorsFrameData; + std::unordered_set mCollisionObjects; float mDefaultPhysicsDt; float mPhysicsDt; float mTimeAccum; diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index c7d19a3b5c..d65231322a 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -811,13 +811,8 @@ namespace MWPhysics // Slow fall reduces fall speed by a factor of (effect magnitude / 200) const float slowFall = 1.f - std::max(0.f, std::min(1.f, effects.get(ESM::MagicEffect::SlowFall).getMagnitude() * 0.005f)); - // Ue current value only if we don't advance the simulation. Otherwise we might get a stale value. - MWWorld::Ptr standingOn; - if (!willSimulate) - standingOn = physicActor->getStandingOnPtr(); - framedata.first.emplace_back(physicActor); - framedata.second.emplace_back(*physicActor, standingOn, waterCollision, slowFall, waterlevel); + framedata.second.emplace_back(*physicActor, waterCollision, slowFall, waterlevel); // if the simulation will run, a jump request will be fulfilled. Update mechanics accordingly. if (willSimulate) @@ -989,10 +984,9 @@ namespace MWPhysics mDebugDrawer->addCollision(position, normal); } - ActorFrameData::ActorFrameData(Actor& actor, const MWWorld::Ptr standingOn, - bool waterCollision, float slowFall, float waterlevel) + ActorFrameData::ActorFrameData(Actor& actor, bool waterCollision, float slowFall, float waterlevel) : mCollisionObject(actor.getCollisionObject()) - , mStandingOn(standingOn) + , mStandingOn(nullptr) , mWasOnGround(actor.getOnGround()) , mIsOnGround(actor.getOnGround()) , mIsOnSlope(actor.getOnSlope()) diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index 9d0d661d22..208e6cc71d 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -78,10 +78,10 @@ namespace MWPhysics struct ActorFrameData { - ActorFrameData(Actor& actor, const MWWorld::Ptr standingOn, bool moveToWaterSurface, float slowFall, float waterlevel); + ActorFrameData(Actor& actor, bool moveToWaterSurface, float slowFall, float waterlevel); void updatePosition(Actor& actor, btCollisionWorld* world); btCollisionObject* mCollisionObject; - MWWorld::Ptr mStandingOn; + const btCollisionObject* mStandingOn; bool mFlying; bool mWasOnGround; bool mIsOnGround;