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

@ -87,12 +87,13 @@ namespace
void updateMechanics(MWPhysics::ActorFrameData& actorData) void updateMechanics(MWPhysics::ActorFrameData& actorData)
{ {
auto ptr = actorData.mActorRaw->getPtr();
if (actorData.mDidJump) 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) 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) else if (actorData.mFallHeight < 0)
stats.addToFallHeight(-actorData.mFallHeight); stats.addToFallHeight(-actorData.mFallHeight);
} }
@ -218,8 +219,13 @@ namespace MWPhysics
{ {
for (auto& data : mActorsFrameData) 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 // 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); updateMechanics(data);

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

@ -78,11 +78,10 @@ namespace MWPhysics
struct ActorFrameData 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(); void updatePosition();
std::weak_ptr<Actor> mActor; std::weak_ptr<Actor> mActor;
Actor* mActorRaw; Actor* mActorRaw;
MWWorld::Ptr mPtr;
MWWorld::Ptr mStandingOn; MWWorld::Ptr mStandingOn;
bool mFlying; bool mFlying;
bool mSwimming; bool mSwimming;

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

Loading…
Cancel
Save