1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-20 15:40:32 +00:00

Decouple PathgridGraph generation from cell

This commit is contained in:
Evil Eye 2023-04-10 15:45:58 +02:00
parent cf9d2e0d89
commit 584f112a7b
5 changed files with 27 additions and 30 deletions

View File

@ -283,7 +283,8 @@ namespace MWMechanics
const auto agentBounds = world->getPathfindingAgentBounds(actor);
const auto navigatorFlags = getNavigatorFlags(actor);
const auto areaCosts = getAreaCosts(actor);
const auto pathGridGraph = getPathGridGraph(actor.getCell());
const ESM::Pathgrid* pathgrid = world->getStore().get<ESM::Pathgrid>().search(*actor.getCell()->getCell());
const auto& pathGridGraph = getPathGridGraph(pathgrid);
mPathFinder.buildPath(actor, vActorPos, vTargetPos, actor.getCell(), pathGridGraph, agentBounds,
navigatorFlags, areaCosts, storage.mAttackRange, PathType::Full);
@ -378,7 +379,7 @@ namespace MWMechanics
for (int i = 0; i < static_cast<int>(pathgrid->mPoints.size()); i++)
{
if (i != closestPointIndex
&& getPathGridGraph(storage.mCell).isPointConnected(closestPointIndex, i))
&& getPathGridGraph(pathgrid).isPointConnected(closestPointIndex, i))
{
points.push_back(pathgrid->mPoints[static_cast<size_t>(i)]);
}

View File

