1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-01 04:45:36 +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); 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. // 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.
@ -234,12 +234,12 @@ namespace MWPhysics
// start by finishing previous background computation // start by finishing previous background computation
if (mNumThreads != 0) 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); updateMechanics(*actor, mActorsFrameData[i]);
updateActor(*actor, data, mAdvanceSimulation, mTimeAccum, mPhysicsDt); updateActor(*actor, mActorsFrameData[i], mAdvanceSimulation, mTimeAccum, mPhysicsDt);
} }
} }
if(mAdvanceSimulation) if(mAdvanceSimulation)
@ -251,15 +251,16 @@ namespace MWPhysics
timeAccum -= numSteps*newDelta; timeAccum -= numSteps*newDelta;
// init // init
for (auto& data : actorsData) for (size_t i = 0; i < actors.size(); ++i)
{ {
assert(data.mActor.lock()); assert(actors[i].lock());
data.updatePosition(*data.mActor.lock(), mCollisionWorld); actorsData[i].updatePosition(*actors[i].lock(), mCollisionWorld);
} }
mPrevStepCount = numSteps; mPrevStepCount = numSteps;
mRemainingSteps = numSteps; mRemainingSteps = numSteps;
mTimeAccum = timeAccum; mTimeAccum = timeAccum;
mPhysicsDt = newDelta; mPhysicsDt = newDelta;
mActors = std::move(actors);
mActorsFrameData = std::move(actorsData); mActorsFrameData = std::move(actorsData);
mAdvanceSimulation = (mRemainingSteps != 0); mAdvanceSimulation = (mRemainingSteps != 0);
mNewFrame = true; mNewFrame = true;
@ -463,7 +464,7 @@ 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 = mActorsFrameData[job].mActor.lock()) if(const auto actor = mActors[job].lock())
{ {
MaybeSharedLock lockColWorld(mCollisionWorldMutex, mThreadSafeBullet); MaybeSharedLock lockColWorld(mCollisionWorldMutex, mThreadSafeBullet);
MovementSolver::move(mActorsFrameData[job], mPhysicsDt, mCollisionWorld, *mWorldFrameData); MovementSolver::move(mActorsFrameData[job], mPhysicsDt, mCollisionWorld, *mWorldFrameData);
@ -476,10 +477,9 @@ 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 = mActorsFrameData[job].mActor.lock()) if(const auto actor = mActors[job].lock())
{ {
auto& actorData = mActorsFrameData[job]; handleFall(mActorsFrameData[job], mAdvanceSimulation);
handleFall(actorData, mAdvanceSimulation);
} }
} }
@ -491,14 +491,14 @@ namespace MWPhysics
void PhysicsTaskScheduler::updateActorsPositions() 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); 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(); actor->updateCollisionObjectPosition();
mCollisionWorld->updateSingleAabb(actor->getCollisionObject()); mCollisionWorld->updateSingleAabb(actor->getCollisionObject());
} }
@ -534,13 +534,13 @@ namespace MWPhysics
updateActorsPositions(); 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); assert(actor);
handleFall(actorData, mAdvanceSimulation); handleFall(mActorsFrameData[i], mAdvanceSimulation);
updateMechanics(*actor, actorData); updateMechanics(*actor, mActorsFrameData[i]);
updateActor(*actor, actorData, mAdvanceSimulation, mTimeAccum, mPhysicsDt); updateActor(*actor, mActorsFrameData[i], mAdvanceSimulation, mTimeAccum, mPhysicsDt);
} }
refreshLOSCache(); refreshLOSCache();
} }
@ -571,11 +571,13 @@ namespace MWPhysics
updateAabbs(); updateAabbs();
if (!mRemainingSteps) if (!mRemainingSteps)
return; return;
for (auto& data : mActorsFrameData) for (size_t i = 0; i < mActors.size(); ++i)
if (const auto actor = data.mActor.lock()) {
if (auto actor = mActors[i].lock())
{ {
std::unique_lock lock(mCollisionWorldMutex); std::unique_lock lock(mCollisionWorldMutex);
MovementSolver::unstuck(data, mCollisionWorld); MovementSolver::unstuck(mActorsFrameData[i], mCollisionWorld);
}
} }
} }

View file

@ -38,7 +38,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<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); void resetSimulation(const ActorMap& actors);
@ -71,6 +71,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<ActorFrameData> mActorsFrameData; std::vector<ActorFrameData> mActorsFrameData;
float mDefaultPhysicsDt; float mDefaultPhysicsDt;
float mPhysicsDt; float mPhysicsDt;

View file

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

View file

@ -78,9 +78,8 @@ namespace MWPhysics
struct ActorFrameData 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); void updatePosition(Actor& actor, btCollisionWorld* world);
std::weak_ptr<Actor> mActor;
btCollisionObject* mCollisionObject; btCollisionObject* mCollisionObject;
MWWorld::Ptr mStandingOn; MWWorld::Ptr mStandingOn;
bool mFlying; bool mFlying;
@ -260,7 +259,7 @@ namespace MWPhysics
void updateWater(); 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; osg::ref_ptr<SceneUtil::UnrefQueue> mUnrefQueue;