Refactor a bit the physics simulation to make it not actor centric:

- inline PhysicsSystem::applyQueuedMovements() into PhysicsSystem::stepSimulation()
- rename PhysicsTaskScheduler::moveActors() to PhysicsTaskScheduler::applyQueuedMovements()
- move the actor movement code from World::doPhysics() to
  PhysicsSystem::moveActors() (analogically to the projectile manager)
cherry-pick-2bee171c
fredzio 3 years ago
parent ca011927f3
commit 35928cf4d3

@ -230,7 +230,7 @@ namespace MWPhysics
return std::make_tuple(numSteps, actualDelta);
}
const std::vector<MWWorld::Ptr>& PhysicsTaskScheduler::moveActors(float & timeAccum, std::vector<ActorFrameData>&& actorsData, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats)
void PhysicsTaskScheduler::applyQueuedMovements(float & timeAccum, 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.
@ -239,8 +239,6 @@ namespace MWPhysics
double timeStart = mTimer->tick();
mMovedActors.clear();
// start by finishing previous background computation
if (mNumThreads != 0)
{
@ -260,7 +258,6 @@ namespace MWPhysics
if (mAdvanceSimulation)
data.mActorRaw->setStandingOnPtr(data.mStandingOn);
data.mActorRaw->setSimulationPosition(interpolateMovements(data, mTimeAccum, mPhysicsDt));
mMovedActors.emplace_back(data.mActorRaw->getPtr());
}
}
if(mAdvanceSimulation)
@ -296,7 +293,7 @@ namespace MWPhysics
syncComputation();
if(mAdvanceSimulation)
mBudget.update(mTimer->delta_s(timeStart, mTimer->tick()), numSteps, mBudgetCursor);
return mMovedActors;
return;
}
mAsyncStartTime = mTimer->tick();
@ -304,23 +301,19 @@ namespace MWPhysics
mHasJob.notify_all();
if (mAdvanceSimulation)
mBudget.update(mTimer->delta_s(timeStart, mTimer->tick()), 1, mBudgetCursor);
return mMovedActors;
}
const std::vector<MWWorld::Ptr>& PhysicsTaskScheduler::resetSimulation(const ActorMap& actors)
void PhysicsTaskScheduler::resetSimulation(const ActorMap& actors)
{
std::unique_lock lock(mSimulationMutex);
mBudget.reset(mDefaultPhysicsDt);
mAsyncBudget.reset(0.0f);
mMovedActors.clear();
mActorsFrameData.clear();
for (const auto& [_, actor] : actors)
{
actor->updatePosition();
actor->updateCollisionObjectPosition();
mMovedActors.emplace_back(actor->getPtr());
}
return mMovedActors;
}
void PhysicsTaskScheduler::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const
@ -561,7 +554,6 @@ namespace MWPhysics
handleFall(actorData, mAdvanceSimulation);
actorData.mActorRaw->setSimulationPosition(interpolateMovements(actorData, mTimeAccum, mPhysicsDt));
updateMechanics(actorData);
mMovedActors.emplace_back(actorData.mActorRaw->getPtr());
if (mAdvanceSimulation)
actorData.mActorRaw->setStandingOnPtr(actorData.mStandingOn);
}

@ -38,9 +38,9 @@ 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 std::vector<MWWorld::Ptr>& moveActors(float & timeAccum, std::vector<ActorFrameData>&& actorsData, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats);
void applyQueuedMovements(float & timeAccum, std::vector<ActorFrameData>&& actorsData, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats);
const std::vector<MWWorld::Ptr>& resetSimulation(const ActorMap& actors);
void resetSimulation(const ActorMap& actors);
// Thread safe wrappers
void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const;
@ -72,7 +72,6 @@ namespace MWPhysics
std::unique_ptr<WorldFrameData> mWorldFrameData;
std::vector<ActorFrameData> mActorsFrameData;
std::vector<MWWorld::Ptr> mMovedActors;
float mDefaultPhysicsDt;
float mPhysicsDt;
float mTimeAccum;

@ -751,17 +751,6 @@ namespace MWPhysics
actor->setVelocity(osg::Vec3f());
}
const std::vector<MWWorld::Ptr>& PhysicsSystem::applyQueuedMovement(float dt, bool skipSimulation, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats)
{
mTimeAccum += dt;
if (skipSimulation)
return mTaskScheduler->resetSimulation(mActors);
// modifies mTimeAccum
return mTaskScheduler->moveActors(mTimeAccum, prepareFrameData(mTimeAccum >= mPhysicsDt), frameStart, frameNumber, stats);
}
std::vector<ActorFrameData> PhysicsSystem::prepareFrameData(bool willSimulate)
{
std::vector<ActorFrameData> actorsFrameData;
@ -798,20 +787,43 @@ namespace MWPhysics
return actorsFrameData;
}
void PhysicsSystem::stepSimulation()
void PhysicsSystem::stepSimulation(float dt, bool skipSimulation, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats)
{
for (Object* animatedObject : mAnimatedObjects)
{
if (animatedObject->animateCollisionShapes())
{
auto obj = mObjects.find(animatedObject->getPtr());
assert(obj != mObjects.end());
mTaskScheduler->updateSingleAabb(obj->second);
}
}
#ifndef BT_NO_PROFILE
CProfileManager::Reset();
CProfileManager::Increment_Frame_Counter();
#endif
mTimeAccum += dt;
if (skipSimulation)
mTaskScheduler->resetSimulation(mActors);
else
// modifies mTimeAccum
mTaskScheduler->applyQueuedMovements(mTimeAccum, prepareFrameData(mTimeAccum >= mPhysicsDt), frameStart, frameNumber, stats);
}
void PhysicsSystem::moveActors()
{
auto* player = getActor(MWMechanics::getPlayer());
auto* world = MWBase::Environment::get().getWorld();
for (auto& [ptr, physicActor] : mActors)
{
if (physicActor.get() == player)
continue;
world->moveObject(physicActor->getPtr(), physicActor->getSimulationPosition(), false, false);
}
world->moveObject(player->getPtr(), player->getSimulationPosition(), false, false);
}
void PhysicsSystem::updateAnimatedCollisionShape(const MWWorld::Ptr& object)

@ -154,7 +154,11 @@ namespace MWPhysics
bool toggleCollisionMode();
void stepSimulation();
/// Determine new position based on all queued movements, then clear the list.
void stepSimulation(float dt, bool skipSimulation, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats);
/// Apply new positions to actors
void moveActors();
void debugDraw();
std::vector<MWWorld::Ptr> getCollisions(const MWWorld::ConstPtr &ptr, int collisionGroup, int collisionMask) const; ///< get handles this object collides with
@ -204,12 +208,9 @@ namespace MWPhysics
osg::BoundingBox getBoundingBox(const MWWorld::ConstPtr &object) const;
/// Queues velocity movement for a Ptr. If a Ptr is already queued, its velocity will
/// be overwritten. Valid until the next call to applyQueuedMovement.
/// be overwritten. Valid until the next call to stepSimulation
void queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity);
/// Apply all queued movements, then clear the list.
const std::vector<MWWorld::Ptr>& applyQueuedMovement(float dt, bool skipSimulation, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats);
/// Clear the queued movements list without applying.
void clearQueuedMovement();

@ -1508,35 +1508,12 @@ namespace MWWorld
void World::doPhysics(float duration, osg::Timer_t frameStart, unsigned int frameNumber, osg::Stats& stats)
{
mPhysics->stepSimulation();
processDoors(duration);
mProjectileManager->update(duration);
const auto& results = mPhysics->applyQueuedMovement(duration, mDiscardMovements, frameStart, frameNumber, stats);
mPhysics->stepSimulation(duration, mDiscardMovements, frameStart, frameNumber, stats);
mProjectileManager->processHits();
mDiscardMovements = false;
for(const auto& actor : results)
{
// Handle player last, in case a cell transition occurs
if(actor != getPlayerPtr())
{
auto* physactor = mPhysics->getActor(actor);
assert(physactor);
const auto position = physactor->getSimulationPosition();
moveObject(actor, position, false, false);
}
}
const auto player = std::find(results.begin(), results.end(), getPlayerPtr());
if (player != results.end())
{
auto* physactor = mPhysics->getActor(*player);
assert(physactor);
const auto position = physactor->getSimulationPosition();
moveObject(*player, position, false, false);
}
mPhysics->moveActors();
}
void World::updateNavigator()

Loading…
Cancel
Save