Don't cache Ptr, it can be updated while the simulation is running.

pull/593/head
fredzio 4 years ago
parent a1065c8376
commit 8e084dea2e

@ -78,12 +78,14 @@ namespace MWPhysics
WorldFrameData& worldData)
{
auto* physicActor = actor.mActorRaw;
auto ptr = actor.mPtr;
const ESM::Position& refpos = actor.mRefpos;
// Early-out for totally static creatures
// (Not sure if gravity should still apply?)
if (!ptr.getClass().isMobile(ptr))
return;
{
const auto ptr = physicActor->getPtr();
if (!ptr.getClass().isMobile(ptr))
return;
}
// Reset per-frame data
physicActor->setWalkingOnWater(false);
@ -211,6 +213,7 @@ namespace MWPhysics
if (result)
{
// don't let pure water creatures move out of water after stepMove
const auto ptr = physicActor->getPtr();
if (ptr.getClass().isPureWaterCreature(ptr) && newPosition.z() + halfExtents.z() > actor.mWaterlevel)
newPosition = oldPosition;
}

@ -87,12 +87,13 @@ namespace
void updateMechanics(MWPhysics::ActorFrameData& actorData)
{
auto ptr = actorData.mActorRaw->getPtr();
if (actorData.mDidJump)
handleJump(actorData.mPtr);
handleJump(ptr);
MWMechanics::CreatureStats& stats = actorData.mPtr.getClass().getCreatureStats(actorData.mPtr);
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
if (actorData.mNeedLand)
stats.land(actorData.mPtr == MWMechanics::getPlayer() && (actorData.mFlying || actorData.mSwimming));
stats.land(ptr == MWMechanics::getPlayer() && (actorData.mFlying || actorData.mSwimming));
else if (actorData.mFallHeight < 0)
stats.addToFallHeight(-actorData.mFallHeight);
}
@ -218,8 +219,13 @@ namespace MWPhysics
{
for (auto& data : mActorsFrameData)
{
const auto actorActive = [&data](const auto& newFrameData) -> bool
{
const auto actor = data.mActor.lock();
return actor && actor->getPtr() == newFrameData.mActorRaw->getPtr();
};
// Only return actors that are still part of the scene
if (std::any_of(actorsData.begin(), actorsData.end(), [&data](const auto& newFrameData) { return data.mActorRaw->getPtr() == newFrameData.mActorRaw->getPtr(); }))
if (std::any_of(actorsData.begin(), actorsData.end(), actorActive))
{
updateMechanics(data);

@ -783,7 +783,7 @@ namespace MWPhysics
if (numSteps == 0)
standingOn = physicActor->getStandingOnPtr();
actorsFrameData.emplace_back(std::move(physicActor), character, standingOn, moveToWaterSurface, movement, slowFall, waterlevel);
actorsFrameData.emplace_back(std::move(physicActor), standingOn, moveToWaterSurface, movement, slowFall, waterlevel);
}
mMovementQueue.clear();
return actorsFrameData;
@ -925,18 +925,18 @@ namespace MWPhysics
mDebugDrawer->addCollision(position, normal);
}
ActorFrameData::ActorFrameData(const std::shared_ptr<Actor>& actor, const MWWorld::Ptr character, const MWWorld::Ptr standingOn,
ActorFrameData::ActorFrameData(const std::shared_ptr<Actor>& actor, const MWWorld::Ptr standingOn,
bool moveToWaterSurface, osg::Vec3f movement, float slowFall, float waterlevel)
: mActor(actor), mActorRaw(actor.get()), mStandingOn(standingOn),
mDidJump(false), mNeedLand(false), mMoveToWaterSurface(moveToWaterSurface),
mWaterlevel(waterlevel), mSlowFall(slowFall), mOldHeight(0), mFallHeight(0), mMovement(movement), mPosition(), mRefpos()
{
const MWBase::World *world = MWBase::Environment::get().getWorld();
mPtr = actor->getPtr();
mFlying = world->isFlying(character);
mSwimming = world->isSwimming(character);
mWantJump = mPtr.getClass().getMovementSettings(mPtr).mPosition[2] != 0;
mIsDead = mPtr.getClass().getCreatureStats(mPtr).isDead();
const auto ptr = actor->getPtr();
mFlying = world->isFlying(ptr);
mSwimming = world->isSwimming(ptr);
mWantJump = ptr.getClass().getMovementSettings(ptr).mPosition[2] != 0;
mIsDead = ptr.getClass().getCreatureStats(ptr).isDead();
mWasOnGround = actor->getOnGround();
}
@ -950,7 +950,7 @@ namespace MWPhysics
mActorRaw->setPosition(mPosition);
}
mOldHeight = mPosition.z();
mRefpos = mPtr.getRefData().getPosition();
mRefpos = mActorRaw->getPtr().getRefData().getPosition();
}
WorldFrameData::WorldFrameData()

@ -78,11 +78,10 @@ namespace MWPhysics
struct ActorFrameData
{
ActorFrameData(const std::shared_ptr<Actor>& actor, const MWWorld::Ptr character, const MWWorld::Ptr standingOn, bool moveToWaterSurface, osg::Vec3f movement, float slowFall, float waterlevel);
ActorFrameData(const std::shared_ptr<Actor>& actor, const MWWorld::Ptr standingOn, bool moveToWaterSurface, osg::Vec3f movement, float slowFall, float waterlevel);
void updatePosition();
std::weak_ptr<Actor> mActor;
Actor* mActorRaw;
MWWorld::Ptr mPtr;
MWWorld::Ptr mStandingOn;
bool mFlying;
bool mSwimming;

@ -1,6 +1,8 @@
#ifndef OPENMW_MWPHYSICS_PTRHOLDER_H
#define OPENMW_MWPHYSICS_PTRHOLDER_H
#include <mutex>
#include "../mwworld/ptr.hpp"
namespace MWPhysics
@ -12,21 +14,27 @@ namespace MWPhysics
void updatePtr(const MWWorld::Ptr& updated)
{
std::scoped_lock lock(mMutex);
mPtr = updated;
}
MWWorld::Ptr getPtr()
{
std::scoped_lock lock(mMutex);
return mPtr;
}
MWWorld::ConstPtr getPtr() const
{
std::scoped_lock lock(mMutex);
return mPtr;
}
protected:
MWWorld::Ptr mPtr;
private:
mutable std::mutex mMutex;
};
}

Loading…
Cancel
Save