@ -154,7 +154,9 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, const osg::Vec3f&
{
if (wasShortcutting || doesPathNeedRecalc(dest, actor)) // if need to rebuild path
{
mPathFinder.buildLimitedPath(actor, position, dest, actor.getCell(), getPathGridGraph(actor.getCell()),
const ESM::Pathgrid* pathgrid
= world->getStore().get<ESM::Pathgrid>().search(*actor.getCell()->getCell());
mPathFinder.buildLimitedPath(actor, position, dest, actor.getCell(), getPathGridGraph(pathgrid),
agentBounds, getNavigatorFlags(actor), getAreaCosts(actor), endTolerance, pathType);
mRotateOnTheRunChecks = 3;
@ -329,26 +331,16 @@ void MWMechanics::AiPackage::openDoors(const MWWorld::Ptr& actor)
}
}
const MWMechanics::PathgridGraph& MWMechanics::AiPackage::getPathGridGraph(const MWWorld::CellStore* cell) const
const MWMechanics::PathgridGraph& MWMechanics::AiPackage::getPathGridGraph(const ESM::Pathgrid* pathgrid) const
{
const ESM::RefId id = cell->getCell()->getId();
if (!pathgrid || pathgrid->mPoints.empty())
return PathgridGraph::sEmpty;
// static cache is OK for now, pathgrids can never change during runtime
typedef std::map<ESM::RefId, std::unique_ptr<MWMechanics::PathgridGraph>> CacheMap;
static CacheMap cache;
CacheMap::iterator found = cache.find(id);
static std::map<const ESM::Pathgrid*, std::unique_ptr<MWMechanics::PathgridGraph>> cache;
auto found = cache.find(pathgrid);
if (found == cache.end())
{
const ESM::Pathgrid* pathgrid
= MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*cell->getCell());
std::unique_ptr<MWMechanics::PathgridGraph> ptr;
if (pathgrid)
ptr = std::make_unique<MWMechanics::PathgridGraph>(MWMechanics::PathgridGraph(*pathgrid));
found = cache.emplace(id, std::move(ptr)).first;
}
const MWMechanics::PathgridGraph* graph = found->second.get();
if (!graph)
return MWMechanics::PathgridGraph::sEmpty;
return *graph;
found = cache.emplace(pathgrid, std::make_unique<MWMechanics::PathgridGraph>(*pathgrid)).first;
return *found->second.get();
}
bool MWMechanics::AiPackage::shortcutPath(const osg::Vec3f& startPoint, const osg::Vec3f& endPoint,

View File

@ -145,7 +145,7 @@ namespace MWMechanics
void openDoors(const MWWorld::Ptr& actor);
const PathgridGraph& getPathGridGraph(const MWWorld::CellStore* cell) const;
const PathgridGraph& getPathGridGraph(const ESM::Pathgrid* pathgrid) const;
DetourNavigator::Flags getNavigatorFlags(const MWWorld::Ptr& actor) const;

View File

@ -210,18 +210,20 @@ namespace MWMechanics
// rebuild a path to it
if (!mPathFinder.isPathConstructed() && mHasDestination)
{
const ESM::Pathgrid* pathgrid
= MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(
*actor.getCell()->getCell());
if (mUsePathgrid)
{
mPathFinder.buildPathByPathgrid(
pos.asVec3(), mDestination, actor.getCell(), getPathGridGraph(actor.getCell()));
pos.asVec3(), mDestination, actor.getCell(), getPathGridGraph(pathgrid));
}
else
{
const auto agentBounds = MWBase::Environment::get().getWorld()->getPathfindingAgentBounds(actor);
constexpr float endTolerance = 0;
mPathFinder.buildPath(actor, pos.asVec3(), mDestination, actor.getCell(),
getPathGridGraph(actor.getCell()), agentBounds, getNavigatorFlags(actor), getAreaCosts(actor),
endTolerance, PathType::Full);
mPathFinder.buildPath(actor, pos.asVec3(), mDestination, actor.getCell(), getPathGridGraph(pathgrid),
agentBounds, getNavigatorFlags(actor), getAreaCosts(actor), endTolerance, PathType::Full);
}
if (mPathFinder.isPathConstructed())
@ -597,15 +599,17 @@ namespace MWMechanics
void AiWander::setPathToAnAllowedNode(
const MWWorld::Ptr& actor, AiWanderStorage& storage, const ESM::Position& actorPos)
{
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
auto world = MWBase::Environment::get().getWorld();
auto& prng = world->getPrng();
unsigned int randNode = Misc::Rng::rollDice(storage.mAllowedNodes.size(), prng);
const ESM::Pathgrid::Point& dest = storage.mAllowedNodes[randNode];
const osg::Vec3f start = actorPos.asVec3();
// don't take shortcuts for wandering
const ESM::Pathgrid* pathgrid = world->getStore().get<ESM::Pathgrid>().search(*actor.getCell()->getCell());
const osg::Vec3f destVec3f = PathFinder::makeOsgVec3(dest);
mPathFinder.buildPathByPathgrid(start, destVec3f, actor.getCell(), getPathGridGraph(actor.getCell()));
mPathFinder.buildPathByPathgrid(start, destVec3f, actor.getCell(), getPathGridGraph(pathgrid));
if (mPathFinder.isPathConstructed())
{
@ -808,7 +812,7 @@ namespace MWMechanics
int index = PathFinder::getClosestPoint(pathgrid, PathFinder::makeOsgVec3(dest));
getPathGridGraph(currentCell).getNeighbouringPoints(index, points);
getPathGridGraph(pathgrid).getNeighbouringPoints(index, points);
}
void AiWander::getAllowedNodes(const MWWorld::Ptr& actor, AiWanderStorage& storage)
@ -849,7 +853,7 @@ namespace MWMechanics
{
osg::Vec3f nodePos(PathFinder::makeOsgVec3(pathgrid->mPoints[counter]));
if ((npcPos - nodePos).length2() <= mDistance * mDistance
&& getPathGridGraph(cellStore).isPointConnected(closestPointIndex, counter))
&& getPathGridGraph(pathgrid).isPointConnected(closestPointIndex, counter))
{
storage.mAllowedNodes.push_back(converter.toWorldPoint(pathgrid->mPoints[counter]));
pointIndex = counter;

View File

@ -36,7 +36,7 @@ namespace
int closestReachableIndex = 0;
// TODO: if this full scan causes performance problems mapping pathgrid
// points to a quadtree may help
for (unsigned int counter = 0; counter < grid->mPoints.size(); counter++)
for (size_t counter = 0; counter < grid->mPoints.size(); counter++)
{
float potentialDistBetween = MWMechanics::PathFinder::distanceSquared(grid->mPoints[counter], pos);
if (potentialDistBetween < closestDistanceReachable)