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:
parent
f68273c3c0
commit
26d9052b8c
4 changed files with 51 additions and 45 deletions
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue