1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-19 20:53:52 +00:00

Move the weak_ptr<Actor> outside of ActorFrameData.

This commit is contained in:
fredzio 2021-07-23 20:39:26 +02:00
parent f68273c3c0
commit 26d9052b8c
4 changed files with 51 additions and 45 deletions

View file

@ -222,7 +222,7 @@ namespace MWPhysics
return std::make_tuple(numSteps, actualDelta);
}
void PhysicsTaskScheduler::applyQueuedMovements(float & timeAccum, std::vector<ActorFrameData>&& actorsData, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats)
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)
{
// This function run in the main thread.
// While the mSimulationMutex is held, background physics threads can't run.
@ -234,12 +234,12 @@ namespace MWPhysics
// start by finishing previous background computation
if (mNumThreads != 0)
{
for (auto& data : mActorsFrameData)
for (size_t i = 0; i < mActors.size(); ++i)
{
if (auto actor = data.mActor.lock())
if (auto actor = mActors[i].lock())
{
updateMechanics(*actor, data);
updateActor(*actor, data, mAdvanceSimulation, mTimeAccum, mPhysicsDt);
updateMechanics(*actor, mActorsFrameData[i]);
updateActor(*actor, mActorsFrameData[i], mAdvanceSimulation, mTimeAccum, mPhysicsDt);
}
}
if(mAdvanceSimulation)
@ -251,15 +251,16 @@ namespace MWPhysics
timeAccum -= numSteps*newDelta;
// init
for (auto& data : actorsData)
for (size_t i = 0; i < actors.size(); ++i)
{
assert(data.mActor.lock());
data.updatePosition(*data.mActor.lock(), mCollisionWorld);
assert(actors[i].lock());
actorsData[i].updatePosition(*actors[i].lock(), mCollisionWorld);
}
mPrevStepCount = numSteps;
mRemainingSteps = numSteps;
mTimeAccum = timeAccum;
mPhysicsDt = newDelta;
mActors = std::move(actors);
mActorsFrameData = std::move(actorsData);
mAdvanceSimulation = (mRemainingSteps != 0);
mNewFrame = true;
@ -463,7 +464,7 @@ namespace MWPhysics
int job = 0;
while (mRemainingSteps && (job = mNextJob.fetch_add(1, std::memory_order_relaxed)) < mNumJobs)
{
if(const auto actor = mActorsFrameData[job].mActor.lock())
if(const auto actor = mActors[job].lock())
{
MaybeSharedLock lockColWorld(mCollisionWorldMutex, mThreadSafeBullet);
MovementSolver::move(mActorsFrameData[job], mPhysicsDt, mCollisionWorld, *mWorldFrameData);
@ -476,10 +477,9 @@ namespace MWPhysics
{
while ((job = mNextJob.fetch_add(1, std::memory_order_relaxed)) < mNumJobs)
{
if(const auto actor = mActorsFrameData[job].mActor.lock())
if(const auto actor = mActors[job].lock())
{
auto& actorData = mActorsFrameData[job];
handleFall(actorData, mAdvanceSimulation);
handleFall(mActorsFrameData[job], mAdvanceSimulation);
}
}
@ -491,14 +491,14 @@ namespace MWPhysics
void PhysicsTaskScheduler::updateActorsPositions()
{
for (auto& actorData : mActorsFrameData)
for (size_t i = 0; i < mActors.size(); ++i)
{
if(const auto actor = actorData.mActor.lock())
if(const auto actor = mActors[i].lock())
{
if (actor->setPosition(actorData.mPosition))
if (actor->setPosition(mActorsFrameData[i].mPosition))
{
std::scoped_lock lock(mCollisionWorldMutex);
actorData.mPosition = actor->getPosition(); // account for potential position change made by script
mActorsFrameData[i].mPosition = actor->getPosition(); // account for potential position change made by script
actor->updateCollisionObjectPosition();
mCollisionWorld->updateSingleAabb(actor->getCollisionObject());
}
@ -534,13 +534,13 @@ namespace MWPhysics
updateActorsPositions();
}
for (auto& actorData : mActorsFrameData)
for (size_t i = 0; i < mActors.size(); ++i)
{
auto actor = actorData.mActor.lock();
auto actor = mActors[i].lock();
assert(actor);
handleFall(actorData, mAdvanceSimulation);
updateMechanics(*actor, actorData);
updateActor(*actor, actorData, mAdvanceSimulation, mTimeAccum, mPhysicsDt);
handleFall(mActorsFrameData[i], mAdvanceSimulation);
updateMechanics(*actor, mActorsFrameData[i]);
updateActor(*actor, mActorsFrameData[i], mAdvanceSimulation, mTimeAccum, mPhysicsDt);
}
refreshLOSCache();
}
@ -571,12 +571,14 @@ namespace MWPhysics
updateAabbs();
if (!mRemainingSteps)
return;
for (auto& data : mActorsFrameData)
if (const auto actor = data.mActor.lock())
for (size_t i = 0; i < mActors.size(); ++i)
{
if (auto actor = mActors[i].lock())
{
std::unique_lock lock(mCollisionWorldMutex);
MovementSolver::unstuck(data, mCollisionWorld);
MovementSolver::unstuck(mActorsFrameData[i], mCollisionWorld);
}
}
}
void PhysicsTaskScheduler::afterPostStep()

View file

@ -38,7 +38,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<ActorFrameData>&& actorsData, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats);
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 resetSimulation(const ActorMap& actors);
@ -71,6 +71,7 @@ namespace MWPhysics
void afterPostSim();
std::unique_ptr<WorldFrameData> mWorldFrameData;
std::vector<std::weak_ptr<Actor>> mActors;
std::vector<ActorFrameData> mActorsFrameData;
float mDefaultPhysicsDt;
float mPhysicsDt;

View file

@ -781,10 +781,11 @@ namespace MWPhysics
actor->setVelocity(osg::Vec3f());
}
std::vector<ActorFrameData> PhysicsSystem::prepareFrameData(bool willSimulate)
std::pair<std::vector<std::weak_ptr<Actor>>, std::vector<ActorFrameData>> PhysicsSystem::prepareFrameData(bool willSimulate)
{
std::vector<ActorFrameData> actorsFrameData;
actorsFrameData.reserve(mActors.size());
std::pair<std::vector<std::weak_ptr<Actor>>, std::vector<ActorFrameData>> framedata;
framedata.first.reserve(mActors.size());
framedata.second.reserve(mActors.size());
const MWBase::World *world = MWBase::Environment::get().getWorld();
for (const auto& [actor, physicActor] : mActors)
{
@ -815,13 +816,14 @@ namespace MWPhysics
if (!willSimulate)
standingOn = physicActor->getStandingOnPtr();
actorsFrameData.emplace_back(physicActor, standingOn, waterCollision, slowFall, waterlevel);
framedata.first.emplace_back(physicActor);
framedata.second.emplace_back(*physicActor, standingOn, waterCollision, slowFall, waterlevel);
// if the simulation will run, a jump request will be fulfilled. Update mechanics accordingly.
if (willSimulate)
handleJump(ptr);
}
return actorsFrameData;
return framedata;
}
void PhysicsSystem::stepSimulation(float dt, bool skipSimulation, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats)
@ -846,8 +848,11 @@ namespace MWPhysics
if (skipSimulation)
mTaskScheduler->resetSimulation(mActors);
else
{
auto [actors, framedata] = prepareFrameData(mTimeAccum >= mPhysicsDt);
// modifies mTimeAccum
mTaskScheduler->applyQueuedMovements(mTimeAccum, prepareFrameData(mTimeAccum >= mPhysicsDt), frameStart, frameNumber, stats);
mTaskScheduler->applyQueuedMovements(mTimeAccum, std::move(actors), std::move(framedata), frameStart, frameNumber, stats);
}
}
void PhysicsSystem::moveActors()
@ -984,36 +989,35 @@ namespace MWPhysics
mDebugDrawer->addCollision(position, normal);
}
ActorFrameData::ActorFrameData(const std::shared_ptr<Actor>& actor, const MWWorld::Ptr standingOn,
ActorFrameData::ActorFrameData(Actor& actor, const MWWorld::Ptr standingOn,
bool waterCollision, float slowFall, float waterlevel)
: mActor(actor)
, mCollisionObject(actor->getCollisionObject())
: mCollisionObject(actor.getCollisionObject())
, mStandingOn(standingOn)
, mWasOnGround(actor->getOnGround())
, mIsOnGround(actor->getOnGround())
, mIsOnSlope(actor->getOnSlope())
, mWasOnGround(actor.getOnGround())
, mIsOnGround(actor.getOnGround())
, mIsOnSlope(actor.getOnSlope())
, mNeedLand(false)
, mWaterCollision(waterCollision)
, mWalkingOnWater(false)
, mSkipCollisionDetection(actor->skipCollisions() || !actor->getCollisionMode())
, mSkipCollisionDetection(actor.skipCollisions() || !actor.getCollisionMode())
, mWaterlevel(waterlevel)
, mSlowFall(slowFall)
, mOldHeight(0)
, mFallHeight(0)
, mHalfExtentsZ(actor->getHalfExtents().z())
, mMovement(actor->velocity())
, mHalfExtentsZ(actor.getHalfExtents().z())
, mMovement(actor.velocity())
, mPosition()
, mRotation()
{
const MWBase::World *world = MWBase::Environment::get().getWorld();
const auto ptr = actor->getPtr();
const auto ptr = actor.getPtr();
mFlying = world->isFlying(ptr);
mIsAquatic = ptr.getClass().isPureWaterCreature(ptr);
const auto& stats = ptr.getClass().getCreatureStats(ptr);
const bool godmode = ptr == world->getPlayerConstPtr() && world->getGodModeState();
mInert = stats.isDead() || (!godmode && stats.getMagicEffects().get(ESM::MagicEffect::Paralyze).getModifier() > 0);
static const float fSwimHeightScale = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fSwimHeightScale")->mValue.getFloat();
mSwimLevel = mWaterlevel - (actor->getRenderingHalfExtents().z() * 2 * fSwimHeightScale);
mSwimLevel = mWaterlevel - (actor.getRenderingHalfExtents().z() * 2 * fSwimHeightScale);
}
void ActorFrameData::updatePosition(Actor& actor, btCollisionWorld* world)

View file

@ -78,9 +78,8 @@ namespace MWPhysics
struct ActorFrameData
{
ActorFrameData(const std::shared_ptr<Actor>& actor, const MWWorld::Ptr standingOn, bool moveToWaterSurface, float slowFall, float waterlevel);
ActorFrameData(Actor& actor, const MWWorld::Ptr standingOn, bool moveToWaterSurface, float slowFall, float waterlevel);
void updatePosition(Actor& actor, btCollisionWorld* world);
std::weak_ptr<Actor> mActor;
btCollisionObject* mCollisionObject;
MWWorld::Ptr mStandingOn;
bool mFlying;
@ -260,7 +259,7 @@ namespace MWPhysics
void updateWater();
std::vector<ActorFrameData> prepareFrameData(bool willSimulate);
std::pair<std::vector<std::weak_ptr<Actor>>, std::vector<ActorFrameData>> prepareFrameData(bool willSimulate);
osg::ref_ptr<SceneUtil::UnrefQueue> mUnrefQueue;