Merge branch 'simplifystanding' into 'master'

Get rid of the StandingActorsMap.

See merge request OpenMW/openmw!409
pull/593/head
psi29a 4 years ago
commit 0a566dbce7

@ -19,7 +19,7 @@ namespace MWPhysics
Actor::Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, PhysicsTaskScheduler* scheduler) Actor::Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, PhysicsTaskScheduler* scheduler)
: mCanWaterWalk(false), mWalkingOnWater(false) : mStandingOnPtr(nullptr), mCanWaterWalk(false), mWalkingOnWater(false)
, mCollisionObject(nullptr), mMeshTranslation(shape->mCollisionBoxTranslate), mHalfExtents(shape->mCollisionBoxHalfExtents) , mCollisionObject(nullptr), mMeshTranslation(shape->mCollisionBoxTranslate), mHalfExtents(shape->mCollisionBoxHalfExtents)
, mForce(0.f, 0.f, 0.f), mOnGround(true), mOnSlope(false) , mForce(0.f, 0.f, 0.f), mOnGround(true), mOnSlope(false)
, mInternalCollisionMode(true) , mInternalCollisionMode(true)
@ -268,4 +268,16 @@ void Actor::setCanWaterWalk(bool waterWalk)
} }
} }
MWWorld::Ptr Actor::getStandingOnPtr() const
{
std::scoped_lock lock(mPositionMutex);
return mStandingOnPtr;
}
void Actor::setStandingOnPtr(const MWWorld::Ptr& ptr)
{
std::scoped_lock lock(mPositionMutex);
mStandingOnPtr = ptr;
}
} }

@ -144,7 +144,11 @@ namespace MWPhysics
void setWalkingOnWater(bool walkingOnWater); void setWalkingOnWater(bool walkingOnWater);
bool isWalkingOnWater() const; bool isWalkingOnWater() const;
MWWorld::Ptr getStandingOnPtr() const;
void setStandingOnPtr(const MWWorld::Ptr& ptr);
private: private:
MWWorld::Ptr mStandingOnPtr;
/// Removes then re-adds the collision object to the dynamics world /// Removes then re-adds the collision object to the dynamics world
void updateCollisionMask(); void updateCollisionMask();
void addCollisionMask(int collisionMask); void addCollisionMask(int collisionMask);

