mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-28 12:40:06 +00:00
Add pathgrid to navmesh as off mesh connection
This commit is contained in:
parent
095a45c714
commit
c4cd3b2c4f
@ -86,7 +86,7 @@ add_openmw_dir (mwmechanics
|
|||||||
drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor aibreathe
|
drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor aibreathe
|
||||||
aicast aiescort aiface aiactivate aicombat recharge repair enchanting pathfinding pathgrid security spellcasting spellresistance
|
aicast aiescort aiface aiactivate aicombat recharge repair enchanting pathfinding pathgrid security spellcasting spellresistance
|
||||||
disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction actor summoning
|
disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction actor summoning
|
||||||
character actors objects aistate coordinateconverter trading weaponpriority spellpriority weapontype spellutil tickableeffects
|
character actors objects aistate trading weaponpriority spellpriority weapontype spellutil tickableeffects
|
||||||
spellabsorption linkedeffects
|
spellabsorption linkedeffects
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "aicombat.hpp"
|
#include "aicombat.hpp"
|
||||||
|
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
#include <components/misc/coordinateconverter.hpp>
|
||||||
|
|
||||||
#include <components/esm/aisequence.hpp>
|
#include <components/esm/aisequence.hpp>
|
||||||
|
|
||||||
@ -21,7 +22,6 @@
|
|||||||
#include "movement.hpp"
|
#include "movement.hpp"
|
||||||
#include "character.hpp"
|
#include "character.hpp"
|
||||||
#include "aicombataction.hpp"
|
#include "aicombataction.hpp"
|
||||||
#include "coordinateconverter.hpp"
|
|
||||||
#include "actorutil.hpp"
|
#include "actorutil.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -302,7 +302,7 @@ namespace MWMechanics
|
|||||||
if (pathgrid && !actor.getClass().isPureWaterCreature(actor))
|
if (pathgrid && !actor.getClass().isPureWaterCreature(actor))
|
||||||
{
|
{
|
||||||
ESM::Pathgrid::PointList points;
|
ESM::Pathgrid::PointList points;
|
||||||
CoordinateConverter coords(storage.mCell->getCell());
|
Misc::CoordinateConverter coords(storage.mCell->getCell());
|
||||||
|
|
||||||
osg::Vec3f localPos = actor.getRefData().getPosition().asVec3();
|
osg::Vec3f localPos = actor.getRefData().getPosition().asVec3();
|
||||||
coords.toLocal(localPos);
|
coords.toLocal(localPos);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <components/esm/loadland.hpp>
|
#include <components/esm/loadland.hpp>
|
||||||
#include <components/esm/loadmgef.hpp>
|
#include <components/esm/loadmgef.hpp>
|
||||||
#include <components/detournavigator/navigator.hpp>
|
#include <components/detournavigator/navigator.hpp>
|
||||||
|
#include <components/misc/coordinateconverter.hpp>
|
||||||
|
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
@ -20,7 +21,6 @@
|
|||||||
#include "movement.hpp"
|
#include "movement.hpp"
|
||||||
#include "steering.hpp"
|
#include "steering.hpp"
|
||||||
#include "actorutil.hpp"
|
#include "actorutil.hpp"
|
||||||
#include "coordinateconverter.hpp"
|
|
||||||
|
|
||||||
#include <osg/Quat>
|
#include <osg/Quat>
|
||||||
|
|
||||||
@ -341,7 +341,7 @@ bool MWMechanics::AiPackage::isNearInactiveCell(osg::Vec3f position)
|
|||||||
if (playerCell->isExterior())
|
if (playerCell->isExterior())
|
||||||
{
|
{
|
||||||
// get actor's distance from origin of center cell
|
// get actor's distance from origin of center cell
|
||||||
CoordinateConverter(playerCell).toLocal(position);
|
Misc::CoordinateConverter(playerCell).toLocal(position);
|
||||||
|
|
||||||
// currently assumes 3 x 3 grid for exterior cells, with player at center cell.
|
// currently assumes 3 x 3 grid for exterior cells, with player at center cell.
|
||||||
// ToDo: (Maybe) use "exterior cell load distance" setting to get count of actual active cells
|
// ToDo: (Maybe) use "exterior cell load distance" setting to get count of actual active cells
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
#include <components/esm/aisequence.hpp>
|
#include <components/esm/aisequence.hpp>
|
||||||
#include <components/detournavigator/navigator.hpp>
|
#include <components/detournavigator/navigator.hpp>
|
||||||
|
#include <components/misc/coordinateconverter.hpp>
|
||||||
|
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
@ -21,7 +22,6 @@
|
|||||||
#include "pathgrid.hpp"
|
#include "pathgrid.hpp"
|
||||||
#include "creaturestats.hpp"
|
#include "creaturestats.hpp"
|
||||||
#include "movement.hpp"
|
#include "movement.hpp"
|
||||||
#include "coordinateconverter.hpp"
|
|
||||||
#include "actorutil.hpp"
|
#include "actorutil.hpp"
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
@ -566,7 +566,7 @@ namespace MWMechanics
|
|||||||
|
|
||||||
void AiWander::ToWorldCoordinates(ESM::Pathgrid::Point& point, const ESM::Cell * cell)
|
void AiWander::ToWorldCoordinates(ESM::Pathgrid::Point& point, const ESM::Cell * cell)
|
||||||
{
|
{
|
||||||
CoordinateConverter(cell).toWorld(point);
|
Misc::CoordinateConverter(cell).toWorld(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AiWander::trimAllowedNodes(std::vector<ESM::Pathgrid::Point>& nodes,
|
void AiWander::trimAllowedNodes(std::vector<ESM::Pathgrid::Point>& nodes,
|
||||||
@ -767,7 +767,7 @@ namespace MWMechanics
|
|||||||
{
|
{
|
||||||
// get NPC's position in local (i.e. cell) coordinates
|
// get NPC's position in local (i.e. cell) coordinates
|
||||||
osg::Vec3f npcPos(mInitialActorPosition);
|
osg::Vec3f npcPos(mInitialActorPosition);
|
||||||
CoordinateConverter(cell).toLocal(npcPos);
|
Misc::CoordinateConverter(cell).toLocal(npcPos);
|
||||||
|
|
||||||
// Find closest pathgrid point
|
// Find closest pathgrid point
|
||||||
int closestPointIndex = PathFinder::getClosestPoint(pathgrid, npcPos);
|
int closestPointIndex = PathFinder::getClosestPoint(pathgrid, npcPos);
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
#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 osg::Vec3f& point)
|
|
||||||
{
|
|
||||||
return osg::Vec3f(
|
|
||||||
point.x() - static_cast<float>(mCellX),
|
|
||||||
point.y() - static_cast<float>(mCellY),
|
|
||||||
point.z()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
#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 osg::Vec3f& point);
|
|
||||||
|
|
||||||
private:
|
|
||||||
int mCellX;
|
|
||||||
int mCellY;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -7,6 +7,7 @@
|
|||||||
#include <components/detournavigator/debug.hpp>
|
#include <components/detournavigator/debug.hpp>
|
||||||
#include <components/detournavigator/navigator.hpp>
|
#include <components/detournavigator/navigator.hpp>
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
|
#include <components/misc/coordinateconverter.hpp>
|
||||||
|
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
@ -17,7 +18,6 @@
|
|||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
#include "pathgrid.hpp"
|
#include "pathgrid.hpp"
|
||||||
#include "coordinateconverter.hpp"
|
|
||||||
#include "actorutil.hpp"
|
#include "actorutil.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -164,7 +164,7 @@ namespace MWMechanics
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: getClosestPoint expects local coordinates
|
// NOTE: getClosestPoint expects local coordinates
|
||||||
CoordinateConverter converter(mCell->getCell());
|
Misc::CoordinateConverter converter(mCell->getCell());
|
||||||
|
|
||||||
// NOTE: It is possible that getClosestPoint returns a pathgrind point index
|
// NOTE: It is possible that getClosestPoint returns a pathgrind point index
|
||||||
// that is unreachable in some situations. e.g. actor is standing
|
// that is unreachable in some situations. e.g. actor is standing
|
||||||
@ -331,6 +331,10 @@ namespace MWMechanics
|
|||||||
if (!actor.getClass().isPureWaterCreature(actor) && !actor.getClass().isPureFlyingCreature(actor))
|
if (!actor.getClass().isPureWaterCreature(actor) && !actor.getClass().isPureFlyingCreature(actor))
|
||||||
buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, std::back_inserter(mPath));
|
buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents, flags, std::back_inserter(mPath));
|
||||||
|
|
||||||
|
if (mPath.empty())
|
||||||
|
buildPathByNavigatorImpl(actor, startPoint, endPoint, halfExtents,
|
||||||
|
flags | DetourNavigator::Flag_usePathgrid, std::back_inserter(mPath));
|
||||||
|
|
||||||
if (mPath.empty())
|
if (mPath.empty())
|
||||||
buildPathByPathgridImpl(startPoint, endPoint, pathgridGraph, std::back_inserter(mPath));
|
buildPathByPathgridImpl(startPoint, endPoint, pathgridGraph, std::back_inserter(mPath));
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <components/esm/loadpgrd.hpp>
|
#include <components/esm/loadpgrd.hpp>
|
||||||
#include <components/sceneutil/pathgridutil.hpp>
|
#include <components/sceneutil/pathgridutil.hpp>
|
||||||
|
#include <components/misc/coordinateconverter.hpp>
|
||||||
|
|
||||||
#include "../mwbase/world.hpp" // these includes can be removed once the static-hack is gone
|
#include "../mwbase/world.hpp" // these includes can be removed once the static-hack is gone
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
@ -15,7 +16,6 @@
|
|||||||
#include "../mwworld/cellstore.hpp"
|
#include "../mwworld/cellstore.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
#include "../mwmechanics/pathfinding.hpp"
|
#include "../mwmechanics/pathfinding.hpp"
|
||||||
#include "../mwmechanics/coordinateconverter.hpp"
|
|
||||||
|
|
||||||
#include "vismask.hpp"
|
#include "vismask.hpp"
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ void Pathgrid::enableCellPathgrid(const MWWorld::CellStore *store)
|
|||||||
if (!pathgrid) return;
|
if (!pathgrid) return;
|
||||||
|
|
||||||
osg::Vec3f cellPathGridPos(0, 0, 0);
|
osg::Vec3f cellPathGridPos(0, 0, 0);
|
||||||
MWMechanics::CoordinateConverter(store->getCell()).toWorld(cellPathGridPos);
|
Misc::CoordinateConverter(store->getCell()).toWorld(cellPathGridPos);
|
||||||
|
|
||||||
osg::ref_ptr<osg::PositionAttitudeTransform> cellPathGrid = new osg::PositionAttitudeTransform;
|
osg::ref_ptr<osg::PositionAttitudeTransform> cellPathGrid = new osg::PositionAttitudeTransform;
|
||||||
cellPathGrid->setPosition(cellPathGridPos);
|
cellPathGrid->setPosition(cellPathGridPos);
|
||||||
|
@ -365,6 +365,9 @@ namespace MWWorld
|
|||||||
if ((*iter)->getCell()->hasWater())
|
if ((*iter)->getCell()->hasWater())
|
||||||
navigator->removeWater(osg::Vec2i(cellX, cellY));
|
navigator->removeWater(osg::Vec2i(cellX, cellY));
|
||||||
|
|
||||||
|
if (const auto pathgrid = world->getStore().get<ESM::Pathgrid>().search(*(*iter)->getCell()))
|
||||||
|
navigator->removePathgrid(*pathgrid);
|
||||||
|
|
||||||
const auto player = world->getPlayerPtr();
|
const auto player = world->getPlayerPtr();
|
||||||
navigator->update(player.getRefData().getPosition().asVec3());
|
navigator->update(player.getRefData().getPosition().asVec3());
|
||||||
|
|
||||||
@ -393,7 +396,8 @@ namespace MWWorld
|
|||||||
float verts = ESM::Land::LAND_SIZE;
|
float verts = ESM::Land::LAND_SIZE;
|
||||||
float worldsize = ESM::Land::REAL_SIZE;
|
float worldsize = ESM::Land::REAL_SIZE;
|
||||||
|
|
||||||
const auto navigator = MWBase::Environment::get().getWorld()->getNavigator();
|
const auto world = MWBase::Environment::get().getWorld();
|
||||||
|
const auto navigator = world->getNavigator();
|
||||||
|
|
||||||
const int cellX = cell->getCell()->getGridX();
|
const int cellX = cell->getCell()->getGridX();
|
||||||
const int cellY = cell->getCell()->getGridY();
|
const int cellY = cell->getCell()->getGridY();
|
||||||
@ -419,6 +423,9 @@ namespace MWWorld
|
|||||||
heightField->getCollisionObject()->getWorldTransform());
|
heightField->getCollisionObject()->getWorldTransform());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (const auto pathgrid = world->getStore().get<ESM::Pathgrid>().search(*cell->getCell()))
|
||||||
|
navigator->addPathgrid(*cell->getCell(), *pathgrid);
|
||||||
|
|
||||||
// register local scripts
|
// register local scripts
|
||||||
// do this before insertCell, to make sure we don't add scripts from levelled creature spawning twice
|
// do this before insertCell, to make sure we don't add scripts from levelled creature spawning twice
|
||||||
MWBase::Environment::get().getWorld()->getLocalScripts().addCell (cell);
|
MWBase::Environment::get().getWorld()->getLocalScripts().addCell (cell);
|
||||||
|
@ -9,6 +9,8 @@ namespace DetourNavigator
|
|||||||
{
|
{
|
||||||
AreaType_null = RC_NULL_AREA,
|
AreaType_null = RC_NULL_AREA,
|
||||||
AreaType_water,
|
AreaType_water,
|
||||||
|
AreaType_door,
|
||||||
|
AreaType_pathgrid,
|
||||||
AreaType_ground = RC_WALKABLE_AREA,
|
AreaType_ground = RC_WALKABLE_AREA,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ namespace DetourNavigator
|
|||||||
Flag_walk = 1 << 0,
|
Flag_walk = 1 << 0,
|
||||||
Flag_swim = 1 << 1,
|
Flag_swim = 1 << 1,
|
||||||
Flag_openDoor = 1 << 2,
|
Flag_openDoor = 1 << 2,
|
||||||
|
Flag_usePathgrid = 1 << 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream& operator <<(std::ostream& stream, const Flag value)
|
inline std::ostream& operator <<(std::ostream& stream, const Flag value)
|
||||||
@ -27,6 +28,8 @@ namespace DetourNavigator
|
|||||||
return stream << "swim";
|
return stream << "swim";
|
||||||
case Flag_openDoor:
|
case Flag_openDoor:
|
||||||
return stream << "openDoor";
|
return stream << "openDoor";
|
||||||
|
case Flag_usePathgrid:
|
||||||
|
return stream << "usePathgrid";
|
||||||
}
|
}
|
||||||
|
|
||||||
return stream;
|
return stream;
|
||||||
@ -45,7 +48,7 @@ namespace DetourNavigator
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (const auto flag : {Flag_walk, Flag_swim, Flag_openDoor})
|
for (const auto flag : {Flag_walk, Flag_swim, Flag_openDoor, Flag_usePathgrid})
|
||||||
{
|
{
|
||||||
if (value.mValue & flag)
|
if (value.mValue & flag)
|
||||||
{
|
{
|
||||||
|
@ -98,6 +98,42 @@ namespace
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Flag getFlag(AreaType areaType)
|
||||||
|
{
|
||||||
|
switch (areaType)
|
||||||
|
{
|
||||||
|
case AreaType_null:
|
||||||
|
return Flag_none;
|
||||||
|
case AreaType_ground:
|
||||||
|
return Flag_walk;
|
||||||
|
case AreaType_water:
|
||||||
|
return Flag_swim;
|
||||||
|
case AreaType_door:
|
||||||
|
return Flag_openDoor;
|
||||||
|
case AreaType_pathgrid:
|
||||||
|
return Flag_usePathgrid;
|
||||||
|
}
|
||||||
|
return Flag_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned char> getOffMeshConAreas(const std::vector<OffMeshConnection>& connections)
|
||||||
|
{
|
||||||
|
std::vector<unsigned char> result;
|
||||||
|
result.reserve(connections.size());
|
||||||
|
std::transform(connections.begin(), connections.end(), std::back_inserter(result),
|
||||||
|
[] (const OffMeshConnection& v) { return v.mAreaType; });
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned short> getOffMeshFlags(const std::vector<OffMeshConnection>& connections)
|
||||||
|
{
|
||||||
|
std::vector<unsigned short> result;
|
||||||
|
result.reserve(connections.size());
|
||||||
|
std::transform(connections.begin(), connections.end(), std::back_inserter(result),
|
||||||
|
[] (const OffMeshConnection& v) { return getFlag(v.mAreaType); });
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
rcConfig makeConfig(const osg::Vec3f& agentHalfExtents, const osg::Vec3f& boundsMin, const osg::Vec3f& boundsMax,
|
rcConfig makeConfig(const osg::Vec3f& agentHalfExtents, const osg::Vec3f& boundsMin, const osg::Vec3f& boundsMax,
|
||||||
const Settings& settings)
|
const Settings& settings)
|
||||||
{
|
{
|
||||||
@ -334,12 +370,7 @@ namespace
|
|||||||
void setPolyMeshFlags(rcPolyMesh& polyMesh)
|
void setPolyMeshFlags(rcPolyMesh& polyMesh)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < polyMesh.npolys; ++i)
|
for (int i = 0; i < polyMesh.npolys; ++i)
|
||||||
{
|
polyMesh.flags[i] = getFlag(static_cast<AreaType>(polyMesh.areas[i]));
|
||||||
if (polyMesh.areas[i] == AreaType_ground)
|
|
||||||
polyMesh.flags[i] = Flag_walk;
|
|
||||||
else if (polyMesh.areas[i] == AreaType_water)
|
|
||||||
polyMesh.flags[i] = Flag_swim;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fillPolyMesh(rcContext& context, const rcConfig& config, rcHeightfield& solid, rcPolyMesh& polyMesh,
|
bool fillPolyMesh(rcContext& context, const rcConfig& config, rcHeightfield& solid, rcPolyMesh& polyMesh,
|
||||||
@ -395,8 +426,8 @@ namespace
|
|||||||
const auto offMeshConVerts = getOffMeshVerts(offMeshConnections);
|
const auto offMeshConVerts = getOffMeshVerts(offMeshConnections);
|
||||||
const std::vector<float> offMeshConRad(offMeshConnections.size(), getRadius(settings, agentHalfExtents));
|
const std::vector<float> offMeshConRad(offMeshConnections.size(), getRadius(settings, agentHalfExtents));
|
||||||
const std::vector<unsigned char> offMeshConDir(offMeshConnections.size(), DT_OFFMESH_CON_BIDIR);
|
const std::vector<unsigned char> offMeshConDir(offMeshConnections.size(), DT_OFFMESH_CON_BIDIR);
|
||||||
const std::vector<unsigned char> offMeshConAreas(offMeshConnections.size(), AreaType_ground);
|
const std::vector<unsigned char> offMeshConAreas = getOffMeshConAreas(offMeshConnections);
|
||||||
const std::vector<unsigned short> offMeshConFlags(offMeshConnections.size(), Flag_openDoor);
|
const std::vector<unsigned short> offMeshConFlags = getOffMeshFlags(offMeshConnections);
|
||||||
|
|
||||||
dtNavMeshCreateParams params;
|
dtNavMeshCreateParams params;
|
||||||
params.verts = polyMesh.verts;
|
params.verts = polyMesh.verts;
|
||||||
|
@ -9,6 +9,12 @@
|
|||||||
#include "recastmesh.hpp"
|
#include "recastmesh.hpp"
|
||||||
#include "recastmeshtiles.hpp"
|
#include "recastmeshtiles.hpp"
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
struct Cell;
|
||||||
|
struct Pathgrid;
|
||||||
|
}
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
struct ObjectShapes
|
struct ObjectShapes
|
||||||
@ -139,6 +145,10 @@ namespace DetourNavigator
|
|||||||
*/
|
*/
|
||||||
virtual bool removeWater(const osg::Vec2i& cellPosition) = 0;
|
virtual bool removeWater(const osg::Vec2i& cellPosition) = 0;
|
||||||
|
|
||||||
|
virtual void addPathgrid(const ESM::Cell& cell, const ESM::Pathgrid& pathgrid) = 0;
|
||||||
|
|
||||||
|
virtual void removePathgrid(const ESM::Pathgrid& pathgrid) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief update start background navmesh update using current scene state.
|
* @brief update start background navmesh update using current scene state.
|
||||||
* @param playerPosition setup initial point to order build tiles of navmesh.
|
* @param playerPosition setup initial point to order build tiles of navmesh.
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
#include "debug.hpp"
|
#include "debug.hpp"
|
||||||
#include "settingsutils.hpp"
|
#include "settingsutils.hpp"
|
||||||
|
|
||||||
|
#include <components/esm/loadpgrd.hpp>
|
||||||
|
#include <components/misc/coordinateconverter.hpp>
|
||||||
|
|
||||||
#include <Recast.h>
|
#include <Recast.h>
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
@ -54,7 +57,8 @@ namespace DetourNavigator
|
|||||||
mNavMeshManager.addOffMeshConnection(
|
mNavMeshManager.addOffMeshConnection(
|
||||||
id,
|
id,
|
||||||
toNavMeshCoordinates(mSettings, shapes.mConnectionStart),
|
toNavMeshCoordinates(mSettings, shapes.mConnectionStart),
|
||||||
toNavMeshCoordinates(mSettings, shapes.mConnectionEnd)
|
toNavMeshCoordinates(mSettings, shapes.mConnectionEnd),
|
||||||
|
AreaType_door
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -95,7 +99,7 @@ namespace DetourNavigator
|
|||||||
const auto water = mWaterIds.find(id);
|
const auto water = mWaterIds.find(id);
|
||||||
if (water != mWaterIds.end())
|
if (water != mWaterIds.end())
|
||||||
result = mNavMeshManager.removeObject(water->second) || result;
|
result = mNavMeshManager.removeObject(water->second) || result;
|
||||||
mNavMeshManager.removeOffMeshConnection(id);
|
mNavMeshManager.removeOffMeshConnections(id);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,6 +115,27 @@ namespace DetourNavigator
|
|||||||
return mNavMeshManager.removeWater(cellPosition);
|
return mNavMeshManager.removeWater(cellPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NavigatorImpl::addPathgrid(const ESM::Cell& cell, const ESM::Pathgrid& pathgrid)
|
||||||
|
{
|
||||||
|
Misc::CoordinateConverter converter(&cell);
|
||||||
|
for (auto edge : pathgrid.mEdges)
|
||||||
|
{
|
||||||
|
const auto src = Misc::Convert::makeOsgVec3f(converter.toWorldPoint(pathgrid.mPoints[edge.mV0]));
|
||||||
|
const auto dst = Misc::Convert::makeOsgVec3f(converter.toWorldPoint(pathgrid.mPoints[edge.mV1]));
|
||||||
|
mNavMeshManager.addOffMeshConnection(
|
||||||
|
ObjectId(&pathgrid),
|
||||||
|
toNavMeshCoordinates(mSettings, src),
|
||||||
|
toNavMeshCoordinates(mSettings, dst),
|
||||||
|
AreaType_pathgrid
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NavigatorImpl::removePathgrid(const ESM::Pathgrid& pathgrid)
|
||||||
|
{
|
||||||
|
mNavMeshManager.removeOffMeshConnections(ObjectId(&pathgrid));
|
||||||
|
}
|
||||||
|
|
||||||
void NavigatorImpl::update(const osg::Vec3f& playerPosition)
|
void NavigatorImpl::update(const osg::Vec3f& playerPosition)
|
||||||
{
|
{
|
||||||
removeUnusedNavMeshes();
|
removeUnusedNavMeshes();
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include "navigator.hpp"
|
#include "navigator.hpp"
|
||||||
#include "navmeshmanager.hpp"
|
#include "navmeshmanager.hpp"
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
class NavigatorImpl final : public Navigator
|
class NavigatorImpl final : public Navigator
|
||||||
@ -38,6 +40,10 @@ namespace DetourNavigator
|
|||||||
|
|
||||||
bool removeWater(const osg::Vec2i& cellPosition) override;
|
bool removeWater(const osg::Vec2i& cellPosition) override;
|
||||||
|
|
||||||
|
void addPathgrid(const ESM::Cell& cell, const ESM::Pathgrid& pathgrid) final;
|
||||||
|
|
||||||
|
void removePathgrid(const ESM::Pathgrid& pathgrid) final;
|
||||||
|
|
||||||
void update(const osg::Vec3f& playerPosition) override;
|
void update(const osg::Vec3f& playerPosition) override;
|
||||||
|
|
||||||
void wait() override;
|
void wait() override;
|
||||||
@ -58,6 +64,7 @@ namespace DetourNavigator
|
|||||||
std::map<osg::Vec3f, std::size_t> mAgents;
|
std::map<osg::Vec3f, std::size_t> mAgents;
|
||||||
std::unordered_map<ObjectId, ObjectId> mAvoidIds;
|
std::unordered_map<ObjectId, ObjectId> mAvoidIds;
|
||||||
std::unordered_map<ObjectId, ObjectId> mWaterIds;
|
std::unordered_map<ObjectId, ObjectId> mWaterIds;
|
||||||
|
std::multimap<ObjectId, ObjectId> mOffMeshConnectionIds;
|
||||||
|
|
||||||
void updateAvoidShapeId(const ObjectId id, const ObjectId avoidId);
|
void updateAvoidShapeId(const ObjectId id, const ObjectId avoidId);
|
||||||
void updateWaterShapeId(const ObjectId id, const ObjectId waterId);
|
void updateWaterShapeId(const ObjectId id, const ObjectId waterId);
|
||||||
|
@ -60,6 +60,10 @@ namespace DetourNavigator
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addPathgrid(const ESM::Cell& /*cell*/, const ESM::Pathgrid& /*pathgrid*/) final {}
|
||||||
|
|
||||||
|
void removePathgrid(const ESM::Pathgrid& /*pathgrid*/) final {}
|
||||||
|
|
||||||
void update(const osg::Vec3f& /*playerPosition*/) override {}
|
void update(const osg::Vec3f& /*playerPosition*/) override {}
|
||||||
|
|
||||||
void wait() override {}
|
void wait() override {}
|
||||||
|
@ -110,10 +110,9 @@ namespace DetourNavigator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavMeshManager::addOffMeshConnection(const ObjectId id, const osg::Vec3f& start, const osg::Vec3f& end)
|
void NavMeshManager::addOffMeshConnection(const ObjectId id, const osg::Vec3f& start, const osg::Vec3f& end, const AreaType areaType)
|
||||||
{
|
{
|
||||||
if (!mOffMeshConnectionsManager.add(id, OffMeshConnection {start, end}))
|
mOffMeshConnectionsManager.add(id, OffMeshConnection {start, end, areaType});
|
||||||
return;
|
|
||||||
|
|
||||||
const auto startTilePosition = getTilePosition(mSettings, start);
|
const auto startTilePosition = getTilePosition(mSettings, start);
|
||||||
const auto endTilePosition = getTilePosition(mSettings, end);
|
const auto endTilePosition = getTilePosition(mSettings, end);
|
||||||
@ -124,18 +123,11 @@ namespace DetourNavigator
|
|||||||
addChangedTile(endTilePosition, ChangeType::add);
|
addChangedTile(endTilePosition, ChangeType::add);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavMeshManager::removeOffMeshConnection(const ObjectId id)
|
void NavMeshManager::removeOffMeshConnections(const ObjectId id)
|
||||||
{
|
{
|
||||||
if (const auto connection = mOffMeshConnectionsManager.remove(id))
|
const auto changedTiles = mOffMeshConnectionsManager.remove(id);
|
||||||
{
|
for (const auto& tile : changedTiles)
|
||||||
const auto startTilePosition = getTilePosition(mSettings, connection->mStart);
|
addChangedTile(tile, ChangeType::update);
|
||||||
const auto endTilePosition = getTilePosition(mSettings, connection->mEnd);
|
|
||||||
|
|
||||||
addChangedTile(startTilePosition, ChangeType::remove);
|
|
||||||
|
|
||||||
if (startTilePosition != endTilePosition)
|
|
||||||
addChangedTile(endTilePosition, ChangeType::remove);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavMeshManager::update(osg::Vec3f playerPosition, const osg::Vec3f& agentHalfExtents)
|
void NavMeshManager::update(osg::Vec3f playerPosition, const osg::Vec3f& agentHalfExtents)
|
||||||
|
@ -39,9 +39,9 @@ namespace DetourNavigator
|
|||||||
|
|
||||||
bool reset(const osg::Vec3f& agentHalfExtents);
|
bool reset(const osg::Vec3f& agentHalfExtents);
|
||||||
|
|
||||||
void addOffMeshConnection(const ObjectId id, const osg::Vec3f& start, const osg::Vec3f& end);
|
void addOffMeshConnection(const ObjectId id, const osg::Vec3f& start, const osg::Vec3f& end, const AreaType areaType);
|
||||||
|
|
||||||
void removeOffMeshConnection(const ObjectId id);
|
void removeOffMeshConnections(const ObjectId id);
|
||||||
|
|
||||||
void update(osg::Vec3f playerPosition, const osg::Vec3f& agentHalfExtents);
|
void update(osg::Vec3f playerPosition, const osg::Vec3f& agentHalfExtents);
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_OFFMESHCONNECTION_H
|
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_OFFMESHCONNECTION_H
|
||||||
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_OFFMESHCONNECTION_H
|
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_OFFMESHCONNECTION_H
|
||||||
|
|
||||||
|
#include "areatype.hpp"
|
||||||
|
|
||||||
#include <osg/Vec3f>
|
#include <osg/Vec3f>
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
@ -9,6 +11,7 @@ namespace DetourNavigator
|
|||||||
{
|
{
|
||||||
osg::Vec3f mStart;
|
osg::Vec3f mStart;
|
||||||
osg::Vec3f mEnd;
|
osg::Vec3f mEnd;
|
||||||
|
AreaType mAreaType;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,14 +11,11 @@
|
|||||||
|
|
||||||
#include <osg/Vec3f>
|
#include <osg/Vec3f>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <mutex>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
@ -29,12 +26,11 @@ namespace DetourNavigator
|
|||||||
: mSettings(settings)
|
: mSettings(settings)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool add(const ObjectId id, const OffMeshConnection& value)
|
void add(const ObjectId id, const OffMeshConnection& value)
|
||||||
{
|
{
|
||||||
const auto values = mValues.lock();
|
const auto values = mValues.lock();
|
||||||
|
|
||||||
if (!values->mById.insert(std::make_pair(id, value)).second)
|
values->mById.insert(std::make_pair(id, value));
|
||||||
return false;
|
|
||||||
|
|
||||||
const auto startTilePosition = getTilePosition(mSettings, value.mStart);
|
const auto startTilePosition = getTilePosition(mSettings, value.mStart);
|
||||||
const auto endTilePosition = getTilePosition(mSettings, value.mEnd);
|
const auto endTilePosition = getTilePosition(mSettings, value.mEnd);
|
||||||
@ -43,32 +39,32 @@ namespace DetourNavigator
|
|||||||
|
|
||||||
if (startTilePosition != endTilePosition)
|
if (startTilePosition != endTilePosition)
|
||||||
values->mByTilePosition[endTilePosition].insert(id);
|
values->mByTilePosition[endTilePosition].insert(id);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<OffMeshConnection> remove(const ObjectId id)
|
std::set<TilePosition> remove(const ObjectId id)
|
||||||
{
|
{
|
||||||
const auto values = mValues.lock();
|
const auto values = mValues.lock();
|
||||||
|
|
||||||
const auto itById = values->mById.find(id);
|
const auto byId = values->mById.equal_range(id);
|
||||||
|
|
||||||
if (itById == values->mById.end())
|
if (byId.first == byId.second) {
|
||||||
return boost::none;
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
const auto result = itById->second;
|
std::set<TilePosition> removed;
|
||||||
|
|
||||||
values->mById.erase(itById);
|
std::for_each(byId.first, byId.second, [&] (const auto& v) {
|
||||||
|
const auto startTilePosition = getTilePosition(mSettings, v.second.mStart);
|
||||||
|
const auto endTilePosition = getTilePosition(mSettings, v.second.mEnd);
|
||||||
|
|
||||||
const auto startTilePosition = getTilePosition(mSettings, result.mStart);
|
removed.emplace(startTilePosition);
|
||||||
const auto endTilePosition = getTilePosition(mSettings, result.mEnd);
|
if (startTilePosition != endTilePosition)
|
||||||
|
removed.emplace(endTilePosition);
|
||||||
|
});
|
||||||
|
|
||||||
removeByTilePosition(values->mByTilePosition, startTilePosition, id);
|
values->mById.erase(byId.first, byId.second);
|
||||||
|
|
||||||
if (startTilePosition != endTilePosition)
|
return removed;
|
||||||
removeByTilePosition(values->mByTilePosition, endTilePosition, id);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<OffMeshConnection> get(const TilePosition& tilePosition)
|
std::vector<OffMeshConnection> get(const TilePosition& tilePosition)
|
||||||
@ -85,9 +81,8 @@ namespace DetourNavigator
|
|||||||
std::for_each(itByTilePosition->second.begin(), itByTilePosition->second.end(),
|
std::for_each(itByTilePosition->second.begin(), itByTilePosition->second.end(),
|
||||||
[&] (const ObjectId v)
|
[&] (const ObjectId v)
|
||||||
{
|
{
|
||||||
const auto itById = values->mById.find(v);
|
const auto byId = values->mById.equal_range(v);
|
||||||
if (itById != values->mById.end())
|
std::for_each(byId.first, byId.second, [&] (const auto& v) { result.push_back(v.second); });
|
||||||
result.push_back(itById->second);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -96,7 +91,7 @@ namespace DetourNavigator
|
|||||||
private:
|
private:
|
||||||
struct Values
|
struct Values
|
||||||
{
|
{
|
||||||
std::unordered_map<ObjectId, OffMeshConnection> mById;
|
std::multimap<ObjectId, OffMeshConnection> mById;
|
||||||
std::map<TilePosition, std::unordered_set<ObjectId>> mByTilePosition;
|
std::map<TilePosition, std::unordered_set<ObjectId>> mByTilePosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef OPENMW_COMPONENTS_MISC_CONVERT_H
|
#ifndef OPENMW_COMPONENTS_MISC_CONVERT_H
|
||||||
#define OPENMW_COMPONENTS_MISC_CONVERT_H
|
#define OPENMW_COMPONENTS_MISC_CONVERT_H
|
||||||
|
|
||||||
|
#include <components/esm/loadpgrd.hpp>
|
||||||
|
|
||||||
#include <LinearMath/btTransform.h>
|
#include <LinearMath/btTransform.h>
|
||||||
#include <LinearMath/btVector3.h>
|
#include <LinearMath/btVector3.h>
|
||||||
#include <LinearMath/btQuaternion.h>
|
#include <LinearMath/btQuaternion.h>
|
||||||
@ -21,6 +23,11 @@ namespace Convert
|
|||||||
return osg::Vec3f(value.x(), value.y(), value.z());
|
return osg::Vec3f(value.x(), value.y(), value.z());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline osg::Vec3f makeOsgVec3f(const ESM::Pathgrid::Point& value)
|
||||||
|
{
|
||||||
|
return osg::Vec3f(value.mX, value.mY, value.mZ);
|
||||||
|
}
|
||||||
|
|
||||||
inline btVector3 toBullet(const osg::Vec3f& vec)
|
inline btVector3 toBullet(const osg::Vec3f& vec)
|
||||||
{
|
{
|
||||||
return btVector3(vec.x(), vec.y(), vec.z());
|
return btVector3(vec.x(), vec.y(), vec.z());
|
||||||
|
68
components/misc/coordinateconverter.hpp
Normal file
68
components/misc/coordinateconverter.hpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#ifndef OPENMW_COMPONENTS_MISC_COORDINATECONVERTER_H
|
||||||
|
#define OPENMW_COMPONENTS_MISC_COORDINATECONVERTER_H
|
||||||
|
|
||||||
|
#include <components/esm/defs.hpp>
|
||||||
|
#include <components/esm/loadcell.hpp>
|
||||||
|
#include <components/esm/loadland.hpp>
|
||||||
|
#include <components/esm/loadpgrd.hpp>
|
||||||
|
|
||||||
|
namespace Misc
|
||||||
|
{
|
||||||
|
/// \brief convert coordinates between world and local cell
|
||||||
|
class CoordinateConverter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CoordinateConverter(bool exterior, int cellX, int cellY)
|
||||||
|
: mCellX(exterior ? cellX * ESM::Land::REAL_SIZE : 0),
|
||||||
|
mCellY(exterior ? cellY * ESM::Land::REAL_SIZE : 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit CoordinateConverter(const ESM::Cell* cell)
|
||||||
|
: CoordinateConverter(cell->isExterior(), cell->mData.mX, cell->mData.mY)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// in-place conversion from local to world
|
||||||
|
void toWorld(ESM::Pathgrid::Point& point) const
|
||||||
|
{
|
||||||
|
point.mX += mCellX;
|
||||||
|
point.mY += mCellY;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESM::Pathgrid::Point toWorldPoint(ESM::Pathgrid::Point point) const
|
||||||
|
{
|
||||||
|
toWorld(point);
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// in-place conversion from local to world
|
||||||
|
void toWorld(osg::Vec3f& point) const
|
||||||
|
{
|
||||||
|
point.x() += static_cast<float>(mCellX);
|
||||||
|
point.y() += static_cast<float>(mCellY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// in-place conversion from world to local
|
||||||
|
void toLocal(osg::Vec3f& point) const
|
||||||
|
{
|
||||||
|
point.x() -= static_cast<float>(mCellX);
|
||||||
|
point.y() -= static_cast<float>(mCellY);
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Vec3f toLocalVec3(const osg::Vec3f& point) const
|
||||||
|
{
|
||||||
|
return osg::Vec3f(
|
||||||
|
point.x() - static_cast<float>(mCellX),
|
||||||
|
point.y() - static_cast<float>(mCellY),
|
||||||
|
point.z()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int mCellX;
|
||||||
|
int mCellY;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user