|
|
|
@ -6,7 +6,7 @@
|
|
|
|
|
#include "recastmesh.hpp"
|
|
|
|
|
#include "settings.hpp"
|
|
|
|
|
#include "settingsutils.hpp"
|
|
|
|
|
#include "debug.hpp"
|
|
|
|
|
#include "sharednavmesh.hpp"
|
|
|
|
|
|
|
|
|
|
#include <DetourNavMesh.h>
|
|
|
|
|
#include <DetourNavMeshBuilder.h>
|
|
|
|
@ -218,22 +218,8 @@ namespace
|
|
|
|
|
|
|
|
|
|
namespace DetourNavigator
|
|
|
|
|
{
|
|
|
|
|
NavMeshPtr makeEmptyNavMesh(const osg::Vec3f& agentHalfExtents, const RecastMesh& recastMesh,
|
|
|
|
|
const Settings& settings)
|
|
|
|
|
NavMeshPtr makeEmptyNavMesh(const Settings& settings)
|
|
|
|
|
{
|
|
|
|
|
log("build empty NavMesh:",
|
|
|
|
|
" agentHeight=", std::setprecision(std::numeric_limits<float>::max_exponent10),
|
|
|
|
|
getHeight(settings, agentHalfExtents),
|
|
|
|
|
" agentMaxClimb=", std::setprecision(std::numeric_limits<float>::max_exponent10),
|
|
|
|
|
getMaxClimb(settings),
|
|
|
|
|
" agentRadius=", std::setprecision(std::numeric_limits<float>::max_exponent10),
|
|
|
|
|
getRadius(settings, agentHalfExtents));
|
|
|
|
|
|
|
|
|
|
osg::Vec3f boundsMin;
|
|
|
|
|
osg::Vec3f boundsMax;
|
|
|
|
|
rcCalcBounds(recastMesh.getVertices().data(), static_cast<int>(recastMesh.getVerticesCount()),
|
|
|
|
|
boundsMin.ptr(), boundsMax.ptr());
|
|
|
|
|
|
|
|
|
|
// Max tiles and max polys affect how the tile IDs are caculated.
|
|
|
|
|
// There are 22 bits available for identifying a tile and a polygon.
|
|
|
|
|
const auto tileBits = 10;
|
|
|
|
@ -242,7 +228,7 @@ namespace DetourNavigator
|
|
|
|
|
const auto maxPolysPerTile = 1 << polyBits;
|
|
|
|
|
|
|
|
|
|
dtNavMeshParams params;
|
|
|
|
|
rcVcopy(params.orig, boundsMin.ptr());
|
|
|
|
|
std::fill_n(params.orig, 3, 0.0f);
|
|
|
|
|
params.tileWidth = settings.mTileSize * settings.mCellSize;
|
|
|
|
|
params.tileHeight = settings.mTileSize * settings.mCellSize;
|
|
|
|
|
params.maxTiles = maxTiles;
|
|
|
|
@ -254,67 +240,8 @@ namespace DetourNavigator
|
|
|
|
|
return navMesh;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NavMeshPtr makeNavMesh(const osg::Vec3f& agentHalfExtents, const RecastMesh& recastMesh,
|
|
|
|
|
const Settings& settings)
|
|
|
|
|
{
|
|
|
|
|
log("build NavMesh with mutiple tiles:",
|
|
|
|
|
" agentHeight=", std::setprecision(std::numeric_limits<float>::max_exponent10),
|
|
|
|
|
getHeight(settings, agentHalfExtents),
|
|
|
|
|
" agentMaxClimb=", std::setprecision(std::numeric_limits<float>::max_exponent10),
|
|
|
|
|
getMaxClimb(settings),
|
|
|
|
|
" agentRadius=", std::setprecision(std::numeric_limits<float>::max_exponent10),
|
|
|
|
|
getRadius(settings, agentHalfExtents));
|
|
|
|
|
|
|
|
|
|
osg::Vec3f boundsMin;
|
|
|
|
|
osg::Vec3f boundsMax;
|
|
|
|
|
rcCalcBounds(recastMesh.getVertices().data(), static_cast<int>(recastMesh.getVerticesCount()),
|
|
|
|
|
boundsMin.ptr(), boundsMax.ptr());
|
|
|
|
|
|
|
|
|
|
const auto minTilePosition = getTilePosition(settings, boundsMin);
|
|
|
|
|
const auto maxTilePosition = getTilePosition(settings, boundsMax);
|
|
|
|
|
|
|
|
|
|
// Max tiles and max polys affect how the tile IDs are caculated.
|
|
|
|
|
// There are 22 bits available for identifying a tile and a polygon.
|
|
|
|
|
const auto tileBits = 10;
|
|
|
|
|
const auto polyBits = 22 - tileBits;
|
|
|
|
|
const auto maxTiles = 1 << tileBits;
|
|
|
|
|
const auto maxPolysPerTile = 1 << polyBits;
|
|
|
|
|
|
|
|
|
|
dtNavMeshParams params;
|
|
|
|
|
std::fill_n(params.orig, 3, 0.0f);
|
|
|
|
|
params.tileWidth = getTileSize(settings);
|
|
|
|
|
params.tileHeight = getTileSize(settings);
|
|
|
|
|
params.maxTiles = maxTiles;
|
|
|
|
|
params.maxPolys = maxPolysPerTile;
|
|
|
|
|
|
|
|
|
|
NavMeshPtr navMesh(dtAllocNavMesh(), &dtFreeNavMesh);
|
|
|
|
|
OPENMW_CHECK_DT_STATUS(navMesh->init(¶ms));
|
|
|
|
|
|
|
|
|
|
for (int y = minTilePosition.y(); y <= maxTilePosition.y(); ++y)
|
|
|
|
|
{
|
|
|
|
|
for (int x = minTilePosition.x(); x <= maxTilePosition.x(); ++x)
|
|
|
|
|
{
|
|
|
|
|
const auto tileBounds = makeTileBounds(settings, TilePosition(x, y));
|
|
|
|
|
const osg::Vec3f tileBorderMin(tileBounds.mMin.x(), boundsMin.y() - 1, tileBounds.mMin.y());
|
|
|
|
|
const osg::Vec3f tileBorderMax(tileBounds.mMax.x(), boundsMax.y() + 1, tileBounds.mMax.y());
|
|
|
|
|
|
|
|
|
|
auto navMeshData = makeNavMeshTileData(agentHalfExtents, recastMesh, x, y,
|
|
|
|
|
tileBorderMin, tileBorderMax, settings);
|
|
|
|
|
|
|
|
|
|
if (!navMeshData.mValue)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
OPENMW_CHECK_DT_STATUS(navMesh->addTile(navMeshData.mValue.get(), navMeshData.mSize,
|
|
|
|
|
DT_TILE_FREE_DATA, 0, 0));
|
|
|
|
|
navMeshData.mValue.release();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return navMesh;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void updateNavMesh(const osg::Vec3f& agentHalfExtents, const RecastMesh& recastMesh,
|
|
|
|
|
const std::set<TilePosition>& changedTiles, const Settings& settings, dtNavMesh& navMesh)
|
|
|
|
|
const TilePosition& changedTile, const Settings& settings, SharedNavMesh& navMesh)
|
|
|
|
|
{
|
|
|
|
|
log("update NavMesh with mutiple tiles:",
|
|
|
|
|
" agentHeight=", std::setprecision(std::numeric_limits<float>::max_exponent10),
|
|
|
|
@ -323,36 +250,36 @@ namespace DetourNavigator
|
|
|
|
|
getMaxClimb(settings),
|
|
|
|
|
" agentRadius=", std::setprecision(std::numeric_limits<float>::max_exponent10),
|
|
|
|
|
getRadius(settings, agentHalfExtents),
|
|
|
|
|
" changedTiles.size()=", changedTiles.size());
|
|
|
|
|
" changedTile=", changedTile);
|
|
|
|
|
|
|
|
|
|
osg::Vec3f boundsMin;
|
|
|
|
|
osg::Vec3f boundsMax;
|
|
|
|
|
rcCalcBounds(recastMesh.getVertices().data(), int(recastMesh.getVerticesCount()),
|
|
|
|
|
boundsMin.ptr(), boundsMax.ptr());
|
|
|
|
|
|
|
|
|
|
const auto& params = *navMesh.getParams();
|
|
|
|
|
const auto& params = *navMesh.lock()->getParams();
|
|
|
|
|
const osg::Vec3f origin(params.orig[0], params.orig[1], params.orig[2]);
|
|
|
|
|
|
|
|
|
|
for (const auto& tilePosition : changedTiles)
|
|
|
|
|
{
|
|
|
|
|
const auto x = tilePosition.x();
|
|
|
|
|
const auto y = tilePosition.y();
|
|
|
|
|
const auto x = changedTile.x();
|
|
|
|
|
const auto y = changedTile.y();
|
|
|
|
|
|
|
|
|
|
navMesh.removeTile(navMesh.getTileRefAt(x, y, 0), nullptr, nullptr);
|
|
|
|
|
{
|
|
|
|
|
const auto locked = navMesh.lock();
|
|
|
|
|
locked->removeTile(locked->getTileRefAt(x, y, 0), nullptr, nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto tileBounds = makeTileBounds(settings, tilePosition);
|
|
|
|
|
const osg::Vec3f tileBorderMin(tileBounds.mMin.x(), boundsMin.y() - 1, tileBounds.mMin.y());
|
|
|
|
|
const osg::Vec3f tileBorderMax(tileBounds.mMax.x(), boundsMax.y() + 1, tileBounds.mMax.y());
|
|
|
|
|
const auto tileBounds = makeTileBounds(settings, changedTile);
|
|
|
|
|
const osg::Vec3f tileBorderMin(tileBounds.mMin.x(), boundsMin.y() - 1, tileBounds.mMin.y());
|
|
|
|
|
const osg::Vec3f tileBorderMax(tileBounds.mMax.x(), boundsMax.y() + 1, tileBounds.mMax.y());
|
|
|
|
|
|
|
|
|
|
auto navMeshData = makeNavMeshTileData(agentHalfExtents, recastMesh, x, y,
|
|
|
|
|
tileBorderMin, tileBorderMax, settings);
|
|
|
|
|
auto navMeshData = makeNavMeshTileData(agentHalfExtents, recastMesh, x, y,
|
|
|
|
|
tileBorderMin, tileBorderMax, settings);
|
|
|
|
|
|
|
|
|
|
if (!navMeshData.mValue)
|
|
|
|
|
continue;
|
|
|
|
|
if (!navMeshData.mValue)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
OPENMW_CHECK_DT_STATUS(navMesh.addTile(navMeshData.mValue.get(), navMeshData.mSize,
|
|
|
|
|
DT_TILE_FREE_DATA, 0, 0));
|
|
|
|
|
navMeshData.mValue.release();
|
|
|
|
|
}
|
|
|
|
|
OPENMW_CHECK_DT_STATUS(navMesh.lock()->addTile(navMeshData.mValue.get(), navMeshData.mSize,
|
|
|
|
|
DT_TILE_FREE_DATA, 0, 0));
|
|
|
|
|
navMeshData.mValue.release();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|