@ -82,14 +82,6 @@ namespace
ptr.getClass().getMovementSettings(ptr).mPosition[2] = 0; ptr.getClass().getMovementSettings(ptr).mPosition[2] = 0;
} }
void updateStandingCollision(MWPhysics::ActorFrameData& actorData, MWPhysics::CollisionMap& standingCollisions)
{
if (!actorData.mStandingOn.isEmpty())
standingCollisions[actorData.mPtr] = actorData.mStandingOn;
else
standingCollisions.erase(actorData.mPtr);
}
void updateMechanics(MWPhysics::ActorFrameData& actorData) void updateMechanics(MWPhysics::ActorFrameData& actorData)
{ {
if (actorData.mDidJump) if (actorData.mDidJump)
@ -215,7 +207,7 @@ namespace MWPhysics
thread.join(); thread.join();
} }
const PtrPositionList& PhysicsTaskScheduler::moveActors(int numSteps, float timeAccum, std::vector<ActorFrameData>&& actorsData, CollisionMap& standingCollisions, bool skipSimulation) const PtrPositionList& PhysicsTaskScheduler::moveActors(int numSteps, float timeAccum, std::vector<ActorFrameData>&& actorsData, bool skipSimulation)
{ {
// 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.
@ -225,9 +217,6 @@ namespace MWPhysics
// start by finishing previous background computation // start by finishing previous background computation
if (mNumThreads != 0) if (mNumThreads != 0)
{ {
if (mAdvanceSimulation)
standingCollisions.clear();
for (auto& data : mActorsFrameData) for (auto& data : mActorsFrameData)
{ {
// Ignore actors that were deleted while the background thread was running // Ignore actors that were deleted while the background thread was running
@ -236,7 +225,7 @@ namespace MWPhysics
updateMechanics(data); updateMechanics(data);
if (mAdvanceSimulation) if (mAdvanceSimulation)
updateStandingCollision(data, standingCollisions); data.mActorRaw->setStandingOnPtr(data.mStandingOn);
if (mMovementResults.find(data.mPtr) != mMovementResults.end()) if (mMovementResults.find(data.mPtr) != mMovementResults.end())
data.mActorRaw->setNextPosition(mMovementResults[data.mPtr]); data.mActorRaw->setNextPosition(mMovementResults[data.mPtr]);
@ -260,10 +249,10 @@ namespace MWPhysics
// just return the actors' reference position without applying the movements // just return the actors' reference position without applying the movements
if (skipSimulation) if (skipSimulation)
{ {
standingCollisions.clear();
mMovementResults.clear(); mMovementResults.clear();
for (const auto& m : mActorsFrameData) for (const auto& m : mActorsFrameData)
{ {
m.mActorRaw->setStandingOnPtr(nullptr);
m.mActorRaw->setPosition(m.mActorRaw->getWorldPosition(), true); m.mActorRaw->setPosition(m.mActorRaw->getWorldPosition(), true);
mMovementResults[m.mPtr] = m.mActorRaw->getWorldPosition(); mMovementResults[m.mPtr] = m.mActorRaw->getWorldPosition();
} }
@ -275,14 +264,10 @@ namespace MWPhysics
mMovementResults.clear(); mMovementResults.clear();
syncComputation(); syncComputation();
if (mAdvanceSimulation)
{
standingCollisions.clear();
for (auto& data : mActorsFrameData)
updateStandingCollision(data, standingCollisions);
}
for (auto& data : mActorsFrameData) for (auto& data : mActorsFrameData)
{ {
if (mAdvanceSimulation)
data.mActorRaw->setStandingOnPtr(data.mStandingOn);
if (mMovementResults.find(data.mPtr) != mMovementResults.end()) if (mMovementResults.find(data.mPtr) != mMovementResults.end())
data.mActorRaw->setNextPosition(mMovementResults[data.mPtr]); data.mActorRaw->setNextPosition(mMovementResults[data.mPtr]);
} }

@ -30,7 +30,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
const PtrPositionList& moveActors(int numSteps, float timeAccum, std::vector<ActorFrameData>&& actorsData, CollisionMap& standingCollisions, bool skip); const PtrPositionList& moveActors(int numSteps, float timeAccum, std::vector<ActorFrameData>&& actorsData, bool skip);
// Thread safe wrappers // Thread safe wrappers
void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const; void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const;

@ -148,11 +148,11 @@ namespace MWPhysics
if (!physactor || !physactor->getOnGround()) if (!physactor || !physactor->getOnGround())
return false; return false;
CollisionMap::const_iterator found = mStandingCollisions.find(actor); const auto obj = physactor->getStandingOnPtr();
if (found == mStandingCollisions.end()) if (obj.isEmpty())
return true; // assume standing on terrain (which is a non-object, so not collision tracked) return true; // assume standing on terrain (which is a non-object, so not collision tracked)
ObjectMap::const_iterator foundObj = mObjects.find(found->second); ObjectMap::const_iterator foundObj = mObjects.find(obj);
if (foundObj == mObjects.end()) if (foundObj == mObjects.end())
return false; return false;
@ -501,22 +501,6 @@ namespace MWPhysics
} }
} }
void PhysicsSystem::updateCollisionMapPtr(CollisionMap& map, const MWWorld::Ptr &old, const MWWorld::Ptr &updated)
{
CollisionMap::iterator found = map.find(old);
if (found != map.end())
{
map[updated] = found->second;
map.erase(found);
}
for (auto& collision : map)
{
if (collision.second == old)
collision.second = updated;
}
}
void PhysicsSystem::updatePtr(const MWWorld::Ptr &old, const MWWorld::Ptr &updated) void PhysicsSystem::updatePtr(const MWWorld::Ptr &old, const MWWorld::Ptr &updated)
{ {
ObjectMap::iterator found = mObjects.find(old); ObjectMap::iterator found = mObjects.find(old);
@ -537,7 +521,11 @@ namespace MWPhysics
mActors.emplace(updated, std::move(actor)); mActors.emplace(updated, std::move(actor));
} }
updateCollisionMapPtr(mStandingCollisions, old, updated); for (auto& [_, actor] : mActors)
{
if (actor->getStandingOnPtr() == old)
actor->setStandingOnPtr(updated);
}
} }
Actor *PhysicsSystem::getActor(const MWWorld::Ptr &ptr) Actor *PhysicsSystem::getActor(const MWWorld::Ptr &ptr)
@ -675,7 +663,6 @@ namespace MWPhysics
void PhysicsSystem::clearQueuedMovement() void PhysicsSystem::clearQueuedMovement()
{ {
mMovementQueue.clear(); mMovementQueue.clear();
mStandingCollisions.clear();
} }
const PtrPositionList& PhysicsSystem::applyQueuedMovement(float dt, bool skipSimulation) const PtrPositionList& PhysicsSystem::applyQueuedMovement(float dt, bool skipSimulation)
@ -688,7 +675,7 @@ namespace MWPhysics
mTimeAccum -= numSteps * mPhysicsDt; mTimeAccum -= numSteps * mPhysicsDt;
return mTaskScheduler->moveActors(numSteps, mTimeAccum, prepareFrameData(numSteps), mStandingCollisions, skipSimulation); return mTaskScheduler->moveActors(numSteps, mTimeAccum, prepareFrameData(numSteps), skipSimulation);
} }
std::vector<ActorFrameData> PhysicsSystem::prepareFrameData(int numSteps) std::vector<ActorFrameData> PhysicsSystem::prepareFrameData(int numSteps)
@ -700,10 +687,8 @@ namespace MWPhysics
{ {
const auto foundActor = mActors.find(character); const auto foundActor = mActors.find(character);
if (foundActor == mActors.end()) // actor was already removed from the scene if (foundActor == mActors.end()) // actor was already removed from the scene
{
mStandingCollisions.erase(character);
continue; continue;
}
auto physicActor = foundActor->second; auto physicActor = foundActor->second;
float waterlevel = -std::numeric_limits<float>::max(); float waterlevel = -std::numeric_limits<float>::max();
@ -734,7 +719,7 @@ namespace MWPhysics
// Ue current value only if we don't advance the simulation. Otherwise we might get a stale value. // Ue current value only if we don't advance the simulation. Otherwise we might get a stale value.
MWWorld::Ptr standingOn; MWWorld::Ptr standingOn;
if (numSteps == 0) if (numSteps == 0)
standingOn = mStandingCollisions[character]; standingOn = physicActor->getStandingOnPtr();
actorsFrameData.emplace_back(std::move(physicActor), character, standingOn, moveToWaterSurface, movement, slowFall, waterlevel); actorsFrameData.emplace_back(std::move(physicActor), character, standingOn, moveToWaterSurface, movement, slowFall, waterlevel);
} }
@ -774,20 +759,18 @@ namespace MWPhysics
bool PhysicsSystem::isActorStandingOn(const MWWorld::Ptr &actor, const MWWorld::ConstPtr &object) const bool PhysicsSystem::isActorStandingOn(const MWWorld::Ptr &actor, const MWWorld::ConstPtr &object) const
{ {
for (const auto& standingActor : mStandingCollisions) const auto physActor = mActors.find(actor);
{ if (physActor != mActors.end())
if (standingActor.first == actor && standingActor.second == object) return physActor->second->getStandingOnPtr() == object;
return true;
}
return false; return false;
} }
void PhysicsSystem::getActorsStandingOn(const MWWorld::ConstPtr &object, std::vector<MWWorld::Ptr> &out) const void PhysicsSystem::getActorsStandingOn(const MWWorld::ConstPtr &object, std::vector<MWWorld::Ptr> &out) const
{ {
for (const auto& standingActor : mStandingCollisions) for (const auto& [_, actor] : mActors)
{ {
if (standingActor.second == object) if (actor->getStandingOnPtr() == object)
out.push_back(standingActor.first); out.emplace_back(actor->getPtr());
} }
} }

