1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-25 03:40:40 +00:00

Merge branch 'physics_clean' into 'master'

Close 2 data races with async physics

See merge request OpenMW/openmw!695
This commit is contained in:
psi29a 2021-03-27 16:56:54 +00:00
commit 08afc4729f
5 changed files with 29 additions and 15 deletions

View File

@ -459,8 +459,7 @@ namespace MWPhysics
const auto verticalHalfExtent = osg::Vec3f(0.0, 0.0, physicActor->getHalfExtents().z()); const auto verticalHalfExtent = osg::Vec3f(0.0, 0.0, physicActor->getHalfExtents().z());
// use a 3d approximation of the movement vector to better judge player intent // use a 3d approximation of the movement vector to better judge player intent
const ESM::Position& refpos = ptr.getRefData().getPosition(); auto velocity = (osg::Quat(actor.mRefpos.rot[0], osg::Vec3f(-1, 0, 0)) * osg::Quat(actor.mRefpos.rot[2], osg::Vec3f(0, 0, -1))) * actor.mMovement;
auto velocity = (osg::Quat(refpos.rot[0], osg::Vec3f(-1, 0, 0)) * osg::Quat(refpos.rot[2], osg::Vec3f(0, 0, -1))) * actor.mMovement;
// try to pop outside of the world before doing anything else if we're inside of it // try to pop outside of the world before doing anything else if we're inside of it
if (!physicActor->getOnGround() || physicActor->getOnSlope()) if (!physicActor->getOnGround() || physicActor->getOnSlope())
velocity += physicActor->getInertialForce(); velocity += physicActor->getInertialForce();

View File

@ -9,6 +9,7 @@
#include "components/settings/settings.hpp" #include "components/settings/settings.hpp"
#include "../mwmechanics/actorutil.hpp" #include "../mwmechanics/actorutil.hpp"
#include "../mwmechanics/movement.hpp" #include "../mwmechanics/movement.hpp"
#include "../mwrender/bulletdebugdraw.hpp"
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
@ -137,11 +138,12 @@ namespace
namespace MWPhysics namespace MWPhysics
{ {
PhysicsTaskScheduler::PhysicsTaskScheduler(float physicsDt, std::shared_ptr<btCollisionWorld> collisionWorld) PhysicsTaskScheduler::PhysicsTaskScheduler(float physicsDt, btCollisionWorld *collisionWorld, MWRender::DebugDrawer* debugDrawer)
: mDefaultPhysicsDt(physicsDt) : mDefaultPhysicsDt(physicsDt)
, mPhysicsDt(physicsDt) , mPhysicsDt(physicsDt)
, mTimeAccum(0.f) , mTimeAccum(0.f)
, mCollisionWorld(std::move(collisionWorld)) , mCollisionWorld(collisionWorld)
, mDebugDrawer(debugDrawer)
, mNumJobs(0) , mNumJobs(0)
, mRemainingSteps(0) , mRemainingSteps(0)
, mLOSCacheExpiry(Settings::Manager::getInt("lineofsight keep inactive cache", "Physics")) , mLOSCacheExpiry(Settings::Manager::getInt("lineofsight keep inactive cache", "Physics"))
@ -185,7 +187,7 @@ namespace MWPhysics
if (data.mActor.lock()) if (data.mActor.lock())
{ {
std::unique_lock lock(mCollisionWorldMutex); std::unique_lock lock(mCollisionWorldMutex);
MovementSolver::unstuck(data, mCollisionWorld.get()); MovementSolver::unstuck(data, mCollisionWorld);
} }
}); });
@ -381,7 +383,7 @@ namespace MWPhysics
void PhysicsTaskScheduler::contactTest(btCollisionObject* colObj, btCollisionWorld::ContactResultCallback& resultCallback) void PhysicsTaskScheduler::contactTest(btCollisionObject* colObj, btCollisionWorld::ContactResultCallback& resultCallback)
{ {
std::shared_lock lock(mCollisionWorldMutex); std::shared_lock lock(mCollisionWorldMutex);
ContactTestWrapper::contactTest(mCollisionWorld.get(), colObj, resultCallback); ContactTestWrapper::contactTest(mCollisionWorld, colObj, resultCallback);
} }
std::optional<btVector3> PhysicsTaskScheduler::getHitPoint(const btTransform& from, btCollisionObject* target) std::optional<btVector3> PhysicsTaskScheduler::getHitPoint(const btTransform& from, btCollisionObject* target)
@ -532,7 +534,7 @@ namespace MWPhysics
if(const auto actor = mActorsFrameData[job].mActor.lock()) if(const auto actor = mActorsFrameData[job].mActor.lock())
{ {
MaybeSharedLock lockColWorld(mCollisionWorldMutex, mThreadSafeBullet); MaybeSharedLock lockColWorld(mCollisionWorldMutex, mThreadSafeBullet);
MovementSolver::move(mActorsFrameData[job], mPhysicsDt, mCollisionWorld.get(), *mWorldFrameData); MovementSolver::move(mActorsFrameData[job], mPhysicsDt, mCollisionWorld, *mWorldFrameData);
} }
} }
@ -594,8 +596,8 @@ namespace MWPhysics
{ {
for (auto& actorData : mActorsFrameData) for (auto& actorData : mActorsFrameData)
{ {
MovementSolver::unstuck(actorData, mCollisionWorld.get()); MovementSolver::unstuck(actorData, mCollisionWorld);
MovementSolver::move(actorData, mPhysicsDt, mCollisionWorld.get(), *mWorldFrameData); MovementSolver::move(actorData, mPhysicsDt, mCollisionWorld, *mWorldFrameData);
} }
updateActorsPositions(); updateActorsPositions();
@ -626,4 +628,10 @@ namespace MWPhysics
mTimeBegin = mTimer->tick(); mTimeBegin = mTimer->tick();
mFrameNumber = frameNumber; mFrameNumber = frameNumber;
} }
void PhysicsTaskScheduler::debugDraw()
{
std::shared_lock lock(mCollisionWorldMutex);
mDebugDrawer->step();
}
} }

View File

@ -20,12 +20,17 @@ namespace Misc
class Barrier; class Barrier;
} }
namespace MWRender
{
class DebugDrawer;
}
namespace MWPhysics namespace MWPhysics
{ {
class PhysicsTaskScheduler class PhysicsTaskScheduler
{ {
public: public:
PhysicsTaskScheduler(float physicsDt, std::shared_ptr<btCollisionWorld> collisionWorld); PhysicsTaskScheduler(float physicsDt, btCollisionWorld* collisionWorld, MWRender::DebugDrawer* debugDrawer);
~PhysicsTaskScheduler(); ~PhysicsTaskScheduler();
/// @brief move actors taking into account desired movements and collisions /// @brief move actors taking into account desired movements and collisions
@ -49,6 +54,7 @@ namespace MWPhysics
void removeCollisionObject(btCollisionObject* collisionObject); void removeCollisionObject(btCollisionObject* collisionObject);
void updateSingleAabb(std::weak_ptr<PtrHolder> ptr, bool immediate=false); void updateSingleAabb(std::weak_ptr<PtrHolder> ptr, bool immediate=false);
bool getLineOfSight(const std::weak_ptr<Actor>& actor1, const std::weak_ptr<Actor>& actor2); bool getLineOfSight(const std::weak_ptr<Actor>& actor1, const std::weak_ptr<Actor>& actor2);
void debugDraw();
private: private:
void syncComputation(); void syncComputation();
@ -67,7 +73,8 @@ namespace MWPhysics
float mDefaultPhysicsDt; float mDefaultPhysicsDt;
float mPhysicsDt; float mPhysicsDt;
float mTimeAccum; float mTimeAccum;
std::shared_ptr<btCollisionWorld> mCollisionWorld; btCollisionWorld* mCollisionWorld;
MWRender::DebugDrawer* mDebugDrawer;
std::vector<LOSRequest> mLOSCache; std::vector<LOSRequest> mLOSCache;
std::set<std::weak_ptr<PtrHolder>, std::owner_less<std::weak_ptr<PtrHolder>>> mUpdateAabb; std::set<std::weak_ptr<PtrHolder>, std::owner_less<std::weak_ptr<PtrHolder>>> mUpdateAabb;

View File

@ -79,7 +79,7 @@ namespace MWPhysics
mDispatcher = std::make_unique<btCollisionDispatcher>(mCollisionConfiguration.get()); mDispatcher = std::make_unique<btCollisionDispatcher>(mCollisionConfiguration.get());
mBroadphase = std::make_unique<btDbvtBroadphase>(); mBroadphase = std::make_unique<btDbvtBroadphase>();
mCollisionWorld = std::make_shared<btCollisionWorld>(mDispatcher.get(), mBroadphase.get(), mCollisionConfiguration.get()); mCollisionWorld = std::make_unique<btCollisionWorld>(mDispatcher.get(), mBroadphase.get(), mCollisionConfiguration.get());
// Don't update AABBs of all objects every frame. Most objects in MW are static, so we don't need this. // Don't update AABBs of all objects every frame. Most objects in MW are static, so we don't need this.
// Should a "static" object ever be moved, we have to update its AABB manually using DynamicsWorld::updateSingleAabb. // Should a "static" object ever be moved, we have to update its AABB manually using DynamicsWorld::updateSingleAabb.
@ -97,8 +97,8 @@ namespace MWPhysics
} }
} }
mTaskScheduler = std::make_unique<PhysicsTaskScheduler>(mPhysicsDt, mCollisionWorld);
mDebugDrawer = std::make_unique<MWRender::DebugDrawer>(mParentNode, mCollisionWorld.get(), mDebugDrawEnabled); mDebugDrawer = std::make_unique<MWRender::DebugDrawer>(mParentNode, mCollisionWorld.get(), mDebugDrawEnabled);
mTaskScheduler = std::make_unique<PhysicsTaskScheduler>(mPhysicsDt, mCollisionWorld.get(), mDebugDrawer.get());
} }
PhysicsSystem::~PhysicsSystem() PhysicsSystem::~PhysicsSystem()
@ -827,7 +827,7 @@ namespace MWPhysics
void PhysicsSystem::debugDraw() void PhysicsSystem::debugDraw()
{ {
if (mDebugDrawEnabled) if (mDebugDrawEnabled)
mDebugDrawer->step(); mTaskScheduler->debugDraw();
} }
bool PhysicsSystem::isActorStandingOn(const MWWorld::Ptr &actor, const MWWorld::ConstPtr &object) const bool PhysicsSystem::isActorStandingOn(const MWWorld::Ptr &actor, const MWWorld::ConstPtr &object) const

View File

@ -259,7 +259,7 @@ namespace MWPhysics
std::unique_ptr<btBroadphaseInterface> mBroadphase; std::unique_ptr<btBroadphaseInterface> mBroadphase;
std::unique_ptr<btDefaultCollisionConfiguration> mCollisionConfiguration; std::unique_ptr<btDefaultCollisionConfiguration> mCollisionConfiguration;
std::unique_ptr<btCollisionDispatcher> mDispatcher; std::unique_ptr<btCollisionDispatcher> mDispatcher;
std::shared_ptr<btCollisionWorld> mCollisionWorld; std::unique_ptr<btCollisionWorld> mCollisionWorld;
std::unique_ptr<PhysicsTaskScheduler> mTaskScheduler; std::unique_ptr<PhysicsTaskScheduler> mTaskScheduler;
std::unique_ptr<Resource::BulletShapeManager> mShapeManager; std::unique_ptr<Resource::BulletShapeManager> mShapeManager;