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)
: mCanWaterWalk(false), mWalkingOnWater(false)
: mStandingOnPtr(nullptr), mCanWaterWalk(false), mWalkingOnWater(false)
, mCollisionObject(nullptr), mMeshTranslation(shape->mCollisionBoxTranslate), mHalfExtents(shape->mCollisionBoxHalfExtents)
, mForce(0.f, 0.f, 0.f), mOnGround(true), mOnSlope(false)
, 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);
bool isWalkingOnWater() const;
MWWorld::Ptr getStandingOnPtr() const;
void setStandingOnPtr(const MWWorld::Ptr& ptr);
private:
MWWorld::Ptr mStandingOnPtr;
/// Removes then re-adds the collision object to the dynamics world
void updateCollisionMask();
void addCollisionMask(int collisionMask);

@ -82,14 +82,6 @@ namespace
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)
{
if (actorData.mDidJump)
@ -215,7 +207,7 @@ namespace MWPhysics
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.
// While the mSimulationMutex is held, background physics threads can't run.
@ -225,9 +217,6 @@ namespace MWPhysics
// start by finishing previous background computation
if (mNumThreads != 0)
{
if (mAdvanceSimulation)
standingCollisions.clear();
for (auto& data : mActorsFrameData)
{
// Ignore actors that were deleted while the background thread was running
@ -236,7 +225,7 @@ namespace MWPhysics
updateMechanics(data);
if (mAdvanceSimulation)
updateStandingCollision(data, standingCollisions);
data.mActorRaw->setStandingOnPtr(data.mStandingOn);
if (mMovementResults.find(data.mPtr) != mMovementResults.end())
data.mActorRaw->setNextPosition(mMovementResults[data.mPtr]);
@ -260,10 +249,10 @@ namespace MWPhysics
// just return the actors' reference position without applying the movements
if (skipSimulation)
{
standingCollisions.clear();
mMovementResults.clear();
for (const auto& m : mActorsFrameData)
{
m.mActorRaw->setStandingOnPtr(nullptr);
m.mActorRaw->setPosition(m.mActorRaw->getWorldPosition(), true);
mMovementResults[m.mPtr] = m.mActorRaw->getWorldPosition();
}
@ -275,14 +264,10 @@ namespace MWPhysics
mMovementResults.clear();
syncComputation();
if (mAdvanceSimulation)
{
standingCollisions.clear();
for (auto& data : mActorsFrameData)
updateStandingCollision(data, standingCollisions);
}
for (auto& data : mActorsFrameData)
{
if (mAdvanceSimulation)
data.mActorRaw->setStandingOnPtr(data.mStandingOn);
if (mMovementResults.find(data.mPtr) != mMovementResults.end())
data.mActorRaw->setNextPosition(mMovementResults[data.mPtr]);
}

@ -30,7 +30,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
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
void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const;

@ -148,11 +148,11 @@ namespace MWPhysics
if (!physactor || !physactor->getOnGround())
return false;
CollisionMap::const_iterator found = mStandingCollisions.find(actor);
if (found == mStandingCollisions.end())
const auto obj = physactor->getStandingOnPtr();
if (obj.isEmpty())
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())
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)
{
ObjectMap::iterator found = mObjects.find(old);
@ -537,7 +521,11 @@ namespace MWPhysics
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)
@ -675,7 +663,6 @@ namespace MWPhysics
void PhysicsSystem::clearQueuedMovement()
{
mMovementQueue.clear();
mStandingCollisions.clear();
}
const PtrPositionList& PhysicsSystem::applyQueuedMovement(float dt, bool skipSimulation)
@ -688,7 +675,7 @@ namespace MWPhysics
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)
@ -700,10 +687,8 @@ namespace MWPhysics
{
const auto foundActor = mActors.find(character);
if (foundActor == mActors.end()) // actor was already removed from the scene
{
mStandingCollisions.erase(character);
continue;
}
auto physicActor = foundActor->second;
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.
MWWorld::Ptr standingOn;
if (numSteps == 0)
standingOn = mStandingCollisions[character];
standingOn = physicActor->getStandingOnPtr();
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
{
for (const auto& standingActor : mStandingCollisions)
{
if (standingActor.first == actor && standingActor.second == object)
return true;
}
const auto physActor = mActors.find(actor);
if (physActor != mActors.end())
return physActor->second->getStandingOnPtr() == object;
return false;
}
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)
out.push_back(standingActor.first);
if (actor->getStandingOnPtr() == object)
out.emplace_back(actor->getPtr());
}
}

@ -50,7 +50,6 @@ class btVector3;
namespace MWPhysics
{
using PtrPositionList = std::map<MWWorld::Ptr, osg::Vec3f>;
using CollisionMap = std::map<MWWorld::Ptr, MWWorld::Ptr>;
class HeightField;
class Object;
@ -272,13 +271,6 @@ namespace MWPhysics
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>>;
PtrVelocityList mMovementQueue;

Loading…
Cancel
Save