1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-10-16 02:16:38 +00:00

Merge branch 'itsgraphingtime' into 'master'

Decouple PathgridGraph generation from cell

See merge request OpenMW/openmw!2914
This commit is contained in:
psi29a 2023-04-10 16:51:16 +00:00
commit c39083ba7e
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 agentBounds = world->getPathfindingAgentBounds(actor);
const auto navigatorFlags = getNavigatorFlags(actor); const auto navigatorFlags = getNavigatorFlags(actor);
const auto areaCosts = getAreaCosts(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, mPathFinder.buildPath(actor, vActorPos, vTargetPos, actor.getCell(), pathGridGraph, agentBounds,
navigatorFlags, areaCosts, storage.mAttackRange, PathType::Full); navigatorFlags, areaCosts, storage.mAttackRange, PathType::Full);
@ -378,7 +379,7 @@ namespace MWMechanics
for (int i = 0; i < static_cast<int>(pathgrid->mPoints.size()); i++) for (int i = 0; i < static_cast<int>(pathgrid->mPoints.size()); i++)
{ {
if (i != closestPointIndex if (i != closestPointIndex
&& getPathGridGraph(storage.mCell).isPointConnected(closestPointIndex, i)) && getPathGridGraph(pathgrid).isPointConnected(closestPointIndex, i))
{ {
points.push_back(pathgrid->mPoints[static_cast<size_t>(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 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); agentBounds, getNavigatorFlags(actor), getAreaCosts(actor), endTolerance, pathType);
mRotateOnTheRunChecks = 3; 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 // static cache is OK for now, pathgrids can never change during runtime
typedef std::map<ESM::RefId, std::unique_ptr<MWMechanics::PathgridGraph>> CacheMap; static std::map<const ESM::Pathgrid*, std::unique_ptr<MWMechanics::PathgridGraph>> cache;
static CacheMap cache; auto found = cache.find(pathgrid);
CacheMap::iterator found = cache.find(id);
if (found == cache.end()) if (found == cache.end())
{ found = cache.emplace(pathgrid, std::make_unique<MWMechanics::PathgridGraph>(*pathgrid)).first;
const ESM::Pathgrid* pathgrid return *found->second.get();
= 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;
} }
bool MWMechanics::AiPackage::shortcutPath(const osg::Vec3f& startPoint, const osg::Vec3f& endPoint, 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); 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; DetourNavigator::Flags getNavigatorFlags(const MWWorld::Ptr& actor) const;

View file

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

View file

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