@ -50,7 +50,6 @@ class btVector3;
namespace MWPhysics namespace MWPhysics
{ {
using PtrPositionList = std::map<MWWorld::Ptr, osg::Vec3f>; using PtrPositionList = std::map<MWWorld::Ptr, osg::Vec3f>;
using CollisionMap = std::map<MWWorld::Ptr, MWWorld::Ptr>;
class HeightField; class HeightField;
class Object; class Object;
@ -272,13 +271,6 @@ namespace MWPhysics
bool mDebugDrawEnabled; bool mDebugDrawEnabled;
// Tracks standing collisions happening during a single frame. <actor handle, collided handle>
// This will detect standing on an object, but won't detect running e.g. against a wall.
CollisionMap mStandingCollisions;
// replaces all occurrences of 'old' in the map by 'updated', no matter if it's a key or value
void updateCollisionMapPtr(CollisionMap& map, const MWWorld::Ptr &old, const MWWorld::Ptr &updated);
using PtrVelocityList = std::vector<std::pair<MWWorld::Ptr, osg::Vec3f>>; using PtrVelocityList = std::vector<std::pair<MWWorld::Ptr, osg::Vec3f>>;
PtrVelocityList mMovementQueue; PtrVelocityList mMovementQueue;

Loading…
Cancel
Save