mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-27 12:35:46 +00:00
Merge remote-tracking branch 'dteviot/PathfindingRefactorDraft'
This commit is contained in:
commit
dc72b24f4e
@ -82,7 +82,7 @@ add_openmw_dir (mwmechanics
|
||||
drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor
|
||||
aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting
|
||||
disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction actor summoning
|
||||
character actors objects aistate
|
||||
character actors objects aistate coordinateconverter
|
||||
)
|
||||
|
||||
add_openmw_dir (mwstate
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "creaturestats.hpp"
|
||||
#include "steering.hpp"
|
||||
#include "movement.hpp"
|
||||
#include "coordinateconverter.hpp"
|
||||
|
||||
|
||||
|
||||
@ -587,11 +588,7 @@ namespace MWMechanics
|
||||
|
||||
void AiWander::ToWorldCoordinates(ESM::Pathgrid::Point& point, const ESM::Cell * cell)
|
||||
{
|
||||
if (cell->isExterior())
|
||||
{
|
||||
point.mX += cell->mData.mX * ESM::Land::REAL_SIZE;
|
||||
point.mY += cell->mData.mY * ESM::Land::REAL_SIZE;
|
||||
}
|
||||
CoordinateConverter(cell).ToWorld(point);
|
||||
}
|
||||
|
||||
void AiWander::trimAllowedNodes(std::vector<ESM::Pathgrid::Point>& nodes,
|
||||
@ -749,11 +746,7 @@ namespace MWMechanics
|
||||
{
|
||||
// get NPC's position in local (i.e. cell) co-ordinates
|
||||
osg::Vec3f npcPos(mInitialActorPosition);
|
||||
if(cell->isExterior())
|
||||
{
|
||||
npcPos[0] = npcPos[0] - static_cast<float>(cell->mData.mX * ESM::Land::REAL_SIZE);
|
||||
npcPos[1] = npcPos[1] - static_cast<float>(cell->mData.mY * ESM::Land::REAL_SIZE);
|
||||
}
|
||||
CoordinateConverter(cell).ToLocal(npcPos);
|
||||
|
||||
// mAllowedNodes for this actor with pathgrid point indexes based on mDistance
|
||||
// NOTE: mPoints and mAllowedNodes are in local co-ordinates
|
||||
|
43
apps/openmw/mwmechanics/coordinateconverter.cpp
Normal file
43
apps/openmw/mwmechanics/coordinateconverter.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#include "coordinateconverter.hpp"
|
||||
|
||||
#include <components/esm/loadcell.hpp>
|
||||
#include <components/esm/loadland.hpp>
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
CoordinateConverter::CoordinateConverter(const ESM::Cell* cell)
|
||||
: mCellX(0), mCellY(0)
|
||||
{
|
||||
if (cell->isExterior())
|
||||
{
|
||||
mCellX = cell->mData.mX * ESM::Land::REAL_SIZE;
|
||||
mCellY = cell->mData.mY * ESM::Land::REAL_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void CoordinateConverter::ToWorld(ESM::Pathgrid::Point& point)
|
||||
{
|
||||
point.mX += mCellX;
|
||||
point.mY += mCellY;
|
||||
}
|
||||
|
||||
void CoordinateConverter::ToWorld(osg::Vec3f& point)
|
||||
{
|
||||
point.x() += static_cast<float>(mCellX);
|
||||
point.y() += static_cast<float>(mCellY);
|
||||
}
|
||||
|
||||
void CoordinateConverter::ToLocal(osg::Vec3f& point)
|
||||
{
|
||||
point.x() -= static_cast<float>(mCellX);
|
||||
point.y() -= static_cast<float>(mCellY);
|
||||
}
|
||||
|
||||
osg::Vec3f CoordinateConverter::ToLocalVec3(const ESM::Pathgrid::Point& point)
|
||||
{
|
||||
return osg::Vec3f(
|
||||
static_cast<float>(point.mX - mCellX),
|
||||
static_cast<float>(point.mY - mCellY),
|
||||
static_cast<float>(point.mZ));
|
||||
}
|
||||
}
|
37
apps/openmw/mwmechanics/coordinateconverter.hpp
Normal file
37
apps/openmw/mwmechanics/coordinateconverter.hpp
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef GAME_MWMECHANICS_COORDINATECONVERTER_H
|
||||
#define GAME_MWMECHANICS_COORDINATECONVERTER_H
|
||||
|
||||
#include <components/esm/defs.hpp>
|
||||
#include <components/esm/loadpgrd.hpp>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct Cell;
|
||||
}
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
/// \brief convert coordinates between world and local cell
|
||||
class CoordinateConverter
|
||||
{
|
||||
public:
|
||||
CoordinateConverter(const ESM::Cell* cell);
|
||||
|
||||
/// in-place conversion from local to world
|
||||
void ToWorld(ESM::Pathgrid::Point& point);
|
||||
|
||||
/// in-place conversion from local to world
|
||||
void ToWorld(osg::Vec3f& point);
|
||||
|
||||
/// in-place conversion from world to local
|
||||
void ToLocal(osg::Vec3f& point);
|
||||
|
||||
osg::Vec3f ToLocalVec3(const ESM::Pathgrid::Point& point);
|
||||
|
||||
private:
|
||||
int mCellX;
|
||||
int mCellY;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
#include "../mwworld/cellstore.hpp"
|
||||
#include "coordinateconverter.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -25,8 +26,7 @@ namespace
|
||||
//
|
||||
int getClosestPoint(const ESM::Pathgrid* grid, const osg::Vec3f& pos)
|
||||
{
|
||||
if(!grid || grid->mPoints.empty())
|
||||
return -1;
|
||||
assert(grid && !grid->mPoints.empty());
|
||||
|
||||
float distanceBetween = distanceSquared(grid->mPoints[0], pos);
|
||||
int closestIndex = 0;
|
||||
@ -107,11 +107,6 @@ namespace MWMechanics
|
||||
return sqrt(x * x + y * y + z * z);
|
||||
}
|
||||
|
||||
osg::Vec3f ToLocalCoordinates(const ESM::Pathgrid::Point &point, float xCell, float yCell)
|
||||
{
|
||||
return osg::Vec3f(point.mX - xCell, point.mY - yCell, static_cast<float>(point.mZ));
|
||||
}
|
||||
|
||||
PathFinder::PathFinder()
|
||||
: mPathgrid(NULL),
|
||||
mCell(NULL)
|
||||
@ -195,23 +190,17 @@ namespace MWMechanics
|
||||
}
|
||||
|
||||
// NOTE: getClosestPoint expects local co-ordinates
|
||||
float xCell = 0;
|
||||
float yCell = 0;
|
||||
if (mCell->isExterior())
|
||||
{
|
||||
xCell = static_cast<float>(mCell->getCell()->mData.mX * ESM::Land::REAL_SIZE);
|
||||
yCell = static_cast<float>(mCell->getCell()->mData.mY * ESM::Land::REAL_SIZE);
|
||||
}
|
||||
CoordinateConverter converter(mCell->getCell());
|
||||
|
||||
// NOTE: It is possible that getClosestPoint returns a pathgrind point index
|
||||
// that is unreachable in some situations. e.g. actor is standing
|
||||
// outside an area enclosed by walls, but there is a pathgrid
|
||||
// point right behind the wall that is closer than any pathgrid
|
||||
// point outside the wall
|
||||
osg::Vec3f startPointInLocalCoords(ToLocalCoordinates(startPoint, xCell, yCell));
|
||||
osg::Vec3f startPointInLocalCoords(converter.ToLocalVec3(startPoint));
|
||||
int startNode = getClosestPoint(mPathgrid, startPointInLocalCoords);
|
||||
|
||||
osg::Vec3f endPointInLocalCoords(ToLocalCoordinates(endPoint, xCell, yCell));
|
||||
osg::Vec3f endPointInLocalCoords(converter.ToLocalVec3(endPoint));
|
||||
std::pair<int, bool> endNode = getClosestReachablePoint(mPathgrid, cell,
|
||||
endPointInLocalCoords,
|
||||
startNode);
|
||||
@ -223,27 +212,38 @@ namespace MWMechanics
|
||||
// nodes are the same
|
||||
if(startNode == endNode.first)
|
||||
{
|
||||
ESM::Pathgrid::Point temp(mPathgrid->mPoints[startNode]);
|
||||
converter.ToWorld(temp);
|
||||
mPath.push_back(temp);
|
||||
|
||||
mPath.push_back(endPoint);
|
||||
return;
|
||||
}
|
||||
|
||||
mPath = mCell->aStarSearch(startNode, endNode.first);
|
||||
assert(!mPath.empty());
|
||||
|
||||
if(!mPath.empty())
|
||||
// convert supplied path to world co-ordinates
|
||||
for (std::list<ESM::Pathgrid::Point>::iterator iter(mPath.begin()); iter != mPath.end(); ++iter)
|
||||
{
|
||||
// Add the destination (which may be different to the closest
|
||||
// pathgrid point). However only add if endNode was the closest
|
||||
// point to endPoint.
|
||||
//
|
||||
// This logic can fail in the opposite situate, e.g. endPoint may
|
||||
// have been reachable but happened to be very close to an
|
||||
// unreachable pathgrid point.
|
||||
//
|
||||
// The AI routines will have to deal with such situations.
|
||||
if(endNode.second)
|
||||
mPath.push_back(endPoint);
|
||||
converter.ToWorld(*iter);
|
||||
}
|
||||
|
||||
// If endNode found is NOT the closest PathGrid point to the endPoint,
|
||||
// assume endPoint is not reachable from endNode. In which case,
|
||||
// path ends at endNode.
|
||||
//
|
||||
// So only add the destination (which may be different to the closest
|
||||
// pathgrid point) when endNode was the closest point to endPoint.
|
||||
//
|
||||
// This logic can fail in the opposite situate, e.g. endPoint may
|
||||
// have been reachable but happened to be very close to an
|
||||
// unreachable pathgrid point.
|
||||
//
|
||||
// The AI routines will have to deal with such situations.
|
||||
if(endNode.second)
|
||||
mPath.push_back(endPoint);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -312,29 +312,15 @@ namespace MWMechanics
|
||||
if(current != goal)
|
||||
return path; // for some reason couldn't build a path
|
||||
|
||||
// reconstruct path to return, using world co-ordinates
|
||||
int xCell = 0;
|
||||
int yCell = 0;
|
||||
if (mIsExterior)
|
||||
{
|
||||
xCell = mPathgrid->mData.mX * ESM::Land::REAL_SIZE;
|
||||
yCell = mPathgrid->mData.mY * ESM::Land::REAL_SIZE;
|
||||
}
|
||||
|
||||
// reconstruct path to return, using local co-ordinates
|
||||
while(graphParent[current] != -1)
|
||||
{
|
||||
ESM::Pathgrid::Point pt = mPathgrid->mPoints[current];
|
||||
pt.mX += xCell;
|
||||
pt.mY += yCell;
|
||||
path.push_front(pt);
|
||||
path.push_front(mPathgrid->mPoints[current]);
|
||||
current = graphParent[current];
|
||||
}
|
||||
|
||||
// add first node to path explicitly
|
||||
ESM::Pathgrid::Point pt = mPathgrid->mPoints[start];
|
||||
pt.mX += xCell;
|
||||
pt.mY += yCell;
|
||||
path.push_front(pt);
|
||||
path.push_front(mPathgrid->mPoints[start]);
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "../mwworld/cellstore.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
#include "../mwmechanics/pathfinding.hpp"
|
||||
#include "../mwmechanics/coordinateconverter.hpp"
|
||||
|
||||
#include "vismask.hpp"
|
||||
|
||||
@ -207,11 +208,7 @@ void Pathgrid::enableCellPathgrid(const MWWorld::CellStore *store)
|
||||
if (!pathgrid) return;
|
||||
|
||||
osg::Vec3f cellPathGridPos(0, 0, 0);
|
||||
if (store->getCell()->isExterior())
|
||||
{
|
||||
cellPathGridPos.x() = static_cast<float>(store->getCell()->mData.mX * ESM::Land::REAL_SIZE);
|
||||
cellPathGridPos.y() = static_cast<float>(store->getCell()->mData.mY * ESM::Land::REAL_SIZE);
|
||||
}
|
||||
MWMechanics::CoordinateConverter(store->getCell()).ToWorld(cellPathGridPos);
|
||||
|
||||
osg::ref_ptr<osg::PositionAttitudeTransform> cellPathGrid = new osg::PositionAttitudeTransform;
|
||||
cellPathGrid->setPosition(cellPathGridPos);
|
||||
|
Loading…
x
Reference in New Issue
Block a user