mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 06:53: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);
|
||||
}
|
||||
|
||||
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.
|
||||
// While the mSimulationMutex is held, background physics threads can't run.
|
||||
|
||||
std::unique_lock lock(mSimulationMutex);
|
||||
assert(actors.size() == actorsData.size());
|
||||
|
||||
double timeStart = mTimer->tick();
|
||||
|
||||
|
@ -221,11 +222,8 @@ namespace MWPhysics
|
|||
{
|
||||
for (size_t i = 0; i < mActors.size(); ++i)
|
||||
{
|
||||
if (auto actor = mActors[i].lock())
|
||||
{
|
||||
updateMechanics(*actor, mActorsFrameData[i]);
|
||||
updateActor(*actor, mActorsFrameData[i], mAdvanceSimulation, mTimeAccum, mPhysicsDt);
|
||||
}
|
||||
updateMechanics(*mActors[i], mActorsFrameData[i]);
|
||||
updateActor(*mActors[i], mActorsFrameData[i], mAdvanceSimulation, mTimeAccum, mPhysicsDt);
|
||||
}
|
||||
if(mAdvanceSimulation)
|
||||
mAsyncBudget.update(mTimer->delta_s(mAsyncStartTime, mTimeEnd), mPrevStepCount, mBudgetCursor);
|
||||
|
@ -238,8 +236,7 @@ namespace MWPhysics
|
|||
// init
|
||||
for (size_t i = 0; i < actors.size(); ++i)
|
||||
{
|
||||
assert(actors[i].lock());
|
||||
actorsData[i].updatePosition(*actors[i].lock(), mCollisionWorld);
|
||||
actorsData[i].updatePosition(*actors[i], mCollisionWorld);
|
||||
}
|
||||
mPrevStepCount = numSteps;
|
||||
mRemainingSteps = numSteps;
|
||||
|
@ -355,7 +352,7 @@ namespace MWPhysics
|
|||
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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
auto actorPtr1 = actor1.lock();
|
||||
auto actorPtr2 = actor2.lock();
|
||||
if (!actorPtr1 || !actorPtr2)
|
||||
return false;
|
||||
|
||||
auto req = LOSRequest(actor1, actor2);
|
||||
auto result = std::find(mLOSCache.begin(), mLOSCache.end(), req);
|
||||
if (result == mLOSCache.end())
|
||||
{
|
||||
req.mResult = hasLineOfSight(actorPtr1.get(), actorPtr2.get());
|
||||
req.mResult = hasLineOfSight(actor1.get(), actor2.get());
|
||||
mLOSCache.push_back(req);
|
||||
return req.mResult;
|
||||
}
|
||||
|
@ -412,31 +404,28 @@ namespace MWPhysics
|
|||
{
|
||||
std::scoped_lock lock(mUpdateAabbMutex);
|
||||
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();
|
||||
}
|
||||
|
||||
void PhysicsTaskScheduler::updatePtrAabb(const std::weak_ptr<PtrHolder>& ptr)
|
||||
{
|
||||
if (const auto p = ptr.lock())
|
||||
void PhysicsTaskScheduler::updatePtrAabb(const std::shared_ptr<PtrHolder>& ptr)
|
||||
{
|
||||
std::scoped_lock lock(mCollisionWorldMutex);
|
||||
if (const auto actor = std::dynamic_pointer_cast<Actor>(p))
|
||||
if (const auto actor = std::dynamic_pointer_cast<Actor>(ptr))
|
||||
{
|
||||
actor->updateCollisionObjectPosition();
|
||||
mCollisionWorld->updateSingleAabb(actor->getCollisionObject());
|
||||
}
|
||||
else if (const auto object = std::dynamic_pointer_cast<Object>(p))
|
||||
else if (const auto object = std::dynamic_pointer_cast<Object>(ptr))
|
||||
{
|
||||
object->commitPositionChange();
|
||||
mCollisionWorld->updateSingleAabb(object->getCollisionObject());
|
||||
}
|
||||
else if (const auto projectile = std::dynamic_pointer_cast<Projectile>(p))
|
||||
else if (const auto projectile = std::dynamic_pointer_cast<Projectile>(ptr))
|
||||
{
|
||||
projectile->commitPositionChange();
|
||||
mCollisionWorld->updateSingleAabb(projectile->getCollisionObject());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void PhysicsTaskScheduler::worker()
|
||||
|
@ -451,25 +440,19 @@ namespace MWPhysics
|
|||
|
||||
int job = 0;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
mPostStepBarrier->wait([this] { afterPostStep(); });
|
||||
|
||||
if (!mRemainingSteps)
|
||||
{
|
||||
while ((job = mNextJob.fetch_add(1, std::memory_order_relaxed)) < mNumJobs)
|
||||
{
|
||||
if(const auto actor = mActors[job].lock())
|
||||
{
|
||||
handleFall(mActorsFrameData[job], mAdvanceSimulation);
|
||||
}
|
||||
}
|
||||
|
||||
refreshLOSCache();
|
||||
mPostSimBarrier->wait([this] { afterPostSim(); });
|
||||
|
@ -481,15 +464,12 @@ namespace MWPhysics
|
|||
{
|
||||
for (size_t i = 0; i < mActors.size(); ++i)
|
||||
{
|
||||
if(const auto actor = mActors[i].lock())
|
||||
{
|
||||
if (actor->setPosition(mActorsFrameData[i].mPosition))
|
||||
if (mActors[i]->setPosition(mActorsFrameData[i].mPosition))
|
||||
{
|
||||
std::scoped_lock lock(mCollisionWorldMutex);
|
||||
mActorsFrameData[i].mPosition = actor->getPosition(); // account for potential position change made by script
|
||||
actor->updateCollisionObjectPosition();
|
||||
mCollisionWorld->updateSingleAabb(actor->getCollisionObject());
|
||||
}
|
||||
mActorsFrameData[i].mPosition = mActors[i]->getPosition(); // account for potential position change made by script
|
||||
mActors[i]->updateCollisionObjectPosition();
|
||||
mCollisionWorld->updateSingleAabb(mActors[i]->getCollisionObject());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -545,11 +525,9 @@ namespace MWPhysics
|
|||
|
||||
for (size_t i = 0; i < mActors.size(); ++i)
|
||||
{
|
||||
auto actor = mActors[i].lock();
|
||||
assert(actor);
|
||||
handleFall(mActorsFrameData[i], mAdvanceSimulation);
|
||||
updateMechanics(*actor, mActorsFrameData[i]);
|
||||
updateActor(*actor, mActorsFrameData[i], mAdvanceSimulation, mTimeAccum, mPhysicsDt);
|
||||
updateMechanics(*mActors[i], mActorsFrameData[i]);
|
||||
updateActor(*mActors[i], mActorsFrameData[i], mAdvanceSimulation, mTimeAccum, mPhysicsDt);
|
||||
}
|
||||
refreshLOSCache();
|
||||
}
|
||||
|
@ -583,20 +561,24 @@ namespace MWPhysics
|
|||
return (*it)->getUserPointer();
|
||||
}
|
||||
|
||||
void PhysicsTaskScheduler::releaseSharedStates()
|
||||
{
|
||||
std::scoped_lock lock(mSimulationMutex, mUpdateAabbMutex);
|
||||
mActors.clear();
|
||||
mUpdateAabb.clear();
|
||||
}
|
||||
|
||||
void PhysicsTaskScheduler::afterPreStep()
|
||||
{
|
||||
updateAabbs();
|
||||
if (!mRemainingSteps)
|
||||
return;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsTaskScheduler::afterPostStep()
|
||||
{
|
||||
|
|
|
@ -39,7 +39,7 @@ 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
|
||||
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);
|
||||
|
||||
|
@ -53,11 +53,13 @@ namespace MWPhysics
|
|||
void setCollisionFilterMask(btCollisionObject* collisionObject, int collisionFilterMask);
|
||||
void addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask);
|
||||
void removeCollisionObject(btCollisionObject* collisionObject);
|
||||
void updateSingleAabb(std::weak_ptr<PtrHolder> ptr, bool immediate=false);
|
||||
bool getLineOfSight(const std::weak_ptr<Actor>& actor1, const std::weak_ptr<Actor>& actor2);
|
||||
void updateSingleAabb(std::shared_ptr<PtrHolder> ptr, bool immediate=false);
|
||||
bool getLineOfSight(const std::shared_ptr<Actor>& actor1, const std::shared_ptr<Actor>& actor2);
|
||||
void debugDraw();
|
||||
void* getUserPointer(const btCollisionObject* object) const;
|
||||
|
||||
void releaseSharedStates(); // destroy all objects whose destructor can't be safely called from ~PhysicsTaskScheduler()
|
||||
|
||||
private:
|
||||
void syncComputation();
|
||||
void worker();
|
||||
|
@ -66,7 +68,7 @@ namespace MWPhysics
|
|||
bool hasLineOfSight(const Actor* actor1, const Actor* actor2);
|
||||
void refreshLOSCache();
|
||||
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);
|
||||
std::tuple<int, float> calculateStepConfig(float timeAccum) const;
|
||||
void afterPreStep();
|
||||
|
@ -74,7 +76,7 @@ namespace MWPhysics
|
|||
void afterPostSim();
|
||||
|
||||
std::unique_ptr<WorldFrameData> mWorldFrameData;
|
||||
std::vector<std::weak_ptr<Actor>> mActors;
|
||||
std::vector<std::shared_ptr<Actor>> mActors;
|
||||
std::vector<ActorFrameData> mActorsFrameData;
|
||||
std::unordered_set<const btCollisionObject*> mCollisionObjects;
|
||||
float mDefaultPhysicsDt;
|
||||
|
@ -83,7 +85,7 @@ namespace MWPhysics
|
|||
btCollisionWorld* mCollisionWorld;
|
||||
MWRender::DebugDrawer* mDebugDrawer;
|
||||
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
|
||||
std::unique_ptr<Misc::Barrier> mPreStepBarrier;
|
||||
|
|
|
@ -153,6 +153,7 @@ namespace MWPhysics
|
|||
if (mWaterCollisionObject)
|
||||
mTaskScheduler->removeCollisionObject(mWaterCollisionObject.get());
|
||||
|
||||
mTaskScheduler->releaseSharedStates();
|
||||
mHeightFields.clear();
|
||||
mObjects.clear();
|
||||
mActors.clear();
|
||||
|
@ -373,15 +374,12 @@ namespace MWPhysics
|
|||
|
||||
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 found = mActors.find(ptr);
|
||||
if (found != mActors.end())
|
||||
return { found->second };
|
||||
return {};
|
||||
};
|
||||
const auto it1 = mActors.find(actor1);
|
||||
const auto it2 = mActors.find(actor2);
|
||||
if (it1 == mActors.end() || it2 == mActors.end())
|
||||
return false;
|
||||
|
||||
return mTaskScheduler->getLineOfSight(getWeakPtr(actor1), getWeakPtr(actor2));
|
||||
return mTaskScheduler->getLineOfSight(it1->second, it2->second);
|
||||
}
|
||||
|
||||
bool PhysicsSystem::isOnGround(const MWWorld::Ptr &actor)
|
||||
|
@ -769,9 +767,9 @@ namespace MWPhysics
|
|||
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.second.reserve(mActors.size());
|
||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
|
|
|
@ -259,7 +259,7 @@ namespace MWPhysics
|
|||
|
||||
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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue