mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 06:23:53 +00:00
Merge branch 'noweak' into 'master'
use shared_ptr inside the physics simulation to simplify the code See merge request OpenMW/openmw!1141
This commit is contained in:
commit
f966fdb65e
4 changed files with 61 additions and 79 deletions
|
@ -207,12 +207,13 @@ namespace MWPhysics
|
||||||
return std::make_tuple(numSteps, actualDelta);
|
return std::make_tuple(numSteps, actualDelta);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsTaskScheduler::applyQueuedMovements(float & timeAccum, std::vector<std::weak_ptr<Actor>>&& actors, std::vector<ActorFrameData>&& actorsData, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats)
|
void PhysicsTaskScheduler::applyQueuedMovements(float & timeAccum, std::vector<std::shared_ptr<Actor>>&& actors, std::vector<ActorFrameData>&& actorsData, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats)
|
||||||
{
|
{
|
||||||
// This function run in the main thread.
|
// This function run in the main thread.
|
||||||
// While the mSimulationMutex is held, background physics threads can't run.
|
// While the mSimulationMutex is held, background physics threads can't run.
|
||||||
|
|
||||||
std::unique_lock lock(mSimulationMutex);
|
std::unique_lock lock(mSimulationMutex);
|
||||||
|
assert(actors.size() == actorsData.size());
|
||||||
|
|
||||||
double timeStart = mTimer->tick();
|
double timeStart = mTimer->tick();
|
||||||
|
|
||||||
|
@ -221,11 +222,8 @@ namespace MWPhysics
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < mActors.size(); ++i)
|
for (size_t i = 0; i < mActors.size(); ++i)
|
||||||
{
|
{
|
||||||
if (auto actor = mActors[i].lock())
|
updateMechanics(*mActors[i], mActorsFrameData[i]);
|
||||||
{
|
updateActor(*mActors[i], mActorsFrameData[i], mAdvanceSimulation, mTimeAccum, mPhysicsDt);
|
||||||
updateMechanics(*actor, mActorsFrameData[i]);
|
|
||||||
updateActor(*actor, mActorsFrameData[i], mAdvanceSimulation, mTimeAccum, mPhysicsDt);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(mAdvanceSimulation)
|
if(mAdvanceSimulation)
|
||||||
mAsyncBudget.update(mTimer->delta_s(mAsyncStartTime, mTimeEnd), mPrevStepCount, mBudgetCursor);
|
mAsyncBudget.update(mTimer->delta_s(mAsyncStartTime, mTimeEnd), mPrevStepCount, mBudgetCursor);
|
||||||
|
@ -238,8 +236,7 @@ namespace MWPhysics
|
||||||
// init
|
// init
|
||||||
for (size_t i = 0; i < actors.size(); ++i)
|
for (size_t i = 0; i < actors.size(); ++i)
|
||||||
{
|
{
|
||||||
assert(actors[i].lock());
|
actorsData[i].updatePosition(*actors[i], mCollisionWorld);
|
||||||
actorsData[i].updatePosition(*actors[i].lock(), mCollisionWorld);
|
|
||||||
}
|
}
|
||||||
mPrevStepCount = numSteps;
|
mPrevStepCount = numSteps;
|
||||||
mRemainingSteps = numSteps;
|
mRemainingSteps = numSteps;
|
||||||
|
@ -355,7 +352,7 @@ namespace MWPhysics
|
||||||
mCollisionWorld->removeCollisionObject(collisionObject);
|
mCollisionWorld->removeCollisionObject(collisionObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsTaskScheduler::updateSingleAabb(std::weak_ptr<PtrHolder> ptr, bool immediate)
|
void PhysicsTaskScheduler::updateSingleAabb(std::shared_ptr<PtrHolder> ptr, bool immediate)
|
||||||
{
|
{
|
||||||
if (immediate || mNumThreads == 0)
|
if (immediate || mNumThreads == 0)
|
||||||
{
|
{
|
||||||
|
@ -368,20 +365,15 @@ namespace MWPhysics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhysicsTaskScheduler::getLineOfSight(const std::weak_ptr<Actor>& actor1, const std::weak_ptr<Actor>& actor2)
|
bool PhysicsTaskScheduler::getLineOfSight(const std::shared_ptr<Actor>& actor1, const std::shared_ptr<Actor>& actor2)
|
||||||
{
|
{
|
||||||
std::unique_lock lock(mLOSCacheMutex);
|
std::unique_lock lock(mLOSCacheMutex);
|
||||||
|
|
||||||
auto actorPtr1 = actor1.lock();
|
|
||||||
auto actorPtr2 = actor2.lock();
|
|
||||||
if (!actorPtr1 || !actorPtr2)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto req = LOSRequest(actor1, actor2);
|
auto req = LOSRequest(actor1, actor2);
|
||||||
auto result = std::find(mLOSCache.begin(), mLOSCache.end(), req);
|
auto result = std::find(mLOSCache.begin(), mLOSCache.end(), req);
|
||||||
if (result == mLOSCache.end())
|
if (result == mLOSCache.end())
|
||||||
{
|
{
|
||||||
req.mResult = hasLineOfSight(actorPtr1.get(), actorPtr2.get());
|
req.mResult = hasLineOfSight(actor1.get(), actor2.get());
|
||||||
mLOSCache.push_back(req);
|
mLOSCache.push_back(req);
|
||||||
return req.mResult;
|
return req.mResult;
|
||||||
}
|
}
|
||||||
|
@ -412,31 +404,28 @@ namespace MWPhysics
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(mUpdateAabbMutex);
|
std::scoped_lock lock(mUpdateAabbMutex);
|
||||||
std::for_each(mUpdateAabb.begin(), mUpdateAabb.end(),
|
std::for_each(mUpdateAabb.begin(), mUpdateAabb.end(),
|
||||||
[this](const std::weak_ptr<PtrHolder>& ptr) { updatePtrAabb(ptr); });
|
[this](const std::shared_ptr<PtrHolder>& ptr) { updatePtrAabb(ptr); });
|
||||||
mUpdateAabb.clear();
|
mUpdateAabb.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsTaskScheduler::updatePtrAabb(const std::weak_ptr<PtrHolder>& ptr)
|
void PhysicsTaskScheduler::updatePtrAabb(const std::shared_ptr<PtrHolder>& ptr)
|
||||||
{
|
{
|
||||||
if (const auto p = ptr.lock())
|
std::scoped_lock lock(mCollisionWorldMutex);
|
||||||
|
if (const auto actor = std::dynamic_pointer_cast<Actor>(ptr))
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(mCollisionWorldMutex);
|
actor->updateCollisionObjectPosition();
|
||||||
if (const auto actor = std::dynamic_pointer_cast<Actor>(p))
|
mCollisionWorld->updateSingleAabb(actor->getCollisionObject());
|
||||||
{
|
}
|
||||||
actor->updateCollisionObjectPosition();
|
else if (const auto object = std::dynamic_pointer_cast<Object>(ptr))
|
||||||
mCollisionWorld->updateSingleAabb(actor->getCollisionObject());
|
{
|
||||||
}
|
object->commitPositionChange();
|
||||||
else if (const auto object = std::dynamic_pointer_cast<Object>(p))
|
mCollisionWorld->updateSingleAabb(object->getCollisionObject());
|
||||||
{
|
}
|
||||||
object->commitPositionChange();
|
else if (const auto projectile = std::dynamic_pointer_cast<Projectile>(ptr))
|
||||||
mCollisionWorld->updateSingleAabb(object->getCollisionObject());
|
{
|
||||||
}
|
projectile->commitPositionChange();
|
||||||
else if (const auto projectile = std::dynamic_pointer_cast<Projectile>(p))
|
mCollisionWorld->updateSingleAabb(projectile->getCollisionObject());
|
||||||
{
|
}
|
||||||
projectile->commitPositionChange();
|
|
||||||
mCollisionWorld->updateSingleAabb(projectile->getCollisionObject());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsTaskScheduler::worker()
|
void PhysicsTaskScheduler::worker()
|
||||||
|
@ -452,11 +441,8 @@ namespace MWPhysics
|
||||||
int job = 0;
|
int job = 0;
|
||||||
while (mRemainingSteps && (job = mNextJob.fetch_add(1, std::memory_order_relaxed)) < mNumJobs)
|
while (mRemainingSteps && (job = mNextJob.fetch_add(1, std::memory_order_relaxed)) < mNumJobs)
|
||||||
{
|
{
|
||||||
if(const auto actor = mActors[job].lock())
|
MaybeSharedLock lockColWorld(mCollisionWorldMutex, mThreadSafeBullet);
|
||||||
{
|
MovementSolver::move(mActorsFrameData[job], mPhysicsDt, mCollisionWorld, *mWorldFrameData);
|
||||||
MaybeSharedLock lockColWorld(mCollisionWorldMutex, mThreadSafeBullet);
|
|
||||||
MovementSolver::move(mActorsFrameData[job], mPhysicsDt, mCollisionWorld, *mWorldFrameData);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mPostStepBarrier->wait([this] { afterPostStep(); });
|
mPostStepBarrier->wait([this] { afterPostStep(); });
|
||||||
|
@ -465,10 +451,7 @@ namespace MWPhysics
|
||||||
{
|
{
|
||||||
while ((job = mNextJob.fetch_add(1, std::memory_order_relaxed)) < mNumJobs)
|
while ((job = mNextJob.fetch_add(1, std::memory_order_relaxed)) < mNumJobs)
|
||||||
{
|
{
|
||||||
if(const auto actor = mActors[job].lock())
|
handleFall(mActorsFrameData[job], mAdvanceSimulation);
|
||||||
{
|
|
||||||
handleFall(mActorsFrameData[job], mAdvanceSimulation);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshLOSCache();
|
refreshLOSCache();
|
||||||
|
@ -481,15 +464,12 @@ namespace MWPhysics
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < mActors.size(); ++i)
|
for (size_t i = 0; i < mActors.size(); ++i)
|
||||||
{
|
{
|
||||||
if(const auto actor = mActors[i].lock())
|
if (mActors[i]->setPosition(mActorsFrameData[i].mPosition))
|
||||||
{
|
{
|
||||||
if (actor->setPosition(mActorsFrameData[i].mPosition))
|
std::scoped_lock lock(mCollisionWorldMutex);
|
||||||
{
|
mActorsFrameData[i].mPosition = mActors[i]->getPosition(); // account for potential position change made by script
|
||||||
std::scoped_lock lock(mCollisionWorldMutex);
|
mActors[i]->updateCollisionObjectPosition();
|
||||||
mActorsFrameData[i].mPosition = actor->getPosition(); // account for potential position change made by script
|
mCollisionWorld->updateSingleAabb(mActors[i]->getCollisionObject());
|
||||||
actor->updateCollisionObjectPosition();
|
|
||||||
mCollisionWorld->updateSingleAabb(actor->getCollisionObject());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -545,11 +525,9 @@ namespace MWPhysics
|
||||||
|
|
||||||
for (size_t i = 0; i < mActors.size(); ++i)
|
for (size_t i = 0; i < mActors.size(); ++i)
|
||||||
{
|
{
|
||||||
auto actor = mActors[i].lock();
|
|
||||||
assert(actor);
|
|
||||||
handleFall(mActorsFrameData[i], mAdvanceSimulation);
|
handleFall(mActorsFrameData[i], mAdvanceSimulation);
|
||||||
updateMechanics(*actor, mActorsFrameData[i]);
|
updateMechanics(*mActors[i], mActorsFrameData[i]);
|
||||||
updateActor(*actor, mActorsFrameData[i], mAdvanceSimulation, mTimeAccum, mPhysicsDt);
|
updateActor(*mActors[i], mActorsFrameData[i], mAdvanceSimulation, mTimeAccum, mPhysicsDt);
|
||||||
}
|
}
|
||||||
refreshLOSCache();
|
refreshLOSCache();
|
||||||
}
|
}
|
||||||
|
@ -583,6 +561,13 @@ namespace MWPhysics
|
||||||
return (*it)->getUserPointer();
|
return (*it)->getUserPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PhysicsTaskScheduler::releaseSharedStates()
|
||||||
|
{
|
||||||
|
std::scoped_lock lock(mSimulationMutex, mUpdateAabbMutex);
|
||||||
|
mActors.clear();
|
||||||
|
mUpdateAabb.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void PhysicsTaskScheduler::afterPreStep()
|
void PhysicsTaskScheduler::afterPreStep()
|
||||||
{
|
{
|
||||||
updateAabbs();
|
updateAabbs();
|
||||||
|
@ -590,11 +575,8 @@ namespace MWPhysics
|
||||||
return;
|
return;
|
||||||
for (size_t i = 0; i < mActors.size(); ++i)
|
for (size_t i = 0; i < mActors.size(); ++i)
|
||||||
{
|
{
|
||||||
if (auto actor = mActors[i].lock())
|
std::unique_lock lock(mCollisionWorldMutex);
|
||||||
{
|
MovementSolver::unstuck(mActorsFrameData[i], mCollisionWorld);
|
||||||
std::unique_lock lock(mCollisionWorldMutex);
|
|
||||||
MovementSolver::unstuck(mActorsFrameData[i], mCollisionWorld);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace MWPhysics
|
||||||
/// @param timeAccum accumulated time from previous run to interpolate movements
|
/// @param timeAccum accumulated time from previous run to interpolate movements
|
||||||
/// @param actorsData per actor data needed to compute new positions
|
/// @param actorsData per actor data needed to compute new positions
|
||||||
/// @return new position of each actor
|
/// @return new position of each actor
|
||||||
void applyQueuedMovements(float & timeAccum, std::vector<std::weak_ptr<Actor>>&& actors, std::vector<ActorFrameData>&& actorsData, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats);
|
void applyQueuedMovements(float & timeAccum, std::vector<std::shared_ptr<Actor>>&& actors, std::vector<ActorFrameData>&& actorsData, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats);
|
||||||
|
|
||||||
void resetSimulation(const ActorMap& actors);
|
void resetSimulation(const ActorMap& actors);
|
||||||
|
|
||||||
|
@ -53,11 +53,13 @@ namespace MWPhysics
|
||||||
void setCollisionFilterMask(btCollisionObject* collisionObject, int collisionFilterMask);
|
void setCollisionFilterMask(btCollisionObject* collisionObject, int collisionFilterMask);
|
||||||
void addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask);
|
void addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask);
|
||||||
void removeCollisionObject(btCollisionObject* collisionObject);
|
void removeCollisionObject(btCollisionObject* collisionObject);
|
||||||
void updateSingleAabb(std::weak_ptr<PtrHolder> ptr, bool immediate=false);
|
void updateSingleAabb(std::shared_ptr<PtrHolder> ptr, bool immediate=false);
|
||||||
bool getLineOfSight(const std::weak_ptr<Actor>& actor1, const std::weak_ptr<Actor>& actor2);
|
bool getLineOfSight(const std::shared_ptr<Actor>& actor1, const std::shared_ptr<Actor>& actor2);
|
||||||
void debugDraw();
|
void debugDraw();
|
||||||
void* getUserPointer(const btCollisionObject* object) const;
|
void* getUserPointer(const btCollisionObject* object) const;
|
||||||
|
|
||||||
|
void releaseSharedStates(); // destroy all objects whose destructor can't be safely called from ~PhysicsTaskScheduler()
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void syncComputation();
|
void syncComputation();
|
||||||
void worker();
|
void worker();
|
||||||
|
@ -66,7 +68,7 @@ namespace MWPhysics
|
||||||
bool hasLineOfSight(const Actor* actor1, const Actor* actor2);
|
bool hasLineOfSight(const Actor* actor1, const Actor* actor2);
|
||||||
void refreshLOSCache();
|
void refreshLOSCache();
|
||||||
void updateAabbs();
|
void updateAabbs();
|
||||||
void updatePtrAabb(const std::weak_ptr<PtrHolder>& ptr);
|
void updatePtrAabb(const std::shared_ptr<PtrHolder>& ptr);
|
||||||
void updateStats(osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats);
|
void updateStats(osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats);
|
||||||
std::tuple<int, float> calculateStepConfig(float timeAccum) const;
|
std::tuple<int, float> calculateStepConfig(float timeAccum) const;
|
||||||
void afterPreStep();
|
void afterPreStep();
|
||||||
|
@ -74,7 +76,7 @@ namespace MWPhysics
|
||||||
void afterPostSim();
|
void afterPostSim();
|
||||||
|
|
||||||
std::unique_ptr<WorldFrameData> mWorldFrameData;
|
std::unique_ptr<WorldFrameData> mWorldFrameData;
|
||||||
std::vector<std::weak_ptr<Actor>> mActors;
|
std::vector<std::shared_ptr<Actor>> mActors;
|
||||||
std::vector<ActorFrameData> mActorsFrameData;
|
std::vector<ActorFrameData> mActorsFrameData;
|
||||||
std::unordered_set<const btCollisionObject*> mCollisionObjects;
|
std::unordered_set<const btCollisionObject*> mCollisionObjects;
|
||||||
float mDefaultPhysicsDt;
|
float mDefaultPhysicsDt;
|
||||||
|
@ -83,7 +85,7 @@ namespace MWPhysics
|
||||||
btCollisionWorld* mCollisionWorld;
|
btCollisionWorld* mCollisionWorld;
|
||||||
MWRender::DebugDrawer* mDebugDrawer;
|
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::shared_ptr<PtrHolder>> mUpdateAabb;
|
||||||
|
|
||||||
// TODO: use std::experimental::flex_barrier or std::barrier once it becomes a thing
|
// TODO: use std::experimental::flex_barrier or std::barrier once it becomes a thing
|
||||||
std::unique_ptr<Misc::Barrier> mPreStepBarrier;
|
std::unique_ptr<Misc::Barrier> mPreStepBarrier;
|
||||||
|
|
|
@ -153,6 +153,7 @@ namespace MWPhysics
|
||||||
if (mWaterCollisionObject)
|
if (mWaterCollisionObject)
|
||||||
mTaskScheduler->removeCollisionObject(mWaterCollisionObject.get());
|
mTaskScheduler->removeCollisionObject(mWaterCollisionObject.get());
|
||||||
|
|
||||||
|
mTaskScheduler->releaseSharedStates();
|
||||||
mHeightFields.clear();
|
mHeightFields.clear();
|
||||||
mObjects.clear();
|
mObjects.clear();
|
||||||
mActors.clear();
|
mActors.clear();
|
||||||
|
@ -373,15 +374,12 @@ namespace MWPhysics
|
||||||
|
|
||||||
bool PhysicsSystem::getLineOfSight(const MWWorld::ConstPtr &actor1, const MWWorld::ConstPtr &actor2) const
|
bool PhysicsSystem::getLineOfSight(const MWWorld::ConstPtr &actor1, const MWWorld::ConstPtr &actor2) const
|
||||||
{
|
{
|
||||||
const auto getWeakPtr = [&](const MWWorld::ConstPtr &ptr) -> std::weak_ptr<Actor>
|
const auto it1 = mActors.find(actor1);
|
||||||
{
|
const auto it2 = mActors.find(actor2);
|
||||||
const auto found = mActors.find(ptr);
|
if (it1 == mActors.end() || it2 == mActors.end())
|
||||||
if (found != mActors.end())
|
return false;
|
||||||
return { found->second };
|
|
||||||
return {};
|
|
||||||
};
|
|
||||||
|
|
||||||
return mTaskScheduler->getLineOfSight(getWeakPtr(actor1), getWeakPtr(actor2));
|
return mTaskScheduler->getLineOfSight(it1->second, it2->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhysicsSystem::isOnGround(const MWWorld::Ptr &actor)
|
bool PhysicsSystem::isOnGround(const MWWorld::Ptr &actor)
|
||||||
|
@ -769,9 +767,9 @@ namespace MWPhysics
|
||||||
actor->setVelocity(osg::Vec3f());
|
actor->setVelocity(osg::Vec3f());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<std::vector<std::weak_ptr<Actor>>, std::vector<ActorFrameData>> PhysicsSystem::prepareFrameData(bool willSimulate)
|
std::pair<std::vector<std::shared_ptr<Actor>>, std::vector<ActorFrameData>> PhysicsSystem::prepareFrameData(bool willSimulate)
|
||||||
{
|
{
|
||||||
std::pair<std::vector<std::weak_ptr<Actor>>, std::vector<ActorFrameData>> framedata;
|
std::pair<std::vector<std::shared_ptr<Actor>>, std::vector<ActorFrameData>> framedata;
|
||||||
framedata.first.reserve(mActors.size());
|
framedata.first.reserve(mActors.size());
|
||||||
framedata.second.reserve(mActors.size());
|
framedata.second.reserve(mActors.size());
|
||||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
|
|
@ -259,7 +259,7 @@ namespace MWPhysics
|
||||||
|
|
||||||
void updateWater();
|
void updateWater();
|
||||||
|
|
||||||
std::pair<std::vector<std::weak_ptr<Actor>>, std::vector<ActorFrameData>> prepareFrameData(bool willSimulate);
|
std::pair<std::vector<std::shared_ptr<Actor>>, std::vector<ActorFrameData>> prepareFrameData(bool willSimulate);
|
||||||
|
|
||||||
osg::ref_ptr<SceneUtil::UnrefQueue> mUnrefQueue;
|
osg::ref_ptr<SceneUtil::UnrefQueue> mUnrefQueue;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue